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