Skip to content

Commit 8d011a1

Browse files
committed
Port pull request google#3987
1 parent 6cc30b3 commit 8d011a1

11 files changed

+495
-34
lines changed

include/flatbuffers/idl.h

+18-7
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ namespace flatbuffers {
6565
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
6666
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
6767
TD(UNION, "", Offset<void>, int, int, int, int, unused)
68-
68+
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
69+
TD(ARRAY, "", int, int, int, int, int, unused)
6970
// The fields are:
7071
// - enum
7172
// - FlatBuffers schema type.
@@ -91,7 +92,8 @@ switch (type) {
9192

9293
#define FLATBUFFERS_GEN_TYPES(TD) \
9394
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
94-
FLATBUFFERS_GEN_TYPES_POINTER(TD)
95+
FLATBUFFERS_GEN_TYPES_POINTER(TD) \
96+
FLATBUFFERS_GEN_TYPE_ARRAY(TD)
9597

9698
// Create an enum for all the types above.
9799
#ifdef __GNUC__
@@ -138,18 +140,19 @@ class Parser;
138140
// and additional information for vectors/structs_.
139141
struct Type {
140142
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
141-
EnumDef *_ed = nullptr)
143+
EnumDef *_ed = nullptr, short _fixed_length = 0)
142144
: base_type(_base_type),
143145
element(BASE_TYPE_NONE),
144146
struct_def(_sd),
145-
enum_def(_ed) {}
147+
enum_def(_ed),
148+
fixed_length(_fixed_length) {}
146149

147150
bool operator==(const Type &o) {
148151
return base_type == o.base_type && element == o.element &&
149152
struct_def == o.struct_def && enum_def == o.enum_def;
150153
}
151154

152-
Type VectorType() const { return Type(element, struct_def, enum_def); }
155+
Type VectorType() const { return Type(element, struct_def, enum_def, fixed_length); }
153156

154157
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
155158

@@ -160,6 +163,7 @@ struct Type {
160163
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
161164
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
162165
// or for an integral type derived from an enum.
166+
short fixed_length; // only set if t == BASE_TYPE_ARRAY
163167
};
164168

165169
// Represents a parsed scalar value, it's type, and field offset.
@@ -319,12 +323,18 @@ inline bool IsStruct(const Type &type) {
319323
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
320324
}
321325

326+
inline bool IsArray(const Type &type) {
327+
return type.base_type == BASE_TYPE_ARRAY;
328+
}
329+
322330
inline size_t InlineSize(const Type &type) {
323-
return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
331+
return IsStruct(type) ? type.struct_def->bytesize : IsArray(type)
332+
? SizeOf(type.element) * type.fixed_length : SizeOf(type.base_type);
324333
}
325334

326335
inline size_t InlineAlignment(const Type &type) {
327-
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
336+
return IsStruct(type) ? type.struct_def->minalign :
337+
SizeOf(IsArray(type) ? type.element : type.base_type);
328338
}
329339

330340
struct EnumVal {
@@ -742,6 +752,7 @@ class Parser : public ParserState {
742752
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
743753
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
744754
FieldDef *field, size_t fieldn);
755+
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
745756
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
746757
size_t fieldn,
747758
const StructDef *parent_struct_def);

include/flatbuffers/reflection_generated.h

+19-6
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ enum BaseType {
4343
String = 13,
4444
Vector = 14,
4545
Obj = 15,
46-
Union = 16
46+
Union = 16,
47+
Array = 17
4748
};
4849

49-
inline const BaseType (&EnumValuesBaseType())[17] {
50+
inline const BaseType (&EnumValuesBaseType())[18] {
5051
static const BaseType values[] = {
5152
None,
5253
UType,
@@ -64,7 +65,8 @@ inline const BaseType (&EnumValuesBaseType())[17] {
6465
String,
6566
Vector,
6667
Obj,
67-
Union
68+
Union,
69+
Array
6870
};
6971
return values;
7072
}
@@ -88,13 +90,14 @@ inline const char * const *EnumNamesBaseType() {
8890
"Vector",
8991
"Obj",
9092
"Union",
93+
"Array",
9194
nullptr
9295
};
9396
return names;
9497
}
9598

9699
inline const char *EnumNameBaseType(BaseType e) {
97-
if (e < None || e > Union) return "";
100+
if (e < None || e > Array) return "";
98101
const size_t index = static_cast<size_t>(e);
99102
return EnumNamesBaseType()[index];
100103
}
@@ -103,7 +106,8 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
103106
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
104107
VT_BASE_TYPE = 4,
105108
VT_ELEMENT = 6,
106-
VT_INDEX = 8
109+
VT_INDEX = 8,
110+
VT_FIXED_LENGTH = 10
107111
};
108112
BaseType base_type() const {
109113
return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
@@ -114,11 +118,15 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
114118
int32_t index() const {
115119
return GetField<int32_t>(VT_INDEX, -1);
116120
}
121+
int16_t fixed_length() const {
122+
return GetField<int16_t>(VT_FIXED_LENGTH, 0);
123+
}
117124
bool Verify(flatbuffers::Verifier &verifier) const {
118125
return VerifyTableStart(verifier) &&
119126
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
120127
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
121128
VerifyField<int32_t>(verifier, VT_INDEX) &&
129+
VerifyField<int16_t>(verifier, VT_FIXED_LENGTH) &&
122130
verifier.EndTable();
123131
}
124132
};
@@ -135,6 +143,9 @@ struct TypeBuilder {
135143
void add_index(int32_t index) {
136144
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
137145
}
146+
void add_fixed_length(int16_t fixed_length) {
147+
fbb_.AddElement<int16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
148+
}
138149
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
139150
: fbb_(_fbb) {
140151
start_ = fbb_.StartTable();
@@ -151,9 +162,11 @@ inline flatbuffers::Offset<Type> CreateType(
151162
flatbuffers::FlatBufferBuilder &_fbb,
152163
BaseType base_type = None,
153164
BaseType element = None,
154-
int32_t index = -1) {
165+
int32_t index = -1,
166+
int16_t fixed_length = 0) {
155167
TypeBuilder builder_(_fbb);
156168
builder_.add_index(index);
169+
builder_.add_fixed_length(fixed_length);
157170
builder_.add_element(element);
158171
builder_.add_base_type(base_type);
159172
return builder_.Finish();

reflection/reflection.fbs

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ enum BaseType : byte {
2323
String,
2424
Vector,
2525
Obj, // Used for tables & structs.
26-
Union
26+
Union,
27+
Array
2728
}
2829

2930
table Type {
@@ -32,6 +33,7 @@ table Type {
3233
index:int = -1; // If base_type == Object, index into "objects" below.
3334
// If base_type == Union, UnionType, or integral derived
3435
// from an enum, index into "enums" below.
36+
fixed_length:short = 0; // Only if base_type == Array.
3537
}
3638

3739
table KeyValue {

src/idl_gen_cpp.cpp

+38-13
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ class CppGenerator : public BaseGenerator {
662662
bool user_facing_type) {
663663
if (IsScalar(type.base_type)) {
664664
return GenTypeBasic(type, user_facing_type) + afterbasic;
665+
} else if (IsArray(type)) {
666+
return beforeptr + GenTypeBasic(type.VectorType(), user_facing_type) + afterptr;
665667
} else {
666668
return beforeptr + GenTypePointer(type) + afterptr;
667669
}
@@ -2673,7 +2675,8 @@ class CppGenerator : public BaseGenerator {
26732675
code_.SetValue("FIELD_TYPE",
26742676
GenTypeGet(field.value.type, " ", "", " ", false));
26752677
code_.SetValue("FIELD_NAME", Name(field));
2676-
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;";
2678+
code_.SetValue("ARRAY", IsArray(field.value.type) ? "[" + NumToString<short>(field.value.type.fixed_length) + "]" : "");
2679+
code_ += (" {{FIELD_TYPE}}{{FIELD_NAME}}_{{ARRAY}};");
26772680

26782681
if (field.padding) {
26792682
std::string padding;
@@ -2711,21 +2714,28 @@ class CppGenerator : public BaseGenerator {
27112714
const auto member_name = Name(field) + "_";
27122715
const auto arg_name = "_" + Name(field);
27132716
const auto arg_type =
2714-
GenTypeGet(field.value.type, " ", "const ", " &", true);
2717+
GenTypeGet(field.value.type, " ", "const ",
2718+
IsArray(field.value.type) ? " *" : " &", true);
27152719

27162720
if (it != struct_def.fields.vec.begin()) {
27172721
arg_list += ", ";
2718-
init_list += ",\n ";
27192722
}
27202723
arg_list += arg_type;
27212724
arg_list += arg_name;
2722-
init_list += member_name;
2723-
if (IsScalar(field.value.type.base_type)) {
2724-
auto type = GenUnderlyingCast(field, false, arg_name);
2725-
init_list += "(flatbuffers::EndianScalar(" + type + "))";
2726-
} else {
2727-
init_list += "(" + arg_name + ")";
2725+
2726+
if (!IsArray(field.value.type)) {
2727+
if (it != struct_def.fields.vec.begin()) {
2728+
init_list += ",\n ";
2729+
}
2730+
init_list += member_name;
2731+
if (IsScalar(field.value.type.base_type)) {
2732+
auto type = GenUnderlyingCast(field, false, arg_name);
2733+
init_list += "(flatbuffers::EndianScalar(" + type + "))";
2734+
} else {
2735+
init_list += "(" + arg_name + ")";
2736+
}
27282737
}
2738+
27292739
if (field.padding) {
27302740
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
27312741
}
@@ -2734,12 +2744,19 @@ class CppGenerator : public BaseGenerator {
27342744
if (!arg_list.empty()) {
27352745
code_.SetValue("ARG_LIST", arg_list);
27362746
code_.SetValue("INIT_LIST", init_list);
2737-
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
2738-
code_ += " : {{INIT_LIST}} {";
2747+
if (!init_list.empty()) {
2748+
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
2749+
code_ += " : {{INIT_LIST}} {";
2750+
} else {
2751+
code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
2752+
}
27392753
padding_id = 0;
27402754
for (auto it = struct_def.fields.vec.begin();
27412755
it != struct_def.fields.vec.end(); ++it) {
27422756
const auto &field = **it;
2757+
if (IsArray(field.value.type)) {
2758+
code_ += " memcpy(" + field.name + "_, _" + field.name + ", " + NumToString(InlineSize(field.value.type)) + ");";
2759+
}
27432760
if (field.padding) {
27442761
std::string padding;
27452762
GenPadding(field, &padding, &padding_id, PaddingNoop);
@@ -2755,7 +2772,8 @@ class CppGenerator : public BaseGenerator {
27552772
it != struct_def.fields.vec.end(); ++it) {
27562773
const auto &field = **it;
27572774

2758-
auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true);
2775+
auto field_type = GenTypeGet(field.value.type, " ", "const ",
2776+
IsArray(field.value.type) ? " *" : " &", true);
27592777
auto is_scalar = IsScalar(field.value.type.base_type);
27602778
auto member = Name(field) + "_";
27612779
auto value =
@@ -2770,8 +2788,15 @@ class CppGenerator : public BaseGenerator {
27702788
code_ += " return {{FIELD_VALUE}};";
27712789
code_ += " }";
27722790

2791+
if (IsArray(field.value.type)) {
2792+
code_ += " int16_t " + field.name + "_length() const { ";
2793+
code_ += " return " + NumToString(field.value.type.fixed_length) + ";";
2794+
code_ += " }";
2795+
}
2796+
27732797
if (parser_.opts.mutable_buffer) {
2774-
auto mut_field_type = GenTypeGet(field.value.type, " ", "", " &", true);
2798+
auto mut_field_type = GenTypeGet(field.value.type, " ", "",
2799+
IsArray(field.value.type) ? " *" : " &", true);
27752800
code_.SetValue("FIELD_TYPE", mut_field_type);
27762801
if (is_scalar) {
27772802
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));

src/idl_gen_text.cpp

+47-2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,29 @@ bool PrintVector(const Vector<T> &v, Type type, int indent,
9999
return true;
100100
}
101101

102+
// Print an array a sequence of JSON values, comma separated, wrapped in "[]".
103+
template<typename T>
104+
bool PrintArray(const T *v, size_t size, Type type, int indent,
105+
const IDLOptions &opts, std::string *_text) {
106+
std::string &text = *_text;
107+
text += "[";
108+
text += NewLine(opts);
109+
for (uoffset_t i = 0; i < size; i++) {
110+
if (i) {
111+
if (!opts.protobuf_ascii_alike) text += ",";
112+
text += NewLine(opts);
113+
}
114+
text.append(indent + Indent(opts), ' ');
115+
if (!Print(v[i], type, indent + Indent(opts), nullptr, opts, _text)) {
116+
return false;
117+
}
118+
}
119+
text += NewLine(opts);
120+
text.append(indent, ' ');
121+
text += "]";
122+
return true;
123+
}
124+
102125
// Specialization of Print above for pointer types.
103126
template<>
104127
bool Print<const void *>(const void *val, Type type, int indent,
@@ -144,6 +167,27 @@ bool Print<const void *>(const void *val, Type type, int indent,
144167
// clang-format on
145168
}
146169
break;
170+
case BASE_TYPE_ARRAY: {
171+
// Call PrintVector above specifically for each element type:
172+
switch (type.VectorType().base_type) {
173+
// clang-format off
174+
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
175+
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
176+
case BASE_TYPE_ ## ENUM: \
177+
if (!PrintArray<CTYPE>( \
178+
reinterpret_cast<const CTYPE *>(val), type.fixed_length, \
179+
type, indent, opts, _text)) { \
180+
return false; \
181+
} \
182+
break;
183+
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
184+
#undef FLATBUFFERS_TD
185+
// clang-format on
186+
// Can't have non-scalar types in an array
187+
default: FLATBUFFERS_ASSERT(0);
188+
}
189+
}
190+
break;
147191
default: FLATBUFFERS_ASSERT(0);
148192
}
149193
return true;
@@ -177,8 +221,8 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
177221
std::string *_text) {
178222
const void *val = nullptr;
179223
if (fixed) {
180-
// The only non-scalar fields in structs are structs.
181-
FLATBUFFERS_ASSERT(IsStruct(fd.value.type));
224+
// The only non-scalar fields in structs are structs or arrays.
225+
FLATBUFFERS_ASSERT(IsStruct(fd.value.type) || IsArray(fd.value.type));
182226
val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
183227
fd.value.offset);
184228
} else if (fd.flexbuffer) {
@@ -241,6 +285,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
241285
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
242286
case BASE_TYPE_ ## ENUM:
243287
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
288+
FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
244289
#undef FLATBUFFERS_TD
245290
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
246291
union_type, opts, _text)) {

0 commit comments

Comments
 (0)