xref: /aosp_15_r20/external/flatbuffers/src/bfbs_gen.h (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker  * Copyright 2021 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker  *
4*890232f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker  *
8*890232f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker  *
10*890232f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker  * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker  */
16*890232f2SAndroid Build Coastguard Worker 
17*890232f2SAndroid Build Coastguard Worker #ifndef FLATBUFFERS_BFBS_GEN_H_
18*890232f2SAndroid Build Coastguard Worker #define FLATBUFFERS_BFBS_GEN_H_
19*890232f2SAndroid Build Coastguard Worker 
20*890232f2SAndroid Build Coastguard Worker #include <cstdint>
21*890232f2SAndroid Build Coastguard Worker 
22*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/bfbs_generator.h"
23*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/reflection_generated.h"
24*890232f2SAndroid Build Coastguard Worker 
25*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
26*890232f2SAndroid Build Coastguard Worker 
27*890232f2SAndroid Build Coastguard Worker namespace {
28*890232f2SAndroid Build Coastguard Worker 
ForAllEnums(const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> * enums,std::function<void (const reflection::Enum *)> func)29*890232f2SAndroid Build Coastguard Worker static void ForAllEnums(
30*890232f2SAndroid Build Coastguard Worker     const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums,
31*890232f2SAndroid Build Coastguard Worker     std::function<void(const reflection::Enum *)> func) {
32*890232f2SAndroid Build Coastguard Worker   for (auto it = enums->cbegin(); it != enums->cend(); ++it) { func(*it); }
33*890232f2SAndroid Build Coastguard Worker }
34*890232f2SAndroid Build Coastguard Worker 
ForAllObjects(const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> * objects,std::function<void (const reflection::Object *)> func)35*890232f2SAndroid Build Coastguard Worker static void ForAllObjects(
36*890232f2SAndroid Build Coastguard Worker     const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects,
37*890232f2SAndroid Build Coastguard Worker     std::function<void(const reflection::Object *)> func) {
38*890232f2SAndroid Build Coastguard Worker   for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
39*890232f2SAndroid Build Coastguard Worker }
40*890232f2SAndroid Build Coastguard Worker 
ForAllEnumValues(const reflection::Enum * enum_def,std::function<void (const reflection::EnumVal *)> func)41*890232f2SAndroid Build Coastguard Worker static void ForAllEnumValues(const reflection::Enum *enum_def,
42*890232f2SAndroid Build Coastguard Worker                       std::function<void(const reflection::EnumVal *)> func) {
43*890232f2SAndroid Build Coastguard Worker   for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
44*890232f2SAndroid Build Coastguard Worker        ++it) {
45*890232f2SAndroid Build Coastguard Worker     func(*it);
46*890232f2SAndroid Build Coastguard Worker   }
47*890232f2SAndroid Build Coastguard Worker }
48*890232f2SAndroid Build Coastguard Worker 
ForAllDocumentation(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> * documentation,std::function<void (const flatbuffers::String *)> func)49*890232f2SAndroid Build Coastguard Worker static void ForAllDocumentation(
50*890232f2SAndroid Build Coastguard Worker     const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
51*890232f2SAndroid Build Coastguard Worker         *documentation,
52*890232f2SAndroid Build Coastguard Worker     std::function<void(const flatbuffers::String *)> func) {
53*890232f2SAndroid Build Coastguard Worker   if (!documentation) { return; }
54*890232f2SAndroid Build Coastguard Worker   for (auto it = documentation->cbegin(); it != documentation->cend(); ++it) {
55*890232f2SAndroid Build Coastguard Worker     func(*it);
56*890232f2SAndroid Build Coastguard Worker   }
57*890232f2SAndroid Build Coastguard Worker }
58*890232f2SAndroid Build Coastguard Worker 
59*890232f2SAndroid Build Coastguard Worker // Maps the field index into object->fields() to the field's ID (the ith element
60*890232f2SAndroid Build Coastguard Worker // in the return vector).
FieldIdToIndex(const reflection::Object * object)61*890232f2SAndroid Build Coastguard Worker static std::vector<uint32_t> FieldIdToIndex(const reflection::Object *object) {
62*890232f2SAndroid Build Coastguard Worker   std::vector<uint32_t> field_index_by_id;
63*890232f2SAndroid Build Coastguard Worker   field_index_by_id.resize(object->fields()->size());
64*890232f2SAndroid Build Coastguard Worker 
65*890232f2SAndroid Build Coastguard Worker   // Create the mapping of field ID to the index into the vector.
66*890232f2SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < object->fields()->size(); ++i) {
67*890232f2SAndroid Build Coastguard Worker     auto field = object->fields()->Get(i);
68*890232f2SAndroid Build Coastguard Worker     field_index_by_id[field->id()] = i;
69*890232f2SAndroid Build Coastguard Worker   }
70*890232f2SAndroid Build Coastguard Worker 
71*890232f2SAndroid Build Coastguard Worker   return field_index_by_id;
72*890232f2SAndroid Build Coastguard Worker }
73*890232f2SAndroid Build Coastguard Worker 
IsStructOrTable(const reflection::BaseType base_type)74*890232f2SAndroid Build Coastguard Worker static bool IsStructOrTable(const reflection::BaseType base_type) {
75*890232f2SAndroid Build Coastguard Worker   return base_type == reflection::Obj;
76*890232f2SAndroid Build Coastguard Worker }
77*890232f2SAndroid Build Coastguard Worker 
IsFloatingPoint(const reflection::BaseType base_type)78*890232f2SAndroid Build Coastguard Worker static bool IsFloatingPoint(const reflection::BaseType base_type) {
79*890232f2SAndroid Build Coastguard Worker   return base_type == reflection::Float || base_type == reflection::Double;
80*890232f2SAndroid Build Coastguard Worker }
81*890232f2SAndroid Build Coastguard Worker 
IsBool(const reflection::BaseType base_type)82*890232f2SAndroid Build Coastguard Worker static bool IsBool(const reflection::BaseType base_type) {
83*890232f2SAndroid Build Coastguard Worker   return base_type == reflection::Bool;
84*890232f2SAndroid Build Coastguard Worker }
85*890232f2SAndroid Build Coastguard Worker 
IsSingleByte(const reflection::BaseType base_type)86*890232f2SAndroid Build Coastguard Worker static bool IsSingleByte(const reflection::BaseType base_type) {
87*890232f2SAndroid Build Coastguard Worker   return base_type >= reflection::UType && base_type <= reflection::UByte;
88*890232f2SAndroid Build Coastguard Worker }
89*890232f2SAndroid Build Coastguard Worker 
IsVector(const reflection::BaseType base_type)90*890232f2SAndroid Build Coastguard Worker static bool IsVector(const reflection::BaseType base_type) {
91*890232f2SAndroid Build Coastguard Worker   return base_type == reflection::Vector;
92*890232f2SAndroid Build Coastguard Worker }
93*890232f2SAndroid Build Coastguard Worker 
94*890232f2SAndroid Build Coastguard Worker } // namespace
95*890232f2SAndroid Build Coastguard Worker 
96*890232f2SAndroid Build Coastguard Worker // A concrete base Flatbuffer Generator that specific language generators can
97*890232f2SAndroid Build Coastguard Worker // derive from.
98*890232f2SAndroid Build Coastguard Worker class BaseBfbsGenerator : public BfbsGenerator {
99*890232f2SAndroid Build Coastguard Worker  public:
~BaseBfbsGenerator()100*890232f2SAndroid Build Coastguard Worker   virtual ~BaseBfbsGenerator() {}
BaseBfbsGenerator()101*890232f2SAndroid Build Coastguard Worker   BaseBfbsGenerator() : schema_(nullptr) {}
102*890232f2SAndroid Build Coastguard Worker 
103*890232f2SAndroid Build Coastguard Worker   virtual GeneratorStatus GenerateFromSchema(
104*890232f2SAndroid Build Coastguard Worker       const reflection::Schema *schema) = 0;
105*890232f2SAndroid Build Coastguard Worker 
106*890232f2SAndroid Build Coastguard Worker   //
107*890232f2SAndroid Build Coastguard Worker   virtual uint64_t SupportedAdvancedFeatures() const = 0;
108*890232f2SAndroid Build Coastguard Worker 
109*890232f2SAndroid Build Coastguard Worker   // Override of the Generator::generate method that does the initial
110*890232f2SAndroid Build Coastguard Worker   // deserialization and verification steps.
Generate(const uint8_t * buffer,int64_t length)111*890232f2SAndroid Build Coastguard Worker   GeneratorStatus Generate(const uint8_t *buffer,
112*890232f2SAndroid Build Coastguard Worker                            int64_t length) FLATBUFFERS_OVERRIDE {
113*890232f2SAndroid Build Coastguard Worker     flatbuffers::Verifier verifier(buffer, static_cast<size_t>(length));
114*890232f2SAndroid Build Coastguard Worker     if (!reflection::VerifySchemaBuffer(verifier)) {
115*890232f2SAndroid Build Coastguard Worker       return FAILED_VERIFICATION;
116*890232f2SAndroid Build Coastguard Worker     }
117*890232f2SAndroid Build Coastguard Worker 
118*890232f2SAndroid Build Coastguard Worker     // Store the root schema since there are cases where leaf nodes refer to
119*890232f2SAndroid Build Coastguard Worker     // things in the root schema (e.g., indexing the objects).
120*890232f2SAndroid Build Coastguard Worker     schema_ = reflection::GetSchema(buffer);
121*890232f2SAndroid Build Coastguard Worker 
122*890232f2SAndroid Build Coastguard Worker     const uint64_t advance_features = schema_->advanced_features();
123*890232f2SAndroid Build Coastguard Worker     if (advance_features > SupportedAdvancedFeatures()) {
124*890232f2SAndroid Build Coastguard Worker       return FAILED_VERIFICATION;
125*890232f2SAndroid Build Coastguard Worker     }
126*890232f2SAndroid Build Coastguard Worker 
127*890232f2SAndroid Build Coastguard Worker     GeneratorStatus status = GenerateFromSchema(schema_);
128*890232f2SAndroid Build Coastguard Worker     schema_ = nullptr;
129*890232f2SAndroid Build Coastguard Worker     return status;
130*890232f2SAndroid Build Coastguard Worker   }
131*890232f2SAndroid Build Coastguard Worker 
132*890232f2SAndroid Build Coastguard Worker  protected:
GetObject(const reflection::Type * type)133*890232f2SAndroid Build Coastguard Worker   const reflection::Object *GetObject(const reflection::Type *type) const {
134*890232f2SAndroid Build Coastguard Worker     if (type->index() >= 0 && IsStructOrTable(type->base_type())) {
135*890232f2SAndroid Build Coastguard Worker       return GetObjectByIndex(type->index());
136*890232f2SAndroid Build Coastguard Worker     }
137*890232f2SAndroid Build Coastguard Worker     return nullptr;
138*890232f2SAndroid Build Coastguard Worker   }
139*890232f2SAndroid Build Coastguard Worker 
GetEnum(const reflection::Type * type)140*890232f2SAndroid Build Coastguard Worker   const reflection::Enum *GetEnum(const reflection::Type *type) const {
141*890232f2SAndroid Build Coastguard Worker     // TODO(derekbailey): it would be better to have a explicit list of allowed
142*890232f2SAndroid Build Coastguard Worker     // base types, instead of negating Obj types.
143*890232f2SAndroid Build Coastguard Worker     if (type->index() >= 0 && !IsStructOrTable(type->base_type())) {
144*890232f2SAndroid Build Coastguard Worker       return GetEnumByIndex(type->index());
145*890232f2SAndroid Build Coastguard Worker     }
146*890232f2SAndroid Build Coastguard Worker     return nullptr;
147*890232f2SAndroid Build Coastguard Worker   }
148*890232f2SAndroid Build Coastguard Worker 
149*890232f2SAndroid Build Coastguard Worker   // Used to get a object that is reference by index. (e.g.
150*890232f2SAndroid Build Coastguard Worker   // reflection::Type::index). Returns nullptr if no object is available.
GetObjectByIndex(int32_t index)151*890232f2SAndroid Build Coastguard Worker   const reflection::Object *GetObjectByIndex(int32_t index) const {
152*890232f2SAndroid Build Coastguard Worker     if (!schema_ || index < 0 ||
153*890232f2SAndroid Build Coastguard Worker         index >= static_cast<int32_t>(schema_->objects()->size())) {
154*890232f2SAndroid Build Coastguard Worker       return nullptr;
155*890232f2SAndroid Build Coastguard Worker     }
156*890232f2SAndroid Build Coastguard Worker     return schema_->objects()->Get(index);
157*890232f2SAndroid Build Coastguard Worker   }
158*890232f2SAndroid Build Coastguard Worker 
159*890232f2SAndroid Build Coastguard Worker   // Used to get a enum that is reference by index. (e.g.
160*890232f2SAndroid Build Coastguard Worker   // reflection::Type::index). Returns nullptr if no enum is available.
GetEnumByIndex(int32_t index)161*890232f2SAndroid Build Coastguard Worker   const reflection::Enum *GetEnumByIndex(int32_t index) const {
162*890232f2SAndroid Build Coastguard Worker     if (!schema_ || index < 0 ||
163*890232f2SAndroid Build Coastguard Worker         index >= static_cast<int32_t>(schema_->enums()->size())) {
164*890232f2SAndroid Build Coastguard Worker       return nullptr;
165*890232f2SAndroid Build Coastguard Worker     }
166*890232f2SAndroid Build Coastguard Worker     return schema_->enums()->Get(index);
167*890232f2SAndroid Build Coastguard Worker   }
168*890232f2SAndroid Build Coastguard Worker 
ForAllFields(const reflection::Object * object,bool reverse,std::function<void (const reflection::Field *)> func)169*890232f2SAndroid Build Coastguard Worker   void ForAllFields(const reflection::Object *object, bool reverse,
170*890232f2SAndroid Build Coastguard Worker                     std::function<void(const reflection::Field *)> func) const {
171*890232f2SAndroid Build Coastguard Worker     const std::vector<uint32_t> field_to_id_map = FieldIdToIndex(object);
172*890232f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < field_to_id_map.size(); ++i) {
173*890232f2SAndroid Build Coastguard Worker       func(object->fields()->Get(
174*890232f2SAndroid Build Coastguard Worker           field_to_id_map[reverse ? field_to_id_map.size() - (i + 1) : i]));
175*890232f2SAndroid Build Coastguard Worker     }
176*890232f2SAndroid Build Coastguard Worker   }
177*890232f2SAndroid Build Coastguard Worker 
178*890232f2SAndroid Build Coastguard Worker   bool IsTable(const reflection::Type *type, bool use_element = false) const {
179*890232f2SAndroid Build Coastguard Worker     return !IsStruct(type, use_element);
180*890232f2SAndroid Build Coastguard Worker   }
181*890232f2SAndroid Build Coastguard Worker 
182*890232f2SAndroid Build Coastguard Worker   bool IsStruct(const reflection::Type *type, bool use_element = false) const {
183*890232f2SAndroid Build Coastguard Worker     const reflection::BaseType base_type =
184*890232f2SAndroid Build Coastguard Worker         use_element ? type->element() : type->base_type();
185*890232f2SAndroid Build Coastguard Worker     return IsStructOrTable(base_type) &&
186*890232f2SAndroid Build Coastguard Worker            GetObjectByIndex(type->index())->is_struct();
187*890232f2SAndroid Build Coastguard Worker   }
188*890232f2SAndroid Build Coastguard Worker 
189*890232f2SAndroid Build Coastguard Worker   const reflection::Schema *schema_;
190*890232f2SAndroid Build Coastguard Worker };
191*890232f2SAndroid Build Coastguard Worker 
192*890232f2SAndroid Build Coastguard Worker }  // namespace flatbuffers
193*890232f2SAndroid Build Coastguard Worker 
194*890232f2SAndroid Build Coastguard Worker #endif  // FLATBUFFERS_BFBS_GEN_H_
195