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

realm / realm-core / github_pull_request_281750

30 Oct 2023 03:37PM UTC coverage: 90.528% (-1.0%) from 91.571%
github_pull_request_281750

Pull #6073

Evergreen

jedelbo
Log free space and history sizes when opening file
Pull Request #6073: Merge next-major

95488 of 175952 branches covered (0.0%)

8973 of 12277 new or added lines in 149 files covered. (73.09%)

622 existing lines in 51 files now uncovered.

233503 of 257934 relevant lines covered (90.53%)

6533720.56 hits per line

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

91.4
/src/realm/array_decimal128.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2019 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_decimal128.hpp>
20
#include <realm/mixed.hpp>
21

22
namespace realm {
23

24
namespace {
25

26
uint8_t min_width(const Decimal128& value, bool zero_width_is_zero)
27
{
292,785✔
28
    Decimal128::Bid128 coefficient;
292,785✔
29
    int exponent;
292,785✔
30
    bool sign;
292,785✔
31

146,247✔
32
    if (value.is_null()) {
292,785✔
33
        return zero_width_is_zero ? 4 : 0;
58,989✔
34
    }
59,790✔
35

116,502✔
36
    value.unpack(coefficient, exponent, sign);
232,995✔
37
    if (coefficient.w[1] == 0) {
232,995✔
38
        if (coefficient.w[0] == 0 && exponent == 0) {
232,929✔
39
            return zero_width_is_zero ? 0 : 4;
43,215✔
40
        }
50,019✔
41
        if (coefficient.w[0] < (1ull << 23) && exponent > -91 && exponent < 91) {
182,910✔
42
            return 4;
161,250✔
43
        }
161,250✔
44
        if (coefficient.w[0] < (1ull << 53) && exponent > -370 && exponent < 370) {
21,660✔
45
            return 8;
222✔
46
        }
222✔
47
    }
21,504✔
48
    return 16;
21,504✔
49
}
21,504✔
50
} // namespace
51

52
void ArrayDecimal128::set(size_t ndx, Decimal128 value)
53
{
72,495✔
54
    REALM_ASSERT(ndx < m_size);
72,495✔
55
    copy_on_write();
72,495✔
56
    switch (upgrade_leaf(min_width(value, Array::get_context_flag()))) {
72,495✔
57
        case 0:
21✔
58
            break;
21✔
59
        case 4: {
66,660✔
60
            auto values = reinterpret_cast<Decimal::Bid32*>(m_data);
66,660✔
61
            auto val = value.to_bid32();
66,660✔
62
            REALM_ASSERT(val);
66,660✔
63
            values[ndx] = *val;
66,660✔
64
            break;
66,660✔
NEW
65
        }
×
66
        case 8: {
138✔
67
            auto values = reinterpret_cast<Decimal::Bid64*>(m_data);
138✔
68
            auto val = value.to_bid64();
138✔
69
            REALM_ASSERT(val);
138✔
70
            values[ndx] = *val;
138✔
71
            break;
138✔
NEW
72
        }
×
73
        case 16: {
5,676✔
74
            auto values = reinterpret_cast<Decimal128*>(m_data);
5,676✔
75
            values[ndx] = value;
5,676✔
76
            break;
5,676✔
NEW
77
        }
×
78
    }
72,495✔
79
}
72,495✔
80

81
void ArrayDecimal128::insert(size_t ndx, Decimal128 value)
82
{
220,014✔
83
    REALM_ASSERT(ndx <= m_size);
220,014✔
84
    if (m_size == 0 && value == Decimal128()) {
220,014✔
85
        // zero width should be interpreted as 0
2,004✔
86
        Array::copy_on_write();
4,005✔
87
        Array::set_context_flag(true);
4,005✔
88
    }
4,005✔
89
    // Allocate room for the new value
109,857✔
90
    switch (upgrade_leaf(min_width(value, Array::get_context_flag()))) {
220,014✔
91
        case 0:
22,416✔
92
            m_size += 1;
22,416✔
93
            Array::copy_on_write();
22,416✔
94
            set_header_size(m_size);
22,416✔
95
            break;
22,416✔
96
        case 4: {
153,918✔
97
            alloc(m_size + 1, 4); // Throws
153,918✔
98

76,956✔
99
            auto src = reinterpret_cast<Decimal::Bid32*>(m_data) + ndx;
153,918✔
100
            auto dst = src + 1;
153,918✔
101

76,956✔
102
            // Make gap for new value
76,956✔
103
            memmove(dst, src, sizeof(Decimal::Bid32) * (m_size - 1 - ndx));
153,918✔
104

76,956✔
105
            // Set new value
76,956✔
106
            auto val = value.to_bid32();
153,918✔
107
            REALM_ASSERT(val);
153,918✔
108
            *src = *val;
153,918✔
109
            break;
153,918✔
NEW
110
        }
×
111
        case 8: {
168✔
112
            alloc(m_size + 1, 8); // Throws
168✔
113

84✔
114
            auto src = reinterpret_cast<Decimal::Bid64*>(m_data) + ndx;
168✔
115
            auto dst = src + 1;
168✔
116

84✔
117
            // Make gap for new value
84✔
118
            memmove(dst, src, sizeof(Decimal::Bid64) * (m_size - 1 - ndx));
168✔
119

84✔
120
            // Set new value
84✔
121
            auto val = value.to_bid64();
168✔
122
            REALM_ASSERT(val);
168✔
123
            *src = *val;
168✔
124
            break;
168✔
NEW
125
        }
×
126
        case 16: {
43,512✔
127
            alloc(m_size + 1, sizeof(Decimal128)); // Throws
43,512✔
128

21,756✔
129
            auto src = reinterpret_cast<Decimal128*>(m_data) + ndx;
43,512✔
130
            auto dst = src + 1;
43,512✔
131

21,756✔
132
            // Make gap for new value
21,756✔
133
            memmove(dst, src, sizeof(Decimal128) * (m_size - 1 - ndx));
43,512✔
134

21,756✔
135
            // Set new value
21,756✔
136
            *src = value;
43,512✔
137
            break;
43,512✔
NEW
138
        }
×
139
    }
220,014✔
140
}
220,014✔
141

142
void ArrayDecimal128::erase(size_t ndx)
143
{
50,409✔
144

25,200✔
145
    REALM_ASSERT(ndx < m_size);
50,409✔
146

25,200✔
147
    copy_on_write();
50,409✔
148

25,200✔
149
    if (m_width) {
50,409✔
150
        auto dst = m_data + ndx * m_width;
50,262✔
151
        memmove(dst, dst + m_width, m_width * (m_size - ndx));
50,262✔
152
    }
50,262✔
153

25,200✔
154
    // Update size (also in header)
25,200✔
155
    m_size -= 1;
50,409✔
156
    set_header_size(m_size);
50,409✔
157
}
50,409✔
158

159
void ArrayDecimal128::move(ArrayDecimal128& dst_arr, size_t ndx)
160
{
72✔
161
    size_t elements_to_move = m_size - ndx;
72✔
162
    if (elements_to_move) {
72✔
163
        if (m_width >= dst_arr.m_width) {
72✔
164
            dst_arr.upgrade_leaf(m_width);
66✔
165
            const auto old_dst_size = dst_arr.m_size;
66✔
166
            dst_arr.alloc(old_dst_size + elements_to_move, m_width);
66✔
167
            auto dst = dst_arr.m_data + old_dst_size * m_width;
66✔
168
            auto src = m_data + ndx * m_width;
66✔
169
            memmove(dst, src, elements_to_move * m_width);
66✔
170
        }
66✔
171
        else {
6✔
172
            for (size_t i = 0; i < elements_to_move; i++) {
12✔
173
                dst_arr.add(get(ndx + i));
6✔
174
            }
6✔
175
        }
6✔
176
    }
72✔
177
    truncate(ndx);
72✔
178
}
72✔
179

180
size_t ArrayDecimal128::find_first(Decimal128 value, size_t start, size_t end) const noexcept
181
{
276✔
182
    auto sz = size();
276✔
183
    if (end == size_t(-1))
276✔
184
        end = sz;
24✔
185
    REALM_ASSERT(start <= sz && end <= sz && start <= end);
276✔
186

138✔
187
    bool zero_width_is_zero = Array::get_context_flag();
276✔
188
    auto width = min_width(value, zero_width_is_zero);
276✔
189
    switch (m_width) {
276✔
NEW
190
        case 0:
✔
NEW
191
            if (zero_width_is_zero) {
×
NEW
192
                if (value == Decimal128()) {
×
NEW
193
                    return 0;
×
NEW
194
                }
×
NEW
195
            }
×
NEW
196
            else {
×
NEW
197
                if (value.is_null()) {
×
NEW
198
                    return 0;
×
NEW
199
                }
×
NEW
200
            }
×
NEW
201
            break;
×
202
        case 4:
270✔
203
            if (width <= 4) {
270✔
204
                // Worth optimizing here
135✔
205
                auto optval32 = value.to_bid32();
270✔
206
                REALM_ASSERT(optval32);
270✔
207
                auto val32 = *optval32;
270✔
208
                auto values = reinterpret_cast<Decimal128::Bid32*>(this->m_data);
270✔
209
                for (size_t i = start; i < end; i++) {
528✔
210
                    if (values[i] == val32)
480✔
211
                        return i;
222✔
212
                }
480✔
213
            }
270✔
214
            break;
159✔
215
        case 8:
138✔
216
            if (width <= 8) {
6✔
217
                auto values = reinterpret_cast<Decimal128::Bid64*>(this->m_data);
6✔
218
                for (size_t i = start; i < end; i++) {
12✔
219
                    if (Decimal128(values[i]) == value)
12✔
220
                        return i;
6✔
221
                }
12✔
222
            }
6✔
223
            break;
3✔
224
        case 16: {
3✔
NEW
225
            auto values = reinterpret_cast<Decimal128*>(this->m_data);
×
NEW
226
            for (size_t i = start; i < end; i++) {
×
NEW
227
                if (values[i] == value)
×
NEW
228
                    return i;
×
NEW
229
            }
×
NEW
230
            break;
×
231
        }
48✔
232
    }
48✔
233

24✔
234
    return realm::npos;
48✔
235
}
48✔
236

237
Mixed ArrayDecimal128::get_any(size_t ndx) const
238
{
22,824✔
239
    return Mixed(get(ndx));
22,824✔
240
}
22,824✔
241

242

243
size_t ArrayDecimal128::upgrade_leaf(uint8_t width)
244
{
292,575✔
245
    if (m_width == 16) {
292,575✔
246
        return 16;
37,740✔
247
    }
37,740✔
248
    if (width <= m_width) {
254,835✔
249
        return m_width;
233,895✔
250
    }
233,895✔
251

10,470✔
252
    if (m_size == 0) {
20,940✔
253
        alloc(m_size, width);
9,825✔
254
        return width;
9,825✔
255
    }
9,825✔
256

5,559✔
257
    if (m_width == 8) {
11,115✔
258
        // Upgrade to 16 bytes
9✔
259
        alloc(m_size, 16);
18✔
260
        auto src = reinterpret_cast<Decimal::Bid64*>(m_data);
18✔
261
        auto dst = reinterpret_cast<Decimal::Bid128*>(m_data);
18✔
262
        for (size_t i = m_size; i > 0; --i) {
144✔
263
            auto val = Decimal128(src[i - 1]);
126✔
264
            dst[i - 1] = *val.raw();
126✔
265
        }
126✔
266
        return 16;
18✔
267
    }
18✔
268

5,550✔
269
    if (m_width == 4) {
11,097✔
270
        alloc(m_size, width);
5,952✔
271
        auto src = reinterpret_cast<Decimal::Bid32*>(m_data);
5,952✔
272
        if (width == 8) {
5,952✔
273
            // Upgrade to 8 bytes
15✔
274
            auto dst = reinterpret_cast<Decimal::Bid64*>(m_data);
30✔
275
            for (size_t i = m_size; i > 0; --i) {
102✔
276
                auto val = Decimal128(src[i - 1]);
72✔
277
                dst[i - 1] = *val.to_bid64();
72✔
278
            }
72✔
279
        }
30✔
280
        else if (width == 16) {
5,922✔
281
            // Upgrade to 16 bytes
2,961✔
282
            auto dst = reinterpret_cast<Decimal::Bid128*>(m_data);
5,922✔
283
            for (size_t i = m_size; i > 0; --i) {
21,108✔
284
                auto val = Decimal128(src[i - 1]);
15,186✔
285
                dst[i - 1] = *val.raw();
15,186✔
286
            }
15,186✔
287
        }
5,922✔
288
        return width;
5,952✔
289
    }
5,952✔
290

2,574✔
291
    // Upgrade from zero width. Fill with either 0 or null.
2,574✔
292
    Decimal128 fill_value = get_context_flag() ? Decimal128(0) : Decimal128(realm::null());
5,145✔
293

2,574✔
294
    if (width == 4) {
5,145✔
295
        // Upgrade to 4 bytes
1,767✔
296
        alloc(m_size, 4);
3,531✔
297
        auto values = reinterpret_cast<Decimal::Bid32*>(m_data);
3,531✔
298
        auto fill = *fill_value.to_bid32();
3,531✔
299
        for (size_t i = 0; i < m_size; i++) {
9,705✔
300
            values[i] = fill;
6,174✔
301
        }
6,174✔
302
        return 4;
3,531✔
303
    }
3,531✔
304
    else if (width == 8) {
1,614✔
305
        // Upgrade to 8 bytes
9✔
306
        alloc(m_size, 8);
18✔
307
        auto values = reinterpret_cast<Decimal::Bid64*>(m_data);
18✔
308
        auto fill = *fill_value.to_bid64();
18✔
309
        for (size_t i = 0; i < m_size; i++) {
84✔
310
            values[i] = fill;
66✔
311
        }
66✔
312
        return 8;
18✔
313
    }
18✔
314

798✔
315
    alloc(m_size, 16);
1,596✔
316
    auto values = reinterpret_cast<Decimal128*>(m_data);
1,596✔
317
    for (size_t i = 0; i < m_size; i++) {
6,264✔
318
        values[i] = fill_value;
4,668✔
319
    }
4,668✔
320
    return 16;
1,596✔
321
}
1,596✔
322

323

324
} // 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