added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / column_link.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_COLUMN_LINK_HPP
20 #define REALM_COLUMN_LINK_HPP
21
22 #include <realm/column.hpp>
23 #include <realm/column_linkbase.hpp>
24 #include <realm/column_backlink.hpp>
25
26 namespace realm {
27
28 /// A link column is an extension of an integer column (Column) and maintains
29 /// its node structure.
30 ///
31 /// The individual values in a link column are indexes of rows in the target
32 /// table (offset with one to allow zero to indicate null links.) The target
33 /// table is specified by the table descriptor.
34 class LinkColumn : public LinkColumnBase {
35 public:
36     using LinkColumnBase::LinkColumnBase;
37     ~LinkColumn() noexcept override;
38
39     static ref_type create(Allocator&, size_t size = 0);
40
41     bool is_nullable() const noexcept override;
42
43     //@{
44
45     /// is_null_link() is shorthand for `get_link() == realm::npos`,
46     /// nullify_link() is shorthand foe `set_link(realm::npos)`, and
47     /// insert_null_link() is shorthand for
48     /// `insert_link(realm::npos)`. set_link() returns the original link, with
49     /// `realm::npos` indicating that it was null.
50
51     size_t get_link(size_t row_ndx) const noexcept;
52     bool is_null(size_t row_ndx) const noexcept override;
53     bool is_null_link(size_t row_ndx) const noexcept;
54     size_t set_link(size_t row_ndx, size_t target_row_ndx);
55     void set_null(size_t row_ndx) override;
56     void nullify_link(size_t row_ndx);
57     void insert_link(size_t row_ndx, size_t target_row_ndx);
58     void insert_null_link(size_t row_ndx);
59
60     //@}
61
62     void insert_rows(size_t, size_t, size_t, bool) override;
63     void erase_rows(size_t, size_t, size_t, bool) override;
64     void move_last_row_over(size_t, size_t, bool) override;
65     void swap_rows(size_t, size_t) override;
66     void clear(size_t, bool) override;
67     void cascade_break_backlinks_to(size_t, CascadeState&) override;
68     void cascade_break_backlinks_to_all_rows(size_t, CascadeState&) override;
69
70     void verify(const Table&, size_t) const override;
71
72 protected:
73     friend class BacklinkColumn;
74     void do_nullify_link(size_t row_ndx, size_t old_target_row_ndx) override;
75     void do_update_link(size_t row_ndx, size_t old_target_row_ndx, size_t new_target_row_ndx) override;
76     void do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) override;
77
78 private:
79     void remove_backlinks(size_t row_ndx);
80 };
81
82
83 // Implementation
84
85 inline LinkColumn::~LinkColumn() noexcept
86 {
87 }
88
89 inline bool LinkColumn::is_nullable() const noexcept
90 {
91     return true;
92 }
93
94 inline ref_type LinkColumn::create(Allocator& alloc, size_t size)
95 {
96     return IntegerColumn::create(alloc, Array::type_Normal, size); // Throws
97 }
98
99 inline bool LinkColumn::is_null(size_t row_ndx) const noexcept
100 {
101     // Null is represented by zero
102     return LinkColumnBase::get(row_ndx) == 0;
103 }
104
105 inline size_t LinkColumn::get_link(size_t row_ndx) const noexcept
106 {
107     // Map zero to realm::npos, and `n+1` to `n`, where `n` is a target row index.
108     return to_size_t(LinkColumnBase::get(row_ndx)) - size_t(1);
109 }
110
111 inline bool LinkColumn::is_null_link(size_t row_ndx) const noexcept
112 {
113     return is_null(row_ndx);
114 }
115
116 inline size_t LinkColumn::set_link(size_t row_ndx, size_t target_row_ndx)
117 {
118     int_fast64_t old_value = LinkColumnBase::get(row_ndx);
119     size_t old_target_row_ndx = to_size_t(old_value) - size_t(1);
120     if (old_value != 0)
121         m_backlink_column->remove_one_backlink(old_target_row_ndx, row_ndx); // Throws
122
123     int_fast64_t new_value = int_fast64_t(size_t(1) + target_row_ndx);
124     LinkColumnBase::set(row_ndx, new_value); // Throws
125
126     if (target_row_ndx != realm::npos)
127         m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws
128
129     return old_target_row_ndx;
130 }
131
132 inline void LinkColumn::set_null(size_t row_ndx)
133 {
134     set_link(row_ndx, realm::npos); // Throws
135 }
136
137 inline void LinkColumn::nullify_link(size_t row_ndx)
138 {
139     set_null(row_ndx); // Throws
140 }
141
142 inline void LinkColumn::insert_link(size_t row_ndx, size_t target_row_ndx)
143 {
144     int_fast64_t value = int_fast64_t(size_t(1) + target_row_ndx);
145     LinkColumnBase::insert(row_ndx, value); // Throws
146
147     if (target_row_ndx != realm::npos)
148         m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws
149 }
150
151 inline void LinkColumn::insert_null_link(size_t row_ndx)
152 {
153     insert_link(row_ndx, realm::npos); // Throws
154 }
155
156 inline void LinkColumn::do_update_link(size_t row_ndx, size_t, size_t new_target_row_ndx)
157 {
158     // Row pos is offset by one, to allow null refs
159     LinkColumnBase::set(row_ndx, new_target_row_ndx + 1);
160 }
161
162 inline void LinkColumn::do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2)
163 {
164     // Row pos is offset by one, to allow null refs
165     ++target_row_ndx_1;
166     ++target_row_ndx_2;
167
168     uint64_t value = LinkColumnBase::get_uint(row_ndx);
169     if (value == target_row_ndx_1) {
170         LinkColumnBase::set_uint(row_ndx, target_row_ndx_2);
171     }
172     else if (value == target_row_ndx_2) {
173         LinkColumnBase::set_uint(row_ndx, target_row_ndx_1);
174     }
175 }
176
177 } // namespace realm
178
179 #endif // REALM_COLUMN_LINK_HPP