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_