-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed array length #5313
Fixed array length #5313
Conversation
Could you add an example of fbs and json as part of
|
An example to monster_extra was added. It seems the JSON generator crashes on parsing the floating point extensions, therefore a JSON schema is generated from array_test.fbs for now.
This syntax is derived from a proposed feature for flatcc.
Again this was derived from flatcc (see above). The expression
shall be equivalent to
in its binary representation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This generally looks great!
Besides the comments below, I am missing documentation, please add to Schema.md at least.
src/idl_gen_general.cpp
Outdated
@@ -312,7 +312,9 @@ class GeneralGenerator : public BaseGenerator { | |||
} | |||
|
|||
std::string GenTypeGet(const Type &type) const { | |||
return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type); | |||
return (IsScalar(type.base_type)) ? GenTypeBasic(type) | |||
: IsArray(type) ? GenTypeBasic(type.VectorType()) + " []" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put ()
around nested ?:
, here and below?
src/idl_gen_general.cpp
Outdated
@@ -980,6 +993,19 @@ class GeneralGenerator : public BaseGenerator { | |||
code += " : " + default_cast; | |||
code += GenDefaultValue(field); | |||
} | |||
} else if (IsArray(field.value.type)) { | |||
std::string type = GenTypeBasic(field.value.type.VectorType()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use auto
where possible.
src/idl_gen_json_schema.cpp
Outdated
|
||
std::string arrayInfo = ""; | ||
if (IsArray(property->value.type)) { | ||
arrayInfo = ",\n \"minItems\": " + NumToString<short>(property->value.type.fixed_length) + ",\n" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure all lines are <= 80 characters, here and elsewhere.
return Error("nested vector types not supported (wrap in table first)."); | ||
return Error("nested vector types not supported (wrap in table first)"); | ||
} | ||
if (token_ == ':') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this feature is not supported by all languages, we'll need a check similar to what is in SupportsAdvancedUnionFeatures
src/idl_parser.cpp
Outdated
return Error("structs_ may contain only scalar or struct fields"); | ||
|
||
if (!struct_def.fixed && IsArray(type)) | ||
return Error("tables can't contain fixed-length arrays"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe "fixed-length array in table must be wrapped in struct" to hint the user how to solve this problem.
tests/MyGame/MonsterExtra.cs
Outdated
|
||
public static Offset<MonsterExtra> CreateMonsterExtra(FlatBufferBuilder builder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this constructor being deleted because we don't generate them for structs that have arrays in them? If so that is fine I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constructor seems to be deleted as soon as a struct is added to a table. This is not related to the patch set.
tests/MyGame/MonsterExtra.py
Outdated
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) | ||
if o != 0: | ||
x = o + self._tab.Pos | ||
from .ArrayStruct import ArrayStruct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this import in the middle of the code? is that a normal thing to do in Python? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again this is seems to be generated when a struct is added to a table. It was not introduced with this patch set :)
tests/arrays_test.fbs
Outdated
namespace MyGame.Example; | ||
|
||
struct ArrayStruct{ | ||
a:float; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consistently indent 2 spaces.
tests/arrays_test_generated.h
Outdated
c_(flatbuffers::EndianScalar(_c)), | ||
padding0__(0), | ||
padding1__(0) { | ||
memcpy(b_, _b, 60); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not work on big endian machines, you'll need a loop with EndianScalar
I'm afraid. Maybe make it a helper templated function in flatbuffers.h
.
tests/arrays_test_generated.h
Outdated
void mutate_a(float _a) { | ||
flatbuffers::WriteScalar(&a_, _a); | ||
} | ||
const int32_t *b() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also endian unsafe. Make a class like Vector
that does all access.
2771eb7
to
10c094a
Compare
Thank you for your kind response. I introduced most of the requested changes and I left some comments on the remaining ones. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include/flatbuffers/flatbuffers.h
Outdated
// Get a mutable pointer to tables/strings inside this array. | ||
mutable_return_type GetMutableObject(uoffset_t i) const { | ||
FLATBUFFERS_ASSERT(i < size()); | ||
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
src/idl_parser.cpp
Outdated
if (token_ != ',') | ||
{ | ||
ECHECK(ParseSingleValue(nullptr, val, false)); | ||
stack.push_back(val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not saying to not use ParseSingleValue
, I am saying not to allocate a whole stack of Value
. You can instead use a single Value
and instead store a buffer of the actual binary values.
tests/MyGame/ArrayStruct.java
Outdated
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; } | ||
public ArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } | ||
|
||
public int [] array() { int [] b = new int[2]; for (int i = 0; i < 2; i++) { b[i] = bb.getInt(bb_pos + 0 + i * 4); } return b; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but those can be reused. Array accesses are potentially performance sensitive, so lets follow the existing vector API design.
|
||
return_type Get(uoffset_t i) const { | ||
FLATBUFFERS_ASSERT(i < size()); | ||
return IndirectHelper<T>::Read(Data(), i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird, github somehow deleted my comment that "same here" refers to.
In short: lets not use IndirectHelper
since unlike Vector
we don't have complex types to dereference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment on struct size.
I also think we need to discuss char arrays. This is a much requested featured because short strings are used in communication buffers etc. The big question is how to deal with the null terminator.
On the schema array syntax referenced in the flatcc doc - I think it was Wouter who originally proposed that syntax elsewhere.
src/idl_parser.cpp
Outdated
"length of fixed-length array must be an integer value"); | ||
} | ||
int64_t fixed_length = StringToInt(attribute_.c_str()); | ||
if (fixed_length < 1 || fixed_length > 0x7fff) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://stackoverflow.com/a/7724909 says 2^16-1 is a C limit on object size, so it would be reasonable to limit the size to 16 bits, though I'm not sure about a 2^15-1 length limit. I'd rather place a limit on struct sizes of 2^16-1 and forego array length limits.
Does the syntax permit hex size?
flatcc generally accepts hex values in the schema parser where integers are permitted. |
On alignment: I think alignment should be to the element size of the fixed array not the array size as such. The statement of equivalence to repeated scalar fields implies that. On lenght limit: flatcc already imposes the following struct limit by default. While this limit is derived fro flatbuffers voffset_t size, it incidentally happens to the limit set by the C standard for portable struct sizes. I don't think the 0x7fff length limit is a good idea. It would prevent 32K lookup tables. config/config.h
|
We probably also want to permit fixed size arrays of structs as they can be used as typedefs. This causes a problem with 0-size arrays because structs can be zero-size. Hence I'm not sure if disallowing array length 0 makes sense since the special case will be present in either case. C does not allow empty arrays or structs. |
I'm not sure if flatc has key attributes on struct fields (flatcc does), but they probably should not be allowed on fixed size arrays. |
include/flatbuffers/flatbuffers.h
Outdated
@@ -393,6 +393,84 @@ template<typename T> static inline size_t VectorLength(const Vector<T> *v) { | |||
return v ? v->size() : 0; | |||
} | |||
|
|||
// This is used as a helper type for accessing arrays. | |||
template<typename T, int length> class Array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type of length should be matched with:
- uoffset_t size() const { return length; }
- short Type::fixed_length
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to uint16_t
.
include/flatbuffers/idl.h
Outdated
@@ -167,6 +170,7 @@ struct Type { | |||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT | |||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE, | |||
// or for an integral type derived from an enum. | |||
short fixed_length; // only set if t == BASE_TYPE_ARRAY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why type of fixed_length
is signed short
?
Somewhere in the code are negative values used?
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i)); | ||
} | ||
|
||
// The raw data in little endian format. Use with care. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does little endian
mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Little endian is the most common storage order of integers with the least significant byte first.
Big endian has the opposite order. There are also other exotic orders found on old machines and in cryptography. The name originates from the childrens book Gulliver's travels where he visits the two neighbouring islands where one population eats their eggs with the big end up, and the other population eats their eggs with the little end up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read Gulliver :)
Let, I have BE
machine and declare an array:
int arr[3]={1,2,3};
auto pu8 = reinterpret_cast<const uint8_t*>(&arr[0]);
By nature, the pu8
is neither BE
nor LE
.
It points to memory with BE integers (not to LE).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrong, but have a new question.
Scalar is always represented in little-endian format. Array of scalars also LE
.
// The raw data in little endian format. Use with care.
uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
const T *data() const { return reinterpret_cast<const T *>(Data()); }
How to use data()
on BE
machine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll hazard a guess. This is a low-level pointer access method that is not endian safe. Hence the "use with care" comment. In flatcc for C, the method is called _get_ptr() where the safe method is _vec_at(field, i) for vectors or _get(field, i) for fixed size arrays (TBD). These return a value converted to the native representation and usually optimizes so it is just as fast as direct array access.
For 8-bit elements it doesn't matter, but uint16_t would be unsafe. I have seen users getting into such problems on big endian hardware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right you have to use Get(i)
and Mutate(i, val)
.
src/idl_gen_cpp.cpp
Outdated
@@ -679,6 +679,10 @@ class CppGenerator : public BaseGenerator { | |||
bool user_facing_type) { | |||
if (IsScalar(type.base_type)) { | |||
return GenTypeBasic(type, user_facing_type) + afterbasic; | |||
} else if (IsArray(type)) { | |||
return beforeptr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code not formatted
src/idl_gen_cpp.cpp
Outdated
@@ -2728,7 +2738,8 @@ class CppGenerator : public BaseGenerator { | |||
|
|||
// Generate a default constructor. | |||
code_ += " {{STRUCT_NAME}}() {"; | |||
code_ += " memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));"; | |||
code_ += | |||
" memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code formatting (indent)
include/flatbuffers/flatbuffers.h
Outdated
typedef VectorReverseIterator<const_iterator> const_reverse_iterator; | ||
|
||
uoffset_t size() const { return length; } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The uoffset_t size() const { return length; }
should be constexpr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added constexpr.
Support added in FlatCC binary format updated, notably removed supported for table fields with fixed length vectors and now call the feature Fixed Size Arrays. https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md The FlatCC JSON parser optionally skips extra elements and zero pads missing elements, but raises an error by default. |
I've made some improvements, especially support for struct arrays was introduced - though the C#, Java and Python ports are not there yet. Also char arrays are not implemented yet (any advice on how to integrate them?). I kept the I also kept the stack of The length check is now capped at Hex values are now supported in the schema to match the behaviour in flatcc. |
src/idl_parser.cpp
Outdated
NEXT(); | ||
if (token_ != kTokenIntegerConstant) { | ||
return Error( | ||
"length of fixed-length array must be an integer value"); | ||
} | ||
int64_t fixed_length = StringToInt(attribute_.c_str()); | ||
if (fixed_length < 1 || fixed_length > 0x7fff) { | ||
int64_t fixed_length = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int64_t fixed_length = 0;
- uint16_t ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of StringToNumber
is an int64_t
. The check prevents an over-/underflow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flatbuffers/include/flatbuffers/util.h
Line 325 in bff7ffb
template<typename T> inline bool StringToNumber(const char *s, T *val) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'oh missed it! Fixed.
include/flatbuffers/flatbuffers.h
Outdated
typedef typename IndirectHelper<T>::return_type return_type; | ||
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type; | ||
|
||
constexpr uint16_t size() const { return length; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FLATBUFFERS_CONSTEXPR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Sounds good. FlatCC will be adding struct arrays and arrays of enums. I think we need to discuss char arrays more before implementing them. I think flatcc has a bug in that the C source cannot compile empty structs that are members of other structs. I'm not sure I'd bother fix it since it is rather messy. C does not support empty structs or other zero size types. |
FlatCC has now support for scalars, enums and fixed size arrays of structs, i.e. arrays of all ordinary struct member types, including JSON parsing and printing. Char arrays are not supported. https://github.com/dvidelabs/flatcc/tree/cf3f22eaf8082bccfd63efa8aeda41460b5be176 |
I have added support for:
|
Sorry, what is the issue with char arrays?
@rw for Python. |
Empty structs are very useful for union types. But it would simplify a lot to remove them. The issue with char arrays is:
Char arrays could also be just chars with no implied zero termination, or it could be optional and part of the specified size. |
@mikkelfj well, Ok, I guess we should be clear what we mean with Also not sure what you mean by |
[string:15] has been suggested earlier, by you I think. I suggested char at that time (some chat a while ago AFAIR). My point of raising it here was merely to agree on not using that syntax (string syntax). I'm not arguing against byte char, we just need to define what it means and how to handle edge cases, and notably 0 termination, if any. |
You are right. Dropped the patches! I think fixing the equality operators should be done in a seperate issue. Do you agree? |
@svenk177 Yes, compare operator for Recommendations (optional) for this PR:
If is ready notify aardappel for final review. |
f7e172f
to
d263454
Compare
@vglavnyy Requested changes commited. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
ECHECK(ParseSingleValue(nullptr, val, false)); | ||
} | ||
stack.push_back(val); | ||
return NoError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove one copy using emplace_back
.
First solution:
vector_emplace_back(&stack, Value());
auto& val = stack.back();
val.type = type;
...
// remove copy: stack.push_back(val);
Second:
stack.push_back(val)
-> vector_emplace_back(&stack, val);
src/idl_parser.cpp
Outdated
|
||
if (length != count) return Error("Fixed-length array size is incorrect."); | ||
|
||
for (auto it = stack.rbegin(); it != stack.rend(); it++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++it
?
tests/test.cpp
Outdated
nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A); | ||
|
||
MyGame::Example::ArrayStruct aStruct(2, 12); | ||
for (int i = 0; i < 15; i++) aStruct.mutable_b()->Mutate(i, i + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use b()->size()
instead of 15
.
Expected checking is desirable.
aStruct.b() is not null;
aStruct.b()->size() is equal to 15
|
||
auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer()); | ||
auto mArStruct = p->mutable_a(); | ||
mArStruct->mutable_b()->Mutate(14, -14); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TEST_ASSERT(mArStruct->mutable_b());
auto mArStruct = p->mutable_a(); | ||
mArStruct->mutable_b()->Mutate(14, -14); | ||
TEST_EQ(mArStruct->a(), 2); | ||
TEST_EQ(mArStruct->b()->size(), 15); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TEST_ASSERT(mArStruct->b());
src/idl_gen_cpp.cpp
Outdated
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to traverse parser_.structs_.vec
?
Is it possible to use lazy checking? For example after line 2745 when a field of a struct is generated.
: field.value.type; | ||
auto is_series = (IsSeries(field.value.type)); | ||
auto underlying_type = | ||
is_series ? field.value.type.VectorType() : field.value.type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const auto &underlying_type
- ?
8d0d5df
to
bc394b3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/idl_gen_cpp.cpp
Outdated
// Check if enum arrays are used without specifying --scoped-enums | ||
if (!parser_.opts.scoped_enums && IsArray(field_type) && | ||
IsEnum(field_type.VectorType())) { | ||
printf("--scoped-enums must be enabled to use enum arrays\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not happy with this error for multiple reasons. First it would be better if --scoped-enums
wasn't required. And if that really isn't possible, I'd prefer to trigger this error in the parser, where are all error handling happens. The generators don't really have a way to do errors, and this print + return false is a bit of a hackey way to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aardappel
The idea to ignore untyped enums was mine. Initially, Array
template had the support of enums without underlying type specification. But this third template parameter complicates the template and complicate compile-time helpers for the Array
(compile-time functions like size()
or other constexpr
features).
There are a few C++ compilers without underlying type specification. I assumed that Array
is a new feature needn't support of legacy. One should use a modern compiler to use Array
.
Of course, this should be documented.
I can restore removed code if I'm not right.
Generator vs parser:
The flag --scoped-enums
needed for C++ code generator only.
Other languages are independent of this flag.
One can use flatc
to convert from json to binary and versa.
The --scoped-enums
isn't necessary for these conversions.
Another way is to silently add an underlying type to generated enums used with Array.
For example, the underlying type silently added for each int64/uint64 enum due to MSVC restrictions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought enums were always explicitly typed. But if they are not, they should IMO default to 32 bit like int
. I actually find it a bit annoying that I have to specify a type for enums since often it really doesn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
umm - I'm talking about flatbuffer schema types - is this about C++ enums being typed (I have given up keeping track of that language) ?
In C the enums are represented as typecast integer defines in order to associate a type, .e.g. #define Red INT32_C(1)
Originally the were constants like const int32_t Red = 1;
but that did not work in switch statements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't like the printf
in there either, therfore I moved the check for scoped-enums into the parser along with a check if it generates code for C++.
@mikkelfj C++11 introduced the following syntax enum A : uint8_t { }
, i.e. sizeof(A) == sizeof(uint8_t)
, unfortunately old compilers do not support it, hence the requirement for --scoped-enums
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The now removed third parameter in the Array
template class was intended for this purpose, but it was indeed a bit messy as @vglavnyy pointed out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just accidentally found this http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2008.pdf
It appers C might get typed enum in C2x, not that it matters since it would not be portable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vglavnyy if it is needed to keep things simple, then so be it. I'd still like the actual error checking to be moved to the parser though, if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aardappel I already moved it into the parser. I had to squash the history as rebasing was not fun otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks!
src/idl_gen_cpp.cpp
Outdated
first++; | ||
continue; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR introduces a lot of blank lines.. prefer to not have them by default, only if a method is really long. And even then, comments are probably a better separator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed most blank lines and added some comments.
2c80d93
to
fd227ae
Compare
fd227ae
to
d062689
Compare
Ok, that means we're once again ready to merge! I see @vglavnyy's last comments have been addressed, so I guess we can go ahead. Thanks everyone for helping get this feature in! |
This PR accidentally broke because of a PR by @vglavnyy I merged just before this one: #5381 (makes Table/Struct internal access). |
Run of |
Thank you all for getting this in :) |
Change-Id: I249140119e6241beb5aec5670d0e5ccddc8f5251
Updated generated code in 123c7a4 |
We have CI errors related to this PR: https://ci.appveyor.com/project/gwvo/flatbuffers/builds/27162701/job/3edsmdethte5y7w9 Note sure why that is failing now all of a sudden? Looking into the errors and the code, the problem appears to be that Relevant code: Lines 2808 to 2839 in 4b870ac
Note e.g. Schema: https://github.com/google/flatbuffers/blob/master/tests/arrays_test.fbs We should a) move the function Possibly remotely related: #5440 which also had some alignment based MSVC errors. |
The test should use flatbuffers/include/flatbuffers/flatbuffers.h Lines 441 to 449 in 4b870ac
Another way (without suppression of always-const warning): // Change elements if you have a non-const pointer to this object.
void Mutate(uoffset_t i, const T &val) {
if (flatbuffers::is_scalar<T>::value) {
FLATBUFFERS_ASSERT(i < size());
WriteScalar(data() + i, val);
}
else {
*(GetMutablePointer(i)) = val;
}
} Or we can use SFINAE but I prefer if-else (C++17 has constexpr-if). Second:
Yes, we have the alignment problem (was detected by ASAN). |
@vglavnyy thanks, yes that is also a nice way to do it. Though of course this code is still going to do strange things if |
this feature is cool, i will port to Go. |
This change ports the pull request #3987 by daksenik and idoroshev to the most recent commit and adds support for generation of JSON schema, Java, C# and Python.