LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/flatgeobuf/flatbuffers - vector.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 8 8 100.0 %
Date: 2024-05-14 23:54:21 Functions: 19 19 100.0 %

          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      400346 :   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      199319 :   return_type Get(uoffset_t i) const {
     170      199319 :     FLATBUFFERS_ASSERT(i < size());
     171      199319 :     return IndirectHelper<T>::Read(Data(), i);
     172             :   }
     173             : 
     174         524 :   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      266658 :   const uint8_t *Data() const {
     248      266658 :     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        1498 :   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_

Generated by: LCOV version 1.14