|
18 | 18 | #define FLATBUFFERS_TABLE_H_ |
19 | 19 |
|
20 | 20 | #include "flatbuffers/base.h" |
| 21 | +#include "flatbuffers/vector.h" |
21 | 22 | #include "flatbuffers/verifier.h" |
22 | 23 |
|
23 | 24 | namespace flatbuffers { |
@@ -70,6 +71,32 @@ class Table { |
70 | 71 | return GetPointer<P, uoffset64_t>(field); |
71 | 72 | } |
72 | 73 |
|
| 74 | + template <typename P, typename SizeT = uoffset_t, |
| 75 | + typename OffsetSize = uoffset_t> |
| 76 | + const Vector<P, SizeT>* GetVectorPointerOrEmpty(voffset_t field) const { |
| 77 | + auto* ptr = GetPointer<const Vector<P, SizeT>*, OffsetSize>(field); |
| 78 | + return ptr ? ptr : EmptyVector<P, SizeT>(); |
| 79 | + } |
| 80 | + |
| 81 | + template <typename P, typename SizeT = uoffset_t> |
| 82 | + const Vector<P, SizeT>* GetVectorPointer64OrEmpty(voffset_t field) const { |
| 83 | + return GetVectorPointerOrEmpty<P, SizeT, uoffset64_t>(field); |
| 84 | + } |
| 85 | + |
| 86 | + template <typename P, typename SizeT = uoffset_t, |
| 87 | + typename OffsetSize = uoffset_t> |
| 88 | + Vector<P, SizeT>* GetMutableVectorPointerOrEmpty(voffset_t field) { |
| 89 | + auto* ptr = GetPointer<Vector<P, SizeT>*, OffsetSize>(field); |
| 90 | + // This is a const_cast, but safe, since all mutable operations on an |
| 91 | + // empty vector are NOPs. |
| 92 | + return ptr ? ptr : const_cast<Vector<P, SizeT>*>(EmptyVector<P, SizeT>()); |
| 93 | + } |
| 94 | + |
| 95 | + template <typename P, typename SizeT = uoffset_t> |
| 96 | + Vector<P, SizeT>* GetMutableVectorPointer64OrEmpty(voffset_t field) { |
| 97 | + return GetMutableVectorPointerOrEmpty<P, SizeT, uoffset64_t>(field); |
| 98 | + } |
| 99 | + |
73 | 100 | template <typename P> |
74 | 101 | P GetStruct(voffset_t field) const { |
75 | 102 | auto field_offset = GetOptionalFieldOffset(field); |
@@ -122,52 +149,94 @@ class Table { |
122 | 149 |
|
123 | 150 | // Verify the vtable of this table. |
124 | 151 | // Call this once per table, followed by VerifyField once per field. |
125 | | - bool VerifyTableStart(Verifier& verifier) const { |
| 152 | + template <bool B> |
| 153 | + bool VerifyTableStart(VerifierTemplate<B>& verifier) const { |
126 | 154 | return verifier.VerifyTableStart(data_); |
127 | 155 | } |
128 | 156 |
|
129 | 157 | // Verify a particular field. |
130 | | - template <typename T> |
131 | | - bool VerifyField(const Verifier& verifier, voffset_t field, |
| 158 | + template <typename T, bool B> |
| 159 | + bool VerifyField(const VerifierTemplate<B>& verifier, voffset_t field, |
132 | 160 | size_t align) const { |
133 | 161 | // Calling GetOptionalFieldOffset should be safe now thanks to |
134 | 162 | // VerifyTable(). |
135 | 163 | auto field_offset = GetOptionalFieldOffset(field); |
136 | 164 | // Check the actual field. |
137 | | - return !field_offset || verifier.VerifyField<T>(data_, field_offset, align); |
| 165 | + return !field_offset || |
| 166 | + verifier.template VerifyField<T>(data_, field_offset, align); |
138 | 167 | } |
139 | 168 |
|
140 | 169 | // VerifyField for required fields. |
141 | | - template <typename T> |
142 | | - bool VerifyFieldRequired(const Verifier& verifier, voffset_t field, |
| 170 | + template <typename T, bool B> |
| 171 | + bool VerifyFieldRequired(const VerifierTemplate<B>& verifier, voffset_t field, |
143 | 172 | size_t align) const { |
144 | 173 | auto field_offset = GetOptionalFieldOffset(field); |
145 | 174 | return verifier.Check(field_offset != 0) && |
146 | | - verifier.VerifyField<T>(data_, field_offset, align); |
| 175 | + verifier.template VerifyField<T>(data_, field_offset, align); |
147 | 176 | } |
148 | 177 |
|
149 | 178 | // Versions for offsets. |
150 | | - template <typename OffsetT = uoffset_t> |
151 | | - bool VerifyOffset(const Verifier& verifier, voffset_t field) const { |
| 179 | + template <typename OffsetT = uoffset_t, bool B = false> |
| 180 | + bool VerifyOffset(const VerifierTemplate<B>& verifier, |
| 181 | + voffset_t field) const { |
152 | 182 | auto field_offset = GetOptionalFieldOffset(field); |
153 | | - return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset); |
| 183 | + return !field_offset || |
| 184 | + verifier.template VerifyOffset<OffsetT>(data_, field_offset); |
154 | 185 | } |
155 | 186 |
|
156 | | - template <typename OffsetT = uoffset_t> |
157 | | - bool VerifyOffsetRequired(const Verifier& verifier, voffset_t field) const { |
| 187 | + template <typename OffsetT = uoffset_t, bool B = false> |
| 188 | + bool VerifyOffsetRequired(const VerifierTemplate<B>& verifier, |
| 189 | + voffset_t field) const { |
158 | 190 | auto field_offset = GetOptionalFieldOffset(field); |
159 | 191 | return verifier.Check(field_offset != 0) && |
160 | | - verifier.VerifyOffset<OffsetT>(data_, field_offset); |
| 192 | + verifier.template VerifyOffset<OffsetT>(data_, field_offset); |
161 | 193 | } |
162 | 194 |
|
163 | | - bool VerifyOffset64(const Verifier& verifier, voffset_t field) const { |
| 195 | + template <bool B> |
| 196 | + bool VerifyOffset64(const VerifierTemplate<B>& verifier, |
| 197 | + voffset_t field) const { |
164 | 198 | return VerifyOffset<uoffset64_t>(verifier, field); |
165 | 199 | } |
166 | 200 |
|
167 | | - bool VerifyOffset64Required(const Verifier& verifier, voffset_t field) const { |
| 201 | + template <bool B> |
| 202 | + bool VerifyOffset64Required(const VerifierTemplate<B>& verifier, |
| 203 | + voffset_t field) const { |
168 | 204 | return VerifyOffsetRequired<uoffset64_t>(verifier, field); |
169 | 205 | } |
170 | 206 |
|
| 207 | + // Verify a string that may have a default value. |
| 208 | + template <typename OffsetT = uoffset_t> |
| 209 | + bool VerifyStringWithDefault(const Verifier& verifier, |
| 210 | + voffset_t field) const { |
| 211 | + auto field_offset = GetOptionalFieldOffset(field); |
| 212 | + return field_offset == 0 || |
| 213 | + verifier.VerifyString(GetPointer<const String*, OffsetT>(field)); |
| 214 | + } |
| 215 | + |
| 216 | + // Verify a vector that has a default empty value. |
| 217 | + template <typename P, typename SizeT = uoffset_t, |
| 218 | + typename OffsetSize = uoffset_t> |
| 219 | + bool VerifyVectorWithDefault(const Verifier& verifier, |
| 220 | + voffset_t field) const { |
| 221 | + auto field_offset = GetOptionalFieldOffset(field); |
| 222 | + return field_offset == 0 || |
| 223 | + verifier.VerifyVector( |
| 224 | + GetPointer<const Vector<P, SizeT>*, OffsetSize>(field)); |
| 225 | + } |
| 226 | + |
| 227 | + template <typename P, typename SizeT = uoffset_t> |
| 228 | + bool VerifyVector64WithDefault(const Verifier& verifier, |
| 229 | + voffset_t field) const { |
| 230 | + return VerifyVectorWithDefault<P, SizeT, uoffset64_t>(verifier, field); |
| 231 | + } |
| 232 | + |
| 233 | + protected: |
| 234 | + template <typename T, typename SizeT = uoffset_t> |
| 235 | + static const Vector<T, SizeT>* EmptyVector() { |
| 236 | + static const SizeT empty_vector_length = 0; |
| 237 | + return reinterpret_cast<const Vector<T, SizeT>*>(&empty_vector_length); |
| 238 | + } |
| 239 | + |
171 | 240 | private: |
172 | 241 | // private constructor & copy constructor: you obtain instances of this |
173 | 242 | // class by pointing to existing data only |
|
0 commit comments