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

realm / realm-core / finn.schiermer-andersen_89

04 Jun 2024 02:04PM UTC coverage: 90.651% (-0.03%) from 90.685%
finn.schiermer-andersen_89

Pull #7654

Evergreen

finnschiermer
optimized string cache gc
Pull Request #7654: Fsa/string interning

102644 of 180648 branches covered (56.82%)

1005 of 1125 new or added lines in 15 files covered. (89.33%)

154 existing lines in 21 files now uncovered.

217953 of 240431 relevant lines covered (90.65%)

7671710.15 hits per line

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

85.52
/src/realm/array_string.cpp
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
#include <realm/array_string.hpp>
20
#include <realm/impl/array_writer.hpp>
21
#include <realm/spec.hpp>
22
#include <realm/mixed.hpp>
23

24
using namespace realm;
25

26
ArrayString::ArrayString(Allocator& a)
27
    : m_alloc(a)
39,380,295✔
28
{
78,684,387✔
29
    m_arr = new (&m_storage) ArrayStringShort(a, true);
78,684,387✔
30
}
78,684,387✔
31

32
void ArrayString::create()
33
{
240,378✔
34
    static_cast<ArrayStringShort*>(m_arr)->create();
240,378✔
35
}
240,378✔
36

37
void ArrayString::init_from_mem(MemRef mem) noexcept
38
{
77,065,029✔
39
    char* header = mem.get_addr();
77,065,029✔
40

41
    ArrayParent* parent = m_arr->get_parent();
77,065,029✔
42
    size_t ndx_in_parent = m_arr->get_ndx_in_parent();
77,065,029✔
43

44
    bool long_strings = Array::get_hasrefs_from_header(header);
77,065,029✔
45
    if (!long_strings) {
77,065,029✔
46
        // Small strings
47
        bool is_small = Array::get_wtype_from_header(header) == Array::wtype_Multiply;
71,632,347✔
48
        if (is_small) {
71,632,347✔
49
            auto arr = new (&m_storage) ArrayStringShort(m_alloc, m_nullable);
66,307,104✔
50
            arr->init_from_mem(mem);
66,307,104✔
51
            m_type = Type::small_strings;
66,307,104✔
52
        }
66,307,104✔
53
        else {
5,325,243✔
54
            auto arr = new (&m_storage) Array(m_alloc);
5,325,243✔
55
            arr->init_from_mem(mem);
5,325,243✔
56
            // The context flag is used to indicate interned strings vs old enum strings
57
            // (in conjunction with has_refs() == false)
58
            if (arr->get_context_flag_from_header(arr->get_header())) {
5,325,243✔
59
                // init for new interned strings (replacing old enum strings)
60
                m_type = Type::interned_strings;
1,661,085✔
61
                // consider if we want this invariant: REALM_ASSERT_DEBUG(m_string_interner);
62
            }
1,661,085✔
63
            else {
3,664,158✔
64
                // init for old enum strings
65
                m_string_enum_values = std::make_unique<ArrayString>(m_alloc);
3,664,158✔
66
                ArrayParent* p;
3,664,158✔
67
                REALM_ASSERT(m_spec != nullptr);
3,664,158✔
68
                REALM_ASSERT(m_col_ndx != realm::npos);
3,664,158✔
69
                ref_type r = m_spec->get_enumkeys_ref(m_col_ndx, p);
3,664,158✔
70
                m_string_enum_values->init_from_ref(r);
3,664,158✔
71
                m_string_enum_values->set_parent(p, m_col_ndx);
3,664,158✔
72
                m_type = Type::enum_strings;
3,664,158✔
73
            }
3,664,158✔
74
        }
5,325,243✔
75
    }
71,632,347✔
76
    else {
5,432,682✔
77
        bool is_big = Array::get_context_flag_from_header(header);
5,432,682✔
78
        if (!is_big) {
5,432,682✔
79
            auto arr = new (&m_storage) ArraySmallBlobs(m_alloc);
795,546✔
80
            arr->init_from_mem(mem);
795,546✔
81
            m_type = Type::medium_strings;
795,546✔
82
        }
795,546✔
83
        else {
4,637,136✔
84
            auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, m_nullable);
4,637,136✔
85
            arr->init_from_mem(mem);
4,637,136✔
86
            m_type = Type::big_strings;
4,637,136✔
87
        }
4,637,136✔
88
    }
