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

realm / realm-core / jorgen.edelbo_402

21 Aug 2024 11:10AM CUT coverage: 91.054% (-0.03%) from 91.085%
jorgen.edelbo_402

Pull #7803

Evergreen

jedelbo
Small fix to Table::typed_write

When writing the realm to a new file from a write transaction,
the Table may be COW so that the top ref is changed. So don't
use the ref that is present in the group when the operation starts.
Pull Request #7803: Feature/string compression

103494 of 181580 branches covered (57.0%)

1929 of 1999 new or added lines in 46 files covered. (96.5%)

695 existing lines in 51 files now uncovered.

220142 of 241772 relevant lines covered (91.05%)

7344461.76 hits per line

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

85.5
/src/realm/array_unsigned.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_unsigned.hpp>
20
#include <realm/array_direct.hpp>
21
#include <algorithm>
22

23
namespace realm {
24

25
void ArrayUnsigned::set_width(uint8_t width)
26
{
227,180,871✔
27
    REALM_ASSERT_DEBUG(width > 0 || m_size == 0);
227,180,871!
28
    m_ubound = uint64_t(-1) >> (64 - width);
227,180,871✔
29
    m_width = width;
227,180,871✔
30
}
227,180,871✔
31

32
inline uint8_t ArrayUnsigned::bit_width(uint64_t value)
33
{
432,555✔
34
    if (value < 0x100) {
432,555✔
35
        return 8;
48,288✔
36
    }
48,288✔
37
    if (value < 0x10000) {
384,267✔
38
        return 16;
289,134✔
39
    }
289,134✔
40
    if (value < 0x100000000) {
95,133✔
41
        return 32;
92,631✔
42
    }
92,631✔
43
    return 64;
2,502✔
44
}
95,133✔
45

46
inline void ArrayUnsigned::_set(size_t ndx, uint8_t width, uint64_t value)
47
{
96,833,394✔
48
    if (width == 8) {
96,833,394✔
49
        reinterpret_cast<uint8_t*>(m_data)[ndx] = uint8_t(value);
5,444,802✔
50
    }
5,444,802✔
51
    else if (width == 16) {
91,388,592✔
52
        reinterpret_cast<uint16_t*>(m_data)[ndx] = uint16_t(value);
73,979,259✔
53
    }
73,979,259✔
54
    else if (width == 32) {
17,409,333✔
55
        reinterpret_cast<uint32_t*>(m_data)[ndx] = uint32_t(value);
17,383,005✔
56
    }
17,383,005✔
57
    else {
26,328✔
58
        reinterpret_cast<uint64_t*>(m_data)[ndx] = uint64_t(value);
26,328✔
59
    }
26,328✔
60
}
96,833,394✔
61

62
inline uint64_t ArrayUnsigned::_get(size_t ndx, uint8_t width) const
63
{
553,811,934✔
64
    if (width == 8) {
553,811,934✔
65
        return reinterpret_cast<uint8_t*>(m_data)[ndx];
22,089,942✔
66
    }
22,089,942✔
67
    if (width == 16) {
531,721,992✔
68
        return reinterpret_cast<uint16_t*>(m_data)[ndx];
74,412,282✔
69
    }
74,412,282✔
70
    if (width == 32) {
457,309,710✔
71
        return reinterpret_cast<uint32_t*>(m_data)[ndx];
436,933,563✔
72
    }
436,933,563✔
73
    return get_direct(m_data, width, ndx);
20,376,147✔
74
    REALM_UNREACHABLE();
75
}
×
76

77
void ArrayUnsigned::create(size_t initial_size, uint64_t ubound_value)
78
{
328,089✔
79
    MemRef mem = create_node(initial_size, get_alloc(), false, Node::type_Normal, wtype_Bits,
328,089✔
80
                             bit_width(ubound_value)); // Throws
328,089✔
81
    init_from_mem(mem);
328,089✔
82
}
328,089✔
83

84
void ArrayUnsigned::update_from_parent() noexcept
85
{
1,225,788✔
86
    REALM_ASSERT_DEBUG(is_attached());
1,225,788✔
87
    ArrayParent* parent = get_parent();
1,225,788✔
88
    REALM_ASSERT_DEBUG(parent);
1,225,788✔
89
    ref_type new_ref = get_ref_from_parent();
1,225,788✔
90
    init_from_ref(new_ref);
1,225,788✔
91
}
1,225,788✔
92

93
size_t ArrayUnsigned::lower_bound(uint64_t value) const noexcept
94
{
61,654,233✔
95
    auto width = get_width_from_header(get_header());
61,654,233✔
96

97
    if (width == 8) {
61,654,233✔
98
        uint8_t* arr = reinterpret_cast<uint8_t*>(m_data);
15,321,561✔
99
        uint8_t* pos = std::lower_bound(arr, arr + m_size, value);
15,321,561✔
100
        return pos - arr;
15,321,561✔
101
    }
15,321,561✔
102
    else if (width == 16) {
46,332,672✔
103
        uint16_t* arr = reinterpret_cast<uint16_t*>(m_data);
38,079,684✔
104
        uint16_t* pos = std::lower_bound(arr, arr + m_size, value);
38,079,684✔
105
        return pos - arr;
38,079,684✔
106
    }
38,079,684✔
107
    else if (width == 32) {
8,252,988✔
108
        uint32_t* arr = reinterpret_cast<uint32_t*>(m_data);
8,042,949✔
109
        uint32_t* pos = std::lower_bound(arr, arr + m_size, value);
8,042,949✔
110
        return pos - arr;
8,042,949✔
111
    }
8,042,949✔
112
    else if (width < 8) {
210,039✔
NEW
113
        switch (width) {
×
114
            case 0:
×
115
                return realm::lower_bound<0>(m_data, m_size, value);
×
116
            case 1:
×
117
                return realm::lower_bound<1>(m_data, m_size, value);
×
118
            case 2:
×
119
                return realm::lower_bound<2>(m_data, m_size, value);
×
120
            case 4:
×
121
                return realm::lower_bound<4>(m_data, m_size, value);
×
122
            default:
×
123
                REALM_UNREACHABLE();
124
                break;
×
125
        }
×
126
        return npos;
×
127
    }
×
128
    uint64_t* arr = reinterpret_cast<uint64_t*>(m_data);
210,039✔
129
    uint64_t* pos = std::lower_bound(arr, arr + m_size, value);
210,039✔
130
    return pos - arr;
210,039✔
131
}
61,654,233✔
132

133
size_t ArrayUnsigned::upper_bound(uint64_t value) const noexcept
134
{
345,941,073✔
135
    auto width = get_width_from_header(get_header());
345,941,073✔
136

137
    if (width == 8) {
345,941,073✔
138
        uint8_t* arr = reinterpret_cast<uint8_t*>(m_data);
1,548✔
139
        uint8_t* pos = std::upper_bound(arr, arr + m_size, value);
1,548✔
140
        return pos - arr;
1,548✔
141
    }
1,548✔
142
    else if (width == 16) {
345,939,525✔
143
        uint16_t* arr = reinterpret_cast<uint16_t*>(m_data);
21,835,806✔
144
        uint16_t* pos = std::upper_bound(arr, arr + m_size, value);
21,835,806✔
145
        return pos - arr;
21,835,806✔
146
    }
21,835,806✔
147
    else if (width == 32) {
324,103,719✔
148
        uint32_t* arr = reinterpret_cast<uint32_t*>(m_data);
298,507,095✔
149
        uint32_t* pos = std::upper_bound(arr, arr + m_size, value);
298,507,095✔
150
        return pos - arr;
298,507,095✔
151
    }
298,507,095✔
152
    else if (width < 8) {
25,596,624✔
NEW
153
        switch (width) {
×
154
            case 0:
×
155
                return realm::upper_bound<0>(m_data, m_size, value);
×
156
            case 1:
×
157
                return realm::upper_bound<1>(m_data, m_size, value);
×
158
            case 2:
×
159
                return realm::upper_bound<2>(m_data, m_size, value);
×
160
            case 4:
×
161
                return realm::upper_bound<4>(m_data, m_size, value);
×
162
            default:
×
163
                REALM_UNREACHABLE();
164
                break;
×
165
        }
×
166
        return npos;
×
167
    }
×
168
    uint64_t* arr = reinterpret_cast<uint64_t*>(m_data);
25,596,624✔
169
    uint64_t* pos = std::upper_bound(arr, arr + m_size, value);
25,596,624✔
170
    return pos - arr;
25,596,624✔
171
}
345,941,073✔
172

173
void ArrayUnsigned::insert(size_t ndx, uint64_t value)
174
{
84,900,882✔
175
    REALM_ASSERT_DEBUG(m_width >= 8);
84,900,882✔
176

177
    bool do_expand = value > (uint64_t)m_ubound;
84,900,882✔
178
    const uint8_t old_width = m_width;
84,900,882✔
179
    const uint8_t new_width = do_expand ? bit_width(value) : m_width;
84,900,882✔
180
    const auto old_size = m_size;
84,900,882✔
181

182
    REALM_ASSERT_DEBUG(!do_expand || new_width > m_width);
84,900,882✔
183
    REALM_ASSERT_DEBUG(ndx <= m_size);
84,900,882✔
184

185
    // Check if we need to copy before modifying
186
    copy_on_write();              // Throws
84,900,882✔
187
    alloc(m_size + 1, new_width); // Throws
84,900,882✔
188

189
    // Move values above insertion (may expand)
190
    if (do_expand) {
84,900,882✔
191
        size_t i = old_size;
92,430✔
192
        while (i > ndx) {
92,442✔
193
            --i;
12✔
194
            auto tmp = _get(i, old_width);
12✔
195
            _set(i + 1, new_width, tmp);
12✔
196
        }
12✔
197
    }
92,430✔
198
    else if (ndx != m_size) {
84,808,452✔
199
        size_t w = (new_width >> 3);
84,716,268✔
200

201
        char* src_begin = m_data + ndx * w;
84,716,268✔
202
        char* src_end = m_data + old_size * w;
84,716,268✔
203
        char* dst = src_end + w;
84,716,268✔
204

205
        std::copy_backward(src_begin, src_end, dst);
84,716,268✔
206
    }
84,716,268✔
207

208
    // Insert the new value
209
    _set(ndx, new_width, value);
84,900,882✔
210

211
    // Expand values before insertion
212
    if (do_expand) {
84,900,882✔
213
        size_t i = ndx;
92,430✔
214
        while (i != 0) {
530,385✔
215
            --i;
437,955✔
216
            _set(i, new_width, _get(i, old_width));
437,955✔
217
        }
437,955✔
218
    }
92,430✔
219
}
84,900,882✔
220

221
void ArrayUnsigned::erase(size_t ndx)
222
{
5,311,614✔
223
    REALM_ASSERT_DEBUG(m_width >= 8);
5,311,614✔
224

225
    copy_on_write(); // Throws
5,311,614✔
226

227
    size_t w = m_width >> 3;
5,311,614✔
228

229
    char* dst = m_data + ndx * w;
5,311,614✔
230
    const char* src = dst + w;
5,311,614✔
231
    size_t num_bytes = (m_size - ndx - 1) * w;
5,311,614✔
232

233
    std::copy_n(src, num_bytes, dst);
5,311,614✔
234

235
    // Update size (also in header)
236
    --m_size;
5,311,614✔
237
    set_header_size(m_size);
5,311,614✔
238
}
5,311,614✔
239

240
uint64_t ArrayUnsigned::get(size_t index) const
241
{
550,106,412✔
242
    return _get(index, m_width);
550,106,412✔
243
}
550,106,412✔
244

245
void ArrayUnsigned::set(size_t ndx, uint64_t value)
246
{
8,426,715✔
247
    REALM_ASSERT_DEBUG(m_width >= 8);
8,426,715✔
248
    copy_on_write(); // Throws
8,426,715✔
249

250
    if (value > m_ubound) {
8,426,715✔
251
        const uint8_t old_width = m_width;
12,036✔
252
        const uint8_t new_width = bit_width(value);
12,036✔
253

254
        alloc(m_size, new_width); // Throws
12,036✔
255

256
        size_t i = m_size;
12,036✔
257
        while (i) {
3,090,930✔
258
            i--;
3,078,894✔
259
            auto v = _get(i, old_width);
3,078,894✔
260
            _set(i, new_width, v);
3,078,894✔
261
        }
3,078,894✔
262
    }
12,036✔
263

264
    _set(ndx, m_width, value);
8,426,715✔
265
}
8,426,715✔
266

267
void ArrayUnsigned::truncate(size_t ndx)
268
{
12,618✔
269
    m_size = ndx;
12,618✔
270
    copy_on_write();
12,618✔
271
    set_header_size(m_size);
12,618✔
272
    if (ndx == 0) {
12,618✔
273
        set_width(8);
7,821✔
274
        set_width_in_header(8, get_header());
7,821✔
275
    }
7,821✔
276
}
12,618✔
277

278
} // namespace realm
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