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

realm / realm-core / jorgen.edelbo_390

12 Aug 2024 12:13PM UTC coverage: 91.108% (+0.02%) from 91.085%
jorgen.edelbo_390

Pull #7979

Evergreen

jedelbo
Create test file in file-format 24
Pull Request #7979: Create test file in file-format 24

102766 of 181590 branches covered (56.59%)

19 of 19 new or added lines in 1 file covered. (100.0%)

1020 existing lines in 55 files now uncovered.

217365 of 238579 relevant lines covered (91.11%)

5621116.99 hits per line

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

92.86
/src/realm/node_header.hpp
1
/*************************************************************************
2
 *
3
 * Copyright 2018 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
#ifndef REALM_NODE_HEADER_HPP
20
#define REALM_NODE_HEADER_HPP
21

22
#include <realm/util/assert.hpp>
23

24
namespace realm {
25

26
const size_t max_array_size = 0x00ffffffL;            // Maximum number of elements in an array
27
const size_t max_array_payload_aligned = 0x07ffffc0L; // Maximum number of bytes that the payload of an array can be
28
// Even though the encoding supports arrays with size up to max_array_payload_aligned,
29
// the maximum allocation size is smaller as it must fit within a memory section
30
// (a contiguous virtual address range). This limitation is enforced in SlabAlloc::do_alloc().
31

32
class NodeHeader {
33
public:
34
    enum Type {
35
        type_Normal,
36

37
        /// This array is the main array of an innner node of a B+-tree as used
38
        /// in table columns.
39
        type_InnerBptreeNode,
40

41
        /// This array may contain refs to subarrays. An element whose least
42
        /// significant bit is zero, is a ref pointing to a subarray. An element
43
        /// whose least significant bit is one, is just a value. It is the
44
        /// responsibility of the application to ensure that non-ref values have
45
        /// their least significant bit set. This will generally be done by
46
        /// shifting the desired vlue to the left by one bit position, and then
47
        /// setting the vacated bit to one.
48
        type_HasRefs
49
    };
50

51
    enum WidthType {
52
        wtype_Bits = 0,     // width indicates how many bits every element occupies
53
        wtype_Multiply = 1, // width indicates how many bytes every element occupies
54
        wtype_Ignore = 2,   // each element is 1 byte
55
    };
56

57
    static const int header_size = 8; // Number of bytes used by header
58

59
    // The encryption layer relies on headers always fitting within a single page.
60
    static_assert(header_size == 8, "Header must always fit in entirely on a page");
61

62
    static char* get_data_from_header(char* header) noexcept
63
    {
1,332,111,741✔
64
        return header + header_size;
1,332,111,741✔
65
    }
1,332,111,741✔
66

67
    static char* get_header_from_data(char* data) noexcept
68
    {
4,294,967,294✔
69
        return data - header_size;
4,294,967,294✔
70
    }
4,294,967,294✔
71

72
    static const char* get_data_from_header(const char* header) noexcept
73
    {
345,303,627✔
74
        return get_data_from_header(const_cast<char*>(header));
345,303,627✔
75
    }
345,303,627✔
76

77
    static bool get_is_inner_bptree_node_from_header(const char* header) noexcept
78
    {
1,097,501,574✔
79
        typedef unsigned char uchar;
1,097,501,574✔
80
        const uchar* h = reinterpret_cast<const uchar*>(header);
1,097,501,574✔
81
        return (int(h[4]) & 0x80) != 0;
1,097,501,574✔
82
    }
1,097,501,574✔
83

84
    static bool get_hasrefs_from_header(const char* header) noexcept
85
    {
873,308,310✔
86
        typedef unsigned char uchar;
873,308,310✔
87
        const uchar* h = reinterpret_cast<const uchar*>(header);
873,308,310✔
88
        return (int(h[4]) & 0x40) != 0;
873,308,310✔
89
    }
873,308,310✔
90

91
    static bool get_context_flag_from_header(const char* header) noexcept
92
    {
779,871,582✔
93
        typedef unsigned char uchar;
779,871,582✔
94
        const uchar* h = reinterpret_cast<const uchar*>(header);
779,871,582✔
95
        return (int(h[4]) & 0x20) != 0;
779,871,582✔
96
    }
779,871,582✔
97

98
    static WidthType get_wtype_from_header(const char* header) noexcept
99
    {
2,064,725,028✔
100
        typedef unsigned char uchar;
2,064,725,028✔
101
        const uchar* h = reinterpret_cast<const uchar*>(header);
2,064,725,028✔
102
        return WidthType((int(h[4]) & 0x18) >> 3);
2,064,725,028✔
103
    }
2,064,725,028✔
104

105
    static uint_least8_t get_width_from_header(const char* header) noexcept
106
    {
4,241,775,931✔
107
        typedef unsigned char uchar;
4,241,775,931✔
108
        const uchar* h = reinterpret_cast<const uchar*>(header);
4,241,775,931✔
109
        return uint_least8_t((1 << (int(h[4]) & 0x07)) >> 1);
4,241,775,931✔
110
    }
4,241,775,931✔
111

112
    static size_t get_size_from_header(const char* header) noexcept
113
    {
2,755,039,479✔
114
        typedef unsigned char uchar;
2,755,039,479✔
115
        const uchar* h = reinterpret_cast<const uchar*>(header);
2,755,039,479✔
116
        return (size_t(h[5]) << 16) + (size_t(h[6]) << 8) + h[7];
2,755,039,479✔
117
    }
2,755,039,479✔
118

119
    static size_t get_capacity_from_header(const char* header) noexcept
120
    {
943,396,740✔
121
        typedef unsigned char uchar;
943,396,740✔
122
        const uchar* h = reinterpret_cast<const uchar*>(header);
943,396,740✔
123
        return (size_t(h[0]) << 19) + (size_t(h[1]) << 11) + (h[2] << 3);
943,396,740✔
124
    }
943,396,740✔
125

126
    static Type get_type_from_header(const char* header) noexcept
UNCOV
127
    {
×
UNCOV
128
        if (get_is_inner_bptree_node_from_header(header))
×
UNCOV
129
            return type_InnerBptreeNode;
×
UNCOV
130
        if (get_hasrefs_from_header(header))
×
UNCOV
131
            return type_HasRefs;
×
UNCOV
132
        return type_Normal;
×
UNCOV
133
    }
×
134

135
    static void set_is_inner_bptree_node_in_header(bool value, char* header) noexcept
136
    {
17,584,947✔
137
        typedef unsigned char uchar;
17,584,947✔
138
        uchar* h = reinterpret_cast<uchar*>(header);
17,584,947✔
139
        h[4] = uchar((int(h[4]) & ~0x80) | int(value) << 7);
17,584,947✔
140
    }
17,584,947✔
141

142
    static void set_hasrefs_in_header(bool value, char* header) noexcept
143
    {
17,585,778✔
144
        typedef unsigned char uchar;
17,585,778✔
145
        uchar* h = reinterpret_cast<uchar*>(header);
17,585,778✔
146
        h[4] = uchar((int(h[4]) & ~0x40) | int(value) << 6);
17,585,778✔
147
    }
17,585,778✔
148

149
    static void set_context_flag_in_header(bool value, char* header) noexcept
150
    {
18,289,482✔
151
        typedef unsigned char uchar;
18,289,482✔
152
        uchar* h = reinterpret_cast<uchar*>(header);
18,289,482✔
153
        h[4] = uchar((int(h[4]) & ~0x20) | int(value) << 5);
18,289,482✔
154
    }
18,289,482✔
155

156
    static void set_wtype_in_header(WidthType value, char* header) noexcept
157
    {
17,581,308✔
158
        // Indicates how to calculate size in bytes based on width
159
        // 0: bits      (width/8) * size
160
        // 1: multiply  width * size
161
        // 2: ignore    1 * size
162
        typedef unsigned char uchar;
17,581,308✔
163
        uchar* h = reinterpret_cast<uchar*>(header);
17,581,308✔
164
        h[4] = uchar((int(h[4]) & ~0x18) | int(value) << 3);
17,581,308✔
165
    }
17,581,308✔
166

167
    static void set_width_in_header(int value, char* header) noexcept
168
    {
43,591,140✔
169
        // Pack width in 3 bits (log2)
170
        int w = 0;
43,591,140✔
171
        while (value) {
153,815,283✔
172
            ++w;
110,224,143✔
173
            value >>= 1;
110,224,143✔
174
        }
110,224,143✔
175
        REALM_ASSERT_3(w, <, 8);
43,591,140✔
176

177
        typedef unsigned char uchar;
43,591,140✔
178
        uchar* h = reinterpret_cast<uchar*>(header);
43,591,140✔
179
        h[4] = uchar((int(h[4]) & ~0x7) | w);
43,591,140✔
180
    }
43,591,140✔
181

182
    static void set_size_in_header(size_t value, char* header) noexcept
183
    {
956,072,073✔
184
        REALM_ASSERT_3(value, <=, max_array_size);
956,072,073✔
185
        typedef unsigned char uchar;
956,072,073✔
186
        uchar* h = reinterpret_cast<uchar*>(header);
956,072,073✔
187
        h[5] = uchar((value >> 16) & 0x000000FF);
956,072,073✔
188
        h[6] = uchar((value >> 8) & 0x000000FF);
956,072,073✔
189
        h[7] = uchar(value & 0x000000FF);
956,072,073✔
190
    }
956,072,073✔
191

192
    // Note: There is a copy of this function is test_alloc.cpp
193
    static void set_capacity_in_header(size_t value, char* header) noexcept
194
    {
36,862,857✔
195
        REALM_ASSERT_3(value, <=, (0xffffff << 3));
36,862,857✔
196
        typedef unsigned char uchar;
36,862,857✔
197
        uchar* h = reinterpret_cast<uchar*>(header);
36,862,857✔
198
        h[0] = uchar((value >> 19) & 0x000000FF);
36,862,857✔
199
        h[1] = uchar((value >> 11) & 0x000000FF);
36,862,857✔
200
        h[2] = uchar(value >> 3 & 0x000000FF);
36,862,857✔
201
    }
36,862,857✔
202

203
    static size_t get_byte_size_from_header(const char* header) noexcept
204
    {
1,205,036,598✔
205
        size_t size = get_size_from_header(header);
1,205,036,598✔
206
        uint_least8_t width = get_width_from_header(header);
1,205,036,598✔
207
        WidthType wtype = get_wtype_from_header(header);
1,205,036,598✔
208
        size_t num_bytes = calc_byte_size(wtype, size, width);
1,205,036,598✔
209
        return num_bytes;
1,205,036,598✔
210
    }
1,205,036,598✔
211

212
    static size_t calc_byte_size(WidthType wtype, size_t size, uint_least8_t width) noexcept
213
    {
1,273,874,073✔
214
        size_t num_bytes = 0;
1,273,874,073✔
215
        switch (wtype) {
1,273,874,073✔
216
            case wtype_Bits: {
987,292,968✔
217
                // Current assumption is that size is at most 2^24 and that width is at most 64.
218
                // In that case the following will never overflow. (Assuming that size_t is at least 32 bits)
219
                REALM_ASSERT_3(size, <, 0x1000000);
987,292,968✔
220
                size_t num_bits = size * width;
987,292,968✔
221
                num_bytes = (num_bits + 7) >> 3;
987,292,968✔
222
                break;
987,292,968✔
UNCOV
223
            }
×
224
            case wtype_Multiply: {
32,189,388✔
225
                num_bytes = size * width;
32,189,388✔
226
                break;
32,189,388✔
UNCOV
227
            }
×
228
            case wtype_Ignore:
325,923,669✔
229
                num_bytes = size;
325,923,669✔
230
                break;
325,923,669✔
231
        }
1,273,874,073✔
232

233
        // Ensure 8-byte alignment
234
        num_bytes = (num_bytes + 7) & ~size_t(7);
1,284,591,204✔
235

236
        num_bytes += header_size;
1,284,591,204✔
237

238
        return num_bytes;
1,284,591,204✔
239
    }
1,273,874,073✔
240
};
241
} // namespace realm
242

243
#endif /* REALM_NODE_HEADER_HPP */
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

© 2026 Coveralls, Inc