Coverage Report

Created: 2025-11-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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_