5,432,682✔
89
    m_arr->set_parent(parent, ndx_in_parent);
77,065,029✔
90
}
77,065,029✔
91

92
void ArrayString::init_from_parent()
93
{
6,734,541✔
94
    ref_type ref = m_arr->get_ref_from_parent();
6,734,541✔
95
    init_from_ref(ref);
6,734,541✔
96
}
6,734,541✔
97

98
void ArrayString::destroy() noexcept
99
{
1,020✔
100
    if (m_arr->is_attached()) {
1,020✔
101
        Array::destroy_deep(m_arr->get_ref(), m_alloc);
456✔
102
        detach();
456✔
103
    }
456✔
104
}
1,020✔
105

106
void ArrayString::detach() noexcept
107
{
490,977✔
108
    m_arr->detach();
490,977✔
109
    // Make sure the object is in a state like right after construction
110
    // Next call must be to create()
111
    m_arr = new (&m_storage) ArrayStringShort(m_alloc, true);
490,977✔
112
    m_type = Type::small_strings;
490,977✔
113
}
490,977✔
114

115
size_t ArrayString::size() const
116
{
13,847,889✔
117
    switch (m_type) {
13,847,889✔
118
        case Type::small_strings:
4,742,925✔
119
            return static_cast<ArrayStringShort*>(m_arr)->size();
4,742,925✔
120
        case Type::medium_strings:
445,461✔
121
            return static_cast<ArraySmallBlobs*>(m_arr)->size();
445,461✔
122
        case Type::big_strings:
8,542,011✔
123
            return static_cast<ArrayBigBlobs*>(m_arr)->size();
8,542,011✔
124
        case Type::enum_strings:
252✔
125
        case Type::interned_strings:
119,139✔
126
            return static_cast<Array*>(m_arr)->size();
119,139✔
127
    }
13,847,889✔
128
    return {};
×
129
}
13,847,889✔
130

131
void ArrayString::add(StringData value)
132
{
136,074✔
133
    switch (upgrade_leaf(value.size())) {
136,074✔
134
        case Type::small_strings:
80,154✔
135
            static_cast<ArrayStringShort*>(m_arr)->add(value);
80,154✔
136
            break;
80,154✔
137
        case Type::medium_strings:
27,858✔
138
            static_cast<ArraySmallBlobs*>(m_arr)->add_string(value);
27,858✔
139
            break;
27,858✔
140
        case Type::big_strings:
28,062✔
141
            static_cast<ArrayBigBlobs*>(m_arr)->add_string(value);
28,062✔
142
            break;
28,062✔
NEW
143
        case Type::enum_strings:
✔
NEW
144
        case Type::interned_strings: {
✔
145
            auto a = static_cast<Array*>(m_arr);
×
146
            size_t ndx = a->size();
×
147
            a->add(0);
×
148
            set(ndx, value);
×
149
            break;
×
150
        }
×
151
    }
136,074✔
152
}
136,074✔
153

154
void ArrayString::set(size_t ndx, StringData value)
155
{
4,709,130✔
156
    switch (upgrade_leaf(value.size())) {
4,709,130✔
157
        case Type::small_strings:
467,178✔
158
            static_cast<ArrayStringShort*>(m_arr)->set(ndx, value);
467,178✔
159
            break;
467,178✔
160
        case Type::medium_strings:
209,757✔
161
            static_cast<ArraySmallBlobs*>(m_arr)->set_string(ndx, value);
209,757✔
162
            break;
209,757✔
163
        case Type::big_strings:
820,152✔
164
            static_cast<ArrayBigBlobs*>(m_arr)->set_string(ndx, value);
820,152✔
165
            break;
820,152✔
166
        case Type::interned_strings: {
588,987✔
167
            auto id = m_string_interner->intern(value);
588,987✔
168
            static_cast<Array*>(m_arr)->set(ndx, id);
588,987✔
169
            break;
588,987✔
NEW
170
        }
×
171
        case Type::enum_strings: {
2,625,945✔
172
            size_t sz = m_string_enum_values->size();
2,625,945✔
173
            size_t res = m_string_enum_values->find_first(value, 0, sz);
2,625,945✔
174
            if (res == realm::not_found) {
2,625,945✔
175
                m_string_enum_values->add(value);
9,576✔
176
                res = sz;
9,576✔
177
            }
9,576✔
178
            static_cast<Array*>(m_arr)->set(ndx, res);
2,625,945✔
179
            break;
2,625,945✔
180
        }
×
181
    }
4,709,130✔
182
}
4,709,130✔
183

