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

realm / realm-core / jorgen.edelbo_334

01 Jul 2024 07:22AM UTC coverage: 90.829% (-0.04%) from 90.865%
jorgen.edelbo_334

Pull #7803

Evergreen

jedelbo
Merge branch 'next-major' into feature/string-compression
Pull Request #7803: Feature/string compression

102912 of 180568 branches covered (56.99%)

1141 of 1267 new or added lines in 33 files covered. (90.06%)

172 existing lines in 24 files now uncovered.

218291 of 240332 relevant lines covered (90.83%)

7818396.4 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
{
226,651,080✔
27
    REALM_ASSERT_DEBUG(width > 0 || m_size == 0);
226,651,080!
28
    m_ubound = uint64_t(-1) >> (64 - width);
226,651,080✔
29
    m_width = width;
226,651,080✔
30
}
226,651,080✔
31

32
inline uint8_t ArrayUnsigned::bit_width(uint64_t value)
33
{
433,287✔
34
    if (value < 0x100) {
433,287✔
35
        return 8;
51,525✔
36
    }
51,525✔
37
    if (value < 0x10000) {
381,762✔
38
        return 16;
287,421✔
39
    }
287,421✔
40
    if (value < 0x100000000) {
94,341✔
41
        return 32;
92,028✔
42
    }
92,028✔
43
    return 64;
2,313✔
44
}
94,341✔
45

46
inline void ArrayUnsigned::_set(size_t ndx, uint8_t width, uint64_t value)
47
{
96,467,019✔
48
    if (width == 8) {
96,467,019✔
49
        reinterpret_cast<uint8_t*>(m_data)[ndx] = uint8_t(value);
5,654,208✔
50
    }
5,654,208✔
51
    else if (width == 16) {
90,812,811✔
52
        reinterpret_cast<uint16_t*>(m_data)[ndx] = uint16_t(value);
73,933,839✔
53
    }
73,933,839✔
54
    else if (width == 32) {
16,898,391✔
55
        reinterpret_cast<uint32_t*>(m_data)[ndx] = uint32_t(value);
16,898,391✔
56
    }
16,898,391✔
57
    else {
4,294,967,294✔
58
        reinterpret_cast<uint64_t*>(m_data)[ndx] = uint64_t(value);
4,294,967,294✔
59
    }
4,294,967,294✔
60
}
96,467,019✔
61

62
inline uint64_t ArrayUnsigned::_get(size_t ndx, uint8_t width) const
63
{
570,739,851✔
64
    if (width == 8) {
570,739,851✔
65
        return reinterpret_cast<uint8_t*>(m_data)[ndx];
19,835,406✔
66
    }
19,835,406✔
67
    if (width == 16) {
550,904,445✔
68
        return reinterpret_cast<uint16_t*>(m_data)[ndx];
71,786,430✔
69
    }
71,786,430✔
70
    if (width == 32) {
479,118,015✔
71
        return reinterpret_cast<uint32_t*>(m_data)[ndx];
456,829,368✔
72
    }
456,829,368✔
73
    return get_direct(m_data, width, ndx);
22,288,647✔
74
    REALM_UNREACHABLE();
75
}
×
76

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

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

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

97
    if (width == 8) {
61,854,600✔
98
        uint8_t* arr = reinterpret_cast<uint8_t*>(m_data);
14,208,684✔
99
        uint8_t* pos = std::lower_bound(arr, arr + m_size, value);
14,208,684✔
100
        return pos - arr;
14,208,684✔
101
    }
14,208,684✔
102
    else if (width == 16) {
47,645,916✔
103
        uint16_t* arr = reinterpret_cast<uint16_t*>(m_data);
38,837,187✔
104
        uint16_t* pos = std::lower_bound(arr, arr + m_size, value);
38,837,187✔
105
        return pos - arr;
38,837,187✔
106
    }
38,837,187✔
107
    else if (width == 32) {
8,815,860✔
108
        uint32_t* arr = reinterpret_cast<uint32_t*>(m_data);
8,786,802✔
109
        uint32_t* pos = std::lower_bound(arr, arr + m_size, value);
8,786,802✔
110
        return pos - arr;
8,786,802✔
111
    }
8,786,802✔
112
    else if (width < 8) {
2,147,512,705✔
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);
2,147,512,705✔
129
    uint64_t* pos = std::lower_bound(arr, arr + m_size, value);
