• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / jorgen.edelbo_337

03 Jul 2024 01:04PM UTC coverage: 90.864% (-0.1%) from 90.984%
jorgen.edelbo_337

Pull #7826

Evergreen

nicola-cab
Merge branch 'master' of github.com:realm/realm-core into next-major
Pull Request #7826: Merge Next major

102968 of 181176 branches covered (56.83%)

3131 of 3738 new or added lines in 54 files covered. (83.76%)

106 existing lines in 23 files now uncovered.

217725 of 239616 relevant lines covered (90.86%)

6844960.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.57
/src/realm/array_mixed.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2018 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
#include <realm/array_mixed.hpp>
20
#include <realm/array_basic.hpp>
21
#include <realm/dictionary.hpp>
22
#include <realm/impl/array_writer.hpp>
23

24
using namespace realm;
25

26
ArrayMixed::ArrayMixed(Allocator& a)
27
    : Array(a)
2,865,765✔
28
    , m_composite(a)
2,865,765✔
29
    , m_ints(a)
2,865,765✔
30
    , m_int_pairs(a)
2,865,765✔
31
    , m_strings(a)
2,865,765✔
32
    , m_refs(a)
2,865,765✔
33
{
5,735,691✔
34
    m_composite.set_parent(this, payload_idx_type);
5,735,691✔
35
}
5,735,691✔
36

37
void ArrayMixed::create()
38
{
363,627✔
39
    Array::create(type_HasRefs, false, payload_idx_size);
363,627✔
40
    m_composite.create(type_Normal);
363,627✔
41
    m_composite.update_parent();
363,627✔
42
}
363,627✔
43

44
void ArrayMixed::init_from_mem(MemRef mem) noexcept
45
{
4,174,257✔
46
    Array::init_from_mem(mem);
4,174,257✔
47
    m_composite.init_from_parent();
4,174,257✔
48
    m_ints.detach();
4,174,257✔
49
    m_int_pairs.detach();
4,174,257✔
50
    m_strings.detach();
4,174,257✔
51
    m_refs.detach();
4,174,257✔
52
}
4,174,257✔
53

54
void ArrayMixed::add(Mixed value)
55
{
49,698✔
56
    if (value.is_null()) {
49,698✔
57
        m_composite.add(0);
54✔
58
        return;
54✔
59
    }
54✔
60
    m_composite.add(store(value));
49,644✔
61
}
49,644✔
62

63

64
void ArrayMixed::set(size_t ndx, Mixed value)
65
{
421,800✔
66
    auto old_type = get_type(ndx);
421,800✔
67
    // If we replace a collections ref value with one of the
68
    // same type, then it is just an update of of the
69
    // ref stored in the parent. If the new type is a different
70
    // type then it means that we are overwriting a collection
71
    // with some other value and hence the collection must be
72
    // destroyed as well as the possible key.
73
    bool destroy_collection = !value.is_type(old_type);
421,800✔
74

75
    if (value.is_null()) {
421,800✔
76
        set_null(ndx);
1,878✔
77
    }
1,878✔
78
    else {
419,922✔
79
        erase_linked_payload(ndx, destroy_collection);
419,922✔
80
        m_composite.set(ndx, store(value));
419,922✔
81
    }
419,922✔
82

83
    if (destroy_collection && Array::size() > payload_idx_key) {
421,800✔
84
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
163,077✔
85
            Array keys(Array::get_alloc());
144,867✔
86
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
144,867✔
87
            keys.init_from_ref(ref);
144,867✔
88
            if (ndx < keys.size())
144,867✔
89
                keys.set(ndx, 0);
144,840✔
90
        }
144,867✔
91
    }
163,077✔
92
}
421,800✔
93

94
void ArrayMixed::insert(size_t ndx, Mixed value)
95
{
1,019,334✔
96
    if (value.is_null()) {
1,019,334✔
97
        m_composite.insert(ndx, 0);
172,146✔
98
    }
172,146✔
99
    else {
847,188✔
100
        m_composite.insert(ndx, store(value));
847,188✔
101
    }
847,188✔
102
    if (Array::size() > payload_idx_key) {
1,019,334✔
103
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
1,019,007✔
104
            Array keys(Array::get_alloc());
169,257✔
105
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
169,257✔
106
            keys.init_from_ref(ref);
169,257✔
107
            keys.insert(ndx, 0);
169,257✔
108
        }
169,257✔
109
    }
1,019,007✔
110
}
1,019,334✔
111

112
void ArrayMixed::set_null(size_t ndx)
113
{
1,878✔
114
    auto val = m_composite.get(ndx);
1,878✔
115
    if (val) {
1,878✔
116
        erase_linked_payload(ndx, true);
1,854✔
117
        m_composite.set(ndx, 0);
1,854✔
118
    }
1,854✔
119
}
1,878✔
120

121
Mixed ArrayMixed::get(size_t ndx) const
122
{
4,727,181✔
123
    int64_t val = m_composite.get(ndx);
4,727,181✔
124

125
    if (val) {
4,727,181✔
126
        int64_t int_val = val >> s_data_shift;
4,534,578✔
127
        size_t payload_ndx = size_t(int_val);
4,534,578✔
128
        DataType type = DataType((val & s_data_type_mask) - 1);
4,534,578✔
129
        switch (type) {
4,534,578✔
130
            case type_Int: {
552,909✔
131
                if (val & s_payload_idx_mask) {
552,909✔
132
                    ensure_int_array();
4,932✔
133
                    return Mixed(m_ints.get(payload_ndx));
4,932✔
134
                }
4,932✔
135
                return Mixed(int_val);
547,977✔
136
            }
552,909✔
137
            case type_Bool:
20,073✔
138
                return Mixed(int_val != 0);
20,073✔
139
            case type_Float:
27,360✔
140
                ensure_int_array();
27,360✔
141
                return Mixed(type_punning<float>(m_ints.get(payload_ndx)));
27,360✔
142
            case type_Double:
59,667✔
143
                ensure_int_array();
59,667✔
144
                return Mixed(type_punning<double>(m_ints.get(payload_ndx)));
59,667✔
145
            case type_String: {
558,450✔
146
                ensure_string_array();
558,450✔
147
                REALM_ASSERT(size_t(int_val) < m_strings.size());
558,450✔
148
                return Mixed(m_strings.get(payload_ndx));
558,450✔
149
            }
552,909✔
150
            case type_Binary: {
20,031✔
151
                ensure_string_array();
20,031✔
152
                REALM_ASSERT(size_t(int_val) < m_strings.size());
20,031✔
153
                auto s = m_strings.get(payload_ndx);
20,031✔
154
                return Mixed(BinaryData(s.data(), s.size()));
20,031✔
155
            }
552,909✔
156
            case type_Timestamp: {
18,183✔
157
                ensure_int_pair_array();
18,183✔
158
                payload_ndx <<= 1;
18,183✔
159
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
18,183✔
160
                return Mixed(Timestamp(m_int_pairs.get(payload_ndx), int32_t(m_int_pairs.get(payload_ndx + 1))));
18,183✔
161
            }
552,909✔
162
            case type_ObjectId: {
26,832✔
163
                ensure_string_array();
26,832✔
164
                REALM_ASSERT(size_t(int_val) < m_strings.size());
26,832✔
165
                auto s = m_strings.get(payload_ndx);
26,832✔
166
                ObjectId id;
26,832✔
167
                memcpy(&id, s.data(), sizeof(ObjectId));
26,832✔
168
                return Mixed(id);
26,832✔
169
            }
552,909✔
170
            case type_Decimal: {
51,603✔
171
                ensure_int_pair_array();
51,603✔
172
                Decimal128::Bid128 raw;
51,603✔
173
                payload_ndx <<= 1;
51,603✔
174
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
51,603✔
175
                raw.w[0] = m_int_pairs.get(payload_ndx);
51,603✔
176
                raw.w[1] = m_int_pairs.get(payload_ndx + 1);
51,603✔
177
                return Mixed(Decimal128(raw));
51,603✔
178
            }
552,909✔
179
            case type_Link:
✔
180
                ensure_int_array();
×
181
                return Mixed(ObjKey(m_ints.get(payload_ndx)));
×
182
            case type_TypedLink: {
1,554,492✔
183
                ensure_int_pair_array();
1,554,492✔
184
                payload_ndx <<= 1;
1,554,492✔
185
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
1,554,492✔
186
                ObjLink ret{TableKey(uint32_t(m_int_pairs.get(payload_ndx))),
1,554,492✔
187
                            ObjKey(m_int_pairs.get(payload_ndx + 1))};
1,554,492✔
188
                return Mixed(ret);
1,554,492✔
189
            }
552,909✔
190
            case type_UUID: {
29,052✔
191
                ensure_string_array();
29,052✔
192
                REALM_ASSERT(size_t(int_val) < m_strings.size());
29,052✔
193
                auto s = m_strings.get(payload_ndx);
29,052✔
194
                UUID::UUIDBytes bytes{};
29,052✔
195
                std::copy_n(s.data(), bytes.size(), bytes.begin());
29,052✔
196
                return Mixed(UUID(bytes));
29,052✔
197
            }
552,909✔
198
            default:
1,616,793✔
199
                if (size_t((val & s_payload_idx_mask) >> s_payload_idx_shift) == payload_idx_ref) {
1,616,811✔
200
                    ensure_ref_array();
1,616,811✔
201
                    return Mixed(m_refs.get(payload_ndx), CollectionType(int(type)));
1,616,811✔
202
                }
1,616,811✔
203
                break;
2,147,483,647✔
204
        }
4,534,578✔
205
    }
4,534,578✔
206

207
    return {};
192,603✔
208
}
4,727,181✔
209

210
void ArrayMixed::clear()
211
{
690✔
212
    m_composite.clear();
690✔
213
    m_ints.destroy();
690✔
214
    m_int_pairs.destroy();
690✔
215
    m_strings.destroy();
690✔
216
    m_refs.destroy_deep();
690✔
217
    Array::set(payload_idx_int, 0);
690✔
218
    Array::set(payload_idx_pair, 0);
690✔
219
    Array::set(payload_idx_str, 0);
690✔
220
    if (Array::size() > payload_idx_ref) {
690✔
221
        Array::set(payload_idx_ref, 0);
690✔
222
    }
690✔
223
    if (Array::size() > payload_idx_key) {
690✔
224
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
690✔
225
            Array::destroy(ref, m_composite.get_alloc());
6✔
226
            Array::set(payload_idx_key, 0);
6✔
227
        }
6✔
228
    }
690✔
229
}
690✔
230

231
void ArrayMixed::erase(size_t ndx)
232
{
165,633✔
233
    erase_linked_payload(ndx, true);
165,633✔
234
    m_composite.erase(ndx);
165,633✔
235
    if (Array::size() > payload_idx_key) {
165,633✔
236
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
165,621✔
237
            Array keys(Array::get_alloc());
144,384✔
238
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
144,384✔
239
            keys.init_from_ref(ref);
144,384✔
240
            keys.erase(ndx);
144,384✔
241
        }
144,384✔
242
    }
165,621✔
243
}
165,633✔
244

245
void ArrayMixed::move(ArrayMixed& dst, size_t ndx)
246
{
534✔
247
    auto sz = size();
534✔
248
    size_t i = ndx;
534✔
249
    const size_t original_dst_size = dst.size();
534✔
250
    while (i < sz) {
50,118✔
251
        auto val = get(i++);
49,584✔
252
        dst.add(val);
49,584✔
253
    }
49,584✔
254
    if (Array::size() > payload_idx_key) {
534✔
255
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
534✔
256
            dst.ensure_keys();
528✔
257
            Array keys(Array::get_alloc());
528✔
258
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
528✔
259
            keys.init_from_ref(ref);
528✔
260
            for (size_t j = original_dst_size, i = ndx; i < sz; i++, j++) {
50,058✔
261
                dst.set_key(j, keys.get(i));
49,530✔
262
            }
49,530✔
263
            keys.truncate(ndx);
528✔
264
        }
528✔
265
    }
534✔
266
    while (i > ndx) {
50,118✔
267
        erase_linked_payload(--i, false);
49,584✔
268
    }
49,584✔
269
    m_composite.truncate(ndx);
534✔
270
}
534✔
271

272
size_t ArrayMixed::find_first(Mixed value, size_t begin, size_t end) const noexcept
273
{
67,476✔
274
    if (value.is_null()) {
67,476✔
275
        return m_composite.find_first(0, begin, end);
468✔
276
    }
468✔
277
    DataType type = value.get_type();
67,008✔
278
    if (end == realm::npos)
67,008✔
279
        end = size();
6✔
280

281
    for (size_t i = begin; i < end; i++) {
633,570✔
282
        if (Mixed::data_types_are_comparable(this->get_type(i), type) && get(i) == value) {
630,816✔
283
            return i;
64,254✔
284
        }
64,254✔
285
    }
630,816✔
286
    return realm::npos;
2,754✔
287
}
67,008✔
288

289
bool ArrayMixed::ensure_keys()
290
{
101,424✔
291
    if (Array::size() < payload_idx_key + 1 || Array::get(payload_idx_key) == 0) {
101,424✔
292
        Array keys(Array::get_alloc());
75,426✔
293
        keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
75,426✔
294
        keys.create(type_Normal, false, size(), 0);
75,426✔
295
        keys.update_parent();
75,426✔
296

297
        return false;
75,426✔
298
    }
75,426✔
299
    return true;
25,998✔
300
}
101,424✔
301

302
size_t ArrayMixed::find_key(int64_t key) const noexcept
303
{
596,181✔
304
    if (ref_type ref = get_as_ref(payload_idx_key)) {
596,181✔
305
        Array keys(Array::get_alloc());
596,145✔
306
        keys.init_from_ref(ref);
596,145✔
307
        return keys.find_first(key);
596,145✔
308
    }
596,145✔
309
    return realm::not_found;
36✔
310
}
596,181✔
311

312
void ArrayMixed::set_key(size_t ndx, int64_t key)
313
{
297,801✔
314
    Array keys(Array::get_alloc());
297,801✔
315
    ensure_array_accessor(keys, payload_idx_key);
297,801✔
316
    while (keys.size() <= ndx) {
350,811✔
317
        keys.add(0);
53,010✔
318
    }
53,010✔
319
    keys.set(ndx, key);
297,801✔
320
}
297,801✔
321

322
int64_t ArrayMixed::get_key(size_t ndx) const
323
{
1,559,934✔
324
    Array keys(Array::get_alloc());
1,559,934✔
325
    if (ref_type ref = get_as_ref(payload_idx_key)) {
1,559,934✔
326
        keys.init_from_ref(ref);
1,559,154✔
327
        return (ndx < keys.size()) ? keys.get(ndx) : 0;
1,559,154✔
328
    }
1,559,154✔
329
    return 0;
780✔
330
}
1,559,934✔
331

332
void ArrayMixed::verify() const
333
{
14,946✔
334
    // TODO: Implement
335
}
14,946✔
336

337
ref_type ArrayMixed::typed_write(ref_type top_ref, _impl::ArrayWriterBase& out, Allocator& alloc)
338
{
74,397✔
339
    if (out.only_modified && alloc.is_read_only(top_ref))
74,397✔
NEW
340
        return top_ref;
×
341

342
    ArrayRef top(alloc);
74,397✔
343
    top.init_from_ref(top_ref);
74,397✔
344
    size_t sz = top.size();
74,397✔
345
    TempArray written_leaf(sz);
74,397✔
346

347
    /*
348
     Mixed stores things using different arrays. We need to take into account this in order to
349
     understand what we need to compress and what we can instead leave not compressed.
350

351
     The main subarrays are:
352

353
     composite array : index 0
354
     int array : index 1
355
     pair_int array: index 2
356
     string array: index 3
357
     ref array: index 4
358
     key array: index 5
359

360
     Description of each array:
361
     1. composite array: the data stored here is either a small int (< 32 bits) or an offset to one of
362
        the other arrays where the actual data is.
363
     2. int and pair int arrays, they are used for storing integers, timestamps, floats, doubles,
364
     decimals, links. In general we can compress them, but we need to be careful, controlling the col_type
365
     should prevent compressing data that we want to leave in the current format.
366
     3. string array is for strings and binary data (no compression for now)
367
     4. ref array is actually storing refs to collections. they can only be BPlusTree<int, Mixed> or
368
     BPlusTree<string, Mixed>.
369
     5. key array stores unique identifiers for collections in mixed (integers that can be compressed)
370
     */
371
    Array composite(alloc);
74,397✔
372
    composite.init_from_ref(top.get_as_ref(0));
74,397✔
373
    written_leaf.set_as_ref(0, composite.write(out, true, out.only_modified, false));
74,397✔
374
    for (size_t i = 1; i < sz; ++i) {
446,358✔
375
        auto ref = top.get(i);
371,961✔
376
        ref_type new_ref = ref;
371,961✔
377
        if (ref && !(out.only_modified && alloc.is_read_only(ref))) {
371,961✔
378
            if (i < 3) { // int, and pair_int
59,478✔
379
                // integer arrays
380
                new_ref = Array::write(ref, alloc, out, out.only_modified, out.compress);
27,012✔
381
            }
27,012✔
382
            else if (i == 4) { // collection in mixed
32,466✔
383
                ArrayRef arr_ref(alloc);
10,344✔
384
                arr_ref.init_from_ref(ref);
10,344✔
385
                auto ref_sz = arr_ref.size();
10,344✔
386
                TempArray written_ref_leaf(ref_sz);
10,344✔
387

388
                for (size_t k = 0; k < ref_sz; k++) {
21,750✔
389
                    ref_type new_sub_ref = 0;
11,406✔
390
                    if (auto sub_ref = arr_ref.get(k)) {
11,406✔
391
                        auto header = alloc.translate(sub_ref);
9,930✔
392
                        // Now we have to find out if the nested collection is a
393
                        // dictionary or a list. If the top array has a size of 2
394
                        // and it is not a BplusTree inner node, then it is a dictionary
395
                        if (NodeHeader::get_size_from_header(header) == 2 &&
9,930✔
396
                            !NodeHeader::get_is_inner_bptree_node_from_header(header)) {
9,930✔
397
                            new_sub_ref = Dictionary::typed_write(sub_ref, out, alloc);
4,764✔
398
                        }
4,764✔
399
                        else {
5,166✔
400
                            new_sub_ref = BPlusTree<Mixed>::typed_write(sub_ref, out, alloc);
5,166✔
401
                        }
5,166✔
402
                    }
9,930✔
403
                    written_ref_leaf.set_as_ref(k, new_sub_ref);
11,406✔
404
                }
11,406✔
405
                new_ref = written_ref_leaf.write(out);
10,344✔
406
            }
10,344✔
407
            else if (i == 5) { // unique keys associated to collections in mixed
22,122✔
408
                new_ref = Array::write(ref, alloc, out, out.only_modified, out.compress);
6,738✔
409
            }
6,738✔
410
            else {
15,384✔
411
                // all the rest we don't want to compress it, at least for now (strings will be needed)
412
                new_ref = Array::write(ref, alloc, out, out.only_modified, false);
15,384✔
413
            }
15,384✔
414
        }
59,478✔
415
        written_leaf.set(i, new_ref);
371,961✔
416
    }
371,961✔
417
    return written_leaf.write(out);
74,397✔
418
}
74,397✔
419