184
void ArrayString::insert(size_t ndx, StringData value)
185
{
4,429,761✔
186
    switch (upgrade_leaf(value.size())) {
4,429,761✔
187
        case Type::small_strings:
1,247,244✔
188
            static_cast<ArrayStringShort*>(m_arr)->insert(ndx, value);
1,247,244✔
189
            break;
1,247,244✔
190
        case Type::medium_strings:
269,022✔
191
            static_cast<ArraySmallBlobs*>(m_arr)->insert_string(ndx, value);
269,022✔
192
            break;
269,022✔
193
        case Type::big_strings:
1,299,762✔
194
            static_cast<ArrayBigBlobs*>(m_arr)->insert_string(ndx, value);
1,299,762✔
195
            break;
1,299,762✔
196
        case Type::enum_strings: {
1,312,905✔
197
            static_cast<Array*>(m_arr)->insert(ndx, 0);
1,312,905✔
198
            set(ndx, value);
1,312,905✔
199
            break;
1,312,905✔
NEW
200
        }
×
201
        case Type::interned_strings: {
302,493✔
202
            static_cast<Array*>(m_arr)->insert(ndx, 0);
302,493✔
203
            set(ndx, value);
302,493✔
204
            break;
302,493✔
UNCOV
205
        }
×
206
    }
4,429,761✔
207
}
4,429,761✔
208

209
StringData ArrayString::get(size_t ndx) const
210
{
84,527,757✔
211
    switch (m_type) {
84,527,757✔
212
        case Type::small_strings:
71,225,484✔
213
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
71,225,484✔
214
        case Type::medium_strings:
1,114,656✔
215
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string(ndx);
1,114,656✔
216
        case Type::big_strings:
9,826,452✔
217
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
9,826,452✔
218
        case Type::enum_strings: {
1,149,918✔
219
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
1,149,918✔
220
            return m_string_enum_values->get(index);
1,149,918✔
221
        }
×
222
        case Type::interned_strings: {
1,404,333✔
223
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
1,404,333✔
224
            return m_string_interner->get(id);
1,404,333✔
NEW
225
        }
×
226
    }
84,527,757✔
227
    return {};
×
228
}
84,527,757✔
229

230
StringData ArrayString::get_legacy(size_t ndx) const
231
{
×
232
    switch (m_type) {
×
233
        case Type::small_strings:
×
234
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
×
235
        case Type::medium_strings:
×
236
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string_legacy(ndx);
×
237
        case Type::big_strings:
×
238
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
×
239
        case Type::enum_strings: {
×
240
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
×
241
            return m_string_enum_values->get(index);
×
242
        }
×
NEW
243
        case Type::interned_strings: {
×
NEW
244
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
×
NEW
245
            return m_string_interner->get(id);
×
NEW
246
        }
×
247
    }
×
248
    return {};
×
249
}
×
250

251
Mixed ArrayString::get_any(size_t ndx) const
252
{
132,879✔
253
    return Mixed(get(ndx));
132,879✔
254
}
132,879✔
255

256
bool ArrayString::is_null(size_t ndx) const
257
{
3,819,375✔
258
    switch (m_type) {
3,819,375✔
259
        case Type::small_strings:
289,281✔
260
            return static_cast<ArrayStringShort*>(m_arr)->is_null(ndx);
289,281✔
261
        case Type::medium_strings:
9,864✔
262
            return static_cast<ArraySmallBlobs*>(m_arr)->is_null(ndx);
9,864✔
263
        case Type::big_strings:
3,282,348✔
264
            return static_cast<ArrayBigBlobs*>(m_arr)->is_null(ndx);
3,282,348✔
265
        case Type::enum_strings: {
✔
NEW
266
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
×
NEW
267
            return m_string_enum_values->is_null(id);
×
NEW
268
        }
×
269
        case Type::interned_strings: {
237,885✔
270
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
237,885✔
271
            return id == 0;
237,885✔
UNCOV
272
        }
×
273
    }
3,819,375✔
274
    return {};
×
275
}
3,819,375✔
276

