• 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

69.39
/src/realm/array_string_short.hpp
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
#ifndef REALM_ARRAY_STRING_SHORT_HPP
20
#define REALM_ARRAY_STRING_SHORT_HPP
21

22
#include <realm/array.hpp>
23
#include <realm/string_data.hpp>
24

25
namespace realm {
26

27
/*
28
ArrayStringShort stores strings as a concecutive list of fixed-length blocks of m_width bytes. The
29
longest string it can store is (m_width - 1) bytes before it needs to expand.
30

31
An example of the format for m_width = 4 is following sequence of bytes, where x is payload:
32

33
xxx0 xx01 x002 0003 0004 (strings "xxx",. "xx", "x", "", realm::null())
34

35
So each string is 0 terminated, and the last byte in a block tells how many 0s are present, except
36
for a realm::null() which has the byte set to m_width (4). The byte is used to compute the length of a string
37
in various functions.
38

39
New: If m_witdh = 0, then all elements are realm::null(). So to add an empty string we must expand m_width
40
New: StringData is null() if-and-only-if StringData::data() == 0.
41
*/
42

43
class ArrayStringShort : public Array {
44
public:
45
    static const size_t max_width = 64;
46

47
    typedef StringData value_type;
48
    // Constructor defaults to non-nullable because we use non-nullable ArrayStringShort so many places internally
49
    // in core (data which isn't user payload) where null isn't needed.
50
    explicit ArrayStringShort(Allocator&, bool nullable = false) noexcept;
51
    ~ArrayStringShort() noexcept override {}
1,889,343✔
52

53
    bool is_null(size_t ndx) const;
54
    void set_null(size_t ndx);
55
    StringData get(size_t ndx) const noexcept;
56
    void add();
57
    void add(StringData value);
58
    void set(size_t ndx, StringData value);
59
    void insert(size_t ndx, StringData value);
60
    void erase(size_t ndx);
61

62
    size_t count(StringData value, size_t begin = 0, size_t end = npos) const noexcept;
63
    size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const noexcept;
64
    void find_all(IntegerColumn& result, StringData value, size_t add_offset = 0, size_t begin = 0,
65
                  size_t end = npos);
66

67
    /// Compare two string arrays for equality.
68
    bool compare_string(const ArrayStringShort&) const noexcept;
69

70
    /// Get the specified element without the cost of constructing an
71
    /// array instance. If an array instance is already available, or
72
    /// you need to get multiple values, then this method will be
73
    /// slower.
74
    static StringData get(const char* header, size_t ndx, bool nullable) noexcept;
75

76
    /// Construct a string array of the specified size and return just
77
    /// the reference to the underlying memory. All elements will be
78
    /// initialized to the empty string.
79
    static MemRef create_array(size_t size, Allocator&);
80

81
    /// Create a new empty string array and attach this accessor to
82
    /// it. This does not modify the parent reference information of
83
    /// this accessor.
84
    ///
85
    /// Note that the caller assumes ownership of the allocated
86
    /// underlying node. It is not owned by the accessor.
87
    void create();
88

89
#ifdef REALM_DEBUG
90
    void string_stats() const;
91
#endif
92

93
private:
94
    size_t calc_byte_len(size_t num_items, size_t width) const override;
95
    size_t calc_item_count(size_t bytes, size_t width) const noexcept override;
96

97
    bool m_nullable;
98
};
99

100

101
// Implementation:
102

103
// Creates new array (but invalid, call init_from_ref() to init)
104
inline ArrayStringShort::ArrayStringShort(Allocator& allocator, bool nullable) noexcept
105
    : Array(allocator)
73,587,555✔
106
    , m_nullable(nullable)
73,587,555✔
107
{
146,935,164✔
108
}
146,935,164✔
109

110
inline void ArrayStringShort::create()
111
{
332,250✔
112
    size_t init_size = 0;
332,250✔
113
    MemRef mem = create_array(init_size, get_alloc()); // Throws
332,250✔
114
    init_from_mem(mem);
332,250✔
115
}
332,250✔
116

117
inline MemRef ArrayStringShort::create_array(size_t init_size, Allocator& allocator)
118
{
615,180✔
119
    bool context_flag = false;
615,180✔
120
    int_fast64_t value = 0;
615,180✔
121
    return Array::create(type_Normal, context_flag, wtype_Multiply, init_size, value, allocator); // Throws
615,180✔
122
}
615,180✔
123

124
inline StringData ArrayStringShort::get(size_t ndx) const noexcept
125
{
75,645,471✔
126
    REALM_ASSERT_3(ndx, <, m_size);
75,645,471✔
127
    if (m_width == 0)
75,645,471✔
128
        return m_nullable ? realm::null() : StringData("");
30,111✔
129

130
    const char* data = m_data + (ndx * m_width);
75,615,360✔
131
    size_t array_size = (m_width - 1) - data[m_width - 1];
75,615,360✔
132

133
    if (array_size == static_cast<size_t>(-1))
75,615,360✔
134
        return m_nullable ? realm::null() : StringData("");
628,122✔
135

136
    REALM_ASSERT_EX(data[array_size] == 0, data[array_size],
74,987,238✔
137
                    array_size); // Realm guarantees 0 terminated return strings
74,987,238✔
138
    return StringData(data, array_size);
74,987,238✔
139
}
75,615,360✔
140

141
inline void ArrayStringShort::add(StringData value)
142
{
366,300✔
143
    REALM_ASSERT(!(!m_nullable && value.is_null()));
366,300✔
144
    insert(m_size, value); // Throws
366,300✔
145
}
366,300✔
146

147
inline void ArrayStringShort::add()
148
{
2✔
149
    add(m_nullable ? realm::null() : StringData("")); // Throws
2✔
150
}
2✔
151

152
inline StringData ArrayStringShort::get(const char* header, size_t ndx, bool nullable) noexcept
UNCOV
153
{
×
UNCOV
154
    REALM_ASSERT(ndx < get_size_from_header(header));
×
UNCOV
155
    uint_least8_t width = get_width_from_header(header);
×
UNCOV
156
    const char* data = get_data_from_header(header) + (ndx * width);
×
UNCOV
157

×
UNCOV
158
    if (width == 0)
×
UNCOV
159
        return nullable ? realm::null() : StringData("");
×
UNCOV
160

×
UNCOV
161
    size_t size = (width - 1) - data[width - 1];
×
UNCOV
162

×
UNCOV
163
    if (size == static_cast<size_t>(-1))
×
UNCOV
164
        return nullable ? realm::null() : StringData("");
×
UNCOV
165

×
UNCOV
166
    return StringData(data, size);
×
UNCOV
167
}
×
168

169

170
} // namespace realm
171

172
#endif // REALM_ARRAY_STRING_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