420
void ArrayMixed::ensure_array_accessor(Array& arr, size_t ndx_in_parent) const
421
{
4,990,842✔
422
    if (!arr.is_attached()) {
4,990,842✔
423
        ref_type ref = get_as_ref(ndx_in_parent);
2,929,479✔
424
        arr.set_parent(const_cast<ArrayMixed*>(this), ndx_in_parent);
2,929,479✔
425
        if (ref) {
2,929,479✔
426
            arr.init_from_ref(ref);
2,590,296✔
427
        }
2,590,296✔
428
        else {
339,183✔
429
            arr.create(ndx_in_parent == payload_idx_ref ? type_HasRefs : type_Normal);
339,183✔
430
            arr.update_parent();
339,183✔
431
        }
339,183✔
432
    }
2,929,479✔
433
}
4,990,842✔
434

435
void ArrayMixed::ensure_int_array() const
436
{
113,211✔
437
    ensure_array_accessor(m_ints, payload_idx_int);
113,211✔
438
}
113,211✔
439

440
void ArrayMixed::ensure_int_pair_array() const
441
{
1,968,546✔
442
    ensure_array_accessor(m_int_pairs, payload_idx_pair);
1,968,546✔
443
}
1,968,546✔
444

445
void ArrayMixed::ensure_string_array() const
446
{
900,381✔
447
    if (!m_strings.is_attached()) {
900,381✔
448
        ref_type ref = get_as_ref(payload_idx_str);
476,376✔
449
        m_strings.set_parent(const_cast<ArrayMixed*>(this), payload_idx_str);
476,376✔
450
        if (ref) {
476,376✔
451
            m_strings.init_from_ref(ref);
325,542✔
452
        }
325,542✔
453
        else {
150,834✔
454
            m_strings.create();
150,834✔
455
            m_strings.update_parent();
150,834✔
456
        }
150,834✔
457
    }
476,376✔
458
}
900,381✔
459

460
void ArrayMixed::ensure_ref_array() const
461
{
2,612,394✔
462
    while (Array::size() < payload_idx_ref + 1) {
2,612,394✔
463
        const_cast<ArrayMixed*>(this)->Array::add(0);
×
464
    }
×
465
    ensure_array_accessor(m_refs, payload_idx_ref);
2,612,394✔
466
}
2,612,394✔
467

468
void ArrayMixed::replace_index(size_t old_ndx, size_t new_ndx, size_t payload_arr_index)
469
{
202,776✔
470
    if (old_ndx != new_ndx) {
202,776✔
471
        size_t sz = m_composite.size();
202,776✔
472
        for (size_t i = 0; i != sz; i++) {
19,990,488✔
473
            int64_t val = m_composite.get(i);
19,990,488✔
474
            if (size_t((val & s_payload_idx_mask) >> s_payload_idx_shift) == payload_arr_index &&
19,990,488✔
475
                (val >> s_data_shift) == int64_t(old_ndx)) {
19,990,488✔
476
                m_composite.set(i, int64_t(new_ndx << s_data_shift) | (val & 0xff));
202,782✔
477
                return;
202,782✔
478
            }
202,782✔
479
        }
19,990,488✔
480
    }
202,776✔
481
}
202,776✔
482

