FlexBuffers: allow any values to be shared.

(see comments in the code).

Change-Id: I5603abb0db436145739653692644bbcfd3c946e3
parent cd75a365
...@@ -914,7 +914,9 @@ class Builder FLATBUFFERS_FINAL_CLASS { ...@@ -914,7 +914,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Bool(b); Bool(b);
} }
void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); } void IndirectInt(int64_t i) {
PushIndirect(i, FBT_INDIRECT_INT, WidthI(i));
}
void IndirectInt(const char *key, int64_t i) { void IndirectInt(const char *key, int64_t i) {
Key(key); Key(key);
IndirectInt(i); IndirectInt(i);
...@@ -1194,6 +1196,26 @@ class Builder FLATBUFFERS_FINAL_CLASS { ...@@ -1194,6 +1196,26 @@ class Builder FLATBUFFERS_FINAL_CLASS {
EndMap(start); EndMap(start);
} }
// If you wish to share a value explicitly (a value not shared automatically
// through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
// functions. Or if you wish to turn those flags off for performance reasons
// and still do some explicit sharing. For example:
// builder.IndirectDouble(M_PI);
// auto id = builder.LastValue(); // Remember where we stored it.
// .. more code goes here ..
// builder.ReuseValue(id); // Refers to same double by offset.
// LastValue works regardless of wether the value has a key or not.
// Works on any data type.
struct Value;
Value LastValue() { return stack_.back(); }
void ReuseValue(Value v) {
stack_.push_back(v);
}
void ReuseValue(const char *key, Value v) {
Key(key);
ReuseValue(v);
}
// Overloaded Add that tries to call the correct function above. // Overloaded Add that tries to call the correct function above.
void Add(int8_t i) { Int(i); } void Add(int8_t i) { Int(i); }
void Add(int16_t i) { Int(i); } void Add(int16_t i) { Int(i); }
...@@ -1319,6 +1341,8 @@ class Builder FLATBUFFERS_FINAL_CLASS { ...@@ -1319,6 +1341,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
: FBT_INT); : FBT_INT);
} }
public:
// This was really intended to be private, except for LastValue/ReuseValue.
struct Value { struct Value {
union { union {
int64_t i_; int64_t i_;
...@@ -1388,6 +1412,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { ...@@ -1388,6 +1412,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} }
}; };
private:
void WriteAny(const Value &val, uint8_t byte_width) { void WriteAny(const Value &val, uint8_t byte_width) {
switch (val.type_) { switch (val.type_) {
case FBT_NULL: case FBT_NULL:
......
...@@ -2514,9 +2514,11 @@ void FlexBuffersTest() { ...@@ -2514,9 +2514,11 @@ void FlexBuffersTest() {
slb += -100; // Equivalent to slb.Add(-100) or slb.Int(-100); slb += -100; // Equivalent to slb.Add(-100) or slb.Int(-100);
slb += "Fred"; slb += "Fred";
slb.IndirectFloat(4.0f); slb.IndirectFloat(4.0f);
auto i_f = slb.LastValue();
uint8_t blob[] = { 77 }; uint8_t blob[] = { 77 };
slb.Blob(blob, 1); slb.Blob(blob, 1);
slb += false; slb += false;
slb.ReuseValue(i_f);
}); });
int ints[] = { 1, 2, 3 }; int ints[] = { 1, 2, 3 };
slb.Vector("bar", ints, 3); slb.Vector("bar", ints, 3);
...@@ -2537,9 +2539,11 @@ void FlexBuffersTest() { ...@@ -2537,9 +2539,11 @@ void FlexBuffersTest() {
slb3 += -100; // Equivalent to slb.Add(-100) or slb.Int(-100); slb3 += -100; // Equivalent to slb.Add(-100) or slb.Int(-100);
slb3 += "Fred"; slb3 += "Fred";
slb3.IndirectFloat(4.0f); slb3.IndirectFloat(4.0f);
auto i_f = slb3.LastValue();
uint8_t blob[] = { 77 }; uint8_t blob[] = { 77 };
slb3.Blob(blob, 1); slb3.Blob(blob, 1);
slb3 += false; slb3 += false;
slb3.ReuseValue(i_f);
}, slb2); }, slb2);
int ints[] = { 1, 2, 3 }; int ints[] = { 1, 2, 3 };
slb2.Vector("bar", ints, 3); slb2.Vector("bar", ints, 3);
...@@ -2563,7 +2567,7 @@ void FlexBuffersTest() { ...@@ -2563,7 +2567,7 @@ void FlexBuffersTest() {
auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap(); auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap();
TEST_EQ(map.size(), 7); TEST_EQ(map.size(), 7);
auto vec = map["vec"].AsVector(); auto vec = map["vec"].AsVector();
TEST_EQ(vec.size(), 5); TEST_EQ(vec.size(), 6);
TEST_EQ(vec[0].AsInt64(), -100); TEST_EQ(vec[0].AsInt64(), -100);
TEST_EQ_STR(vec[1].AsString().c_str(), "Fred"); TEST_EQ_STR(vec[1].AsString().c_str(), "Fred");
TEST_EQ(vec[1].AsInt64(), 0); // Number parsing failed. TEST_EQ(vec[1].AsInt64(), 0); // Number parsing failed.
...@@ -2571,13 +2575,11 @@ void FlexBuffersTest() { ...@@ -2571,13 +2575,11 @@ void FlexBuffersTest() {
TEST_EQ(vec[2].AsString().IsTheEmptyString(), true); // Wrong Type. TEST_EQ(vec[2].AsString().IsTheEmptyString(), true); // Wrong Type.
TEST_EQ_STR(vec[2].AsString().c_str(), ""); // This still works though. TEST_EQ_STR(vec[2].AsString().c_str(), ""); // This still works though.
TEST_EQ_STR(vec[2].ToString().c_str(), "4.0"); // Or have it converted. TEST_EQ_STR(vec[2].ToString().c_str(), "4.0"); // Or have it converted.
// Few tests for templated version of As. // Few tests for templated version of As.
TEST_EQ(vec[0].As<int64_t>(), -100); TEST_EQ(vec[0].As<int64_t>(), -100);
TEST_EQ_STR(vec[1].As<std::string>().c_str(), "Fred"); TEST_EQ_STR(vec[1].As<std::string>().c_str(), "Fred");
TEST_EQ(vec[1].As<int64_t>(), 0); // Number parsing failed. TEST_EQ(vec[1].As<int64_t>(), 0); // Number parsing failed.
TEST_EQ(vec[2].As<double>(), 4.0); TEST_EQ(vec[2].As<double>(), 4.0);
// Test that the blob can be accessed. // Test that the blob can be accessed.
TEST_EQ(vec[3].IsBlob(), true); TEST_EQ(vec[3].IsBlob(), true);
auto blob = vec[3].AsBlob(); auto blob = vec[3].AsBlob();
...@@ -2585,6 +2587,7 @@ void FlexBuffersTest() { ...@@ -2585,6 +2587,7 @@ void FlexBuffersTest() {
TEST_EQ(blob.data()[0], 77); TEST_EQ(blob.data()[0], 77);
TEST_EQ(vec[4].IsBool(), true); // Check if type is a bool TEST_EQ(vec[4].IsBool(), true); // Check if type is a bool
TEST_EQ(vec[4].AsBool(), false); // Check if value is false TEST_EQ(vec[4].AsBool(), false); // Check if value is false
TEST_EQ(vec[5].AsDouble(), 4.0); // This is shared with vec[2] !
auto tvec = map["bar"].AsTypedVector(); auto tvec = map["bar"].AsTypedVector();
TEST_EQ(tvec.size(), 3); TEST_EQ(tvec.size(), 3);
TEST_EQ(tvec[2].AsInt8(), 3); TEST_EQ(tvec[2].AsInt8(), 3);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment