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

realm / realm-core / nicola.cabiddu_1042

27 Sep 2023 06:04PM CUT coverage: 91.085% (-1.8%) from 92.915%
nicola.cabiddu_1042

Pull #6766

Evergreen

nicola-cab
Fix logic for dictionaries
Pull Request #6766: Client Reset for collections in mixed / nested collections

97276 of 178892 branches covered (0.0%)

1994 of 2029 new or added lines in 7 files covered. (98.28%)

4556 existing lines in 112 files now uncovered.

237059 of 260260 relevant lines covered (91.09%)

6321099.55 hits per line

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

92.57
/src/realm/array_blobs_small.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 <utility> // pair
20

21
#include <realm/array_blobs_small.hpp>
22
#include <realm/array_blob.hpp>
23
#include <realm/impl/destroy_guard.hpp>
24

25
using namespace realm;
26

27
void ArraySmallBlobs::init_from_mem(MemRef mem) noexcept
28
{
2,827,062✔
29
    Array::init_from_mem(mem);
2,827,062✔
30
    ref_type offsets_ref = get_as_ref(0);
2,827,062✔
31
    ref_type blob_ref = get_as_ref(1);
2,827,062✔
32

1,482,687✔
33
    m_offsets.init_from_ref(offsets_ref);
2,827,062✔
34
    m_blob.init_from_ref(blob_ref);
2,827,062✔
35

1,482,687✔
36
    // In theory you could have an array that survived from ancient days where this array was not present
1,482,687✔
37
    if (Array::size() > 2) {
2,827,062✔
38
        ref_type nulls_ref = get_as_ref(2);
2,825,439✔
39
        m_nulls.init_from_ref(nulls_ref);
2,825,439✔
40
    }
2,825,439✔
41
}
2,827,062✔
42

43
void ArraySmallBlobs::add(BinaryData value, bool add_zero_term)
44
{
77,526✔
45
    REALM_ASSERT_7(value.size(), ==, 0, ||, value.data(), !=, 0);
77,526✔
46

38,865✔
47
    m_blob.add(value.data(), value.size(), add_zero_term);
77,526✔
48
    size_t end = value.size();
77,526✔
49
    if (add_zero_term)
77,526✔
50
        ++end;
62,142✔
51
    if (!m_offsets.is_empty())
77,526✔
52
        end += to_size_t(m_offsets.back());
48,858✔
53
    m_offsets.add(end);
77,526✔
54
    m_nulls.add(value.is_null());
77,526✔
55
}
77,526✔
56

57
void ArraySmallBlobs::set(size_t ndx, BinaryData value, bool add_zero_term)
58
{
322,311✔
59
    REALM_ASSERT_3(ndx, <, m_offsets.size());
322,311✔
60
    REALM_ASSERT_3(value.size(), == 0 ||, value.data());
322,311✔
61

161,034✔
62
    int_fast64_t start = ndx ? m_offsets.get(ndx - 1) : 0;
305,070✔
63
    int_fast64_t current_end = m_offsets.get(ndx);
322,311✔
64
    size_t stored_size = value.size();
322,311✔
65
    if (add_zero_term)
322,311✔
66
        ++stored_size;
246,720✔
67
    int_fast64_t diff = (start + stored_size) - current_end;
322,311✔
68
    m_blob.replace(to_size_t(start), to_size_t(current_end), value.data(), value.size(), add_zero_term);
322,311✔
69
    m_offsets.adjust(ndx, m_offsets.size(), diff);
322,311✔
70
    m_nulls.set(ndx, value.is_null());
322,311✔
71
}
322,311✔
72