483
void ArrayMixed::erase_linked_payload(size_t ndx, bool free_linked_arrays)
484
{
636,924✔
485
    auto val = m_composite.get(ndx);
636,924✔
486
    auto payload_arr_index = size_t((val & s_payload_idx_mask) >> s_payload_idx_shift);
636,924✔
487

488
    if (payload_arr_index) {
636,924✔
489
        // A value is stored in one of the payload arrays
490
        size_t last_ndx = 0;
469,482✔
491
        size_t erase_ndx = size_t(val >> s_data_shift);
469,482✔
492
        // Clean up current value by moving last over
493
        switch (payload_arr_index) {
469,482✔
494
            case payload_idx_int: {
4,668✔
495
                ensure_int_array();
4,668✔
496
                last_ndx = m_ints.size() - 1;
4,668✔
497
                if (erase_ndx != last_ndx) {
4,668✔
498
                    m_ints.set(erase_ndx, m_ints.get(last_ndx));
3,423✔
499
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
3,423✔
500
                }
3,423✔
501
                m_ints.erase(last_ndx);
4,668✔
502
                break;
4,668✔
503
            }
×
504
            case payload_idx_str: {
6,072✔
505
                ensure_string_array();
6,072✔
506
                last_ndx = m_strings.size() - 1;
6,072✔
507
                if (erase_ndx != last_ndx) {
6,072✔
508
                    StringData tmp = m_strings.get(last_ndx);
3,336✔
509
                    std::string tmp_val(tmp.data(), tmp.size());
3,336✔
510
                    m_strings.set(erase_ndx, StringData(tmp_val));
3,336✔
511
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
3,336✔
512
                }
3,336✔
513
                m_strings.erase(last_ndx);
6,072✔
514
                break;
6,072✔
515
            }
×
516
            case payload_idx_pair: {
12,102✔
517
                ensure_int_pair_array();
12,102✔
518
                last_ndx = m_int_pairs.size() - 2;
12,102✔
519
                erase_ndx <<= 1;
12,102✔
520
                if (erase_ndx != last_ndx) {
12,102✔
521
                    m_int_pairs.set(erase_ndx, m_int_pairs.get(last_ndx));
5,394✔
522
                    m_int_pairs.set(erase_ndx + 1, m_int_pairs.get(last_ndx + 1));
5,394✔
523
                    replace_index(last_ndx >> 1, erase_ndx >> 1, payload_arr_index);
5,394✔
524
                }
5,394✔
525
                m_int_pairs.truncate(last_ndx);
12,102✔
526
                break;
12,102✔
527
            }
×
528
            case payload_idx_ref: {
446,637✔
529
                ensure_ref_array();
446,637✔
530
                last_ndx = m_refs.size() - 1;
446,637✔
531
                auto old_ref = m_refs.get(erase_ndx);
446,637✔
532
                if (erase_ndx != last_ndx) {
446,637✔
533
                    m_refs.set(erase_ndx, m_refs.get(last_ndx));
190,605✔
534
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
190,605✔
535
                }
190,605✔
536
                m_refs.erase(last_ndx);
446,637✔
537
                if (old_ref && free_linked_arrays)
446,637✔
538
                    Array::destroy_deep(old_ref, m_composite.get_alloc());
145,005✔
539
                break;
446,637✔
540
            }
×
541
            default:
✔
542
                break;
×
543
        }
469,482✔
544
    }
469,482✔
545
}
636,924✔
546

