1717#ifndef FLATBUFFERS_BUFFER_H_
1818#define FLATBUFFERS_BUFFER_H_
1919
20+ #include < algorithm>
21+
2022#include " flatbuffers/base.h"
2123
2224namespace flatbuffers {
2325
2426// Wrapper for uoffset_t to allow safe template specialization.
2527// 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+ template <typename T = void > struct Offset {
29+ // The type of offset to use.
30+ typedef uoffset_t offset_type;
31+
32+ offset_type o;
2833 Offset () : o(0 ) {}
29- Offset (uoffset_t _o) : o(_o) {}
30- Offset<void > Union () const { return Offset< void >(o) ; }
34+ Offset (const offset_type _o) : o(_o) {}
35+ Offset<> Union () const { return o ; }
3136 bool IsNull () const { return !o; }
3237};
3338
39+ // Wrapper for uoffset64_t Offsets.
40+ template <typename T = void > struct Offset64 {
41+ // The type of offset to use.
42+ typedef uoffset64_t offset_type;
43+
44+ offset_type o;
45+ Offset64 () : o(0 ) {}
46+ Offset64 (const offset_type offset) : o(offset) {}
47+ Offset64<> Union () const { return o; }
48+ bool IsNull () const { return !o; }
49+ };
50+
51+ // Litmus check for ensuring the Offsets are the expected size.
52+ static_assert (sizeof (Offset<>) == 4 , " Offset has wrong size" );
53+ static_assert (sizeof (Offset64<>) == 8 , " Offset64 has wrong size" );
54+
3455inline void EndianCheck () {
3556 int endiantest = 1 ;
3657 // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
@@ -73,25 +94,59 @@ template<typename T> struct IndirectHelper {
7394 typedef T return_type;
7495 typedef T mutable_return_type;
7596 static const size_t element_stride = sizeof (T);
76- static return_type Read (const uint8_t *p, uoffset_t i) {
97+
98+ static return_type Read (const uint8_t *p, const size_t i) {
7799 return EndianScalar ((reinterpret_cast <const T *>(p))[i]);
78100 }
101+ static mutable_return_type Read (uint8_t *p, const size_t i) {
102+ return reinterpret_cast <mutable_return_type>(
103+ Read (const_cast <const uint8_t *>(p), i));
104+ }
79105};
80- template <typename T> struct IndirectHelper <Offset<T>> {
106+
107+ // For vector of Offsets.
108+ template <typename T, template <typename > class OffsetT >
109+ struct IndirectHelper <OffsetT<T>> {
81110 typedef const T *return_type;
82111 typedef T *mutable_return_type;
83- static const size_t element_stride = sizeof (uoffset_t );
84- static return_type Read (const uint8_t *p, uoffset_t i) {
85- p += i * sizeof (uoffset_t );
86- return reinterpret_cast <return_type>(p + ReadScalar<uoffset_t >(p));
112+ typedef typename OffsetT<T>::offset_type offset_type;
113+ static const offset_type element_stride = sizeof (offset_type);
114+
115+ static return_type Read (const uint8_t *const p, const offset_type i) {
116+ // Offsets are relative to themselves, so first update the pointer to
117+ // point to the offset location.
118+ const uint8_t *const offset_location = p + i * element_stride;
119+
120+ // Then read the scalar value of the offset (which may be 32 or 64-bits) and
121+ // then determine the relative location from the offset location.
122+ return reinterpret_cast <return_type>(
123+ offset_location + ReadScalar<offset_type>(offset_location));
124+ }
125+ static mutable_return_type Read (uint8_t *const p, const offset_type i) {
126+ // Offsets are relative to themselves, so first update the pointer to
127+ // point to the offset location.
128+ uint8_t *const offset_location = p + i * element_stride;
129+
130+ // Then read the scalar value of the offset (which may be 32 or 64-bits) and
131+ // then determine the relative location from the offset location.
132+ return reinterpret_cast <mutable_return_type>(
133+ offset_location + ReadScalar<offset_type>(offset_location));
87134 }
88135};
136+
137+ // For vector of structs.
89138template <typename T> struct IndirectHelper <const T *> {
90139 typedef const T *return_type;
91140 typedef T *mutable_return_type;
92141 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));
142+
143+ static return_type Read (const uint8_t *const p, const size_t i) {
144+ // Structs are stored inline, relative to the first struct pointer.
145+ return reinterpret_cast <return_type>(p + i * element_stride);
146+ }
147+ static mutable_return_type Read (uint8_t *const p, const size_t i) {
148+ // Structs are stored inline, relative to the first struct pointer.
149+ return reinterpret_cast <mutable_return_type>(p + i * element_stride);
95150 }
96151};
97152
@@ -118,25 +173,27 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
118173// / @cond FLATBUFFERS_INTERNAL
119174// Helpers to get a typed pointer to the root object contained in the buffer.
120175template <typename T> T *GetMutableRoot (void *buf) {
176+ if (!buf) return nullptr ;
121177 EndianCheck ();
122178 return reinterpret_cast <T *>(
123179 reinterpret_cast <uint8_t *>(buf) +
124180 EndianScalar (*reinterpret_cast <uoffset_t *>(buf)));
125181}
126182
127- template <typename T> T * GetMutableSizePrefixedRoot ( void *buf) {
128- return GetMutableRoot<T>( reinterpret_cast < uint8_t *>( buf) +
129- sizeof (uoffset_t ));
183+ template <typename T, typename SizeT = uoffset_t >
184+ T * GetMutableSizePrefixedRoot ( void * buf) {
185+ return GetMutableRoot<T>( reinterpret_cast < uint8_t *>(buf) + sizeof (SizeT ));
130186}
131187
132188template <typename T> const T *GetRoot (const void *buf) {
133189 return GetMutableRoot<T>(const_cast <void *>(buf));
134190}
135191
136- template <typename T> const T *GetSizePrefixedRoot (const void *buf) {
137- return GetRoot<T>(reinterpret_cast <const uint8_t *>(buf) + sizeof (uoffset_t ));
192+ template <typename T, typename SizeT = uoffset_t >
193+ const T *GetSizePrefixedRoot (const void *buf) {
194+ return GetRoot<T>(reinterpret_cast <const uint8_t *>(buf) + sizeof (SizeT));
138195}
139196
140197} // namespace flatbuffers
141198
142- #endif // FLATBUFFERS_BUFFER_H_
199+ #endif // FLATBUFFERS_BUFFER_H_
0 commit comments