mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
Added a bit_flags attribute to enum declarations that 1<<N every value.
Change-Id: Ib9ec0cb3ddec60b1ca124eaf815fb1ae0cc53e1c Tested: on Windows and Linux Bug: 16186562
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
package Example
|
||||
|
||||
const (
|
||||
ColorRed = 0
|
||||
ColorGreen = 1
|
||||
ColorBlue = 2
|
||||
ColorRed = 1
|
||||
ColorGreen = 2
|
||||
ColorBlue = 8
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user