/src/gdal/third_party/flatbuffers/array.h
Line | Count | Source |
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 | 0 | FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::size() const Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::size() const |
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 | 0 | const uint8_t *Data() const { return data_; }Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::Data() const Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::Data() const |
94 | | |
95 | 0 | uint8_t *Data() { return data_; }Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::Data() Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::Data() |
96 | | |
97 | | // Similarly, but typed, much like std::vector::data |
98 | 0 | const T *data() const { return reinterpret_cast<const T *>(Data()); }Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::data() const Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::data() const |
99 | 0 | T *data() { return reinterpret_cast<T *>(Data()); }Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::data() Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::data() |
100 | | |
101 | | // Copy data from a span with endian conversion. |
102 | | // If this Array and the span overlap, the behavior is undefined. |
103 | 0 | void CopyFromSpan(flatbuffers::span<const T, length> src) { |
104 | 0 | const auto p1 = reinterpret_cast<const uint8_t *>(src.data()); |
105 | 0 | const auto p2 = Data(); |
106 | 0 | FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && |
107 | 0 | !(p2 >= p1 && p2 < (p1 + length))); |
108 | 0 | (void)p1; |
109 | 0 | (void)p2; |
110 | 0 | CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src); |
111 | 0 | } Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::CopyFromSpan(gdal_flatbuffers::span<unsigned char const, 12ul>) Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::CopyFromSpan(gdal_flatbuffers::span<unsigned char const, 8ul>) |
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 | 0 | flatbuffers::span<const T, length> src) { |
125 | 0 | // Use std::memcpy() instead of std::copy() to avoid performance degradation |
126 | 0 | // due to aliasing if T is char or unsigned char. |
127 | 0 | // The size is known at compile time, so memcpy would be inlined. |
128 | 0 | std::memcpy(data(), src.data(), length * sizeof(T)); |
129 | 0 | } Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>::CopyFromSpanImpl(std::__1::integral_constant<bool, true>, gdal_flatbuffers::span<unsigned char const, 12ul>) Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>::CopyFromSpanImpl(std::__1::integral_constant<bool, true>, gdal_flatbuffers::span<unsigned char const, 8ul>) |
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 | 0 | Array<T, length> &CastToArray(T (&arr)[length]) { |
221 | 0 | return *reinterpret_cast<Array<T, length> *>(arr); |
222 | 0 | } Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12>& gdal_flatbuffers::CastToArray<unsigned char, (unsigned short)12>(unsigned char (&) [(unsigned short)12]) Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8>& gdal_flatbuffers::CastToArray<unsigned char, (unsigned short)8>(unsigned char (&) [(unsigned short)8]) |
223 | | |
224 | | template<typename T, uint16_t length> |
225 | 0 | const Array<T, length> &CastToArray(const T (&arr)[length]) { |
226 | 0 | return *reinterpret_cast<const Array<T, length> *>(arr); |
227 | 0 | } Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)12> const& gdal_flatbuffers::CastToArray<unsigned char, (unsigned short)12>(unsigned char const (&) [(unsigned short)12]) Unexecuted instantiation: gdal_flatbuffers::Array<unsigned char, (unsigned short)8> const& gdal_flatbuffers::CastToArray<unsigned char, (unsigned short)8>(unsigned char const (&) [(unsigned short)8]) |
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_ |