blob: 8e3c6f37242e3e3140cd7711c2f7d412eed93ea3 [file] [log] [blame]
James Kuszmauldac091f2022-03-22 09:35:06 -07001/*
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_BFBS_GEN_H_
18#define FLATBUFFERS_BFBS_GEN_H_
19
20#include <cstdint>
21
22#include "flatbuffers/bfbs_generator.h"
23#include "flatbuffers/reflection_generated.h"
24
25namespace flatbuffers {
26
Austin Schuha1d006e2022-09-14 21:50:42 -070027namespace {
28
29static void ForAllEnums(
James Kuszmauldac091f2022-03-22 09:35:06 -070030 const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums,
31 std::function<void(const reflection::Enum *)> func) {
32 for (auto it = enums->cbegin(); it != enums->cend(); ++it) { func(*it); }
33}
34
Austin Schuha1d006e2022-09-14 21:50:42 -070035static void ForAllObjects(
James Kuszmauldac091f2022-03-22 09:35:06 -070036 const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects,
37 std::function<void(const reflection::Object *)> func) {
38 for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
39}
40
James Kuszmaul65541cb2022-11-08 14:53:47 -080041static void ForAllEnumValues(
42 const reflection::Enum *enum_def,
43 std::function<void(const reflection::EnumVal *)> func) {
James Kuszmauldac091f2022-03-22 09:35:06 -070044 for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
45 ++it) {
46 func(*it);
47 }
48}
49
Austin Schuha1d006e2022-09-14 21:50:42 -070050static void ForAllDocumentation(
James Kuszmauldac091f2022-03-22 09:35:06 -070051 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
52 *documentation,
53 std::function<void(const flatbuffers::String *)> func) {
54 if (!documentation) { return; }
55 for (auto it = documentation->cbegin(); it != documentation->cend(); ++it) {
56 func(*it);
57 }
58}
59
60// Maps the field index into object->fields() to the field's ID (the ith element
61// in the return vector).
62static std::vector<uint32_t> FieldIdToIndex(const reflection::Object *object) {
63 std::vector<uint32_t> field_index_by_id;
64 field_index_by_id.resize(object->fields()->size());
65
66 // Create the mapping of field ID to the index into the vector.
67 for (uint32_t i = 0; i < object->fields()->size(); ++i) {
68 auto field = object->fields()->Get(i);
69 field_index_by_id[field->id()] = i;
70 }
71
72 return field_index_by_id;
73}
74
75static bool IsStructOrTable(const reflection::BaseType base_type) {
76 return base_type == reflection::BaseType::Obj;
77}
78
James Kuszmauldac091f2022-03-22 09:35:06 -070079static bool IsFloatingPoint(const reflection::BaseType base_type) {
80 return base_type == reflection::BaseType::Float || base_type == reflection::BaseType::Double;
81}
82
83static bool IsBool(const reflection::BaseType base_type) {
84 return base_type == reflection::BaseType::Bool;
85}
86
87static bool IsSingleByte(const reflection::BaseType base_type) {
88 return base_type >= reflection::BaseType::UType && base_type <= reflection::BaseType::UByte;
89}
90
91static bool IsVector(const reflection::BaseType base_type) {
92 return base_type == reflection::BaseType::Vector;
93}
94
James Kuszmaul65541cb2022-11-08 14:53:47 -080095} // namespace
James Kuszmauldac091f2022-03-22 09:35:06 -070096
97// A concrete base Flatbuffer Generator that specific language generators can
98// derive from.
99class BaseBfbsGenerator : public BfbsGenerator {
100 public:
101 virtual ~BaseBfbsGenerator() {}
102 BaseBfbsGenerator() : schema_(nullptr) {}
103
104 virtual GeneratorStatus GenerateFromSchema(
105 const reflection::Schema *schema) = 0;
106
107 //
108 virtual uint64_t SupportedAdvancedFeatures() const = 0;
109
110 // Override of the Generator::generate method that does the initial
111 // deserialization and verification steps.
112 GeneratorStatus Generate(const uint8_t *buffer,
113 int64_t length) FLATBUFFERS_OVERRIDE {
114 flatbuffers::Verifier verifier(buffer, static_cast<size_t>(length));
115 if (!reflection::VerifySchemaBuffer(verifier)) {
116 return FAILED_VERIFICATION;
117 }
118
119 // Store the root schema since there are cases where leaf nodes refer to
120 // things in the root schema (e.g., indexing the objects).
121 schema_ = reflection::GetSchema(buffer);
122
123 const uint64_t advance_features = static_cast<uint64_t>(schema_->advanced_features());
124 if (advance_features > SupportedAdvancedFeatures()) {
125 return FAILED_VERIFICATION;
126 }
127
128 GeneratorStatus status = GenerateFromSchema(schema_);
129 schema_ = nullptr;
130 return status;
131 }
132
133 protected:
James Kuszmaul65541cb2022-11-08 14:53:47 -0800134 // GetObject returns the underlying object struct of the given type
135 // if element_type is true and GetObject is a list of objects then
136 // GetObject will correctly return the object struct of the vector's elements
137 const reflection::Object *GetObject(const reflection::Type *type,
138 bool element_type = false) const {
139 const reflection::BaseType base_type =
140 element_type ? type->element() : type->base_type();
141 if (type->index() >= 0 && IsStructOrTable(base_type)) {
James Kuszmauldac091f2022-03-22 09:35:06 -0700142 return GetObjectByIndex(type->index());
143 }
144 return nullptr;
145 }
146
James Kuszmaul65541cb2022-11-08 14:53:47 -0800147 // GetEnum returns the underlying enum struct of the given type
148 // if element_type is true and GetEnum is a list of enums then
149 // GetEnum will correctly return the enum struct of the vector's elements
150 const reflection::Enum *GetEnum(const reflection::Type *type,
151 bool element_type = false) const {
152 const reflection::BaseType base_type =
153 element_type ? type->element() : type->base_type();
James Kuszmauldac091f2022-03-22 09:35:06 -0700154 // TODO(derekbailey): it would be better to have a explicit list of allowed
155 // base types, instead of negating Obj types.
James Kuszmaul65541cb2022-11-08 14:53:47 -0800156 if (type->index() >= 0 && !IsStructOrTable(base_type)) {
James Kuszmauldac091f2022-03-22 09:35:06 -0700157 return GetEnumByIndex(type->index());
158 }
159 return nullptr;
160 }
161
162 // Used to get a object that is reference by index. (e.g.
163 // reflection::Type::index). Returns nullptr if no object is available.
164 const reflection::Object *GetObjectByIndex(int32_t index) const {
165 if (!schema_ || index < 0 ||
166 index >= static_cast<int32_t>(schema_->objects()->size())) {
167 return nullptr;
168 }
169 return schema_->objects()->Get(index);
170 }
171
172 // Used to get a enum that is reference by index. (e.g.
173 // reflection::Type::index). Returns nullptr if no enum is available.
174 const reflection::Enum *GetEnumByIndex(int32_t index) const {
175 if (!schema_ || index < 0 ||
176 index >= static_cast<int32_t>(schema_->enums()->size())) {
177 return nullptr;
178 }
179 return schema_->enums()->Get(index);
180 }
181
182 void ForAllFields(const reflection::Object *object, bool reverse,
183 std::function<void(const reflection::Field *)> func) const {
184 const std::vector<uint32_t> field_to_id_map = FieldIdToIndex(object);
185 for (size_t i = 0; i < field_to_id_map.size(); ++i) {
186 func(object->fields()->Get(
187 field_to_id_map[reverse ? field_to_id_map.size() - (i + 1) : i]));
188 }
189 }
190
191 bool IsTable(const reflection::Type *type, bool use_element = false) const {
192 return !IsStruct(type, use_element);
193 }
194
195 bool IsStruct(const reflection::Type *type, bool use_element = false) const {
196 const reflection::BaseType base_type =
197 use_element ? type->element() : type->base_type();
198 return IsStructOrTable(base_type) &&
199 GetObjectByIndex(type->index())->is_struct();
200 }
201
202 const reflection::Schema *schema_;
203};
204
205} // namespace flatbuffers
206
207#endif // FLATBUFFERS_BFBS_GEN_H_