diff options
-rw-r--r-- | docs/html/md__schemas.html | 1 | ||||
-rwxr-xr-x | docs/source/Schemas.md | 4 | ||||
-rw-r--r-- | src/idl_gen_text.cpp | 3 | ||||
-rw-r--r-- | src/idl_parser.cpp | 17 | ||||
-rw-r--r-- | tests/MyGame/Example/Color.go | 6 | ||||
-rwxr-xr-x | tests/MyGame/Example/Color.java | 6 | ||||
-rw-r--r-- | tests/MyGame/Example/Monster.go | 4 | ||||
-rwxr-xr-x | tests/MyGame/Example/Monster.java | 4 | ||||
-rwxr-xr-x | tests/monster_test.fbs | 2 | ||||
-rwxr-xr-x | tests/monster_test_generated.h | 16 | ||||
-rw-r--r-- | tests/test.cpp | 1 |
11 files changed, 40 insertions, 24 deletions
diff --git a/docs/html/md__schemas.html b/docs/html/md__schemas.html index 6f1c6f61..85381e7f 100644 --- a/docs/html/md__schemas.html +++ b/docs/html/md__schemas.html @@ -123,6 +123,7 @@ root_type Monster; <li><code>deprecated</code> (on a field): do not generate accessors for this field anymore, code should stop using this data.</li> <li><code>original_order</code> (on a table): since elements in a table do not need to be stored in any particular order, they are often optimized for space by sorting them to size. This attribute stops that from happening.</li> <li><code>force_align: size</code> (on a struct): force the alignment of this struct to be something higher than what it is naturally aligned to. Causes these structs to be aligned to that amount inside a buffer, IF that buffer is allocated with that alignment (which is not necessarily the case for buffers accessed directly inside a <code>FlatBufferBuilder</code>).</li> +<li><code>bit_flags</code> (on an enum): the values of this field indicate bits, meaning that any value N specified in the schema will end up representing 1<<N, or if you don't specify values at all, you'll get the sequence 1, 2, 4, 8, ...</li> </ul> <h2>Gotchas</h2> <h3>Schemas and version control</h3> diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index debab679..4a02179d 100755 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -188,6 +188,10 @@ Current understood attributes: these structs to be aligned to that amount inside a buffer, IF that buffer is allocated with that alignment (which is not necessarily the case for buffers accessed directly inside a `FlatBufferBuilder`). +- `bit_flags` (on an enum): the values of this field indicate bits, + meaning that any value N specified in the schema will end up + representing 1<<N, or if you don't specify values at all, you'll get + the sequence 1, 2, 4, 8, ... ## Gotchas diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index f35e8840..fc833c13 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -100,7 +100,8 @@ static void EscapeString(const String &s, std::string *_text) { text += c; } else { auto u = static_cast<unsigned char>(c); - text += "\\x" + IntToStringHex(u); + text += "\\x"; + text += IntToStringHex(u); } break; } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 436d0bca..29b328c2 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -629,10 +629,10 @@ void Parser::ParseEnum(bool is_union) { std::string dc = doc_comment_; Expect(kTokenIdentifier); auto prevsize = enum_def.vals.vec.size(); - auto &ev = *new EnumVal(name, static_cast<int>( - enum_def.vals.vec.size() - ? enum_def.vals.vec.back()->value + 1 - : 0)); + auto value = enum_def.vals.vec.size() + ? enum_def.vals.vec.back()->value + 1 + : 0; + auto &ev = *new EnumVal(name, value); if (enum_def.vals.Add(name, &ev)) Error("enum value already exists: " + name); ev.doc_comment = dc; @@ -647,6 +647,15 @@ void Parser::ParseEnum(bool is_union) { } } while (IsNext(',')); Expect('}'); + if (enum_def.attributes.Lookup("bit_flags")) { + for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); + ++it) { + if (static_cast<size_t>((*it)->value) >= + SizeOf(enum_def.underlying_type.base_type) * 8) + Error("bit flag out of range of underlying integral type"); + (*it)->value = 1 << (*it)->value; + } + } } void Parser::ParseDecl() { diff --git a/tests/MyGame/Example/Color.go b/tests/MyGame/Example/Color.go index f4cc633f..289a7b06 100644 --- a/tests/MyGame/Example/Color.go +++ b/tests/MyGame/Example/Color.go @@ -3,7 +3,7 @@ package Example const ( - ColorRed = 0 - ColorGreen = 1 - ColorBlue = 2 + ColorRed = 1 + ColorGreen = 2 + ColorBlue = 8 ) diff --git a/tests/MyGame/Example/Color.java b/tests/MyGame/Example/Color.java index 44738ea4..8144e419 100755 --- a/tests/MyGame/Example/Color.java +++ b/tests/MyGame/Example/Color.java @@ -3,8 +3,8 @@ package MyGame.Example; public class Color { - public static final byte Red = 0; - public static final byte Green = 1; - public static final byte Blue = 2; + public static final byte Red = 1; + public static final byte Green = 2; + public static final byte Blue = 8; }; diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 16894f16..2e35ab6c 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -80,7 +80,7 @@ func (rcv *Monster) Color() int8 { if o != 0 { return rcv._tab.GetInt8(o + rcv._tab.Pos) } - return 2 + return 8 } func (rcv *Monster) TestType() byte { @@ -200,7 +200,7 @@ func MonsterAddHp(builder *flatbuffers.Builder, hp int16) { builder.PrependInt16 func MonsterAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(name), 0) } func MonsterAddInventory(builder *flatbuffers.Builder, inventory flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(inventory), 0) } func MonsterStartInventoryVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(1, numElems) } -func MonsterAddColor(builder *flatbuffers.Builder, color int8) { builder.PrependInt8Slot(6, color, 2) } +func MonsterAddColor(builder *flatbuffers.Builder, color int8) { builder.PrependInt8Slot(6, color, 8) } func MonsterAddTestType(builder *flatbuffers.Builder, testType byte) { builder.PrependByteSlot(7, testType, 0) } func MonsterAddTest(builder *flatbuffers.Builder, test flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(8, flatbuffers.UOffsetT(test), 0) } func MonsterAddTest4(builder *flatbuffers.Builder, test4 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(9, flatbuffers.UOffsetT(test4), 0) } diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java index dcb7699c..a6c584aa 100755 --- a/tests/MyGame/Example/Monster.java +++ b/tests/MyGame/Example/Monster.java @@ -17,7 +17,7 @@ public class Monster extends Table { public String name() { int o = __offset(10); return o != 0 ? __string(o) : null; } public byte inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } public int inventoryLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } - public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 2; } + public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 8; } public byte testType() { int o = __offset(18); return o != 0 ? bb.get(o + bb_pos) : 0; } public Table test(Table obj) { int o = __offset(20); return o != 0 ? __union(obj, o) : null; } public Test test4(int j) { return test4(new Test(), j); } @@ -41,7 +41,7 @@ public class Monster extends Table { public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(3, nameOffset, 0); } public static void addInventory(FlatBufferBuilder builder, int inventoryOffset) { builder.addOffset(5, inventoryOffset, 0); } public static void startInventoryVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems); } - public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(6, color, 2); } + public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(6, color, 8); } public static void addTestType(FlatBufferBuilder builder, byte testType) { builder.addByte(7, testType, 0); } public static void addTest(FlatBufferBuilder builder, int testOffset) { builder.addOffset(8, testOffset, 0); } public static void addTest4(FlatBufferBuilder builder, int test4Offset) { builder.addOffset(9, test4Offset, 0); } diff --git a/tests/monster_test.fbs b/tests/monster_test.fbs index 9e6d4446..caf6946d 100755 --- a/tests/monster_test.fbs +++ b/tests/monster_test.fbs @@ -2,7 +2,7 @@ namespace MyGame.Example; -enum Color:byte { Red = 0, Green, Blue = 2 } +enum Color:byte (bit_flags) { Red = 0, Green, Blue = 3 } union Any { Monster } // TODO: add more elements diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index e6beb77b..e362bd5c 100755 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -9,17 +9,17 @@ namespace MyGame { namespace Example { enum { - Color_Red = 0, - Color_Green = 1, - Color_Blue = 2, + Color_Red = 1, + Color_Green = 2, + Color_Blue = 8, }; inline const char **EnumNamesColor() { - static const char *names[] = { "Red", "Green", "Blue", nullptr }; + static const char *names[] = { "Red", "Green", "", "", "", "", "", "Blue", nullptr }; return names; } -inline const char *EnumNameColor(int e) { return EnumNamesColor()[e]; } +inline const char *EnumNameColor(int e) { return EnumNamesColor()[e - Color_Red]; } enum { Any_NONE = 0, @@ -85,7 +85,7 @@ struct Monster : private flatbuffers::Table { int16_t hp() const { return GetField<int16_t>(8, 100); } const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(10); } const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(14); } - int8_t color() const { return GetField<int8_t>(16, 2); } + int8_t color() const { return GetField<int8_t>(16, 8); } uint8_t test_type() const { return GetField<uint8_t>(18, 0); } const void *test() const { return GetPointer<const void *>(20); } const flatbuffers::Vector<const Test *> *test4() const { return GetPointer<const flatbuffers::Vector<const Test *> *>(22); } @@ -131,7 +131,7 @@ struct MonsterBuilder { void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(8, hp, 100); } void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(10, name); } void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(14, inventory); } - void add_color(int8_t color) { fbb_.AddElement<int8_t>(16, color, 2); } + void add_color(int8_t color) { fbb_.AddElement<int8_t>(16, color, 8); } void add_test_type(uint8_t test_type) { fbb_.AddElement<uint8_t>(18, test_type, 0); } void add_test(flatbuffers::Offset<void> test) { fbb_.AddOffset(20, test); } void add_test4(flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4) { fbb_.AddOffset(22, test4); } @@ -150,7 +150,7 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder int16_t hp = 100, flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0, - int8_t color = 2, + int8_t color = 8, uint8_t test_type = 0, flatbuffers::Offset<void> test = 0, flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4 = 0, diff --git a/tests/test.cpp b/tests/test.cpp index b3dcab3a..c28be7de 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -477,6 +477,7 @@ void ErrorTest() { TestError("enum X:float {}", "underlying"); TestError("enum X:byte { Y, Y }", "value already"); TestError("enum X:byte { Y=2, Z=1 }", "ascending"); + TestError("enum X:byte (bit_flags) { Y=8 }", "bit flag out"); TestError("table X { Y:int; } table X {", "datatype already"); TestError("struct X (force_align: 7) { Y:int; }", "force_align"); TestError("{}", "no root"); |