/src/flatbuffers/include/flatbuffers/buffer.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_BUFFER_H_ |
18 | | #define FLATBUFFERS_BUFFER_H_ |
19 | | |
20 | | #include <algorithm> |
21 | | |
22 | | #include "flatbuffers/base.h" |
23 | | #include "flatbuffers/stl_emulation.h" |
24 | | |
25 | | namespace flatbuffers { |
26 | | |
27 | | // Wrapper for uoffset_t to allow safe template specialization. |
28 | | // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). |
29 | | template <typename T = void> |
30 | | struct Offset { |
31 | | // The type of offset to use. |
32 | | typedef uoffset_t offset_type; |
33 | | |
34 | | offset_type o; |
35 | | Offset() : o(0) {} |
36 | | Offset(const offset_type _o) : o(_o) {} |
37 | 0 | Offset<> Union() const { return o; }Unexecuted instantiation: flatbuffers::Offset<MyGame::Example::Monster>::Union() const Unexecuted instantiation: flatbuffers::Offset<MyGame::Example::TestSimpleTableWithEnum>::Union() const Unexecuted instantiation: flatbuffers::Offset<MyGame::Example2::Monster>::Union() const |
38 | 0 | bool IsNull() const { return !o; }Unexecuted instantiation: flatbuffers::Offset<flatbuffers::String>::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<unsigned char, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<void>::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<MyGame::Example::Test const*, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Monster>, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<MyGame::Example::Monster>::IsNull() const Unexecuted instantiation: flatbuffers::Offset<MyGame::Example::Stat>::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<MyGame::Example::Ability const*, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<long, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<double, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<MyGame::InParentNamespace>::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Referrable>, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<unsigned long, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<MyGame::Example::Color, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Stat>, unsigned int> >::IsNull() const Unexecuted instantiation: flatbuffers::Offset<flatbuffers::Vector<signed char, unsigned int> >::IsNull() const |
39 | | }; |
40 | | |
41 | | template <typename T> |
42 | | struct is_specialisation_of_Offset : false_type {}; |
43 | | template <typename T> |
44 | | struct is_specialisation_of_Offset<Offset<T>> : true_type {}; |
45 | | |
46 | | // Wrapper for uoffset64_t Offsets. |
47 | | template <typename T = void> |
48 | | struct Offset64 { |
49 | | // The type of offset to use. |
50 | | typedef uoffset64_t offset_type; |
51 | | |
52 | | offset_type o; |
53 | | Offset64() : o(0) {} |
54 | | Offset64(const offset_type offset) : o(offset) {} |
55 | | Offset64<> Union() const { return o; } |
56 | | bool IsNull() const { return !o; } |
57 | | }; |
58 | | |
59 | | template <typename T> |
60 | | struct is_specialisation_of_Offset64 : false_type {}; |
61 | | template <typename T> |
62 | | struct is_specialisation_of_Offset64<Offset64<T>> : true_type {}; |
63 | | |
64 | | // Litmus check for ensuring the Offsets are the expected size. |
65 | | static_assert(sizeof(Offset<>) == 4, "Offset has wrong size"); |
66 | | static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size"); |
67 | | |
68 | 0 | inline void EndianCheck() { |
69 | 0 | int endiantest = 1; |
70 | 0 | // If this fails, see FLATBUFFERS_LITTLEENDIAN above. |
71 | 0 | FLATBUFFERS_ASSERT(*reinterpret_cast<char*>(&endiantest) == |
72 | 0 | FLATBUFFERS_LITTLEENDIAN); |
73 | 0 | (void)endiantest; |
74 | 0 | } |
75 | | |
76 | | template <typename T> |
77 | 0 | FLATBUFFERS_CONSTEXPR size_t AlignOf() { |
78 | 0 | // clang-format off |
79 | 0 | #ifdef _MSC_VER |
80 | 0 | return __alignof(T); |
81 | 0 | #else |
82 | 0 | #ifndef alignof |
83 | 0 | return __alignof__(T); |
84 | 0 | #else |
85 | 0 | return alignof(T); |
86 | 0 | #endif |
87 | 0 | #endif |
88 | 0 | // clang-format on |
89 | 0 | } Unexecuted instantiation: unsigned long flatbuffers::AlignOf<unsigned long>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<unsigned int>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<MyGame::Example::Vec3>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<MyGame::Example::Test>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<unsigned char>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<flatbuffers::Offset<flatbuffers::String> >() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<flatbuffers::Offset<MyGame::Example::Monster> >() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<MyGame::Example::Ability>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<long>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<double>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<flatbuffers::Offset<MyGame::Example::Referrable> >() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<MyGame::Example::Color>() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<flatbuffers::Offset<MyGame::Example::Stat> >() Unexecuted instantiation: unsigned long flatbuffers::AlignOf<signed char>() |
90 | | |
91 | | // Lexicographically compare two strings (possibly containing nulls), and |
92 | | // return true if the first is less than the second. |
93 | | static inline bool StringLessThan(const char* a_data, uoffset_t a_size, |
94 | 0 | const char* b_data, uoffset_t b_size) { |
95 | 0 | const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); |
96 | 0 | return cmp == 0 ? a_size < b_size : cmp < 0; |
97 | 0 | } |
98 | | |
99 | | // When we read serialized data from memory, in the case of most scalars, |
100 | | // we want to just read T, but in the case of Offset, we want to actually |
101 | | // perform the indirection and return a pointer. |
102 | | // The template specialization below does just that. |
103 | | // It is wrapped in a struct since function templates can't overload on the |
104 | | // return type like this. |
105 | | // The typedef is for the convenience of callers of this function |
106 | | // (avoiding the need for a trailing return decltype) |
107 | | template <typename T, typename Enable = void> |
108 | | struct IndirectHelper { |
109 | | typedef T return_type; |
110 | | typedef T mutable_return_type; |
111 | | static const size_t element_stride = sizeof(T); |
112 | | |
113 | 0 | static return_type Read(const uint8_t* p, const size_t i) { |
114 | 0 | return EndianScalar((reinterpret_cast<const T*>(p))[i]); |
115 | 0 | } Unexecuted instantiation: flatbuffers::IndirectHelper<unsigned char, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<long, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<double, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<unsigned long, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::Color, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<signed char, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::Any, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::AnyUniqueAliases, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::AnyAmbiguousAliases, void>::Read(unsigned char const*, unsigned long) |
116 | | static mutable_return_type Read(uint8_t* p, const size_t i) { |
117 | | return reinterpret_cast<mutable_return_type>( |
118 | | Read(const_cast<const uint8_t*>(p), i)); |
119 | | } |
120 | | }; |
121 | | |
122 | | // For vector of Offsets. |
123 | | template <typename T, template <typename> class OffsetT> |
124 | | struct IndirectHelper<OffsetT<T>> { |
125 | | typedef const T* return_type; |
126 | | typedef T* mutable_return_type; |
127 | | typedef typename OffsetT<T>::offset_type offset_type; |
128 | | static const offset_type element_stride = sizeof(offset_type); |
129 | | |
130 | 1.75M | static return_type Read(const uint8_t* const p, const offset_type i) { |
131 | | // Offsets are relative to themselves, so first update the pointer to |
132 | | // point to the offset location. |
133 | 1.75M | const uint8_t* const offset_location = p + i * element_stride; |
134 | | |
135 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and |
136 | | // then determine the relative location from the offset location. |
137 | 1.75M | return reinterpret_cast<return_type>( |
138 | 1.75M | offset_location + ReadScalar<offset_type>(offset_location)); |
139 | 1.75M | } flatbuffers::IndirectHelper<flatbuffers::Offset<flatbuffers::String>, void>::Read(unsigned char const*, unsigned int) Line | Count | Source | 130 | 643k | static return_type Read(const uint8_t* const p, const offset_type i) { | 131 | | // Offsets are relative to themselves, so first update the pointer to | 132 | | // point to the offset location. | 133 | 643k | const uint8_t* const offset_location = p + i * element_stride; | 134 | | | 135 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and | 136 | | // then determine the relative location from the offset location. | 137 | 643k | return reinterpret_cast<return_type>( | 138 | 643k | offset_location + ReadScalar<offset_type>(offset_location)); | 139 | 643k | } |
flatbuffers::IndirectHelper<flatbuffers::Offset<MyGame::Example::Monster>, void>::Read(unsigned char const*, unsigned int) Line | Count | Source | 130 | 1.04M | static return_type Read(const uint8_t* const p, const offset_type i) { | 131 | | // Offsets are relative to themselves, so first update the pointer to | 132 | | // point to the offset location. | 133 | 1.04M | const uint8_t* const offset_location = p + i * element_stride; | 134 | | | 135 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and | 136 | | // then determine the relative location from the offset location. | 137 | 1.04M | return reinterpret_cast<return_type>( | 138 | 1.04M | offset_location + ReadScalar<offset_type>(offset_location)); | 139 | 1.04M | } |
flatbuffers::IndirectHelper<flatbuffers::Offset<MyGame::Example::Referrable>, void>::Read(unsigned char const*, unsigned int) Line | Count | Source | 130 | 56.0k | static return_type Read(const uint8_t* const p, const offset_type i) { | 131 | | // Offsets are relative to themselves, so first update the pointer to | 132 | | // point to the offset location. | 133 | 56.0k | const uint8_t* const offset_location = p + i * element_stride; | 134 | | | 135 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and | 136 | | // then determine the relative location from the offset location. | 137 | 56.0k | return reinterpret_cast<return_type>( | 138 | 56.0k | offset_location + ReadScalar<offset_type>(offset_location)); | 139 | 56.0k | } |
flatbuffers::IndirectHelper<flatbuffers::Offset<MyGame::Example::Stat>, void>::Read(unsigned char const*, unsigned int) Line | Count | Source | 130 | 8.28k | static return_type Read(const uint8_t* const p, const offset_type i) { | 131 | | // Offsets are relative to themselves, so first update the pointer to | 132 | | // point to the offset location. | 133 | 8.28k | const uint8_t* const offset_location = p + i * element_stride; | 134 | | | 135 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and | 136 | | // then determine the relative location from the offset location. | 137 | 8.28k | return reinterpret_cast<return_type>( | 138 | 8.28k | offset_location + ReadScalar<offset_type>(offset_location)); | 139 | 8.28k | } |
Unexecuted instantiation: flatbuffers::IndirectHelper<flatbuffers::Offset<void>, void>::Read(unsigned char const*, unsigned int) |
140 | | static mutable_return_type Read(uint8_t* const p, const offset_type i) { |
141 | | // Offsets are relative to themselves, so first update the pointer to |
142 | | // point to the offset location. |
143 | | uint8_t* const offset_location = p + i * element_stride; |
144 | | |
145 | | // Then read the scalar value of the offset (which may be 32 or 64-bits) and |
146 | | // then determine the relative location from the offset location. |
147 | | return reinterpret_cast<mutable_return_type>( |
148 | | offset_location + ReadScalar<offset_type>(offset_location)); |
149 | | } |
150 | | }; |
151 | | |
152 | | // For vector of structs. |
153 | | template <typename T> |
154 | | struct IndirectHelper< |
155 | | T, typename std::enable_if< |
156 | | !std::is_scalar<typename std::remove_pointer<T>::type>::value && |
157 | | !is_specialisation_of_Offset<T>::value && |
158 | | !is_specialisation_of_Offset64<T>::value>::type> { |
159 | | private: |
160 | | typedef typename std::remove_pointer<typename std::remove_cv<T>::type>::type |
161 | | pointee_type; |
162 | | |
163 | | public: |
164 | | typedef const pointee_type* return_type; |
165 | | typedef pointee_type* mutable_return_type; |
166 | | static const size_t element_stride = sizeof(pointee_type); |
167 | | |
168 | 0 | static return_type Read(const uint8_t* const p, const size_t i) { |
169 | 0 | // Structs are stored inline, relative to the first struct pointer. |
170 | 0 | return reinterpret_cast<return_type>(p + i * element_stride); |
171 | 0 | } Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::Test const*, void>::Read(unsigned char const*, unsigned long) Unexecuted instantiation: flatbuffers::IndirectHelper<MyGame::Example::Ability const*, void>::Read(unsigned char const*, unsigned long) |
172 | | static mutable_return_type Read(uint8_t* const p, const size_t i) { |
173 | | // Structs are stored inline, relative to the first struct pointer. |
174 | | return reinterpret_cast<mutable_return_type>(p + i * element_stride); |
175 | | } |
176 | | }; |
177 | | |
178 | | /// @brief Get a pointer to the file_identifier section of the buffer. |
179 | | /// @return Returns a const char pointer to the start of the file_identifier |
180 | | /// characters in the buffer. The returned char * has length |
181 | | /// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. |
182 | | /// This function is UNDEFINED for FlatBuffers whose schema does not include |
183 | | /// a file_identifier (likely points at padding or the start of a the root |
184 | | /// vtable). |
185 | | inline const char* GetBufferIdentifier(const void* buf, |
186 | 5.52k | bool size_prefixed = false) { |
187 | 5.52k | return reinterpret_cast<const char*>(buf) + |
188 | 5.52k | ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); |
189 | 5.52k | } |
190 | | |
191 | | // Helper to see if the identifier in a buffer has the expected value. |
192 | | inline bool BufferHasIdentifier(const void* buf, const char* identifier, |
193 | 5.52k | bool size_prefixed = false) { |
194 | 5.52k | return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, |
195 | 5.52k | flatbuffers::kFileIdentifierLength) == 0; |
196 | 5.52k | } |
197 | | |
198 | | /// @cond FLATBUFFERS_INTERNAL |
199 | | // Helpers to get a typed pointer to the root object contained in the buffer. |
200 | | template <typename T> |
201 | 0 | T* GetMutableRoot(void* buf) { |
202 | 0 | if (!buf) return nullptr; |
203 | 0 | EndianCheck(); |
204 | 0 | return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(buf) + |
205 | 0 | EndianScalar(*reinterpret_cast<uoffset_t*>(buf))); |
206 | 0 | } |
207 | | |
208 | | template <typename T, typename SizeT = uoffset_t> |
209 | 0 | T* GetMutableSizePrefixedRoot(void* buf) { |
210 | 0 | return GetMutableRoot<T>(reinterpret_cast<uint8_t*>(buf) + sizeof(SizeT)); |
211 | 0 | } |
212 | | |
213 | | template <typename T> |
214 | 0 | const T* GetRoot(const void* buf) { |
215 | 0 | return GetMutableRoot<T>(const_cast<void*>(buf)); |
216 | 0 | } |
217 | | |
218 | | template <typename T, typename SizeT = uoffset_t> |
219 | 0 | const T* GetSizePrefixedRoot(const void* buf) { |
220 | 0 | return GetRoot<T>(reinterpret_cast<const uint8_t*>(buf) + sizeof(SizeT)); |
221 | 0 | } |
222 | | |
223 | | } // namespace flatbuffers |
224 | | |
225 | | #endif // FLATBUFFERS_BUFFER_H_ |