• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TABLE_H_
18 #define FLATBUFFERS_TABLE_H_
19 
20 #include "flatbuffers/base.h"
21 #include "flatbuffers/verifier.h"
22 
23 namespace flatbuffers {
24 
25 // "tables" use an offset table (possibly shared) that allows fields to be
26 // omitted and added at will, but uses an extra indirection to read.
27 class Table {
28  public:
GetVTable()29   const uint8_t *GetVTable() const {
30     return data_ - ReadScalar<soffset_t>(data_);
31   }
32 
33   // This gets the field offset for any of the functions below it, or 0
34   // if the field was not present.
GetOptionalFieldOffset(voffset_t field)35   voffset_t GetOptionalFieldOffset(voffset_t field) const {
36     // The vtable offset is always at the start.
37     auto vtable = GetVTable();
38     // The first element is the size of the vtable (fields + type id + itself).
39     auto vtsize = ReadScalar<voffset_t>(vtable);
40     // If the field we're accessing is outside the vtable, we're reading older
41     // data, so it's the same as if the offset was 0 (not present).
42     return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
43   }
44 
GetField(voffset_t field,T defaultval)45   template<typename T> T GetField(voffset_t field, T defaultval) const {
46     auto field_offset = GetOptionalFieldOffset(field);
47     return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
48   }
49 
50   template<typename P, typename OffsetSize = uoffset_t>
GetPointer(voffset_t field)51   P GetPointer(voffset_t field) {
52     auto field_offset = GetOptionalFieldOffset(field);
53     auto p = data_ + field_offset;
54     return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
55                         : nullptr;
56   }
57   template<typename P, typename OffsetSize = uoffset_t>
GetPointer(voffset_t field)58   P GetPointer(voffset_t field) const {
59     return const_cast<Table *>(this)->GetPointer<P, OffsetSize>(field);
60   }
61 
GetPointer64(voffset_t field)62   template<typename P> P GetPointer64(voffset_t field) {
63     return GetPointer<P, uoffset64_t>(field);
64   }
65 
GetPointer64(voffset_t field)66   template<typename P> P GetPointer64(voffset_t field) const {
67     return GetPointer<P, uoffset64_t>(field);
68   }
69 
GetStruct(voffset_t field)70   template<typename P> P GetStruct(voffset_t field) const {
71     auto field_offset = GetOptionalFieldOffset(field);
72     auto p = const_cast<uint8_t *>(data_ + field_offset);
73     return field_offset ? reinterpret_cast<P>(p) : nullptr;
74   }
75 
76   template<typename Raw, typename Face>
GetOptional(voffset_t field)77   flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
78     auto field_offset = GetOptionalFieldOffset(field);
79     auto p = data_ + field_offset;
80     return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
81                         : Optional<Face>();
82   }
83 
SetField(voffset_t field,T val,T def)84   template<typename T> bool SetField(voffset_t field, T val, T def) {
85     auto field_offset = GetOptionalFieldOffset(field);
86     if (!field_offset) return IsTheSameAs(val, def);
87     WriteScalar(data_ + field_offset, val);
88     return true;
89   }
SetField(voffset_t field,T val)90   template<typename T> bool SetField(voffset_t field, T val) {
91     auto field_offset = GetOptionalFieldOffset(field);
92     if (!field_offset) return false;
93     WriteScalar(data_ + field_offset, val);
94     return true;
95   }
96 
SetPointer(voffset_t field,const uint8_t * val)97   bool SetPointer(voffset_t field, const uint8_t *val) {
98     auto field_offset = GetOptionalFieldOffset(field);
99     if (!field_offset) return false;
100     WriteScalar(data_ + field_offset,
101                 static_cast<uoffset_t>(val - (data_ + field_offset)));
102     return true;
103   }
104 
GetAddressOf(voffset_t field)105   uint8_t *GetAddressOf(voffset_t field) {
106     auto field_offset = GetOptionalFieldOffset(field);
107     return field_offset ? data_ + field_offset : nullptr;
108   }
GetAddressOf(voffset_t field)109   const uint8_t *GetAddressOf(voffset_t field) const {
110     return const_cast<Table *>(this)->GetAddressOf(field);
111   }
112 
CheckField(voffset_t field)113   bool CheckField(voffset_t field) const {
114     return GetOptionalFieldOffset(field) != 0;
115   }
116 
117   // Verify the vtable of this table.
118   // Call this once per table, followed by VerifyField once per field.
VerifyTableStart(Verifier & verifier)119   bool VerifyTableStart(Verifier &verifier) const {
120     return verifier.VerifyTableStart(data_);
121   }
122 
123   // Verify a particular field.
124   template<typename T>
VerifyField(const Verifier & verifier,voffset_t field,size_t align)125   bool VerifyField(const Verifier &verifier, voffset_t field,
126                    size_t align) const {
127     // Calling GetOptionalFieldOffset should be safe now thanks to
128     // VerifyTable().
129     auto field_offset = GetOptionalFieldOffset(field);
130     // Check the actual field.
131     return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
132   }
133 
134   // VerifyField for required fields.
135   template<typename T>
VerifyFieldRequired(const Verifier & verifier,voffset_t field,size_t align)136   bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
137                            size_t align) const {
138     auto field_offset = GetOptionalFieldOffset(field);
139     return verifier.Check(field_offset != 0) &&
140            verifier.VerifyField<T>(data_, field_offset, align);
141   }
142 
143   // Versions for offsets.
144   template<typename OffsetT = uoffset_t>
VerifyOffset(const Verifier & verifier,voffset_t field)145   bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
146     auto field_offset = GetOptionalFieldOffset(field);
147     return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset);
148   }
149 
150   template<typename OffsetT = uoffset_t>
VerifyOffsetRequired(const Verifier & verifier,voffset_t field)151   bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
152     auto field_offset = GetOptionalFieldOffset(field);
153     return verifier.Check(field_offset != 0) &&
154            verifier.VerifyOffset<OffsetT>(data_, field_offset);
155   }
156 
VerifyOffset64(const Verifier & verifier,voffset_t field)157   bool VerifyOffset64(const Verifier &verifier, voffset_t field) const {
158     return VerifyOffset<uoffset64_t>(verifier, field);
159   }
160 
VerifyOffset64Required(const Verifier & verifier,voffset_t field)161   bool VerifyOffset64Required(const Verifier &verifier, voffset_t field) const {
162     return VerifyOffsetRequired<uoffset64_t>(verifier, field);
163   }
164 
165  private:
166   // private constructor & copy constructor: you obtain instances of this
167   // class by pointing to existing data only
168   Table();
169   Table(const Table &other);
170   Table &operator=(const Table &);
171 
172   uint8_t data_[1];
173 };
174 
175 // This specialization allows avoiding warnings like:
176 // MSVC C4800: type: forcing value to bool 'true' or 'false'.
177 template<>
178 inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
179     voffset_t field) const {
180   auto field_offset = GetOptionalFieldOffset(field);
181   auto p = data_ + field_offset;
182   return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
183                       : Optional<bool>();
184 }
185 
186 }  // namespace flatbuffers
187 
188 #endif  // FLATBUFFERS_TABLE_H_
189