2,147,512,705✔
130
    return pos - arr;
2,147,512,705✔
131
}
61,854,600✔
132

133
size_t ArrayUnsigned::upper_bound(uint64_t value) const noexcept
134
{
340,969,836✔
135
    auto width = get_width_from_header(get_header());
340,969,836✔
136

137
    if (width == 8) {
340,969,836✔
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) {
340,968,288✔
143
        uint16_t* arr = reinterpret_cast<uint16_t*>(m_data);
21,261,579✔
144
        uint16_t* pos = std::upper_bound(arr, arr + m_size, value);
21,261,579✔
145
        return pos - arr;
21,261,579✔
146
    }
21,261,579✔
147
    else if (width == 32) {
319,706,709✔
148
        uint32_t* arr = reinterpret_cast<uint32_t*>(m_data);
293,541,177✔
149
        uint32_t* pos = std::upper_bound(arr, arr + m_size, value);
293,541,177✔
150
        return pos - arr;
293,541,177✔
151
    }
293,541,177✔
152
    else if (width < 8) {
26,165,532✔
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);
26,165,532✔
169
    uint64_t* pos = std::upper_bound(arr, arr + m_size, value);
26,165,532✔
170
    return pos - arr;
26,165,532✔
171
}
340,969,836✔
172

173
void ArrayUnsigned::insert(size_t ndx, uint64_t value)
174
{
83,875,326✔
175
    REALM_ASSERT_DEBUG(m_width >= 8);
83,875,326✔
176

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

182
    REALM_ASSERT_DEBUG(!do_expand || new_width > m_width);
83,875,326✔
183
    REALM_ASSERT_DEBUG(ndx <= m_size);
83,875,326✔
184

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

189
    // Move values above insertion (may expand)
190
    if (do_expand) {
83,875,326✔
191
        size_t i = old_size;
95,376✔
192
        while (i > ndx) {
95,388✔
193
            --i;
12✔
194
            auto tmp = _get(i, old_width);
12✔
195
            _set(i + 1, new_width, tmp);
12✔
196
        }
12✔
197
    }
95,376✔
198
    else if (ndx != m_size) {
83,779,950✔
199
        size_t w = (new_width >> 3);
83,649,222✔
200

201
        char* src_begin = m_data + ndx * w;
83,649,222✔
202
        char* src_end = m_data + old_size * w;
83,649,222✔
203
        char* dst = src_end + w;
83,649,222✔
204

205
        std::copy_backward(src_begin, src_end, dst);
83,649,222✔
206
    }
83,649,222✔
207

208
    // Insert the new value
209
    _set(ndx, new_width, value);
83,875,326✔
210

211
    // Expand values before insertion
212
    if (do_expand) {
83,875,326✔
213
        size_t i = ndx;
95,376✔
214
        while (i != 0) {
993,396✔
215
            --i;
898,020✔
216
            _set(i, new_width, _get(i, old_width));
898,020✔
217
        }
898,020✔
218
    }
95,376✔
219
}
83,875,326✔
220

221
void ArrayUnsigned::erase(size_t ndx)
222
{
4,994,676✔
223
    REALM_ASSERT_DEBUG(m_width >= 8);
4,994,676✔
224

225
    copy_on_write(); // Throws
4,994,676✔
226

227
    size_t w = m_width >> 3;
4,994,676✔
228

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

233
    std::copy_n(src, num_bytes, dst);
4,994,676✔
234

235
    // Update size (also in header)
236
    --m_size;
4,994,676✔
237
    set_header_size(m_size);
4,994,676✔
238
}
4,994,676✔
239

240
uint64_t ArrayUnsigned::get(size_t index) const
241
{
566,947,353✔
242
    return _get(index, m_width);
566,947,353✔
243
}
566,947,353✔
244

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

250
    if (value > m_ubound) {
8,636,778✔
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,636,778✔
265
}
8,636,778✔
266

267
void ArrayUnsigned::truncate(size_t ndx)
268
{
11,766✔
269
    m_size = ndx;
11,766✔
270
    copy_on_write();
11,766✔
271
    set_header_size(m_size);
11,766✔
272
    if (ndx == 0) {
11,766✔
273
        set_width(8);
6,900✔
274
        set_width_in_header(8, get_header());
6,900✔
275
    }
6,900✔
276
}
11,766✔
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