github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/_include/flatbuffers/vector.h (about)

     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    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    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.
   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    const uint8_t *Data() const {
   248      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    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  // 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>
   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>
   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:
   352    uoffset_t size() const { return EndianScalar(length_); }
   353  
   354    const uint8_t *Data() const {
   355      return reinterpret_cast<const uint8_t *>(&length_ + 1);
   356    }
   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>
   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>
   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).
   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_