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_