• 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> 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 
VectorIteratorVectorIterator37   VectorIterator(const uint8_t *data, uoffset_t i)
38       : data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIteratorVectorIterator39   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIteratorVectorIterator40   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> {
VectorReverseIteratorVectorReverseIterator124   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 
size()159   uoffset_t size() const { return EndianScalar(length_); }
160 
161   // Deprecated: use size(). Here for backwards compatibility.
FLATBUFFERS_ATTRIBUTE()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 
Get(uoffset_t i)169   return_type Get(uoffset_t i) const {
170     FLATBUFFERS_ASSERT(i < size());
171     return IndirectHelper<T>::Read(Data(), i);
172   }
173 
174   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.
GetEnum(uoffset_t i)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!
GetAs(uoffset_t i)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!
GetAsString(uoffset_t i)191   const String *GetAsString(uoffset_t i) const {
192     return reinterpret_cast<const String *>(Get(i));
193   }
194 
GetStructFromOffset(size_t o)195   const void *GetStructFromOffset(size_t o) const {
196     return reinterpret_cast<const void *>(Data() + o);
197   }
198 
begin()199   iterator begin() { return iterator(Data(), 0); }
begin()200   const_iterator begin() const { return const_iterator(Data(), 0); }
201 
end()202   iterator end() { return iterator(Data(), size()); }
end()203   const_iterator end() const { return const_iterator(Data(), size()); }
204 
rbegin()205   reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin()206   const_reverse_iterator rbegin() const {
207     return const_reverse_iterator(end());
208   }
209 
rend()210   reverse_iterator rend() { return reverse_iterator(begin()); }
rend()211   const_reverse_iterator rend() const {
212     return const_reverse_iterator(begin());
213   }
214 
cbegin()215   const_iterator cbegin() const { return begin(); }
216 
cend()217   const_iterator cend() const { return end(); }
218 
crbegin()219   const_reverse_iterator crbegin() const { return rbegin(); }
220 
crend()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.
Mutate(uoffset_t i,const T & val)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().
MutateOffset(uoffset_t i,const uint8_t * val)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.
GetMutableObject(uoffset_t i)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.
Data()247   const uint8_t *Data() const {
248     return reinterpret_cast<const uint8_t *>(&length_ + 1);
249   }
250 
Data()251   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
252 
253   // Similarly, but typed, much like std::vector::data
data()254   const T *data() const { return reinterpret_cast<const T *>(Data()); }
data()255   T *data() { return reinterpret_cast<T *>(Data()); }
256 
LookupByKey(K key)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 
MutableLookupByKey(K key)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 
KeyCompare(const void * ap,const void * bp)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>
make_span(Vector<U> & vec)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>
make_span(const Vector<U> & vec)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>
make_bytes_span(Vector<U> & vec)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>
make_bytes_span(const Vector<U> & vec)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 // Convenient helper functions to get a span of any vector, regardless
331 // of whether it is null or not (the field is not set).
332 template<class U>
make_span(Vector<U> * ptr)333 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr)
334     FLATBUFFERS_NOEXCEPT {
335   static_assert(Vector<U>::is_span_observable,
336                 "wrong type U, only LE-scalar, or byte types are allowed");
337   return ptr ? make_span(*ptr) : span<U>();
338 }
339 
340 template<class U>
make_span(const Vector<U> * ptr)341 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
342     const Vector<U> *ptr) 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<const U>();
346 }
347 
348 // Represent a vector much like the template above, but in this case we
349 // don't know what the element types are (used with reflection.h).
350 class VectorOfAny {
351  public:
size()352   uoffset_t size() const { return EndianScalar(length_); }
353 
Data()354   const uint8_t *Data() const {
355     return reinterpret_cast<const uint8_t *>(&length_ + 1);
356   }
Data()357   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
358 
359  protected:
360   VectorOfAny();
361 
362   uoffset_t length_;
363 
364  private:
365   VectorOfAny(const VectorOfAny &);
366   VectorOfAny &operator=(const VectorOfAny &);
367 };
368 
369 template<typename T, typename U>
VectorCast(Vector<Offset<U>> * ptr)370 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
371   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
372   return reinterpret_cast<Vector<Offset<T>> *>(ptr);
373 }
374 
375 template<typename T, typename U>
VectorCast(const Vector<Offset<U>> * ptr)376 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
377   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
378   return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
379 }
380 
381 // Convenient helper function to get the length of any vector, regardless
382 // of whether it is null or not (the field is not set).
VectorLength(const Vector<T> * v)383 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
384   return v ? v->size() : 0;
385 }
386 
387 }  // namespace flatbuffers
388 
389 #endif  // FLATBUFFERS_VERIFIER_H_
390