@@ -25,14 +25,33 @@ namespace flatbuffers {
25
25
26
26
// Wrapper for uoffset_t to allow safe template specialization.
27
27
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
28
- template <typename T> struct Offset {
29
- 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;
30
33
Offset () : o(0 ) {}
31
- Offset (uoffset_t _o) : o(_o) {}
32
- Offset<void > Union () const { return Offset<void >(o); }
34
+ Offset (const offset_type _o) : o(_o) {}
35
+ Offset<> Union () const { return o; }
36
+ bool IsNull () const { return !o; }
37
+ };
38
+
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; }
33
48
bool IsNull () const { return !o; }
34
49
};
35
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
+
36
55
inline void EndianCheck () {
37
56
int endiantest = 1 ;
38
57
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
@@ -75,35 +94,59 @@ template<typename T> struct IndirectHelper {
75
94
typedef T return_type;
76
95
typedef T mutable_return_type;
77
96
static const size_t element_stride = sizeof (T);
78
- 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) {
79
99
return EndianScalar ((reinterpret_cast <const T *>(p))[i]);
80
100
}
81
- static return_type Read (uint8_t *p, uoffset_t i) {
82
- return Read (const_cast <const uint8_t *>(p), i);
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));
83
104
}
84
105
};
85
- 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>> {
86
110
typedef const T *return_type;
87
111
typedef T *mutable_return_type;
88
- static const size_t element_stride = sizeof (uoffset_t );
89
- static return_type Read (const uint8_t *p, uoffset_t i) {
90
- p += i * sizeof (uoffset_t );
91
- 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));
92
124
}
93
- static mutable_return_type Read (uint8_t *p, uoffset_t i) {
94
- p += i * sizeof (uoffset_t );
95
- return reinterpret_cast <mutable_return_type>(p + ReadScalar<uoffset_t >(p));
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));
96
134
}
97
135
};
136
+
137
+ // For vector of structs.
98
138
template <typename T> struct IndirectHelper <const T *> {
99
139
typedef const T *return_type;
100
140
typedef T *mutable_return_type;
101
141
static const size_t element_stride = sizeof (T);
102
- static return_type Read (const uint8_t *p, uoffset_t i) {
103
- return reinterpret_cast <return_type>(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);
104
146
}
105
- static mutable_return_type Read (uint8_t *p, uoffset_t i) {
106
- return reinterpret_cast <mutable_return_type>(p + i * sizeof (T));
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);
107
150
}
108
151
};
109
152
@@ -130,23 +173,25 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
130
173
// / @cond FLATBUFFERS_INTERNAL
131
174
// Helpers to get a typed pointer to the root object contained in the buffer.
132
175
template <typename T> T *GetMutableRoot (void *buf) {
176
+ if (!buf) return nullptr ;
133
177
EndianCheck ();
134
178
return reinterpret_cast <T *>(
135
179
reinterpret_cast <uint8_t *>(buf) +
136
180
EndianScalar (*reinterpret_cast <uoffset_t *>(buf)));
137
181
}
138
182
139
- template <typename T> T * GetMutableSizePrefixedRoot ( void *buf) {
140
- return GetMutableRoot<T>( reinterpret_cast < uint8_t *>( buf) +
141
- 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 ));
142
186
}
143
187
144
188
template <typename T> const T *GetRoot (const void *buf) {
145
189
return GetMutableRoot<T>(const_cast <void *>(buf));
146
190
}
147
191
148
- template <typename T> const T *GetSizePrefixedRoot (const void *buf) {
149
- 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));
150
195
}
151
196
152
197
} // namespace flatbuffers
0 commit comments