73
void ArraySmallBlobs::insert(size_t ndx, BinaryData value, bool add_zero_term)
74
{
1,223,472✔
75
    REALM_ASSERT_3(ndx, <=, m_offsets.size());
1,223,472✔
76
    REALM_ASSERT_3(value.size(), == 0 ||, value.data());
1,223,472✔
77

629,826✔
78
    size_t pos = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
1,145,466✔
79
    m_blob.insert(pos, value.data(), value.size(), add_zero_term);
1,223,472✔
80

629,826✔
81
    size_t stored_size = value.size();
1,223,472✔
82
    if (add_zero_term)
1,223,472✔
83
        ++stored_size;
281,676✔
84
    m_offsets.insert(ndx, pos + stored_size);
1,223,472✔
85
    m_offsets.adjust(ndx + 1, m_offsets.size(), stored_size);
1,223,472✔
86
    m_nulls.insert(ndx, value.is_null());
1,223,472✔
87
}
1,223,472✔
88

89
void ArraySmallBlobs::erase(size_t ndx)
90
{
751,026✔
91
    REALM_ASSERT_3(ndx, <, m_offsets.size());
751,026✔
92

395,157✔
93
    size_t start = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
649,374✔
94
    size_t end = to_size_t(m_offsets.get(ndx));
751,026✔
95

395,157✔
96
    m_blob.erase(start, end);
751,026✔
97
    m_offsets.erase(ndx);
751,026✔
98
    m_offsets.adjust(ndx, m_offsets.size(), int64_t(start) - end);
751,026✔
99
    m_nulls.erase(ndx);
751,026✔
100
}
751,026✔
101

102
BinaryData ArraySmallBlobs::get(const char* header, size_t ndx, Allocator& alloc) noexcept
103
{
328,092✔
104
    int64_t ref_val = Array::get(header, 2);
328,092✔
105
    const char* nulls_header = alloc.translate(to_ref(ref_val));
328,092✔
106
    int64_t n = Array::get(nulls_header, ndx);
328,092✔
107
    // 0 or 1 is all that is ever written to m_nulls; any other content would be a bug
164,361✔
108
    REALM_ASSERT_3(n == 1, ||, n == 0);
328,092✔
109
    bool null = (n != 0);
328,092✔
110
    if (null)
328,092✔
111
        return BinaryData{};
21,141✔
112

152,997✔
113
    std::pair<int64_t, int64_t> p = Array::get_two(header, 0);
306,951✔
114
    const char* offsets_header = alloc.translate(to_ref(p.first));
306,951✔
115
    const char* blob_header = alloc.translate(to_ref(p.second));
306,951✔
116
    size_t begin, end;
306,951✔
117
    if (ndx) {
306,951✔
118
        p = get_two(offsets_header, ndx - 1);
289,569✔
119
        begin = to_size_t(p.first);
289,569✔
120
        end = to_size_t(p.second);
289,569✔
121
    }
289,569✔
122
    else {
17,382✔
123
        begin = 0;
17,382✔
124
        end = to_size_t(Array::get(offsets_header, ndx));
17,382✔
125
    }
17,382✔
126
    BinaryData bd = BinaryData(ArrayBlob::get(blob_header, begin), end - begin);
306,951✔
127
    return bd;
306,951✔
128
}
306,951✔
129

