Line data Source code
1 : /*
2 : * Copyright 2021 Google Inc. All rights reserved.
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : #ifndef FLATBUFFERS_VECTOR_H_
18 : #define FLATBUFFERS_VECTOR_H_
19 :
20 : #include "flatbuffers/base.h"
21 : #include "flatbuffers/buffer.h"
22 : #include "flatbuffers/stl_emulation.h"
23 :
24 : namespace flatbuffers {
25 :
26 : struct String;
27 :
28 : // An STL compatible iterator implementation for Vector below, effectively
29 : // calling Get() for every element.
30 : template<typename T, typename IT> struct VectorIterator {
31 : typedef std::random_access_iterator_tag iterator_category;
32 : typedef IT value_type;
33 : typedef ptrdiff_t difference_type;
34 : typedef IT *pointer;
35 : typedef IT &reference;
36 :
37 : VectorIterator(const uint8_t *data, uoffset_t i)
38 : : data_(data + IndirectHelper<T>::element_stride * i) {}
39 : VectorIterator(const VectorIterator &other) : data_(other.data_) {}
40 : VectorIterator() : data_(nullptr) {}
41 :
42 : VectorIterator &operator=(const VectorIterator &other) {
43 : data_ = other.data_;
44 : return *this;
45 : }
46 :
47 : VectorIterator &operator=(VectorIterator &&other) {
48 : data_ = other.data_;
49 : return *this;
50 : }
51 :
52 : bool operator==(const VectorIterator &other) const {
53 : return data_ == other.data_;
54 : }
55 :
56 : bool operator<(const VectorIterator &other) const {
57 : return data_ < other.data_;
58 : }
59 :
60 : bool operator!=(const VectorIterator &other) const {
61 : return data_ != other.data_;
62 : }
63 :
64 : difference_type operator-(const VectorIterator &other) const {
65 : return (data_ - other.data_) / IndirectHelper<T>::element_stride;
66 : }
67 :
68 : // Note: return type is incompatible with the standard
69 : // `reference operator*()`.
70 : IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
71 :
72 : // Note: return type is incompatible with the standard
73 : // `pointer operator->()`.
74 : IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
75 :
76 : VectorIterator &operator++() {
77 : data_ += IndirectHelper<T>::element_stride;
78 : return *this;
79 : }
80 :
81 : VectorIterator operator++(int) {
82 : VectorIterator temp(data_, 0);
83 : data_ += IndirectHelper<T>::element_stride;
84 : return temp;
85 : }
86 :
87 : VectorIterator operator+(const uoffset_t &offset) const {
88 : return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
89 : 0);
90 : }
91 :
92 : VectorIterator &operator+=(const uoffset_t &offset) {
93 : data_ += offset * IndirectHelper<T>::element_stride;
94 : return *this;
95 : }
96 :
97 : VectorIterator &operator--() {
98 : data_ -= IndirectHelper<T>::element_stride;
99 : return *this;
100 : }
101 :
102 : VectorIterator operator--(int) {
103 : VectorIterator temp(data_, 0);
104 : data_ -= IndirectHelper<T>::element_stride;
105 : return temp;
106 : }
107 :
108 : VectorIterator operator-(const uoffset_t &offset) const {
109 : return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
110 : 0);
111 : }
112 :
113 : VectorIterator &operator-=(const uoffset_t &offset) {
114 : data_ -= offset * IndirectHelper<T>::element_stride;
115 : return *this;
116 : }
117 :
118 : private:
119 : const uint8_t *data_;
120 : };
121 :
122 : template<typename Iterator>
123 : struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
124 : explicit VectorReverseIterator(Iterator iter)
125 : : std::reverse_iterator<Iterator>(iter) {}
126 :
127 : // Note: return type is incompatible with the standard
128 : // `reference operator*()`.
129 : typename Iterator::value_type operator*() const {
130 : auto tmp = std::reverse_iterator<Iterator>::current;
131 : return *--tmp;
132 : }
133 :
134 : // Note: return type is incompatible with the standard
135 : // `pointer operator->()`.
136 : typename Iterator::value_type operator->() const {
137 : auto tmp = std::reverse_iterator<Iterator>::current;
138 : return *--tmp;
139 : }
140 : };
141 :
142 : // This is used as a helper type for accessing vectors.
143 : // Vector::data() assumes the vector elements start after the length field.
144 : template<typename T> class Vector {
145 : public:
146 : typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
147 : iterator;
148 : typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
149 : const_iterator;
150 : typedef VectorReverseIterator<iterator> reverse_iterator;
151 : typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
152 :
153 : typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
154 : scalar_tag;
155 :
156 : static FLATBUFFERS_CONSTEXPR bool is_span_observable =
157 : scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
158 :
159 400409 : uoffset_t size() const { return EndianScalar(length_); }
160 :
161 : // Deprecated: use size(). Here for backwards compatibility.
162 : FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
163 : uoffset_t Length() const { return size(); }
164 :
165 : typedef typename IndirectHelper<T>::return_type return_type;
166 : typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
167 : typedef return_type value_type;
168 :
169 199338 : return_type Get(uoffset_t i) const {
170 199338 : FLATBUFFERS_ASSERT(i < size());
171 199338 : return IndirectHelper<T>::Read(Data(), i);
172 : }
173 :
174 528 : return_type operator[](uoffset_t i) const { return Get(i); }
175 :
176 : // If this is a Vector of enums, T will be its storage type, not the enum
177 : // type. This function makes it convenient to retrieve value with enum
178 : // type E.
179 : template<typename E> E GetEnum(uoffset_t i) const {
180 : return static_cast<E>(Get(i));
181 : }
182 :
183 : // If this a vector of unions, this does the cast for you. There's no check
184 : // to make sure this is the right type!
185 : template<typename U> const U *GetAs(uoffset_t i) const {
186 : return reinterpret_cast<const U *>(Get(i));
187 : }
188 :
189 : // If this a vector of unions, this does the cast for you. There's no check
190 : // to make sure this is actually a string!
191 : const String *GetAsString(uoffset_t i) const {
192 : return reinterpret_cast<const String *>(Get(i));
193 : }
194 :
195 : const void *GetStructFromOffset(size_t o) const {
196 : return reinterpret_cast<const void *>(Data() + o);
197 : }
198 :
199 : iterator begin() { return iterator(Data(), 0); }
200 : const_iterator begin() const { return const_iterator(Data(), 0); }
201 :
202 : iterator end() { return iterator(Data(), size()); }
203 : const_iterator end() const { return const_iterator(Data(), size()); }
204 :
205 : reverse_iterator rbegin() { return reverse_iterator(end()); }
206 : const_reverse_iterator rbegin() const {
207 : return const_reverse_iterator(end());
208 : }
209 :
210 : reverse_iterator rend() { return reverse_iterator(begin()); }
211 : const_reverse_iterator rend() const {
212 : return const_reverse_iterator(begin());
213 : }
214 :
215 : const_iterator cbegin() const { return begin(); }
216 :
217 : const_iterator cend() const { return end(); }
218 :
219 : const_reverse_iterator crbegin() const { return rbegin(); }
220 :
221 : const_reverse_iterator crend() const { return rend(); }
222 :
223 : // Change elements if you have a non-const pointer to this object.
224 : // Scalars only. See reflection.h, and the documentation.
225 : void Mutate(uoffset_t i, const T &val) {
226 : FLATBUFFERS_ASSERT(i < size());
227 : WriteScalar(data() + i, val);
228 : }
229 :
230 : // Change an element of a vector of tables (or strings).
231 : // "val" points to the new table/string, as you can obtain from
232 : // e.g. reflection::AddFlatBuffer().
233 : void MutateOffset(uoffset_t i, const uint8_t *val) {
234 : FLATBUFFERS_ASSERT(i < size());
235 : static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
236 : WriteScalar(data() + i,
237 : static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
238 : }
239 :
240 : // Get a mutable pointer to tables/strings inside this vector.
241 : mutable_return_type GetMutableObject(uoffset_t i) const {
242 : FLATBUFFERS_ASSERT(i < size());
243 : return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
244 : }
245 :
246 : // The raw data in little endian format. Use with care.
247 266695 : const uint8_t *Data() const {
248 266695 : return reinterpret_cast<const uint8_t *>(&length_ + 1);
249 : }
250 :
251 : uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
252 :
253 : // Similarly, but typed, much like std::vector::data
254 1513 : const T *data() const { return reinterpret_cast<const T *>(Data()); }
255 : T *data() { return reinterpret_cast<T *>(Data()); }
256 :
257 : template<typename K> return_type LookupByKey(K key) const {
258 : void *search_result = std::bsearch(
259 : &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
260 :
261 : if (!search_result) {
262 : return nullptr; // Key not found.
263 : }
264 :
265 : const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
266 :
267 : return IndirectHelper<T>::Read(element, 0);
268 : }
269 :
270 : template<typename K> mutable_return_type MutableLookupByKey(K key) {
271 : return const_cast<mutable_return_type>(LookupByKey(key));
272 : }
273 :
274 : protected:
275 : // This class is only used to access pre-existing data. Don't ever
276 : // try to construct these manually.
277 : Vector();
278 :
279 : uoffset_t length_;
280 :
281 : private:
282 : // This class is a pointer. Copying will therefore create an invalid object.
283 : // Private and unimplemented copy constructor.
284 : Vector(const Vector &);
285 : Vector &operator=(const Vector &);
286 :
287 : template<typename K> static int KeyCompare(const void *ap, const void *bp) {
288 : const K *key = reinterpret_cast<const K *>(ap);
289 : const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
290 : auto table = IndirectHelper<T>::Read(data, 0);
291 :
292 : // std::bsearch compares with the operands transposed, so we negate the
293 : // result here.
294 : return -table->KeyCompareWithValue(*key);
295 : }
296 : };
297 :
298 : template<class U>
299 : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
300 : FLATBUFFERS_NOEXCEPT {
301 : static_assert(Vector<U>::is_span_observable,
302 : "wrong type U, only LE-scalar, or byte types are allowed");
303 : return span<U>(vec.data(), vec.size());
304 : }
305 :
306 : template<class U>
307 : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
308 : const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
309 : static_assert(Vector<U>::is_span_observable,
310 : "wrong type U, only LE-scalar, or byte types are allowed");
311 : return span<const U>(vec.data(), vec.size());
312 : }
313 :
314 : template<class U>
315 : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
316 : Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
317 : static_assert(Vector<U>::scalar_tag::value,
318 : "wrong type U, only LE-scalar, or byte types are allowed");
319 : return span<uint8_t>(vec.Data(), vec.size() * sizeof(U));
320 : }
321 :
322 : template<class U>
323 : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
324 : const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
325 : static_assert(Vector<U>::scalar_tag::value,
326 : "wrong type U, only LE-scalar, or byte types are allowed");
327 : return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
328 : }
329 :
330 : // Represent a vector much like the template above, but in this case we
331 : // don't know what the element types are (used with reflection.h).
332 : class VectorOfAny {
333 : public:
334 : uoffset_t size() const { return EndianScalar(length_); }
335 :
336 : const uint8_t *Data() const {
337 : return reinterpret_cast<const uint8_t *>(&length_ + 1);
338 : }
339 : uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
340 :
341 : protected:
342 : VectorOfAny();
343 :
344 : uoffset_t length_;
345 :
346 : private:
347 : VectorOfAny(const VectorOfAny &);
348 : VectorOfAny &operator=(const VectorOfAny &);
349 : };
350 :
351 : template<typename T, typename U>
352 : Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
353 : static_assert(std::is_base_of<T, U>::value, "Unrelated types");
354 : return reinterpret_cast<Vector<Offset<T>> *>(ptr);
355 : }
356 :
357 : template<typename T, typename U>
358 : const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
359 : static_assert(std::is_base_of<T, U>::value, "Unrelated types");
360 : return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
361 : }
362 :
363 : // Convenient helper function to get the length of any vector, regardless
364 : // of whether it is null or not (the field is not set).
365 : template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
366 : return v ? v->size() : 0;
367 : }
368 :
369 : } // namespace flatbuffers
370 :
371 : #endif // FLATBUFFERS_VERIFIER_H_
|