277
void ArrayString::erase(size_t ndx)
278
{
127,968✔
279
    switch (m_type) {
127,968✔
280
        case Type::small_strings:
28,203✔
281
            static_cast<ArrayStringShort*>(m_arr)->erase(ndx);
28,203✔
282
            break;
28,203✔
283
        case Type::medium_strings:
55,962✔
284
            static_cast<ArraySmallBlobs*>(m_arr)->erase(ndx);
55,962✔
285
            break;
55,962✔
286
        case Type::big_strings:
22,158✔
287
            static_cast<ArrayBigBlobs*>(m_arr)->erase(ndx);
22,158✔
288
            break;
22,158✔
289
        case Type::interned_strings:
13,296✔
290
        case Type::enum_strings:
21,648✔
291
            static_cast<Array*>(m_arr)->erase(ndx);
21,648✔
292
            break;
21,648✔
293
    }
127,968✔
294
}
127,968✔
295

296
void ArrayString::move(ArrayString& dst, size_t ndx)
297
{
66✔
298
    size_t sz = size();
66✔
299
    for (size_t i = ndx; i < sz; i++) {
20,730✔
300
        dst.add(get(i));
20,664✔
301
    }
20,664✔
302

303
    switch (m_type) {
66✔
304
        case Type::small_strings:
✔
305
            static_cast<ArrayStringShort*>(m_arr)->truncate(ndx);
×
306
            break;
×
307
        case Type::medium_strings:
60✔
308
            static_cast<ArraySmallBlobs*>(m_arr)->truncate(ndx);
60✔
309
            break;
60✔
310
        case Type::big_strings:
6✔
311
            static_cast<ArrayBigBlobs*>(m_arr)->truncate(ndx);
6✔
312
            break;
6✔
313
        case Type::enum_strings:
✔
314
            // this operation will never be called for enumerated columns
315
            REALM_UNREACHABLE();
316
            break;
×
NEW
317
        case Type::interned_strings:
✔
NEW
318
            m_arr->truncate(ndx);
×
NEW
319
            break;
×
320
    }
66✔
321
}
66✔
322

323
void ArrayString::clear()
324
{
354✔
325
    switch (m_type) {
354✔
326
        case Type::small_strings:
300✔
327
            static_cast<ArrayStringShort*>(m_arr)->clear();
300✔
328
            break;
300✔
329
        case Type::medium_strings:
6✔
330
            static_cast<ArraySmallBlobs*>(m_arr)->clear();
6✔
331
            break;
6✔
332
        case Type::big_strings:
48✔
333
            static_cast<ArrayBigBlobs*>(m_arr)->clear();
48✔
334
            break;
48✔
335
        case Type::enum_strings:
✔
NEW
336
        case Type::interned_strings:
✔
337
            static_cast<Array*>(m_arr)->clear();
×
338
            break;
×
339
    }
354✔
340
}
354✔
341

342
size_t ArrayString::find_first(StringData value, size_t begin, size_t end) const noexcept
343
{
4,093,353✔
344
    switch (m_type) {
4,093,353✔
345
        case Type::small_strings:
3,084,873✔
346
            return static_cast<ArrayStringShort*>(m_arr)->find_first(value, begin, end);
3,084,873✔
347
        case Type::medium_strings: {
94,932✔
348
            BinaryData as_binary(value.data(), value.size());
94,932✔
349
            return static_cast<ArraySmallBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
94,932✔
350
            break;
×
351
        }
×
352
        case Type::big_strings: {
255,294✔
353
            BinaryData as_binary(value.data(), value.size());
255,294✔
354
            return static_cast<ArrayBigBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
255,294✔
355
            break;
×
356
        }
×
357
        case Type::enum_strings: {
595,215✔
358
            size_t sz = m_string_enum_values->size();
595,215✔
359
            size_t res = m_string_enum_values->find_first(value, 0, sz);
595,215✔
360
            if (res != realm::not_found) {
595,215✔
361
                return static_cast<Array*>(m_arr)->find_first(res, begin, end);
595,215✔
362
            }
595,215✔
363
            break;
×
364
        }
595,215✔
365
        case Type::interned_strings: {
63,126✔
366
            // we need a way to avoid this lookup for each leaf array. The lookup must appear
367
            // higher up the call stack and passed down.
368
            auto id = m_string_interner->lookup(value);
63,126✔
369
            if (id) {
63,126✔
370
                return static_cast<Array*>(m_arr)->find_first(*id, begin, end);
59,910✔
371
            }
59,910✔
372
            break;
3,216✔
373
        }
63,126✔
374
    }
4,093,353✔
375
    return not_found;
3,216✔
376
}
4,093,353✔
377

