Add a wrapper around flatbuffers::TypeTable
So I can implement it on top of a Schema too.
Change-Id: I56502593e302c186cf48d3e2b42233a48202176d
diff --git a/aos/BUILD b/aos/BUILD
index 790f845..96c5b3d 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -337,6 +337,7 @@
target_compatible_with = ["@platforms//os:linux"],
deps = [
"@com_github_google_flatbuffers//:flatbuffers",
+ "@com_github_google_glog//:glog",
],
)
diff --git a/aos/flatbuffer_utils.cc b/aos/flatbuffer_utils.cc
index 1060fa8..b0615df 100644
--- a/aos/flatbuffer_utils.cc
+++ b/aos/flatbuffer_utils.cc
@@ -1 +1,147 @@
#include "aos/flatbuffer_utils.h"
+
+#include "flatbuffers/minireflect.h"
+#include "glog/logging.h"
+
+namespace aos {
+
+bool FlatbufferType::IsSequence() const {
+ if (type_table_) {
+ return type_table_->st != flatbuffers::ST_ENUM;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+bool FlatbufferType::IsEnum() const {
+ if (type_table_) {
+ return type_table_->st == flatbuffers::ST_ENUM;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+bool FlatbufferType::FieldIsSequence(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ const flatbuffers::TypeCode &type_code = type_table_->type_codes[index];
+ if (type_code.base_type != flatbuffers::ET_SEQUENCE) {
+ return false;
+ }
+ DCHECK(FieldType(index).IsSequence());
+ return true;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+bool FlatbufferType::FieldIsEnum(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ const flatbuffers::TypeCode &type_code = type_table_->type_codes[index];
+ if (type_code.base_type == flatbuffers::ET_SEQUENCE) {
+ return false;
+ }
+ if (type_code.sequence_ref == -1) {
+ // Not an enum.
+ return false;
+ }
+ DCHECK(FieldType(index).IsEnum());
+ return true;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+std::optional<int64_t> FlatbufferType::EnumValue(std::string_view name) const {
+ DCHECK(IsEnum());
+ if (type_table_) {
+ for (size_t i = 0; i < type_table_->num_elems; ++i) {
+ if (name == type_table_->names[i]) {
+ if (type_table_->values) {
+ return type_table_->values[i];
+ } else {
+ return i;
+ }
+ }
+ }
+ return std::nullopt;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+bool FlatbufferType::FieldIsRepeating(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ const flatbuffers::TypeCode &type_code = type_table_->type_codes[index];
+ return type_code.is_repeating;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+int FlatbufferType::FieldIndex(std::string_view field_name) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ for (size_t i = 0; i < type_table_->num_elems; ++i) {
+ if (field_name == std::string_view(type_table_->names[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+std::string_view FlatbufferType::FieldName(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ return type_table_->names[index];
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+flatbuffers::ElementaryType FlatbufferType::FieldElementaryType(
+ int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ const flatbuffers::TypeCode &type_code = type_table_->type_codes[index];
+ return static_cast<flatbuffers::ElementaryType>(type_code.base_type);
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+size_t FlatbufferType::FieldInlineSize(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ return flatbuffers::InlineSize(FieldElementaryType(index), type_table_);
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+int FlatbufferType::NumberFields() const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ return type_table_->num_elems;
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+FlatbufferType FlatbufferType::FieldType(int index) const {
+ DCHECK(IsSequence());
+ if (type_table_) {
+ DCHECK_LT(static_cast<size_t>(index), type_table_->num_elems);
+ const flatbuffers::TypeCode &type_code = type_table_->type_codes[index];
+ CHECK_GE(type_code.sequence_ref, 0);
+ // type_refs can be shorter than num_elems, but not longer, so this is still
+ // a valid sanity check.
+ DCHECK_LT(static_cast<size_t>(type_code.sequence_ref),
+ type_table_->num_elems);
+ const flatbuffers::TypeFunction type_function =
+ type_table_->type_refs[type_code.sequence_ref];
+ return FlatbufferType(type_function());
+ }
+ LOG(FATAL) << "Unimplemented";
+}
+
+} // namespace aos
diff --git a/aos/flatbuffer_utils.h b/aos/flatbuffer_utils.h
index 2b1c1ab..2118fd6 100644
--- a/aos/flatbuffer_utils.h
+++ b/aos/flatbuffer_utils.h
@@ -1,7 +1,11 @@
#ifndef AOS_FLATBUFFER_UTILS_
#define AOS_FLATBUFFER_UTILS_
+#include <optional>
+#include <string_view>
+
#include "flatbuffers/flatbuffers.h"
+#include "glog/logging.h"
namespace aos {
@@ -11,6 +15,86 @@
return flatbuffers::ElementaryTypeNames()[elementary_type] + 3;
}
+// A least-common-denominator API for a TypeTable or a Schema.
+//
+// An instance may represent an enum or a sequence (table, struct, or union).
+// Schemas have objects for the individual fields, but these are not exposed as
+// FlatbufferType instances.
+class FlatbufferType final {
+ public:
+ // Implicit on purpose, to allow freely creating a FlatbufferType.
+ FlatbufferType(const flatbuffers::TypeTable *type_table)
+ : type_table_(CHECK_NOTNULL(type_table)) {}
+
+ // This is deliberately copyable, for ease of memory management. It is cheap
+ // to pass by value.
+ FlatbufferType(const FlatbufferType &) = default;
+ FlatbufferType(FlatbufferType &&) = default;
+ FlatbufferType &operator=(const FlatbufferType &) = default;
+ FlatbufferType &operator=(FlatbufferType &&) = default;
+
+ // Returns whether this type is a sequence (table, struct, or union).
+ bool IsSequence() const;
+
+ // Returns whether this type is an enum.
+ bool IsEnum() const;
+
+ // Returns whether the given field is a sequence (table, struct, or union).
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ bool FieldIsSequence(int index) const;
+
+ // Returns whether the given field is an enum.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ bool FieldIsEnum(int index) const;
+
+ // Returns the value for a given enumerator.
+ //
+ // Only valid for enums.
+ std::optional<int64_t> EnumValue(std::string_view name) const;
+
+ // Returns whether the given field is either a vector (in a table) or an array
+ // (in a struct).
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ bool FieldIsRepeating(int index) const;
+
+ // Returns the field index in a table given the name, or -1 if the name is not
+ // found.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ int FieldIndex(std::string_view field_name) const;
+
+ // Returns the name for a field.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ std::string_view FieldName(int index) const;
+
+ // Returns the type of a field.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ flatbuffers::ElementaryType FieldElementaryType(int index) const;
+
+ // See flatbuffers::InlineSize for details.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ size_t FieldInlineSize(int index) const;
+
+ // Returns the total number of fields.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ int NumberFields() const;
+
+ // Returns the type for a field.
+ //
+ // Only valid for sequences (tables, structs, or unions).
+ FlatbufferType FieldType(int index) const;
+
+ private:
+ const flatbuffers::TypeTable *type_table_ = nullptr;
+};
+
} // namespace aos
#endif // AOS_FLATBUFFER_UTILS_
diff --git a/aos/json_to_flatbuffer.cc b/aos/json_to_flatbuffer.cc
index 036ae01..f64991d 100644
--- a/aos/json_to_flatbuffer.cc
+++ b/aos/json_to_flatbuffer.cc
@@ -17,19 +17,6 @@
// one is and how to test it. So everything rejects it.
namespace aos {
-
-// Finds the field index in the table given the name.
-int FieldIndex(const flatbuffers::TypeTable *typetable,
- const char *field_name) {
- CHECK(typetable->values == nullptr);
- for (size_t i = 0; i < typetable->num_elems; ++i) {
- if (strcmp(field_name, typetable->names[i]) == 0) {
- return i;
- }
- }
- return -1;
-}
-
namespace {
// Class to hold one of the 3 json types for an array.
@@ -77,30 +64,29 @@
// Adds a single element. This assumes that vectors have been dealt with
// already. Returns true on success.
-bool AddSingleElement(const flatbuffers::TypeTable *typetable,
- const FieldElement &field_element,
+bool AddSingleElement(FlatbufferType type, const FieldElement &field_element,
::std::vector<bool> *fields_in_use,
flatbuffers::FlatBufferBuilder *fbb);
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
- int64_t int_value, flatbuffers::FlatBufferBuilder *fbb);
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
- double double_value, flatbuffers::FlatBufferBuilder *fbb);
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
+bool AddSingleElement(FlatbufferType type, int field_index, int64_t int_value,
+ flatbuffers::FlatBufferBuilder *fbb);
+bool AddSingleElement(FlatbufferType type, int field_index, double double_value,
+ flatbuffers::FlatBufferBuilder *fbb);
+bool AddSingleElement(FlatbufferType type, int field_index,
flatbuffers::Offset<flatbuffers::String> offset_element,
flatbuffers::FlatBufferBuilder *fbb);
-// Writes an array of FieldElement (with the definition in the type
-// table) to the builder. Returns the offset of the table.
-flatbuffers::uoffset_t WriteTable(const flatbuffers::TypeTable *typetable,
+// Writes an array of FieldElement (with the definition in "type") to the
+// builder. Returns the offset of the resulting table.
+flatbuffers::uoffset_t WriteTable(FlatbufferType type,
const ::std::vector<FieldElement> &elements,
flatbuffers::FlatBufferBuilder *fbb) {
// End of a nested struct! Add it.
const flatbuffers::uoffset_t start = fbb->StartTable();
- ::std::vector<bool> fields_in_use(typetable->num_elems, false);
+ ::std::vector<bool> fields_in_use(type.NumberFields(), false);
for (const FieldElement &field_element : elements) {
- AddSingleElement(typetable, field_element, &fields_in_use, fbb);
+ AddSingleElement(type, field_element, &fields_in_use, fbb);
}
return fbb->EndTable(start);
@@ -123,10 +109,10 @@
// Parses the json into a flatbuffer. Returns either an empty vector on
// error, or a vector with the flatbuffer data in it.
- flatbuffers::Offset<flatbuffers::Table> Parse(
- const std::string_view data, const flatbuffers::TypeTable *typetable) {
+ flatbuffers::Offset<flatbuffers::Table> Parse(const std::string_view data,
+ FlatbufferType type) {
flatbuffers::uoffset_t end = 0;
- bool result = DoParse(typetable, data, &end);
+ bool result = DoParse(type, data, &end);
if (result) {
// On success, finish the table and build the vector.
@@ -143,8 +129,8 @@
// Parses the flatbuffer. This is a second method so we can do easier
// cleanup at the top level. Returns true on success.
- bool DoParse(const flatbuffers::TypeTable *typetable,
- const std::string_view data, flatbuffers::uoffset_t *table_end);
+ bool DoParse(FlatbufferType type, const std::string_view data,
+ flatbuffers::uoffset_t *table_end);
// Adds *_value for the provided field. If we are in a vector, queues the
// data up in vector_elements. Returns true on success.
@@ -169,7 +155,7 @@
// nested structures.
struct FlatBufferContext {
// Type of the current type.
- const flatbuffers::TypeTable *typetable;
+ FlatbufferType type;
// If true, we are parsing a vector.
bool in_vector;
// The field index of the current field.
@@ -194,10 +180,9 @@
::std::vector<FlatBufferContext> stack_;
};
-bool JsonParser::DoParse(const flatbuffers::TypeTable *typetable,
- const std::string_view data,
+bool JsonParser::DoParse(FlatbufferType type, const std::string_view data,
flatbuffers::uoffset_t *table_end) {
- ::std::vector<const flatbuffers::TypeTable *> stack;
+ ::std::vector<FlatbufferType> stack;
Tokenizer t(data);
@@ -220,23 +205,22 @@
case Tokenizer::TokenType::kStartObject: // {
if (stack_.size() == 0) {
- stack_.push_back({typetable, false, -1, "", {}, {}});
+ stack_.push_back({type, false, -1, "", {}, {}});
} else {
int field_index = stack_.back().field_index;
- const flatbuffers::TypeCode &type_code =
- stack_.back().typetable->type_codes[field_index];
-
- if (type_code.base_type != flatbuffers::ET_SEQUENCE) {
+ if (!stack_.back().type.FieldIsSequence(field_index)) {
fprintf(stderr, "Field '%s' is not a sequence\n",
stack_.back().field_name.c_str());
return false;
}
- flatbuffers::TypeFunction type_function =
- stack_.back().typetable->type_refs[type_code.sequence_ref];
-
- stack_.push_back({type_function(), false, -1, "", {}, {}});
+ stack_.push_back({stack_.back().type.FieldType(field_index),
+ false,
+ -1,
+ "",
+ {},
+ {}});
}
break;
case Tokenizer::TokenType::kEndObject: // }
@@ -247,7 +231,7 @@
} else {
// End of a nested struct! Add it.
const flatbuffers::uoffset_t end =
- WriteTable(stack_.back().typetable, stack_.back().elements, fbb_);
+ WriteTable(stack_.back().type, stack_.back().elements, fbb_);
// We now want to talk about the parent structure. Pop the child.
stack_.pop_back();
@@ -335,8 +319,8 @@
case Tokenizer::TokenType::kField: // field name
{
stack_.back().field_name = t.field_name();
- stack_.back().field_index = FieldIndex(
- stack_.back().typetable, stack_.back().field_name.c_str());
+ stack_.back().field_index =
+ stack_.back().type.FieldIndex(stack_.back().field_name.c_str());
if (stack_.back().field_index == -1) {
fprintf(stderr, "Invalid field name '%s'\n",
@@ -350,10 +334,7 @@
}
bool JsonParser::AddElement(int field_index, int64_t int_value) {
- flatbuffers::TypeCode type_code =
- stack_.back().typetable->type_codes[field_index];
-
- if (type_code.is_repeating != in_vector()) {
+ if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
return false;
}
@@ -367,10 +348,7 @@
}
bool JsonParser::AddElement(int field_index, double double_value) {
- flatbuffers::TypeCode type_code =
- stack_.back().typetable->type_codes[field_index];
-
- if (type_code.is_repeating != in_vector()) {
+ if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
return false;
}
@@ -384,16 +362,13 @@
}
bool JsonParser::AddElement(int field_index, const ::std::string &data) {
- flatbuffers::TypeCode type_code =
- stack_.back().typetable->type_codes[field_index];
-
- if (type_code.is_repeating != in_vector()) {
+ if (stack_.back().type.FieldIsRepeating(field_index) != in_vector()) {
fprintf(stderr, "Type and json disagree on if we are in a vector or not\n");
return false;
}
const flatbuffers::ElementaryType elementary_type =
- static_cast<flatbuffers::ElementaryType>(type_code.base_type);
+ stack_.back().type.FieldElementaryType(field_index);
switch (elementary_type) {
case flatbuffers::ET_CHAR:
case flatbuffers::ET_UCHAR:
@@ -403,40 +378,25 @@
case flatbuffers::ET_UINT:
case flatbuffers::ET_LONG:
case flatbuffers::ET_ULONG:
- if (type_code.sequence_ref != -1) {
+ if (stack_.back().type.FieldIsEnum(field_index)) {
// We have an enum.
- const flatbuffers::TypeTable *type_table = stack_.back().typetable;
- flatbuffers::TypeFunction type_function =
- type_table->type_refs[type_code.sequence_ref];
+ const FlatbufferType type = stack_.back().type;
+ const FlatbufferType enum_type = type.FieldType(field_index);
+ CHECK(enum_type.IsEnum());
- const flatbuffers::TypeTable *enum_type_table = type_function();
+ const std::optional<int64_t> int_value = enum_type.EnumValue(data);
- CHECK_EQ(enum_type_table->st, flatbuffers::ST_ENUM);
-
- int64_t int_value = 0;
- bool found = false;
- for (size_t i = 0; i < enum_type_table->num_elems; ++i) {
- if (data == enum_type_table->names[i]) {
- if (enum_type_table->values) {
- int_value = enum_type_table->values[i];
- } else {
- int_value = i;
- }
- found = true;
- break;
- }
- }
-
- if (!found) {
- fprintf(stderr, "Enum value '%s' not found for field '%s'\n",
- data.c_str(), type_table->names[field_index]);
+ if (!int_value) {
+ const std::string_view name = type.FieldName(field_index);
+ fprintf(stderr, "Enum value '%s' not found for field '%.*s'\n",
+ data.c_str(), static_cast<int>(name.size()), name.data());
return false;
}
if (in_vector()) {
- stack_.back().vector_elements.emplace_back(int_value);
+ stack_.back().vector_elements.emplace_back(*int_value);
} else {
- stack_.back().elements.emplace_back(field_index, int_value);
+ stack_.back().elements.emplace_back(field_index, *int_value);
}
return true;
}
@@ -457,13 +417,13 @@
return true;
}
-bool AddSingleElement(const flatbuffers::TypeTable *typetable,
- const FieldElement &field_element,
+bool AddSingleElement(FlatbufferType type, const FieldElement &field_element,
::std::vector<bool> *fields_in_use,
flatbuffers::FlatBufferBuilder *fbb) {
if ((*fields_in_use)[field_element.field_index]) {
- fprintf(stderr, "Duplicate field: '%s'\n",
- typetable->names[field_element.field_index]);
+ const std::string_view name = type.FieldName(field_element.field_index);
+ fprintf(stderr, "Duplicate field: '%.*s'\n", static_cast<int>(name.size()),
+ name.data());
return false;
}
@@ -471,29 +431,27 @@
switch (field_element.element.type) {
case Element::ElementType::INT:
- return AddSingleElement(typetable, field_element.field_index,
+ return AddSingleElement(type, field_element.field_index,
field_element.element.int_element, fbb);
case Element::ElementType::DOUBLE:
- return AddSingleElement(typetable, field_element.field_index,
+ return AddSingleElement(type, field_element.field_index,
field_element.element.double_element, fbb);
case Element::ElementType::OFFSET:
- return AddSingleElement(typetable, field_element.field_index,
+ return AddSingleElement(type, field_element.field_index,
field_element.element.offset_element, fbb);
}
return false;
}
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
- int64_t int_value, flatbuffers::FlatBufferBuilder *fbb
+bool AddSingleElement(FlatbufferType type, int field_index, int64_t int_value,
+ flatbuffers::FlatBufferBuilder *fbb
) {
flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
static_cast<flatbuffers::voffset_t>(field_index));
- flatbuffers::TypeCode type_code = typetable->type_codes[field_index];
-
const flatbuffers::ElementaryType elementary_type =
- static_cast<flatbuffers::ElementaryType>(type_code.base_type);
+ type.FieldElementaryType(field_index);
switch (elementary_type) {
case flatbuffers::ET_BOOL:
fbb->AddElement<bool>(field_offset, int_value, 0);
@@ -530,25 +488,25 @@
return true;
case flatbuffers::ET_STRING:
case flatbuffers::ET_UTYPE:
- case flatbuffers::ET_SEQUENCE:
- fprintf(
- stderr, "Mismatched type for field '%s'. Got: integer, expected %s\n",
- typetable->names[field_index], ElementaryTypeName(elementary_type));
+ case flatbuffers::ET_SEQUENCE: {
+ const std::string_view name = type.FieldName(field_index);
+ fprintf(stderr,
+ "Mismatched type for field '%.*s'. Got: integer, expected %s\n",
+ static_cast<int>(name.size()), name.data(),
+ ElementaryTypeName(elementary_type));
return false;
+ }
};
return false;
}
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
- double double_value,
+bool AddSingleElement(FlatbufferType type, int field_index, double double_value,
flatbuffers::FlatBufferBuilder *fbb) {
flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
static_cast<flatbuffers::voffset_t>(field_index));
- flatbuffers::TypeCode type_code = typetable->type_codes[field_index];
-
const flatbuffers::ElementaryType elementary_type =
- static_cast<flatbuffers::ElementaryType>(type_code.base_type);
+ type.FieldElementaryType(field_index);
switch (elementary_type) {
case flatbuffers::ET_UTYPE:
case flatbuffers::ET_BOOL:
@@ -561,11 +519,14 @@
case flatbuffers::ET_LONG:
case flatbuffers::ET_ULONG:
case flatbuffers::ET_STRING:
- case flatbuffers::ET_SEQUENCE:
- fprintf(
- stderr, "Mismatched type for field '%s'. Got: double, expected %s\n",
- typetable->names[field_index], ElementaryTypeName(elementary_type));
+ case flatbuffers::ET_SEQUENCE: {
+ const std::string_view name = type.FieldName(field_index);
+ fprintf(stderr,
+ "Mismatched type for field '%.*s'. Got: double, expected %s\n",
+ static_cast<int>(name.size()), name.data(),
+ ElementaryTypeName(elementary_type));
return false;
+ }
case flatbuffers::ET_FLOAT:
fbb->AddElement<float>(field_offset, double_value, 0);
return true;
@@ -575,22 +536,20 @@
}
return false;
}
-bool AddSingleElement(const flatbuffers::TypeTable *typetable, int field_index,
+bool AddSingleElement(FlatbufferType type, int field_index,
flatbuffers::Offset<flatbuffers::String> offset_element,
flatbuffers::FlatBufferBuilder *fbb) {
- flatbuffers::TypeCode type_code = typetable->type_codes[field_index];
-
flatbuffers::voffset_t field_offset = flatbuffers::FieldIndexToOffset(
static_cast<flatbuffers::voffset_t>(field_index));
// Vectors will always be Offset<>'s.
- if (type_code.is_repeating) {
+ if (type.FieldIsRepeating(field_index)) {
fbb->AddOffset(field_offset, offset_element);
return true;
}
const flatbuffers::ElementaryType elementary_type =
- static_cast<flatbuffers::ElementaryType>(type_code.base_type);
+ type.FieldElementaryType(field_index);
switch (elementary_type) {
case flatbuffers::ET_CHAR:
case flatbuffers::ET_UCHAR:
@@ -603,16 +562,15 @@
case flatbuffers::ET_UTYPE:
case flatbuffers::ET_BOOL:
case flatbuffers::ET_FLOAT:
- case flatbuffers::ET_DOUBLE:
- fprintf(
- stderr, "Mismatched type for field '%s'. Got: string, expected %s\n",
- typetable->names[field_index], ElementaryTypeName(elementary_type));
- CHECK_EQ(type_code.sequence_ref, -1)
- << ": Field name " << typetable->names[field_index]
- << " Got string expected " << ElementaryTypeName(elementary_type);
+ case flatbuffers::ET_DOUBLE: {
+ const std::string_view name = type.FieldName(field_index);
+ fprintf(stderr,
+ "Mismatched type for field '%.*s'. Got: string, expected %s\n",
+ static_cast<int>(name.size()), name.data(),
+ ElementaryTypeName(elementary_type));
return false;
+ }
case flatbuffers::ET_STRING:
- CHECK_EQ(type_code.sequence_ref, -1);
case flatbuffers::ET_SEQUENCE:
fbb->AddOffset(field_offset, offset_element);
return true;
@@ -621,16 +579,12 @@
}
bool JsonParser::FinishVector(int field_index) {
- flatbuffers::TypeCode type_code =
- stack_.back().typetable->type_codes[field_index];
+ // Vectors have a start (unfortunately which needs to know the size)
+ fbb_->StartVector(stack_.back().vector_elements.size(),
+ stack_.back().type.FieldInlineSize(field_index));
const flatbuffers::ElementaryType elementary_type =
- static_cast<flatbuffers::ElementaryType>(type_code.base_type);
-
- // Vectors have a start (unfortunately which needs to know the size)
- fbb_->StartVector(
- stack_.back().vector_elements.size(),
- flatbuffers::InlineSize(elementary_type, stack_.back().typetable));
+ stack_.back().type.FieldElementaryType(field_index);
// Then the data (in reverse order for some reason...)
for (size_t i = stack_.back().vector_elements.size(); i > 0;) {
@@ -640,8 +594,6 @@
if (!PushElement(elementary_type, element.int_element)) return false;
break;
case Element::ElementType::DOUBLE:
- CHECK_EQ(type_code.sequence_ref, -1)
- << ": Field index is " << field_index;
if (!PushElement(elementary_type, element.double_element)) return false;
break;
case Element::ElementType::OFFSET:
@@ -768,19 +720,19 @@
} // namespace
flatbuffers::Offset<flatbuffers::Table> JsonToFlatbuffer(
- const std::string_view data, const flatbuffers::TypeTable *typetable,
+ const std::string_view data, FlatbufferType type,
flatbuffers::FlatBufferBuilder *fbb) {
JsonParser p(fbb);
- return p.Parse(data, typetable);
+ return p.Parse(data, type);
}
-flatbuffers::DetachedBuffer JsonToFlatbuffer(
- const std::string_view data, const flatbuffers::TypeTable *typetable) {
+flatbuffers::DetachedBuffer JsonToFlatbuffer(const std::string_view data,
+ FlatbufferType type) {
flatbuffers::FlatBufferBuilder fbb;
fbb.ForceDefaults(true);
const flatbuffers::Offset<flatbuffers::Table> result =
- JsonToFlatbuffer(data, typetable, &fbb);
+ JsonToFlatbuffer(data, type, &fbb);
if (result.o != 0) {
fbb.Finish(result);
diff --git a/aos/json_to_flatbuffer.h b/aos/json_to_flatbuffer.h
index c1aa736..052fa9c 100644
--- a/aos/json_to_flatbuffer.h
+++ b/aos/json_to_flatbuffer.h
@@ -7,6 +7,7 @@
#include <string_view>
#include "aos/fast_string_builder.h"
+#include "aos/flatbuffer_utils.h"
#include "aos/flatbuffers.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/reflection.h"
@@ -14,25 +15,25 @@
namespace aos {
// Parses the flatbuffer into the buffer, or returns an empty buffer.
-flatbuffers::DetachedBuffer JsonToFlatbuffer(
- const std::string_view data, const flatbuffers::TypeTable *typetable);
+flatbuffers::DetachedBuffer JsonToFlatbuffer(std::string_view data,
+ FlatbufferType type);
// Parses the flatbuffer into the builder, and returns the offset.
flatbuffers::Offset<flatbuffers::Table> JsonToFlatbuffer(
- const std::string_view data, const flatbuffers::TypeTable *typetable,
+ std::string_view data, FlatbufferType type,
flatbuffers::FlatBufferBuilder *fbb);
// Typed versions of the above methods.
template <typename T>
inline flatbuffers::DetachedBuffer JsonToFlatbuffer(
const std::string_view data) {
- return JsonToFlatbuffer(data, T::MiniReflectTypeTable());
+ return JsonToFlatbuffer(data, FlatbufferType(T::MiniReflectTypeTable()));
}
template <typename T>
inline flatbuffers::Offset<T> JsonToFlatbuffer(
const std::string_view data, flatbuffers::FlatBufferBuilder *fbb) {
return flatbuffers::Offset<T>(
- JsonToFlatbuffer(data, T::MiniReflectTypeTable(), fbb).o);
+ JsonToFlatbuffer(data, FlatbufferType(T::MiniReflectTypeTable()), fbb).o);
}
struct JsonOptions {
@@ -68,17 +69,17 @@
Flatbuffer<T>::MiniReflectTypeTable(), json_options);
}
-std::string FlatbufferToJson(const reflection::Schema *const schema,
- const uint8_t *const data,
+std::string FlatbufferToJson(const reflection::Schema *schema,
+ const uint8_t *data,
JsonOptions json_options = {});
void FlatbufferToJson(FastStringBuilder *builder,
- const reflection::Schema *const schema,
- const uint8_t *const data, JsonOptions json_options = {});
+ const reflection::Schema *schema, const uint8_t *data,
+ JsonOptions json_options = {});
// Writes a Flatbuffer to a file, or dies.
template <typename T>
-inline void WriteFlatbufferToJson(const std::string_view filename,
+inline void WriteFlatbufferToJson(std::string_view filename,
const Flatbuffer<T> &msg) {
std::ofstream json_file(std::string(filename), std::ios::out);
CHECK(json_file) << ": Couldn't open " << filename;
@@ -88,7 +89,7 @@
// Writes a NonSizePrefixedFlatbuffer to a binary file, or dies.
template <typename T>
-inline void WriteFlatbufferToFile(const std::string_view filename,
+inline void WriteFlatbufferToFile(std::string_view filename,
const NonSizePrefixedFlatbuffer<T> &msg) {
std::ofstream file(std::string(filename),
std::ios::out | std::ofstream::binary);