123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- #ifndef REALM_NODE_HEADER_HPP
- #define REALM_NODE_HEADER_HPP
- #include <realm/util/assert.hpp>
- namespace realm {
- const size_t max_array_size = 0x00ffffffL;
- const size_t max_array_payload_aligned = 0x07ffffc0L;
- class NodeHeader {
- public:
- enum Type {
- type_Normal,
-
-
- type_InnerBptreeNode,
-
-
-
-
-
-
-
- type_HasRefs
- };
- enum WidthType {
- wtype_Bits = 0,
- wtype_Multiply = 1,
- wtype_Ignore = 2,
- };
- static const int header_size = 8;
-
- static_assert(header_size == 8, "Header must always fit in entirely on a page");
- static char* get_data_from_header(char* header) noexcept
- {
- return header + header_size;
- }
- static char* get_header_from_data(char* data) noexcept
- {
- return data - header_size;
- }
- static const char* get_data_from_header(const char* header) noexcept
- {
- return get_data_from_header(const_cast<char*>(header));
- }
- static bool get_is_inner_bptree_node_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return (int(h[4]) & 0x80) != 0;
- }
- static bool get_hasrefs_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return (int(h[4]) & 0x40) != 0;
- }
- static bool get_context_flag_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return (int(h[4]) & 0x20) != 0;
- }
- static WidthType get_wtype_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return WidthType((int(h[4]) & 0x18) >> 3);
- }
- static uint_least8_t get_width_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return uint_least8_t((1 << (int(h[4]) & 0x07)) >> 1);
- }
- static size_t get_size_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return (size_t(h[5]) << 16) + (size_t(h[6]) << 8) + h[7];
- }
- static size_t get_capacity_from_header(const char* header) noexcept
- {
- typedef unsigned char uchar;
- const uchar* h = reinterpret_cast<const uchar*>(header);
- return (size_t(h[0]) << 19) + (size_t(h[1]) << 11) + (h[2] << 3);
- }
- static Type get_type_from_header(const char* header) noexcept
- {
- if (get_is_inner_bptree_node_from_header(header))
- return type_InnerBptreeNode;
- if (get_hasrefs_from_header(header))
- return type_HasRefs;
- return type_Normal;
- }
- static void set_is_inner_bptree_node_in_header(bool value, char* header) noexcept
- {
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[4] = uchar((int(h[4]) & ~0x80) | int(value) << 7);
- }
- static void set_hasrefs_in_header(bool value, char* header) noexcept
- {
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[4] = uchar((int(h[4]) & ~0x40) | int(value) << 6);
- }
- static void set_context_flag_in_header(bool value, char* header) noexcept
- {
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[4] = uchar((int(h[4]) & ~0x20) | int(value) << 5);
- }
- static void set_wtype_in_header(WidthType value, char* header) noexcept
- {
-
-
-
-
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[4] = uchar((int(h[4]) & ~0x18) | int(value) << 3);
- }
- static void set_width_in_header(int value, char* header) noexcept
- {
-
- int w = 0;
- while (value) {
- ++w;
- value >>= 1;
- }
- REALM_ASSERT_3(w, <, 8);
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[4] = uchar((int(h[4]) & ~0x7) | w);
- }
- static void set_size_in_header(size_t value, char* header) noexcept
- {
- REALM_ASSERT_3(value, <=, max_array_size);
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[5] = uchar((value >> 16) & 0x000000FF);
- h[6] = uchar((value >> 8) & 0x000000FF);
- h[7] = uchar(value & 0x000000FF);
- }
-
- static void set_capacity_in_header(size_t value, char* header) noexcept
- {
- REALM_ASSERT_3(value, <=, (0xffffff << 3));
- typedef unsigned char uchar;
- uchar* h = reinterpret_cast<uchar*>(header);
- h[0] = uchar((value >> 19) & 0x000000FF);
- h[1] = uchar((value >> 11) & 0x000000FF);
- h[2] = uchar(value >> 3 & 0x000000FF);
- }
- static size_t get_byte_size_from_header(const char* header) noexcept
- {
- size_t size = get_size_from_header(header);
- uint_least8_t width = get_width_from_header(header);
- WidthType wtype = get_wtype_from_header(header);
- size_t num_bytes = calc_byte_size(wtype, size, width);
- return num_bytes;
- }
- static size_t calc_byte_size(WidthType wtype, size_t size, uint_least8_t width) noexcept
- {
- size_t num_bytes = 0;
- switch (wtype) {
- case wtype_Bits: {
-
-
- REALM_ASSERT_3(size, <, 0x1000000);
- size_t num_bits = size * width;
- num_bytes = (num_bits + 7) >> 3;
- break;
- }
- case wtype_Multiply: {
- num_bytes = size * width;
- break;
- }
- case wtype_Ignore:
- num_bytes = size;
- break;
- }
-
- num_bytes = (num_bytes + 7) & ~size_t(7);
- num_bytes += header_size;
- return num_bytes;
- }
- };
- }
- #endif
|