378
namespace {
379

380
template <class T>
381
inline StringData get_string(const T* arr, size_t ndx)
382
{
437,337✔
383
    return arr->get_string(ndx);
437,337✔
384
}
437,337✔
385

386
template <>
387
inline StringData get_string(const ArrayStringShort* arr, size_t ndx)
388
{
93,651✔
389
    return arr->get(ndx);
93,651✔
390
}
93,651✔
391

392
template <class T, class U>
393
size_t lower_bound_string(const T* arr, U value)
394
{
234,912✔
395
    size_t i = 0;
234,912✔
396
    size_t sz = arr->size();
234,912✔
397
    while (0 < sz) {
765,900✔
398
        size_t half = sz / 2;
530,988✔
399
        size_t mid = i + half;
530,988✔
400
        auto probe = get_string(arr, mid);
530,988✔
401
        if (probe < value) {
530,988✔
402
            i = mid + 1;
190,689✔
403
            sz -= half + 1;
190,689✔
404
        }
190,689✔
405
        else {
340,299✔
406
            sz = half;
340,299✔
407
        }
340,299✔
408
    }
530,988✔
409
    return i;
234,912✔
410
}
234,912✔
411
} // namespace
412

413
size_t ArrayString::lower_bound(StringData value)
414
{
234,912✔
415
    switch (m_type) {
234,912✔
416
        case Type::small_strings:
58,434✔
417
            return lower_bound_string(static_cast<ArrayStringShort*>(m_arr), value);
58,434✔
418
        case Type::medium_strings:
68,418✔
419
            return lower_bound_string(static_cast<ArraySmallBlobs*>(m_arr), value);
68,418✔
420
        case Type::big_strings:
108,060✔
421
            return lower_bound_string(static_cast<ArrayBigBlobs*>(m_arr), value);
108,060✔
422
        case Type::enum_strings:
✔
423
            break;
×
NEW
424
        case Type::interned_strings:
✔
425
            REALM_UNREACHABLE();
NEW
426
            break;
×
427
    }
234,912✔
428
    return realm::npos;
×
429
}
234,912✔
430

431
ArrayString::Type ArrayString::upgrade_leaf(size_t value_size)
432
{
9,271,695✔
433
    if (m_type == Type::big_strings)
9,271,695✔
434
        return Type::big_strings;
2,142,051✔
435

436
    if (m_type == Type::enum_strings)
7,129,644✔
437
        return Type::enum_strings;
3,938,850✔
438

439
    if (m_type == Type::interned_strings)
3,190,794✔
440
        return Type::interned_strings;
891,471✔
441

442
    if (m_type == Type::medium_strings) {
2,299,323✔
443
        if (value_size <= medium_string_max_size)
501,927✔
444
            return Type::medium_strings;
501,411✔
445

446
        // Upgrade root leaf from medium to big strings
447
        auto string_medium = static_cast<ArraySmallBlobs*>(m_arr);
516✔
448
        ArrayBigBlobs big_blobs(m_alloc, true);
516✔
449
        big_blobs.create(); // Throws
516✔
450

451
        size_t n = string_medium->size();
516✔
452
        for (size_t i = 0; i < n; i++) {
9,525✔
453
            big_blobs.add_string(string_medium->get_string(i)); // Throws
9,009✔
454
        }
9,009✔
455
        auto parent = string_medium->get_parent();
516✔
456
        auto ndx_in_parent = string_medium->get_ndx_in_parent();
516✔
457
        string_medium->destroy();
516✔
458

459
        auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, true);
516✔
460
        arr->init_from_mem(big_blobs.get_mem());
516✔
461
        arr->set_parent(parent, ndx_in_parent);
516✔
462
        arr->update_parent();
516✔
463

464
        m_type = Type::big_strings;
516✔
465
        return Type::big_strings;
516✔
466
    }
501,927✔
467

468
    // m_type == Type::small
