LCOV - code coverage report
Current view: top level - third_party/flatbuffers - array.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 5 5 100.0 %
Date: 2026-06-19 21:24:00 Functions: 8 8 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_ARRAY_H_
      18             : #define FLATBUFFERS_ARRAY_H_
      19             : 
      20             : #include "flatbuffers/base.h"
      21             : #include "flatbuffers/stl_emulation.h"
      22             : #include "flatbuffers/vector.h"
      23             : 
      24             : namespace flatbuffers {
      25             : 
      26             : // This is used as a helper type for accessing arrays.
      27             : template<typename T, uint16_t length> class Array {
      28             :   // Array<T> can carry only POD data types (scalars or structs).
      29             :   typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
      30             :       scalar_tag;
      31             :   typedef
      32             :       typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
      33             :           IndirectHelperType;
      34             : 
      35             :  public:
      36             :   typedef uint16_t size_type;
      37             :   typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
      38             :   typedef VectorIterator<T, return_type> const_iterator;
      39             :   typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
      40             : 
      41             :   // If T is a LE-scalar or a struct (!scalar_tag::value).
      42             :   static FLATBUFFERS_CONSTEXPR bool is_span_observable =
      43             :       (scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) ||
      44             :       !scalar_tag::value;
      45             : 
      46       21602 :   FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
      47             : 
      48             :   return_type Get(uoffset_t i) const {
      49             :     FLATBUFFERS_ASSERT(i < size());
      50             :     return IndirectHelper<IndirectHelperType>::Read(Data(), i);
      51             :   }
      52             : 
      53             :   return_type operator[](uoffset_t i) const { return Get(i); }
      54             : 
      55             :   // If this is a Vector of enums, T will be its storage type, not the enum
      56             :   // type. This function makes it convenient to retrieve value with enum
      57             :   // type E.
      58             :   template<typename E> E GetEnum(uoffset_t i) const {
      59             :     return static_cast<E>(Get(i));
      60             :   }
      61             : 
      62             :   const_iterator begin() const { return const_iterator(Data(), 0); }
      63             :   const_iterator end() const { return const_iterator(Data(), size()); }
      64             : 
      65             :   const_reverse_iterator rbegin() const {
      66             :     return const_reverse_iterator(end());
      67             :   }
      68             :   const_reverse_iterator rend() const {
      69             :     return const_reverse_iterator(begin());
      70             :   }
      71             : 
      72             :   const_iterator cbegin() const { return begin(); }
      73             :   const_iterator cend() const { return end(); }
      74             : 
      75             :   const_reverse_iterator crbegin() const { return rbegin(); }
      76             :   const_reverse_iterator crend() const { return rend(); }
      77             : 
      78             :   // Get a mutable pointer to elements inside this array.
      79             :   // This method used to mutate arrays of structs followed by a @p Mutate
      80             :   // operation. For primitive types use @p Mutate directly.
      81             :   // @warning Assignments and reads to/from the dereferenced pointer are not
      82             :   //  automatically converted to the correct endianness.
      83             :   typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
      84             :   GetMutablePointer(uoffset_t i) const {
      85             :     FLATBUFFERS_ASSERT(i < size());
      86             :     return const_cast<T *>(&data()[i]);
      87             :   }
      88             : 
      89             :   // Change elements if you have a non-const pointer to this object.
      90             :   void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
      91             : 
      92             :   // The raw data in little endian format. Use with care.
      93       32572 :   const uint8_t *Data() const { return data_; }
      94             : 
      95             :   uint8_t *Data() { return data_; }
      96             : 
      97             :   // Similarly, but typed, much like std::vector::data
      98       32572 :   const T *data() const { return reinterpret_cast<const T *>(Data()); }
      99             :   T *data() { return reinterpret_cast<T *>(Data()); }
     100             : 
     101             :   // Copy data from a span with endian conversion.
     102             :   // If this Array and the span overlap, the behavior is undefined.
     103             :   void CopyFromSpan(flatbuffers::span<const T, length> src) {
     104             :     const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
     105             :     const auto p2 = Data();
     106             :     FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
     107             :                        !(p2 >= p1 && p2 < (p1 + length)));
     108             :     (void)p1;
     109             :     (void)p2;
     110             :     CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
     111             :   }
     112             : 
     113             :  protected:
     114             :   void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) {
     115             :     FLATBUFFERS_ASSERT(i < size());
     116             :     WriteScalar(data() + i, val);
     117             :   }
     118             : 
     119             :   void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) {
     120             :     *(GetMutablePointer(i)) = val;
     121             :   }
     122             : 
     123             :   void CopyFromSpanImpl(flatbuffers::true_type,
     124             :                         flatbuffers::span<const T, length> src) {
     125             :     // Use std::memcpy() instead of std::copy() to avoid performance degradation
     126             :     // due to aliasing if T is char or unsigned char.
     127             :     // The size is known at compile time, so memcpy would be inlined.
     128             :     std::memcpy(data(), src.data(), length * sizeof(T));
     129             :   }
     130             : 
     131             :   // Copy data from flatbuffers::span with endian conversion.
     132             :   void CopyFromSpanImpl(flatbuffers::false_type,
     133             :                         flatbuffers::span<const T, length> src) {
     134             :     for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
     135             :   }
     136             : 
     137             :   // This class is only used to access pre-existing data. Don't ever
     138             :   // try to construct these manually.
     139             :   // 'constexpr' allows us to use 'size()' at compile time.
     140             :   // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
     141             :   //  a constructor.
     142             : #if defined(__cpp_constexpr)
     143             :   constexpr Array();
     144             : #else
     145             :   Array();
     146             : #endif
     147             : 
     148             :   uint8_t data_[length * sizeof(T)];
     149             : 
     150             :  private:
     151             :   // This class is a pointer. Copying will therefore create an invalid object.
     152             :   // Private and unimplemented copy constructor.
     153             :   Array(const Array &);
     154             :   Array &operator=(const Array &);
     155             : };
     156             : 
     157             : // Specialization for Array[struct] with access using Offset<void> pointer.
     158             : // This specialization used by idl_gen_text.cpp.
     159             : template<typename T, uint16_t length> class Array<Offset<T>, length> {
     160             :   static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
     161             : 
     162             :  public:
     163             :   typedef const void *return_type;
     164             : 
     165             :   const uint8_t *Data() const { return data_; }
     166             : 
     167             :   // Make idl_gen_text.cpp::PrintContainer happy.
     168             :   return_type operator[](uoffset_t) const {
     169             :     FLATBUFFERS_ASSERT(false);
     170             :     return nullptr;
     171             :   }
     172             : 
     173             :  private:
     174             :   // This class is only used to access pre-existing data.
     175             :   Array();
     176             :   Array(const Array &);
     177             :   Array &operator=(const Array &);
     178             : 
     179             :   uint8_t data_[1];
     180             : };
     181             : 
     182             : template<class U, uint16_t N>
     183             : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
     184             :     FLATBUFFERS_NOEXCEPT {
     185             :   static_assert(
     186             :       Array<U, N>::is_span_observable,
     187             :       "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
     188             :   return span<U, N>(arr.data(), N);
     189             : }
     190             : 
     191             : template<class U, uint16_t N>
     192             : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
     193             :     const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
     194             :   static_assert(
     195             :       Array<U, N>::is_span_observable,
     196             :       "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
     197             :   return span<const U, N>(arr.data(), N);
     198             : }
     199             : 
     200             : template<class U, uint16_t N>
     201             : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
     202             : make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
     203             :   static_assert(Array<U, N>::is_span_observable,
     204             :                 "internal error, Array<T> might hold only scalars or structs");
     205             :   return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
     206             : }
     207             : 
     208             : template<class U, uint16_t N>
     209             : FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
     210             : make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
     211             :   static_assert(Array<U, N>::is_span_observable,
     212             :                 "internal error, Array<T> might hold only scalars or structs");
     213             :   return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
     214             : }
     215             : 
     216             : // Cast a raw T[length] to a raw flatbuffers::Array<T, length>
     217             : // without endian conversion. Use with care.
     218             : // TODO: move these Cast-methods to `internal` namespace.
     219             : template<typename T, uint16_t length>
     220             : Array<T, length> &CastToArray(T (&arr)[length]) {
     221             :   return *reinterpret_cast<Array<T, length> *>(arr);
     222             : }
     223             : 
     224             : template<typename T, uint16_t length>
     225       36845 : const Array<T, length> &CastToArray(const T (&arr)[length]) {
     226       36845 :   return *reinterpret_cast<const Array<T, length> *>(arr);
     227             : }
     228             : 
     229             : template<typename E, typename T, uint16_t length>
     230             : Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
     231             :   static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
     232             :   return *reinterpret_cast<Array<E, length> *>(arr);
     233             : }
     234             : 
     235             : template<typename E, typename T, uint16_t length>
     236             : const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {
     237             :   static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
     238             :   return *reinterpret_cast<const Array<E, length> *>(arr);
     239             : }
     240             : 
     241             : }  // namespace flatbuffers
     242             : 
     243             : #endif  // FLATBUFFERS_ARRAY_H_

Generated by: LCOV version 1.14