• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, typename Data = uint8_t *,
31          typename SizeT = uoffset_t>
32 struct VectorIterator {
33   typedef std::random_access_iterator_tag iterator_category;
34   typedef IT value_type;
35   typedef ptrdiff_t difference_type;
36   typedef IT *pointer;
37   typedef IT &reference;
38 
39   static const SizeT element_stride = IndirectHelper<T>::element_stride;
40 
VectorIteratorVectorIterator41   VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
VectorIteratorVectorIterator42   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIteratorVectorIterator43   VectorIterator() : data_(nullptr) {}
44 
45   VectorIterator &operator=(const VectorIterator &other) {
46     data_ = other.data_;
47     return *this;
48   }
49 
50   VectorIterator &operator=(VectorIterator &&other) {
51     data_ = other.data_;
52     return *this;
53   }
54 
55   bool operator==(const VectorIterator &other) const {
56     return data_ == other.data_;
57   }
58 
59   bool operator<(const VectorIterator &other) const {
60     return data_ < other.data_;
61   }
62 
63   bool operator!=(const VectorIterator &other) const {
64     return data_ != other.data_;
65   }
66 
67   difference_type operator-(const VectorIterator &other) const {
68     return (data_ - other.data_) / element_stride;
69   }
70 
71   // Note: return type is incompatible with the standard
72   // `reference operator*()`.
73   IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
74 
75   // Note: return type is incompatible with the standard
76   // `pointer operator->()`.
77   IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
78 
79   VectorIterator &operator++() {
80     data_ += element_stride;
81     return *this;
82   }
83 
84   VectorIterator operator++(int) {
85     VectorIterator temp(data_, 0);
86     data_ += element_stride;
87     return temp;
88   }
89 
90   VectorIterator operator+(const SizeT &offset) const {
91     return VectorIterator(data_ + offset * element_stride, 0);
92   }
93 
94   VectorIterator &operator+=(const SizeT &offset) {
95     data_ += offset * element_stride;
96     return *this;
97   }
98 
99   VectorIterator &operator--() {
100     data_ -= element_stride;
101     return *this;
102   }
103 
104   VectorIterator operator--(int) {
105     VectorIterator temp(data_, 0);
106     data_ -= element_stride;
107     return temp;
108   }
109 
110   VectorIterator operator-(const SizeT &offset) const {
111     return VectorIterator(data_ - offset * element_stride, 0);
112   }
113 
114   VectorIterator &operator-=(const SizeT &offset) {
115     data_ -= offset * element_stride;
116     return *this;
117   }
118 
119  private:
120   Data data_;
121 };
122 
123 template<typename T, typename IT, typename SizeT = uoffset_t>
124 using VectorConstIterator = VectorIterator<T, IT, const uint8_t *, SizeT>;
125 
126 template<typename Iterator>
127 struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
VectorReverseIteratorVectorReverseIterator128   explicit VectorReverseIterator(Iterator iter)
129       : std::reverse_iterator<Iterator>(iter) {}
130 
131   // Note: return type is incompatible with the standard
132   // `reference operator*()`.
133   typename Iterator::value_type operator*() const {
134     auto tmp = std::reverse_iterator<Iterator>::current;
135     return *--tmp;
136   }
137 
138   // Note: return type is incompatible with the standard
139   // `pointer operator->()`.
140   typename Iterator::value_type operator->() const {
141     auto tmp = std::reverse_iterator<Iterator>::current;
142     return *--tmp;
143   }
144 };
145 
146 // This is used as a helper type for accessing vectors.
147 // Vector::data() assumes the vector elements start after the length field.
148 template<typename T, typename SizeT = uoffset_t> class Vector {
149  public:
150   typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type,
151                          uint8_t *, SizeT>
152       iterator;
153   typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type, SizeT>
154       const_iterator;
155   typedef VectorReverseIterator<iterator> reverse_iterator;
156   typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
157 
158   typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
159       scalar_tag;
160 
161   static FLATBUFFERS_CONSTEXPR bool is_span_observable =
162       scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
163 
size()164   SizeT size() const { return EndianScalar(length_); }
165 
166   // Deprecated: use size(). Here for backwards compatibility.
FLATBUFFERS_ATTRIBUTE()167   FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
168   SizeT Length() const { return size(); }
169 
170   typedef SizeT size_type;
171   typedef typename IndirectHelper<T>::return_type return_type;
172   typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
173   typedef return_type value_type;
174 
Get(SizeT i)175   return_type Get(SizeT i) const {
176     FLATBUFFERS_ASSERT(i < size());
177     return IndirectHelper<T>::Read(Data(), i);
178   }
179 
180   return_type operator[](SizeT i) const { return Get(i); }
181 
182   // If this is a Vector of enums, T will be its storage type, not the enum
183   // type. This function makes it convenient to retrieve value with enum
184   // type E.
GetEnum(SizeT i)185   template<typename E> E GetEnum(SizeT i) const {
186     return static_cast<E>(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 the right type!
GetAs(SizeT i)191   template<typename U> const U *GetAs(SizeT i) const {
192     return reinterpret_cast<const U *>(Get(i));
193   }
194 
195   // If this a vector of unions, this does the cast for you. There's no check
196   // to make sure this is actually a string!
GetAsString(SizeT i)197   const String *GetAsString(SizeT i) const {
198     return reinterpret_cast<const String *>(Get(i));
199   }
200 
GetStructFromOffset(size_t o)201   const void *GetStructFromOffset(size_t o) const {
202     return reinterpret_cast<const void *>(Data() + o);
203   }
204 
begin()205   iterator begin() { return iterator(Data(), 0); }
begin()206   const_iterator begin() const { return const_iterator(Data(), 0); }
207 
end()208   iterator end() { return iterator(Data(), size()); }
end()209   const_iterator end() const { return const_iterator(Data(), size()); }
210 
rbegin()211   reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin()212   const_reverse_iterator rbegin() const {
213     return const_reverse_iterator(end());
214   }
215 
rend()216   reverse_iterator rend() { return reverse_iterator(begin()); }
rend()217   const_reverse_iterator rend() const {
218     return const_reverse_iterator(begin());
219   }
220 
cbegin()221   const_iterator cbegin() const { return begin(); }
222 
cend()223   const_iterator cend() const { return end(); }
224 
crbegin()225   const_reverse_iterator crbegin() const { return rbegin(); }
226 
crend()227   const_reverse_iterator crend() const { return rend(); }
228 
229   // Change elements if you have a non-const pointer to this object.
230   // Scalars only. See reflection.h, and the documentation.
Mutate(SizeT i,const T & val)231   void Mutate(SizeT i, const T &val) {
232     FLATBUFFERS_ASSERT(i < size());
233     WriteScalar(data() + i, val);
234   }
235 
236   // Change an element of a vector of tables (or strings).
237   // "val" points to the new table/string, as you can obtain from
238   // e.g. reflection::AddFlatBuffer().
MutateOffset(SizeT i,const uint8_t * val)239   void MutateOffset(SizeT i, const uint8_t *val) {
240     FLATBUFFERS_ASSERT(i < size());
241     static_assert(sizeof(T) == sizeof(SizeT), "Unrelated types");
242     WriteScalar(data() + i,
243                 static_cast<SizeT>(val - (Data() + i * sizeof(SizeT))));
244   }
245 
246   // Get a mutable pointer to tables/strings inside this vector.
GetMutableObject(SizeT i)247   mutable_return_type GetMutableObject(SizeT i) const {
248     FLATBUFFERS_ASSERT(i < size());
249     return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
250   }
251 
252   // The raw data in little endian format. Use with care.
Data()253   const uint8_t *Data() const {
254     return reinterpret_cast<const uint8_t *>(&length_ + 1);
255   }
256 
Data()257   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
258 
259   // Similarly, but typed, much like std::vector::data
data()260   const T *data() const { return reinterpret_cast<const T *>(Data()); }
data()261   T *data() { return reinterpret_cast<T *>(Data()); }
262 
LookupByKey(K key)263   template<typename K> return_type LookupByKey(K key) const {
264     void *search_result = std::bsearch(
265         &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
266 
267     if (!search_result) {
268       return nullptr;  // Key not found.
269     }
270 
271     const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
272 
273     return IndirectHelper<T>::Read(element, 0);
274   }
275 
MutableLookupByKey(K key)276   template<typename K> mutable_return_type MutableLookupByKey(K key) {
277     return const_cast<mutable_return_type>(LookupByKey(key));
278   }
279 
280  protected:
281   // This class is only used to access pre-existing data. Don't ever
282   // try to construct these manually.
283   Vector();
284 
285   SizeT length_;
286 
287  private:
288   // This class is a pointer. Copying will therefore create an invalid object.
289   // Private and unimplemented copy constructor.
290   Vector(const Vector &);
291   Vector &operator=(const Vector &);
292 
KeyCompare(const void * ap,const void * bp)293   template<typename K> static int KeyCompare(const void *ap, const void *bp) {
294     const K *key = reinterpret_cast<const K *>(ap);
295     const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
296     auto table = IndirectHelper<T>::Read(data, 0);
297 
298     // std::bsearch compares with the operands transposed, so we negate the
299     // result here.
300     return -table->KeyCompareWithValue(*key);
301   }
302 };
303 
304 template<typename T> using Vector64 = Vector<T, uoffset64_t>;
305 
306 template<class U>
make_span(Vector<U> & vec)307 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
308     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<U>(vec.data(), vec.size());
312 }
313 
314 template<class U>
make_span(const Vector<U> & vec)315 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
316     const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
317   static_assert(Vector<U>::is_span_observable,
318                 "wrong type U, only LE-scalar, or byte types are allowed");
319   return span<const U>(vec.data(), vec.size());
320 }
321 
322 template<class U>
make_bytes_span(Vector<U> & vec)323 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
324     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<uint8_t>(vec.Data(), vec.size() * sizeof(U));
328 }
329 
330 template<class U>
make_bytes_span(const Vector<U> & vec)331 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
332     const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
333   static_assert(Vector<U>::scalar_tag::value,
334                 "wrong type U, only LE-scalar, or byte types are allowed");
335   return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
336 }
337 
338 // Convenient helper functions to get a span of any vector, regardless
339 // of whether it is null or not (the field is not set).
340 template<class U>
make_span(Vector<U> * ptr)341 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr)
342     FLATBUFFERS_NOEXCEPT {
343   static_assert(Vector<U>::is_span_observable,
344                 "wrong type U, only LE-scalar, or byte types are allowed");
345   return ptr ? make_span(*ptr) : span<U>();
346 }
347 
348 template<class U>
make_span(const Vector<U> * ptr)349 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
350     const Vector<U> *ptr) FLATBUFFERS_NOEXCEPT {
351   static_assert(Vector<U>::is_span_observable,
352                 "wrong type U, only LE-scalar, or byte types are allowed");
353   return ptr ? make_span(*ptr) : span<const U>();
354 }
355 
356 // Represent a vector much like the template above, but in this case we
357 // don't know what the element types are (used with reflection.h).
358 class VectorOfAny {
359  public:
size()360   uoffset_t size() const { return EndianScalar(length_); }
361 
Data()362   const uint8_t *Data() const {
363     return reinterpret_cast<const uint8_t *>(&length_ + 1);
364   }
Data()365   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
366 
367  protected:
368   VectorOfAny();
369 
370   uoffset_t length_;
371 
372  private:
373   VectorOfAny(const VectorOfAny &);
374   VectorOfAny &operator=(const VectorOfAny &);
375 };
376 
377 template<typename T, typename U>
VectorCast(Vector<Offset<U>> * ptr)378 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
379   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
380   return reinterpret_cast<Vector<Offset<T>> *>(ptr);
381 }
382 
383 template<typename T, typename U>
VectorCast(const Vector<Offset<U>> * ptr)384 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
385   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
386   return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
387 }
388 
389 // Convenient helper function to get the length of any vector, regardless
390 // of whether it is null or not (the field is not set).
VectorLength(const Vector<T> * v)391 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
392   return v ? v->size() : 0;
393 }
394 
395 }  // namespace flatbuffers
396 
397 #endif  // FLATBUFFERS_VERIFIER_H_
398