130
MemRef ArraySmallBlobs::create_array(size_t size, Allocator& alloc, BinaryData values)
131
{
164,607✔
132
    // Only null and zero-length non-null allowed as initialization value
80,775✔
133
    REALM_ASSERT(values.size() == 0);
164,607✔
134
    Array top(alloc);
164,607✔
135
    _impl::DeepArrayDestroyGuard dg(&top);
164,607✔
136
    top.create(type_HasRefs); // Throws
164,607✔
137

80,775✔
138
    _impl::DeepArrayRefDestroyGuard dg_2(alloc);
164,607✔
139
    {
164,607✔
140
        bool context_flag = false;
164,607✔
141
        int64_t value = 0;
164,607✔
142
        MemRef mem = Array::create_array(type_Normal, context_flag, size, value, alloc); // Throws
164,607✔
143
        dg_2.reset(mem.get_ref());
164,607✔
144
        int64_t v = from_ref(mem.get_ref());
164,607✔
145
        top.add(v); // Throws
164,607✔
146
        dg_2.release();
164,607✔
147
    }
164,607✔
148
    {
164,607✔
149
        size_t blobs_size = 0;
164,607✔
150
        MemRef mem = ArrayBlob::create_array(blobs_size, alloc); // Throws
164,607✔
151
        dg_2.reset(mem.get_ref());
164,607✔
152
        int64_t v = from_ref(mem.get_ref());
164,607✔
153
        top.add(v); // Throws
164,607✔
154
        dg_2.release();
164,607✔
155
    }
164,607✔
156
    {
164,607✔
157
        // Always create a m_nulls array, regardless if its column is marked as nullable or not.
80,775✔
158
        bool context_flag = false;
164,607✔
159
        int64_t value = values.is_null() ? 1 : 0;
164,607✔
160
        MemRef mem = Array::create_array(type_Normal, context_flag, size, value, alloc); // Throws
164,607✔
161
        dg_2.reset(mem.get_ref());
164,607✔
162
        int64_t v = from_ref(mem.get_ref());
164,607✔
163
        top.add(v); // Throws
164,607✔
164
        dg_2.release();
164,607✔
165
    }
164,607✔
166

80,775✔
167
    dg.release();
164,607✔
168
    return top.get_mem();
164,607✔
169
}
164,607✔
170

171
size_t ArraySmallBlobs::find_first(BinaryData value, bool is_string, size_t begin, size_t end) const noexcept
172
{
104,868✔
173
    size_t sz = size();
104,868✔
174
    if (end == npos)
104,868✔
175
        end = sz;
×
176
    REALM_ASSERT_11(begin, <=, sz, &&, end, <=, sz, &&, begin, <=, end);
104,868✔
177

63,102✔
178
    if (value.is_null()) {
104,868✔
179
        for (size_t i = begin; i != end; ++i) {
1,803✔
180
            if (m_nulls.get(i))
1,797✔
181
                return i;
1,659✔
182
        }
1,797✔
183
    }
1,665✔
184
    else {
103,203✔
185
        // When strings are stored as blobs, they are always zero-terminated
62,151✔
186
        // but the value we get as input might not be.
62,151✔
187
        size_t value_size = value.size();
103,203✔
188
        size_t full_size = is_string ? value_size + 1 : value_size;
103,071✔
189

62,151✔
190
        size_t start_ofs = begin ? to_size_t(m_offsets.get(begin - 1)) : 0;
96,297✔
191
        for (size_t i = begin; i != end; ++i) {
378,969✔
192
            size_t end_ofs = to_size_t(m_offsets.get(i));
360,426✔
193
            size_t this_size = end_ofs - start_ofs;
360,426✔
194
            if (!m_nulls.get(i) && this_size == full_size) {
360,426✔
195
                const char* blob_value = m_blob.get(start_ofs);
126,255✔
196
                if (std::equal(blob_value, blob_value + value_size, value.data()))
126,255✔
197
                    return i;
84,660✔
198
            }
275,766✔
199
            start_ofs = end_ofs;
275,766✔
200
        }
275,766✔
201
    }
103,203✔
202

63,102✔
203
    return not_found;
70,155✔
204
}
104,868✔
205

206
StringData ArraySmallBlobs::get_string_legacy(size_t ndx) const
UNCOV
207
{
×
UNCOV
208
    REALM_ASSERT_3(ndx, <, m_offsets.size());
×
209

210
    // In file format versions prior to 10 a true value means that the element is not null
UNCOV
211
    if (Array::size() == 3 && !m_nulls.get(ndx)) {
×
UNCOV
212
        return {};
×
UNCOV
213
    }
×
UNCOV
214
    else {
×
UNCOV
215
        size_t begin = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
×
UNCOV
216
        size_t end = to_size_t(m_offsets.get(ndx));
×
UNCOV
217
        StringData str = StringData(m_blob.get(begin), (end - begin) - 1);
×
UNCOV
218
        return str;
×
UNCOV
219
    }
×
UNCOV
220
}
×
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