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_BUFFER_H_ 18 : #define FLATBUFFERS_BUFFER_H_ 19 : 20 : #include "flatbuffers/base.h" 21 : 22 : namespace flatbuffers { 23 : 24 : // Wrapper for uoffset_t to allow safe template specialization. 25 : // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). 26 : template<typename T> struct Offset { 27 : uoffset_t o; 28 : Offset() : o(0) {} 29 662814 : Offset(uoffset_t _o) : o(_o) {} 30 : Offset<void> Union() const { return Offset<void>(o); } 31 530584 : bool IsNull() const { return !o; } 32 : }; 33 : 34 1412 : inline void EndianCheck() { 35 1412 : int endiantest = 1; 36 : // If this fails, see FLATBUFFERS_LITTLEENDIAN above. 37 1412 : FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) == 38 : FLATBUFFERS_LITTLEENDIAN); 39 : (void)endiantest; 40 1412 : } 41 : 42 559 : template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() { 43 : // clang-format off 44 : #ifdef _MSC_VER 45 : return __alignof(T); 46 : #else 47 : #ifndef alignof 48 559 : return __alignof__(T); 49 : #else 50 : return alignof(T); 51 : #endif 52 : #endif 53 : // clang-format on 54 : } 55 : 56 : // Lexicographically compare two strings (possibly containing nulls), and 57 : // return true if the first is less than the second. 58 : static inline bool StringLessThan(const char *a_data, uoffset_t a_size, 59 : const char *b_data, uoffset_t b_size) { 60 : const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); 61 : return cmp == 0 ? a_size < b_size : cmp < 0; 62 : } 63 : 64 : // When we read serialized data from memory, in the case of most scalars, 65 : // we want to just read T, but in the case of Offset, we want to actually 66 : // perform the indirection and return a pointer. 67 : // The template specialization below does just that. 68 : // It is wrapped in a struct since function templates can't overload on the 69 : // return type like this. 70 : // The typedef is for the convenience of callers of this function 71 : // (avoiding the need for a trailing return decltype) 72 : template<typename T> struct IndirectHelper { 73 : typedef T return_type; 74 : typedef T mutable_return_type; 75 : static const size_t element_stride = sizeof(T); 76 586 : static return_type Read(const uint8_t *p, uoffset_t i) { 77 586 : return EndianScalar((reinterpret_cast<const T *>(p))[i]); 78 : } 79 : }; 80 : template<typename T> struct IndirectHelper<Offset<T>> { 81 : typedef const T *return_type; 82 : typedef T *mutable_return_type; 83 : static const size_t element_stride = sizeof(uoffset_t); 84 198752 : static return_type Read(const uint8_t *p, uoffset_t i) { 85 198752 : p += i * sizeof(uoffset_t); 86 198752 : return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p)); 87 : } 88 : }; 89 : template<typename T> struct IndirectHelper<const T *> { 90 : typedef const T *return_type; 91 : typedef T *mutable_return_type; 92 : static const size_t element_stride = sizeof(T); 93 : static return_type Read(const uint8_t *p, uoffset_t i) { 94 : return reinterpret_cast<const T *>(p + i * sizeof(T)); 95 : } 96 : }; 97 : 98 : /// @brief Get a pointer to the the file_identifier section of the buffer. 99 : /// @return Returns a const char pointer to the start of the file_identifier 100 : /// characters in the buffer. The returned char * has length 101 : /// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. 102 : /// This function is UNDEFINED for FlatBuffers whose schema does not include 103 : /// a file_identifier (likely points at padding or the start of a the root 104 : /// vtable). 105 0 : inline const char *GetBufferIdentifier(const void *buf, 106 : bool size_prefixed = false) { 107 0 : return reinterpret_cast<const char *>(buf) + 108 0 : ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); 109 : } 110 : 111 : // Helper to see if the identifier in a buffer has the expected value. 112 0 : inline bool BufferHasIdentifier(const void *buf, const char *identifier, 113 : bool size_prefixed = false) { 114 0 : return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, 115 0 : flatbuffers::kFileIdentifierLength) == 0; 116 : } 117 : 118 : /// @cond FLATBUFFERS_INTERNAL 119 : // Helpers to get a typed pointer to the root object contained in the buffer. 120 853 : template<typename T> T *GetMutableRoot(void *buf) { 121 853 : EndianCheck(); 122 : return reinterpret_cast<T *>( 123 : reinterpret_cast<uint8_t *>(buf) + 124 853 : EndianScalar(*reinterpret_cast<uoffset_t *>(buf))); 125 : } 126 : 127 : template<typename T> T *GetMutableSizePrefixedRoot(void *buf) { 128 : return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + 129 : sizeof(uoffset_t)); 130 : } 131 : 132 853 : template<typename T> const T *GetRoot(const void *buf) { 133 853 : return GetMutableRoot<T>(const_cast<void *>(buf)); 134 : } 135 : 136 : template<typename T> const T *GetSizePrefixedRoot(const void *buf) { 137 : return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t)); 138 : } 139 : 140 : } // namespace flatbuffers 141 : 142 : #endif // FLATBUFFERS_BUFFER_H_