github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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, 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  
    41    VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
    42    VectorIterator(const VectorIterator &other) : data_(other.data_) {}
    43    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> {
   128    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  
   164    SizeT size() const { return EndianScalar(length_); }
   165  
   166    // Deprecated: use size(). Here for backwards compatibility.
   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  
   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.
   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!
   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!
   197    const String *GetAsString(SizeT i) const {
   198      return reinterpret_cast<const String *>(Get(i));
   199    }
   200  
   201    const void *GetStructFromOffset(size_t o) const {
   202      return reinterpret_cast<const void *>(Data() + o);
   203    }
   204  
   205    iterator begin() { return iterator(Data(), 0); }
   206    const_iterator begin() const { return const_iterator(Data(), 0); }
   207  
   208    iterator end() { return iterator(Data(), size()); }
   209    const_iterator end() const { return const_iterator(Data(), size()); }
   210  
   211    reverse_iterator rbegin() { return reverse_iterator(end()); }
   212    const_reverse_iterator rbegin() const {
   213      return const_reverse_iterator(end());
   214    }
   215  
   216    reverse_iterator rend() { return reverse_iterator(begin()); }
   217    const_reverse_iterator rend() const {
   218      return const_reverse_iterator(begin());
   219    }
   220  
   221    const_iterator cbegin() const { return begin(); }
   222  
   223    const_iterator cend() const { return end(); }
   224  
   225    const_reverse_iterator crbegin() const { return rbegin(); }
   226  
   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.
   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().
   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.
   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.
   253    const uint8_t *Data() const {
   254      return reinterpret_cast<const uint8_t *>(&length_ + 1);
   255    }
   256  
   257    uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
   258  
   259    // Similarly, but typed, much like std::vector::data
   260    const T *data() const { return reinterpret_cast<const T *>(Data()); }
   261    T *data() { return reinterpret_cast<T *>(Data()); }
   262  
   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  
   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  
   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>
   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>
   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>
   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>
   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>
   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>
   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:
   360    uoffset_t size() const { return EndianScalar(length_); }
   361  
   362    const uint8_t *Data() const {
   363      return reinterpret_cast<const uint8_t *>(&length_ + 1);
   364    }
   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>
   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>
   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).
   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_