469
    if (value_size <= small_string_max_size)
1,797,396✔
470
        return Type::small_strings;
1,794,477✔
471

472
    if (value_size <= medium_string_max_size) {
2,147,487,580✔
473
        // Upgrade root leaf from small to medium strings
474
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
5,172✔
475
        ArraySmallBlobs string_long(m_alloc);
5,172✔
476
        string_long.create(); // Throws
5,172✔
477

478
        size_t n = string_short->size();
5,172✔
479
        for (size_t i = 0; i < n; i++) {
15,945✔
480
            string_long.add_string(string_short->get(i)); // Throws
10,773✔
481
        }
10,773✔
482
        auto parent = string_short->get_parent();
5,172✔
483
        auto ndx_in_parent = string_short->get_ndx_in_parent();
5,172✔
484
        string_short->destroy();
5,172✔
485

486
        auto arr = new (&m_storage) ArraySmallBlobs(m_alloc);
5,172✔
487
        arr->init_from_mem(string_long.get_mem());
5,172✔
488
        arr->set_parent(parent, ndx_in_parent);
5,172✔
489
        arr->update_parent();
5,172✔
490

491
        m_type = Type::medium_strings;
5,172✔
492
    }
5,172✔
493
    else {
2,147,484,976✔
494
        // Upgrade root leaf from small to big strings
495
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
2,147,484,976✔
496
        ArrayBigBlobs big_blobs(m_alloc, true);
2,147,484,976✔
497
        big_blobs.create(); // Throws
2,147,484,976✔
498

499
        size_t n = string_short->size();
2,147,484,976✔
500
        for (size_t i = 0; i < n; i++) {
2,147,487,616✔
501
            big_blobs.add_string(string_short->get(i)); // Throws
5,208✔
502
        }
5,208✔
503
        auto parent = string_short->get_parent();
2,147,484,976✔
504
        auto ndx_in_parent = string_short->get_ndx_in_parent();
2,147,484,976✔
505
        string_short->destroy();
2,147,484,976✔
506

507
        auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, true);
2,147,484,976✔
508
        arr->init_from_mem(big_blobs.get_mem());
2,147,484,976✔
509
        arr->set_parent(parent, ndx_in_parent);
2,147,484,976✔
510
        arr->update_parent();
2,147,484,976✔
511

512
        m_type = Type::big_strings;
2,147,484,976✔
513
    }
2,147,484,976✔
514

515
    return m_type;
2,147,487,580✔
516
}
1,797,396✔
517

518
void ArrayString::verify() const
519
{
204,957✔
520
#ifdef REALM_DEBUG
204,957✔
521
    switch (m_type) {
204,957✔
522
        case Type::small_strings:
79,812✔
523
            static_cast<ArrayStringShort*>(m_arr)->verify();
79,812✔
524
            break;
79,812✔
525
        case Type::medium_strings:
735✔
526
            static_cast<ArraySmallBlobs*>(m_arr)->verify();
735✔
527
            break;
735✔
528
        case Type::big_strings:
5,346✔
529
            static_cast<ArrayBigBlobs*>(m_arr)->verify();
5,346✔
530
            break;
5,346✔
531
        case Type::enum_strings:
252✔
532
        case Type::interned_strings:
119,064✔
533
            static_cast<Array*>(m_arr)->verify();
119,064✔
534
            break;
119,064✔
535
    }
204,957✔
536
#endif
204,957✔
537
}
204,957✔
538

539
ref_type ArrayString::write(_impl::ArrayWriterBase& out, StringInterner* interner)
540
{
114,813✔
541
    REALM_ASSERT(interner);
114,813✔
542
    // we have to write out all, modified or not, to match the total cleanup
543
    Array interned(Allocator::get_default());
114,813✔
544
    auto sz = size();
114,813✔
545
    interned.create(NodeHeader::type_Normal, true, sz);
114,813✔
546
    for (size_t i = 0; i < sz; ++i) {
1,378,794✔
547
        interned.set(i, interner->intern(get(i)));
1,263,981✔
548
    }
1,263,981✔
549
    auto retval = interned.write(out, false, false, out.compress);
114,813✔
550
    interned.destroy();
114,813✔
551
    return retval;
114,813✔
552
    // return m_arr->write(out, true, false, false);
553
}
114,813✔
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