Coverage Report

Created: 2025-07-11 06:48

/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_