summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/html/md__schemas.html1
-rwxr-xr-xdocs/source/Schemas.md4
-rw-r--r--src/idl_gen_text.cpp3
-rw-r--r--src/idl_parser.cpp17
-rw-r--r--tests/MyGame/Example/Color.go6
-rwxr-xr-xtests/MyGame/Example/Color.java6
-rw-r--r--tests/MyGame/Example/Monster.go4
-rwxr-xr-xtests/MyGame/Example/Monster.java4
-rwxr-xr-xtests/monster_test.fbs2
-rwxr-xr-xtests/monster_test_generated.h16
-rw-r--r--tests/test.cpp1
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&lt;&lt;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");