1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
19 #ifndef REALM_ARRAY_STRING_LONG_HPP
20 #define REALM_ARRAY_STRING_LONG_HPP
22 #include <realm/array_blob.hpp>
23 #include <realm/array_integer.hpp>
28 class ArrayStringLong : public Array {
30 typedef StringData value_type;
32 explicit ArrayStringLong(Allocator&, bool nullable) noexcept;
33 ~ArrayStringLong() noexcept override
37 // Disable copying, this is not allowed.
38 ArrayStringLong& operator=(const ArrayStringLong&) = delete;
39 ArrayStringLong(const ArrayStringLong&) = delete;
41 /// Create a new empty long string array and attach this accessor to
42 /// it. This does not modify the parent reference information of
45 /// Note that the caller assumes ownership of the allocated
46 /// underlying node. It is not owned by the accessor.
50 /// Overriding functions of Array
51 void init_from_ref(ref_type) noexcept;
52 void init_from_mem(MemRef) noexcept;
53 void init_from_parent() noexcept;
56 bool is_empty() const noexcept;
57 size_t size() const noexcept;
59 StringData get(size_t ndx) const noexcept;
62 void add(StringData value);
63 void set(size_t ndx, StringData value);
64 void insert(size_t ndx, StringData value);
65 void erase(size_t ndx);
66 void truncate(size_t size);
70 bool is_null(size_t ndx) const;
71 void set_null(size_t ndx);
73 size_t count(StringData value, size_t begin = 0, size_t end = npos) const noexcept;
74 size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const noexcept;
75 void find_all(IntegerColumn& result, StringData value, size_t add_offset = 0, size_t begin = 0,
76 size_t end = npos) const;
78 /// Get the specified element without the cost of constructing an
79 /// array instance. If an array instance is already available, or
80 /// you need to get multiple values, then this method will be
82 static StringData get(const char* header, size_t ndx, Allocator&, bool nullable) noexcept;
84 ref_type bptree_leaf_insert(size_t ndx, StringData, TreeInsertBase&);
86 static size_t get_size_from_header(const char*, Allocator&) noexcept;
88 /// Construct a long string array of the specified size and return
89 /// just the reference to the underlying memory. All elements will
90 /// be initialized to zero size blobs.
91 static MemRef create_array(size_t size, Allocator&, bool nullable);
93 /// Construct a copy of the specified slice of this long string
94 /// array using the specified target allocator.
95 MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const;
98 void to_dot(std::ostream&, StringData title = StringData()) const;
101 bool update_from_parent(size_t old_baseline) noexcept;
104 ArrayInteger m_offsets;
112 inline ArrayStringLong::ArrayStringLong(Allocator& allocator, bool nullable) noexcept
114 , m_offsets(allocator)
116 , m_nulls(nullable ? allocator : Allocator::get_default())
117 , m_nullable(nullable)
119 m_offsets.set_parent(this, 0);
120 m_blob.set_parent(this, 1);
122 m_nulls.set_parent(this, 2);
125 inline void ArrayStringLong::create()
127 size_t init_size = 0;
128 MemRef mem = create_array(init_size, get_alloc(), m_nullable); // Throws
132 inline void ArrayStringLong::init_from_ref(ref_type ref) noexcept
135 char* header = get_alloc().translate(ref);
136 init_from_mem(MemRef(header, ref, m_alloc));
137 m_nullable = (Array::size() == 3);
140 inline void ArrayStringLong::init_from_parent() noexcept
142 ref_type ref = get_ref_from_parent();
146 inline bool ArrayStringLong::is_empty() const noexcept
148 return m_offsets.is_empty();
151 inline size_t ArrayStringLong::size() const noexcept
153 return m_offsets.size();
156 inline StringData ArrayStringLong::get(size_t ndx) const noexcept
158 REALM_ASSERT_3(ndx, <, m_offsets.size());
160 if (m_nullable && m_nulls.get(ndx) == 0)
161 return realm::null();
165 begin = to_size_t(m_offsets.get(ndx - 1));
166 end = to_size_t(m_offsets.get(ndx));
170 end = to_size_t(m_offsets.get(0));
172 --end; // Discount the terminating zero
174 return StringData(m_blob.get(begin), end - begin);
177 inline void ArrayStringLong::truncate(size_t new_size)
179 REALM_ASSERT_3(new_size, <, m_offsets.size());
181 size_t blob_size = new_size ? to_size_t(m_offsets.get(new_size - 1)) : 0;
183 m_offsets.truncate(new_size);
184 m_blob.truncate(blob_size);
186 m_nulls.truncate(new_size);
189 inline void ArrayStringLong::clear()
197 inline void ArrayStringLong::destroy()
206 inline bool ArrayStringLong::update_from_parent(size_t old_baseline) noexcept
208 bool res = Array::update_from_parent(old_baseline);
210 m_blob.update_from_parent(old_baseline);
211 m_offsets.update_from_parent(old_baseline);
213 m_nulls.update_from_parent(old_baseline);
218 inline size_t ArrayStringLong::get_size_from_header(const char* header, Allocator& alloc) noexcept
220 ref_type offsets_ref = to_ref(Array::get(header, 0));
221 const char* offsets_header = alloc.translate(offsets_ref);
222 return Array::get_size_from_header(offsets_header);
228 #endif // REALM_ARRAY_STRING_LONG_HPP