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

realm / realm-core / 1772

20 Oct 2023 07:34PM UTC coverage: 91.61% (+0.04%) from 91.567%
1772

push

Evergreen

web-flow
Added sync socket result enum for sync socket callback handlers in C API (#7015)

* Added sync socket result enum for sync socket callback handlers in C API
* Updated changelog
* CAPI: timer callbacks are now released by canceled/complete function
* Updated c_api tests to use all sync socket c_api functions
* Additional updates to sync socket c api test
* Added CAPI write callback manager to manage async write callbacks
* Pass error codes up to default socket provider for async_write_binary() callbacks
* Removed async write callback manager from CAPI
* Updated changelog after release
* clang format and updates from review
* Update async_write_binary() error handling to not throw exception
* Updated a few comments
* Another comment update
* Updates from review

94360 of 173622 branches covered (0.0%)

111 of 150 new or added lines in 8 files covered. (74.0%)

66 existing lines in 17 files now uncovered.

230703 of 251832 relevant lines covered (91.61%)

6730695.32 hits per line

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

87.78
/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/spec.hpp>
21
#include <realm/mixed.hpp>
22

23
using namespace realm;
24

25
ArrayString::ArrayString(Allocator& a)
26
    : m_alloc(a)
27
{
20,096,424✔
28
    m_arr = new (&m_storage.m_string_short) ArrayStringShort(a, true);
20,096,424✔
29
}
20,096,424✔
30

31
void ArrayString::create()
32
{
362,739✔
33
    static_cast<ArrayStringShort*>(m_arr)->create();
362,739✔
34
}
362,739✔
35

36
void ArrayString::init_from_mem(MemRef mem) noexcept
37
{
18,063,618✔
38
    char* header = mem.get_addr();
18,063,618✔
39

8,930,103✔
40
    ArrayParent* parent = m_arr->get_parent();
18,063,618✔
41
    size_t ndx_in_parent = m_arr->get_ndx_in_parent();
18,063,618✔
42

8,930,103✔
43
    bool long_strings = Array::get_hasrefs_from_header(header);
18,063,618✔
44
    if (!long_strings) {
18,063,618✔
45
        // Small strings
6,608,592✔
46
        bool is_small = Array::get_wtype_from_header(header) == Array::wtype_Multiply;
13,416,036✔
47
        if (is_small) {
13,416,036✔
48
            auto arr = new (&m_storage.m_string_short) ArrayStringShort(m_alloc, m_nullable);
7,755,939✔
49
            arr->init_from_mem(mem);
7,755,939✔
50
            m_type = Type::small_strings;
7,755,939✔
51
        }
7,755,939✔
52
        else {
5,660,097✔
53
            auto arr = new (&m_storage.m_enum) Array(m_alloc);
5,660,097✔
54
            arr->init_from_mem(mem);
5,660,097✔
55
            m_string_enum_values = std::make_unique<ArrayString>(m_alloc);
5,660,097✔
56
            ArrayParent* p;
5,660,097✔
57
            REALM_ASSERT(m_spec != nullptr);
5,660,097✔
58
            REALM_ASSERT(m_col_ndx != realm::npos);
5,660,097✔
59
            ref_type r = m_spec->get_enumkeys_ref(m_col_ndx, p);
5,660,097✔
60
            m_string_enum_values->init_from_ref(r);
5,660,097✔
61
            m_string_enum_values->set_parent(p, m_col_ndx);
5,660,097✔
62
            m_type = Type::enum_strings;
5,660,097✔
63
        }
5,660,097✔
64
    }
13,416,036✔
65
    else {
4,647,582✔
66
        bool is_big = Array::get_context_flag_from_header(header);
4,647,582✔
67
        if (!is_big) {
4,647,582✔
68
            auto arr = new (&m_storage.m_string_long) ArraySmallBlobs(m_alloc);
1,211,412✔
69
            arr->init_from_mem(mem);
1,211,412✔
70
            m_type = Type::medium_strings;
1,211,412✔
71
        }
1,211,412✔
72
        else {
3,436,170✔
73
            auto arr = new (&m_storage.m_big_blobs) ArrayBigBlobs(m_alloc, m_nullable);
3,436,170✔
74
            arr->init_from_mem(mem);
3,436,170✔
75
            m_type = Type::big_strings;
3,436,170✔
76
        }
3,436,170✔
77
    }
4,647,582✔
78
    m_arr->set_parent(parent, ndx_in_parent);
18,063,618✔
79
}
18,063,618✔
80

81
void ArrayString::init_from_parent()
82
{
5,341,725✔
83
    ref_type ref = m_arr->get_ref_from_parent();
5,341,725✔
84
    init_from_ref(ref);
5,341,725✔
85
}
5,341,725✔
86

87
void ArrayString::destroy() noexcept
88
{
366✔
89
    if (m_arr->is_attached()) {
366✔
90
        Array::destroy_deep(m_arr->get_ref(), m_alloc);
360✔
91
        detach();
360✔
92
    }
360✔
93
}
366✔
94

95
void ArrayString::detach() noexcept
96
{
281,532✔
97
    m_arr->detach();
281,532✔
98
    // Make sure the object is in a state like right after construction
140,403✔
99
    // Next call must be to create()
140,403✔
100
    m_arr = new (&m_storage.m_string_short) ArrayStringShort(m_alloc, true);
281,532✔
101
    m_type = Type::small_strings;
281,532✔
102
}
281,532✔
103

104
size_t ArrayString::size() const
105
{
15,279,606✔
106
    switch (m_type) {
15,279,606✔
107
        case Type::small_strings:
6,737,058✔
108
            return static_cast<ArrayStringShort*>(m_arr)->size();
6,737,058✔
109
        case Type::medium_strings:
432,288✔
110
            return static_cast<ArraySmallBlobs*>(m_arr)->size();
432,288✔
111
        case Type::big_strings:
8,134,284✔
112
            return static_cast<ArrayBigBlobs*>(m_arr)->size();
8,134,284✔
113
        case Type::enum_strings:
282✔
114
            return static_cast<Array*>(m_arr)->size();
282✔
115
    }
×
116
    return {};
×
117
}
×
118

119
void ArrayString::add(StringData value)
120
{
159,948✔
121
    switch (upgrade_leaf(value.size())) {
159,948✔
122
        case Type::small_strings:
104,667✔
123
            static_cast<ArrayStringShort*>(m_arr)->add(value);
104,667✔
124
            break;
104,667✔
125
        case Type::medium_strings:
27,831✔
126
            static_cast<ArraySmallBlobs*>(m_arr)->add_string(value);
27,831✔
127
            break;
27,831✔
128
        case Type::big_strings:
27,450✔
129
            static_cast<ArrayBigBlobs*>(m_arr)->add_string(value);
27,450✔
130
            break;
27,450✔
131
        case Type::enum_strings: {
✔
132
            auto a = static_cast<Array*>(m_arr);
×
133
            size_t ndx = a->size();
×
134
            a->add(0);
×
135
            set(ndx, value);
×
136
            break;
×
137
        }
×
138
    }
159,948✔
139
}
159,948✔
140

141
void ArrayString::set(size_t ndx, StringData value)
142
{
3,820,209✔
143
    switch (upgrade_leaf(value.size())) {
3,820,209✔
144
        case Type::small_strings:
540,669✔
145
            static_cast<ArrayStringShort*>(m_arr)->set(ndx, value);
540,669✔
146
            break;
540,669✔
147
        case Type::medium_strings:
246,633✔
148
            static_cast<ArraySmallBlobs*>(m_arr)->set_string(ndx, value);
246,633✔
149
            break;
246,633✔
150
        case Type::big_strings:
408,900✔
151
            static_cast<ArrayBigBlobs*>(m_arr)->set_string(ndx, value);
408,900✔
152
            break;
408,900✔
153
        case Type::enum_strings: {
2,625,657✔
154
            size_t sz = m_string_enum_values->size();
2,625,657✔
155
            size_t res = m_string_enum_values->find_first(value, 0, sz);
2,625,657✔
156
            if (res == realm::not_found) {
2,625,657✔
157
                m_string_enum_values->add(value);
9,696✔
158
                res = sz;
9,696✔
159
            }
9,696✔
160
            static_cast<Array*>(m_arr)->set(ndx, res);
2,625,657✔
161
            break;
2,625,657✔
162
        }
×
163
    }
3,820,209✔
164
}
3,820,209✔
165

166
void ArrayString::insert(size_t ndx, StringData value)
167
{
3,359,601✔
168
    switch (upgrade_leaf(value.size())) {
3,359,601✔
169
        case Type::small_strings:
1,023,537✔
170
            static_cast<ArrayStringShort*>(m_arr)->insert(ndx, value);
1,023,537✔
171
            break;
1,023,537✔
172
        case Type::medium_strings:
285,825✔
173
            static_cast<ArraySmallBlobs*>(m_arr)->insert_string(ndx, value);
285,825✔
174
            break;
285,825✔
175
        case Type::big_strings:
738,123✔
176
            static_cast<ArrayBigBlobs*>(m_arr)->insert_string(ndx, value);
738,123✔
177
            break;
738,123✔
178
        case Type::enum_strings: {
1,313,304✔
179
            static_cast<Array*>(m_arr)->insert(ndx, 0);
1,313,304✔
180
            set(ndx, value);
1,313,304✔
181
        }
1,313,304✔
182
    }
3,359,601✔
183
}
3,359,601✔
184

185
StringData ArrayString::get(size_t ndx) const
186
{
22,423,407✔
187
    switch (m_type) {
22,423,407✔
188
        case Type::small_strings:
9,205,110✔
189
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
9,205,110✔
190
        case Type::medium_strings:
1,379,052✔
191
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string(ndx);
1,379,052✔
192
        case Type::big_strings:
8,775,738✔
193
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
8,775,738✔
194
        case Type::enum_strings: {
3,081,546✔
195
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
3,081,546✔
196
            return m_string_enum_values->get(index);
3,081,546✔
197
        }
×
198
    }
×
199
    return {};
×
200
}
×
201

202
StringData ArrayString::get_legacy(size_t ndx) const
203
{
6,648✔
204
    switch (m_type) {
6,648✔
205
        case Type::small_strings:
402✔
206
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
402✔
207
        case Type::medium_strings:
3,060✔
208
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string_legacy(ndx);
3,060✔
209
        case Type::big_strings:
3,078✔
210
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
3,078✔
211
        case Type::enum_strings: {
108✔
212
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
108✔
213
            return m_string_enum_values->get(index);
108✔
214
        }
×
215
    }
×
216
    return {};
×
217
}
×
218

219
Mixed ArrayString::get_any(size_t ndx) const
220
{
22,464✔
221
    return Mixed(get(ndx));
22,464✔
222
}
22,464✔
223

224
bool ArrayString::is_null(size_t ndx) const
225
{
3,893,709✔
226
    switch (m_type) {
3,893,709✔
227
        case Type::small_strings:
701,622✔
228
            return static_cast<ArrayStringShort*>(m_arr)->is_null(ndx);
701,622✔
229
        case Type::medium_strings:
14,694✔
230
            return static_cast<ArraySmallBlobs*>(m_arr)->is_null(ndx);
14,694✔
231
        case Type::big_strings:
3,188,199✔
232
            return static_cast<ArrayBigBlobs*>(m_arr)->is_null(ndx);
3,188,199✔
233
        case Type::enum_strings: {
✔
234
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
×
235
            return m_string_enum_values->is_null(index);
×
236
        }
×
237
    }
×
238
    return {};
×
239
}
×
240

241
void ArrayString::erase(size_t ndx)
242
{
179,610✔
243
    switch (m_type) {
179,610✔
244
        case Type::small_strings:
88,344✔
245
            static_cast<ArrayStringShort*>(m_arr)->erase(ndx);
88,344✔
246
            break;
88,344✔
247
        case Type::medium_strings:
58,884✔
248
            static_cast<ArraySmallBlobs*>(m_arr)->erase(ndx);
58,884✔
249
            break;
58,884✔
250
        case Type::big_strings:
24,072✔
251
            static_cast<ArrayBigBlobs*>(m_arr)->erase(ndx);
24,072✔
252
            break;
24,072✔
253
        case Type::enum_strings:
8,313✔
254
            static_cast<Array*>(m_arr)->erase(ndx);
8,313✔
255
            break;
8,313✔
256
    }
179,610✔
257
}
179,610✔
258

259
void ArrayString::move(ArrayString& dst, size_t ndx)
260
{
66✔
261
    size_t sz = size();
66✔
262
    for (size_t i = ndx; i < sz; i++) {
20,730✔
263
        dst.add(get(i));
20,664✔
264
    }
20,664✔
265

33✔
266
    switch (m_type) {
66✔
267
        case Type::small_strings:
✔
268
            static_cast<ArrayStringShort*>(m_arr)->truncate(ndx);
×
269
            break;
×
270
        case Type::medium_strings:
60✔
271
            static_cast<ArraySmallBlobs*>(m_arr)->truncate(ndx);
60✔
272
            break;
60✔
273
        case Type::big_strings:
6✔
274
            static_cast<ArrayBigBlobs*>(m_arr)->truncate(ndx);
6✔
275
            break;
6✔
276
        case Type::enum_strings:
✔
277
            // this operation will never be called for enumerated columns
278
            REALM_UNREACHABLE();
×
279
            break;
×
280
    }
66✔
281
}
66✔
282

283
void ArrayString::clear()
284
{
336✔
285
    switch (m_type) {
336✔
286
        case Type::small_strings:
282✔
287
            static_cast<ArrayStringShort*>(m_arr)->clear();
282✔
288
            break;
282✔
289
        case Type::medium_strings:
6✔
290
            static_cast<ArraySmallBlobs*>(m_arr)->clear();
6✔
291
            break;
6✔
292
        case Type::big_strings:
48✔
293
            static_cast<ArrayBigBlobs*>(m_arr)->clear();
48✔
294
            break;
48✔
295
        case Type::enum_strings:
✔
296
            static_cast<Array*>(m_arr)->clear();
×
297
            break;
×
298
    }
336✔
299
}
336✔
300

301
size_t ArrayString::find_first(StringData value, size_t begin, size_t end) const noexcept
302
{
4,086,180✔
303
    switch (m_type) {
4,086,180✔
304
        case Type::small_strings:
3,129,939✔
305
            return static_cast<ArrayStringShort*>(m_arr)->find_first(value, begin, end);
3,129,939✔
306
        case Type::medium_strings: {
105,582✔
307
            BinaryData as_binary(value.data(), value.size());
105,582✔
308
            return static_cast<ArraySmallBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
105,582✔
309
            break;
×
310
        }
×
311
        case Type::big_strings: {
254,643✔
312
            BinaryData as_binary(value.data(), value.size());
254,643✔
313
            return static_cast<ArrayBigBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
254,643✔
314
            break;
×
315
        }
×
316
        case Type::enum_strings: {
597,180✔
317
            size_t sz = m_string_enum_values->size();
597,180✔
318
            size_t res = m_string_enum_values->find_first(value, 0, sz);
597,180✔
319
            if (res != realm::not_found) {
597,180✔
320
                return static_cast<Array*>(m_arr)->find_first(res, begin, end);
597,180✔
321
            }
597,180✔
UNCOV
322
            break;
×
UNCOV
323
        }
×
324
    }
×
325
    return not_found;
×
326
}
×
327

328
namespace {
329

330
template <class T>
331
inline StringData get_string(const T* arr, size_t ndx)
332
{
437,337✔
333
    return arr->get_string(ndx);
437,337✔
334
}
437,337✔
335

336
template <>
337
inline StringData get_string(const ArrayStringShort* arr, size_t ndx)
338
{
93,696✔
339
    return arr->get(ndx);
93,696✔
340
}
93,696✔
341

342
template <class T, class U>
343
size_t lower_bound_string(const T* arr, U value)
344
{
234,912✔
345
    size_t i = 0;
234,912✔
346
    size_t sz = arr->size();
234,912✔
347
    while (0 < sz) {
765,945✔
348
        size_t half = sz / 2;
531,033✔
349
        size_t mid = i + half;
531,033✔
350
        auto probe = get_string(arr, mid);
531,033✔
351
        if (probe < value) {
531,033✔
352
            i = mid + 1;
190,872✔
353
            sz -= half + 1;
190,872✔
354
        }
190,872✔
355
        else {
340,161✔
356
            sz = half;
340,161✔
357
        }
340,161✔
358
    }
531,033✔
359
    return i;
234,912✔
360
}
234,912✔
361
}
362

363
size_t ArrayString::lower_bound(StringData value)
364
{
234,912✔
365
    switch (m_type) {
234,912✔
366
        case Type::small_strings:
58,434✔
367
            return lower_bound_string(static_cast<ArrayStringShort*>(m_arr), value);
58,434✔
368
        case Type::medium_strings:
68,418✔
369
            return lower_bound_string(static_cast<ArraySmallBlobs*>(m_arr), value);
68,418✔
370
        case Type::big_strings:
108,060✔
371
            return lower_bound_string(static_cast<ArrayBigBlobs*>(m_arr), value);
108,060✔
372
        case Type::enum_strings:
✔
373
            break;
×
374
    }
×
375
    return realm::npos;
×
376
}
×
377

378
ArrayString::Type ArrayString::upgrade_leaf(size_t value_size)
379
{
7,334,595✔
380
    if (m_type == Type::big_strings)
7,334,595✔
381
        return Type::big_strings;
1,136,841✔
382

3,046,023✔
383
    if (m_type == Type::enum_strings)
6,197,754✔
384
        return Type::enum_strings;
3,938,430✔
385

1,077,096✔
386
    if (m_type == Type::medium_strings) {
2,259,324✔
387
        if (value_size <= medium_string_max_size)
531,246✔
388
            return Type::medium_strings;
530,670✔
389

276✔
390
        // Upgrade root leaf from medium to big strings
276✔
391
        auto string_medium = static_cast<ArraySmallBlobs*>(m_arr);
576✔
392
        ArrayBigBlobs big_blobs(m_alloc, true);
576✔
393
        big_blobs.create(); // Throws
576✔
394

276✔
395
        size_t n = string_medium->size();
576✔
396
        for (size_t i = 0; i < n; i++) {
11,451✔
397
            big_blobs.add_string(string_medium->get_string(i)); // Throws
10,875✔
398
        }
10,875✔
399
        auto parent = string_medium->get_parent();
576✔
400
        auto ndx_in_parent = string_medium->get_ndx_in_parent();
576✔
401
        string_medium->destroy();
576✔
402

276✔
403
        auto arr = new (&m_storage.m_big_blobs) ArrayBigBlobs(m_alloc, true);
576✔
404
        arr->init_from_mem(big_blobs.get_mem());
576✔
405
        arr->set_parent(parent, ndx_in_parent);
576✔
406
        arr->update_parent();
576✔
407

276✔
408
        m_type = Type::big_strings;
576✔
409
        return Type::big_strings;
576✔
410
    }
576✔
411

811,017✔
412
    // m_type == Type::small
811,017✔
413
    if (value_size <= small_string_max_size)
1,728,078✔
414
        return Type::small_strings;
1,668,468✔
415

27,702✔
416
    if (value_size <= medium_string_max_size) {
59,610✔
417
        // Upgrade root leaf from small to medium strings
14,496✔
418
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
29,571✔
419
        ArraySmallBlobs string_long(m_alloc);
29,571✔
420
        string_long.create(); // Throws
29,571✔
421

14,496✔
422
        size_t n = string_short->size();
29,571✔
423
        for (size_t i = 0; i < n; i++) {
64,056✔
424
            string_long.add_string(string_short->get(i)); // Throws
34,485✔
425
        }
34,485✔
426
        auto parent = string_short->get_parent();
29,571✔
427
        auto ndx_in_parent = string_short->get_ndx_in_parent();
29,571✔
428
        string_short->destroy();
29,571✔
429

14,496✔
430
        auto arr = new (&m_storage.m_string_long) ArraySmallBlobs(m_alloc);
29,571✔
431
        arr->init_from_mem(string_long.get_mem());
29,571✔
432
        arr->set_parent(parent, ndx_in_parent);
29,571✔
433
        arr->update_parent();
29,571✔
434

14,496✔
435
        m_type = Type::medium_strings;
29,571✔
436
    }
29,571✔
437
    else {
30,039✔
438
        // Upgrade root leaf from small to big strings
13,206✔
439
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
30,039✔
440
        ArrayBigBlobs big_blobs(m_alloc, true);
30,039✔
441
        big_blobs.create(); // Throws
30,039✔
442

13,206✔
443
        size_t n = string_short->size();
30,039✔
444
        for (size_t i = 0; i < n; i++) {
67,395✔
445
            big_blobs.add_string(string_short->get(i)); // Throws
37,356✔
446
        }
37,356✔
447
        auto parent = string_short->get_parent();
30,039✔
448
        auto ndx_in_parent = string_short->get_ndx_in_parent();
30,039✔
449
        string_short->destroy();
30,039✔
450

13,206✔
451
        auto arr = new (&m_storage.m_big_blobs) ArrayBigBlobs(m_alloc, true);
30,039✔
452
        arr->init_from_mem(big_blobs.get_mem());
30,039✔
453
        arr->set_parent(parent, ndx_in_parent);
30,039✔
454
        arr->update_parent();
30,039✔
455

13,206✔
456
        m_type = Type::big_strings;
30,039✔
457
    }
30,039✔
458

27,702✔
459
    return m_type;
59,610✔
460
}
59,610✔
461

462
void ArrayString::verify() const
463
{
2,941,290✔
464
#ifdef REALM_DEBUG
2,941,290✔
465
    switch (m_type) {
2,941,290✔
466
        case Type::small_strings:
2,934,876✔
467
            static_cast<ArrayStringShort*>(m_arr)->verify();
2,934,876✔
468
            break;
2,934,876✔
469
        case Type::medium_strings:
768✔
470
            static_cast<ArraySmallBlobs*>(m_arr)->verify();
768✔
471
            break;
768✔
472
        case Type::big_strings:
5,403✔
473
            static_cast<ArrayBigBlobs*>(m_arr)->verify();
5,403✔
474
            break;
5,403✔
475
        case Type::enum_strings:
246✔
476
            static_cast<Array*>(m_arr)->verify();
246✔
477
            break;
246✔
478
    }
2,941,290✔
479
#endif
2,941,290✔
480
}
2,941,290✔
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