547
int64_t ArrayMixed::store(const Mixed& value)
548
{
1,316,283✔
549
    DataType type = value.get_type();
1,316,283✔
550
    int64_t val;
1,316,283✔
551
    switch (type) {
1,316,283✔
552
        case type_Int: {
159,807✔
553
            int64_t int_val = value.get_int();
159,807✔
554
            if (std::numeric_limits<int32_t>::min() <= int_val && int_val <= std::numeric_limits<int32_t>::max()) {
159,807✔
555
                val = (static_cast<uint64_t>(int_val) << s_data_shift);
155,757✔
556
            }
155,757✔
557
            else {
4,050✔
558
                ensure_int_array();
4,050✔
559
                size_t ndx = m_ints.size();
4,050✔
560
                m_ints.add(int_val);
4,050✔
561
                val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
4,050✔
562
            }
4,050✔
563
            break;
159,807✔
564
        }
×
565
        case type_Bool:
2,832✔
566
            val = (value.get_bool() << s_data_shift);
2,832✔
567
            break;
2,832✔
568
        case type_Float: {
6,006✔
569
            ensure_int_array();
6,006✔
570
            size_t ndx = m_ints.size();
6,006✔
571
            m_ints.add(type_punning<int64_t>(value.get_float()));
6,006✔
572
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
6,006✔
573
            break;
6,006✔
574
        }
×
575
        case type_Double: {
6,528✔
576
            ensure_int_array();
6,528✔
577
            size_t ndx = m_ints.size();
6,528✔
578
            m_ints.add(type_punning<int64_t>(value.get_double()));
6,528✔
579
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
6,528✔
580
            break;
6,528✔
581
        }
×
582
        case type_String: {
246,168✔
583
            ensure_string_array();
246,168✔
584
            size_t ndx = m_strings.size();
246,168✔
585
            m_strings.add(value.get_string());
246,168✔
586
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
246,168✔
587
            break;
246,168✔
588
        }
×
589
        case type_Binary: {
5,052✔
590
            ensure_string_array();
5,052✔
591
            size_t ndx = m_strings.size();
5,052✔
592
            auto bin = value.get<Binary>();
5,052✔
593
            m_strings.add(StringData(bin.data(), bin.size()));
5,052✔
594
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
5,052✔
595
            break;
5,052✔
596
        }
×
597
        case type_Timestamp: {
3,528✔
598
            ensure_int_pair_array();
3,528✔
599
            size_t ndx = m_int_pairs.size() / 2;
3,528✔
600
            auto t = value.get_timestamp();
3,528✔
601
            m_int_pairs.add(t.get_seconds());
3,528✔
602
            m_int_pairs.add(t.get_nanoseconds());
3,528✔
603
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
3,528✔
604
            break;
3,528✔
605
        }
×
606
        case type_ObjectId: {
3,684✔
607
            ensure_string_array();
3,684✔
608
            size_t ndx = m_strings.size();
3,684✔
609
            auto id = value.get<ObjectId>();
3,684✔
610
            char buffer[sizeof(ObjectId)];
3,684✔
611
            memcpy(buffer, &id, sizeof(ObjectId));
3,684✔
612
            m_strings.add(StringData(buffer, sizeof(ObjectId)));
3,684✔
613
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
3,684✔
614
            break;
3,684✔
615
        }
×
616
        case type_Decimal: {
5,538✔
617
            ensure_int_pair_array();
5,538✔
618
            size_t ndx = m_int_pairs.size() / 2;
5,538✔
619
            auto t = value.get<Decimal128>();
5,538✔
620
            m_int_pairs.add(t.raw()->w[0]);
5,538✔
621
            m_int_pairs.add(t.raw()->w[1]);
5,538✔
622
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
5,538✔
623
            break;
5,538✔
624
        }
×
625
        case type_Link: {
✔
626
            ensure_int_array();
×
627
            size_t ndx = m_ints.size();
×
628
            m_ints.add(value.get<ObjKey>().value);
×
629
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
×
630
            break;
×
631
        }
×
632
        case type_TypedLink: {
323,154✔
633
            ensure_int_pair_array();
323,154✔
634
            size_t ndx = m_int_pairs.size() / 2;
323,154✔
635
            auto t = value.get<ObjLink>();
323,154✔
636
            m_int_pairs.add(int64_t(t.get_table_key().value));
323,154✔
637
            m_int_pairs.add(t.get_obj_key().value);
323,154✔
638
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
323,154✔
639
            break;
323,154✔
640
        }
×
641
        case type_UUID: {
5,052✔
642
            ensure_string_array();
5,052✔
643
            size_t ndx = m_strings.size();
5,052✔
644
            auto id = value.get<UUID>();
5,052✔
645
            const auto uuid_bytes = id.to_bytes();
5,052✔
646
            m_strings.add(StringData(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()));
5,052✔
647
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
5,052✔
648
            break;
5,052✔
649
        }
×
650
        default:
549,498✔
651
            REALM_ASSERT(type == type_List || type == type_Dictionary);
549,498✔
652
            ensure_ref_array();
549,498✔
653
            size_t ndx = m_refs.size();
549,498✔
654
            m_refs.add(value.get_ref());
549,498✔
655
            val = int64_t(ndx << s_data_shift) | (payload_idx_ref << s_payload_idx_shift);
549,498✔
656
            break;
549,498✔
657
    }
1,316,283✔
658
    return val + int(type) + 1;
1,316,133✔
659
}
1,316,283✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc