added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / column_mixed.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_MIXED_HPP
20 #define REALM_COLUMN_MIXED_HPP
21
22 #include <limits>
23
24 #include <realm/column.hpp>
25 #include <realm/column_type.hpp>
26 #include <realm/column_table.hpp>
27 #include <realm/table.hpp>
28 #include <realm/utilities.hpp>
29
30
31 namespace realm {
32
33
34 // Pre-declarations
35 class BinaryColumn;
36
37
38 /// A mixed column (MixedColumn) is composed of three subcolumns. The first
39 /// subcolumn is an integer column (Column) and stores value types. The second
40 /// one stores values and is a subtable parent column (SubtableColumnBase),
41 /// which is a subclass of an integer column (Column). The last one is a binary
42 /// column (BinaryColumn) and stores additional data for values of type string
43 /// or binary data. The last subcolumn is optional. The root of a mixed column
44 /// is an array node of type Array that stores the root refs of the subcolumns.
45 class MixedColumn : public ColumnBaseSimple {
46 public:
47     /// Create a mixed column wrapper and attach it to a preexisting
48     /// underlying structure of arrays.
49     ///
50     /// \param alloc The memory allocator to change the underlying
51     /// structure in memory.
52     ///
53     /// \param ref The memory reference of the MixedColumn for which
54     /// this accessor should be creator for.
55     ///
56     /// \param table If this column is used as part of a table you
57     /// must pass a pointer to that table. Otherwise you must pass
58     /// null
59     ///
60     /// \param column_ndx If this column is used as part of a table
61     /// you must pass the logical index of the column within that
62     /// table. Otherwise you should pass zero.
63     MixedColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx);
64
65     ~MixedColumn() noexcept override;
66
67     DataType get_type(size_t ndx) const noexcept;
68     size_t size() const noexcept final
69     {
70         return m_types->size();
71     }
72     bool is_empty() const noexcept
73     {
74         return size() == 0;
75     }
76
77     int64_t get_int(size_t ndx) const noexcept;
78     bool get_bool(size_t ndx) const noexcept;
79     OldDateTime get_olddatetime(size_t ndx) const noexcept;
80     Timestamp get_timestamp(size_t ndx) const noexcept;
81     float get_float(size_t ndx) const noexcept;
82     double get_double(size_t ndx) const noexcept;
83     StringData get_string(size_t ndx) const noexcept;
84     BinaryData get_binary(size_t ndx) const noexcept;
85     StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept override;
86
87     /// The returned array ref is zero if the specified row does not
88     /// contain a subtable.
89     ref_type get_subtable_ref(size_t row_ndx) const noexcept;
90
91     /// The returned size is zero if the specified row does not
92     /// contain a subtable.
93     size_t get_subtable_size(size_t row_ndx) const noexcept;
94
95     TableRef get_subtable_accessor(size_t row_ndx) const noexcept override;
96
97     void discard_subtable_accessor(size_t row_ndx) noexcept override;
98
99     /// If the value at the specified index is a subtable, return a
100     /// TableRef to that accessor for that subtable. Otherwise return
101     /// null. The accessor will be created if it does not already
102     /// exist.
103     TableRef get_subtable_tableref(size_t row_ndx);
104
105     ConstTableRef get_subtable_tableref(size_t subtable_ndx) const;
106
107     void set_int(size_t ndx, int64_t value);
108     void set_bool(size_t ndx, bool value);
109     void set_olddatetime(size_t ndx, OldDateTime value);
110     void set_timestamp(size_t ndx, Timestamp value);
111     void set_float(size_t ndx, float value);
112     void set_double(size_t ndx, double value);
113     void set_string(size_t ndx, StringData value) override;
114     void set_binary(size_t ndx, BinaryData value);
115     void set_subtable(size_t ndx, const Table* value);
116
117     void insert_int(size_t ndx, int_fast64_t value);
118     void insert_bool(size_t ndx, bool value);
119     void insert_olddatetime(size_t ndx, OldDateTime value);
120     void insert_timestamp(size_t ndx, Timestamp value);
121     void insert_float(size_t ndx, float value);
122     void insert_double(size_t ndx, double value);
123     void insert_string(size_t ndx, StringData value);
124     void insert_binary(size_t ndx, BinaryData value);
125     void insert_subtable(size_t ndx, const Table* value);
126
127     void erase(size_t row_ndx);
128     void move_last_over(size_t row_ndx);
129     void clear();
130
131     /// Compare two mixed columns for equality.
132     bool compare_mixed(const MixedColumn&) const;
133
134     int compare_values(size_t row1, size_t row2) const noexcept override;
135
136     void discard_child_accessors() noexcept;
137
138     static ref_type create(Allocator&, size_t size = 0);
139
140     static size_t get_size_from_ref(ref_type root_ref, Allocator&) noexcept;
141
142     // Overriding method in ColumnBase
143     ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override;
144
145     void insert_rows(size_t, size_t, size_t, bool) override;
146     void erase_rows(size_t, size_t, size_t, bool) override;
147     void move_last_row_over(size_t, size_t, bool) override;
148     void swap_rows(size_t, size_t) override;
149     void clear(size_t, bool) override;
150     void update_from_parent(size_t) noexcept override;
151     void adj_acc_insert_rows(size_t, size_t) noexcept override;
152     void adj_acc_erase_row(size_t) noexcept override;
153     void adj_acc_move_over(size_t, size_t) noexcept override;
154     void adj_acc_swap_rows(size_t, size_t) noexcept override;
155     void adj_acc_move_row(size_t, size_t) noexcept override;
156     void adj_acc_clear_root_table() noexcept override;
157     void mark(int) noexcept override;
158     void refresh_accessor_tree(size_t, const Spec&) override;
159
160     void verify() const override;
161     void verify(const Table&, size_t) const override;
162     void to_dot(std::ostream&, StringData title) const override;
163     void do_dump_node_structure(std::ostream&, int) const override;
164
165 private:
166     enum MixedColType {
167         // NOTE: below numbers must be kept in sync with ColumnType
168         // Column types used in Mixed
169         mixcol_Int = 0,
170         mixcol_Bool = 1,
171         mixcol_String = 2,
172         //                    3, used for STRING_ENUM in ColumnType
173         mixcol_Binary = 4,
174         mixcol_Table = 5,
175         mixcol_Mixed = 6,
176         mixcol_OldDateTime = 7,
177         mixcol_Timestamp = 8,
178         mixcol_Float = 9,
179         mixcol_Double = 10,    // Positive Double
180         mixcol_DoubleNeg = 11, // Negative Double
181         mixcol_IntNeg = 12     // Negative Integers
182     };
183
184     class RefsColumn;
185
186     /// Stores the MixedColType of each value at the given index. For
187     /// values that uses all 64 bits, the type also encodes the sign
188     /// bit by having distinct types for positive negative values.
189     std::unique_ptr<IntegerColumn> m_types;
190
191     /// Stores the data for each entry. For a subtable, the stored
192     /// value is the ref of the subtable. For string, binary data,
193     /// the stored value is an index within `m_binary_data`. Likewise,
194     /// for timestamp, an index into `m_timestamp` is stored. For other
195     /// types the stored value is itself. Since we only have 63 bits
196     /// available for a non-ref value, the sign of numeric values is
197     /// encoded as part of the type in `m_types`.
198     std::unique_ptr<RefsColumn> m_data;
199
200     /// For string and binary data types, the bytes are stored here.
201     std::unique_ptr<BinaryColumn> m_binary_data;
202
203     /// Timestamps are stored here.
204     std::unique_ptr<TimestampColumn> m_timestamp_data;
205
206     void do_erase(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows);
207     void do_move_last_over(size_t row_ndx, size_t prior_num_rows);
208     void do_swap_rows(size_t, size_t);
209     void do_clear(size_t num_rows);
210
211     void create(Allocator&, ref_type, Table*, size_t column_ndx);
212     void ensure_binary_data_column();
213     void ensure_timestamp_column();
214
215     MixedColType clear_value(size_t ndx, MixedColType new_type); // Returns old type
216     void clear_value_and_discard_subtab_acc(size_t ndx, MixedColType new_type);
217
218     // Get/set/insert 64-bit values in m_data/m_types
219     int64_t get_value(size_t ndx) const noexcept;
220     void set_value(size_t ndx, int64_t value, MixedColType);
221     void set_int64(size_t ndx, int64_t value, MixedColType pos_type, MixedColType neg_type);
222
223     void insert_value(size_t row_ndx, int_fast64_t types_value, int_fast64_t data_value);
224     void insert_int(size_t ndx, int_fast64_t value, MixedColType type);
225     void insert_pos_neg(size_t ndx, int_fast64_t value, MixedColType pos_type, MixedColType neg_type);
226
227     void do_discard_child_accessors() noexcept override;
228
229 #ifdef REALM_DEBUG
230     void do_verify(const Table*, size_t col_ndx) const;
231 #endif
232     void leaf_to_dot(MemRef, ArrayParent*, size_t, std::ostream&) const override;
233 };
234
235 // LCOV_EXCL_START
236 inline StringData MixedColumn::get_index_data(size_t, StringIndex::StringConversionBuffer&) const noexcept
237 {
238     REALM_ASSERT(false && "Index not supported for MixedColumn yet.");
239     REALM_UNREACHABLE();
240     return {};
241 }
242 // LCOV_EXCL_STOP
243
244
245 class MixedColumn::RefsColumn : public SubtableColumnBase {
246 public:
247     RefsColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx);
248     ~RefsColumn() noexcept override;
249
250     using SubtableColumnBase::get_subtable_tableref;
251
252     void refresh_accessor_tree(size_t, const Spec&) override;
253
254     friend class MixedColumn;
255 };
256
257
258 } // namespace realm
259
260
261 // Implementation
262 #include <realm/column_mixed_tpl.hpp>
263
264
265 #endif // REALM_COLUMN_MIXED_HPP