Mutable FlatBuffers: in-place updates.

This commit contains the first step in providing mutable FlatBuffers,
non-const accessors and mutation functions for existing fields generated
from --gen-mutable.

Change-Id: Iebee3975f05c1001f8e22824725edeaa6d85fbee
Tested: on Linux.
Bug: 15777024
This commit is contained in:
Wouter van Oortmerssen
2015-04-27 16:25:06 -07:00
parent a8d6962ac2
commit 3ec5dddb00
10 changed files with 225 additions and 22 deletions

View File

@@ -221,22 +221,41 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
++it) {
auto &field = **it;
if (!field.deprecated) { // Deprecated fields won't be accessible.
auto is_scalar = IsScalar(field.value.type.base_type);
GenComment(field.doc_comment, code_ptr, nullptr, " ");
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " *",
true);
code += field.name + "() const { return ";
// Call a different accessor for pointers, that indirects.
std::string call = IsScalar(field.value.type.base_type)
auto accessor = is_scalar
? "GetField<"
: (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<");
call += GenTypeGet(parser, field.value.type, "", "const ", " *", false);
call += ">(" + NumToString(field.value.offset);
auto offsetstr = NumToString(field.value.offset);
auto call =
accessor +
GenTypeGet(parser, field.value.type, "", "const ", " *", false) +
">(" + offsetstr;
// Default value as second arg for non-pointer types.
if (IsScalar(field.value.type.base_type))
call += ", " + field.value.constant;
call += ")";
code += GenUnderlyingCast(parser, field, true, call);
code += "; }\n";
if (opts.mutable_buffer) {
if (is_scalar) {
code += " bool mutate_" + field.name + "(";
code += GenTypeBasic(parser, field.value.type, true);
code += " " + field.name + ") { return SetField(" + offsetstr + ", ";
code += GenUnderlyingCast(parser, field, false, field.name);
code += "); }\n";
} else {
auto type = GenTypeGet(parser, field.value.type, " ", "", " *", true);
code += " " + type + "mutable_" + field.name + "() { return ";
code += GenUnderlyingCast(parser, field, true,
accessor + type + ">(" + offsetstr + ")");
code += "; }\n";
}
}
auto nested = field.attributes.Lookup("nested_flatbuffer");
if (nested) {
auto nested_root = parser.structs_.Lookup(nested->constant);
@@ -416,7 +435,8 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
code += " return builder_.Finish();\n}\n\n";
}
static void GenPadding(const FieldDef &field, const std::function<void (int bits)> &f) {
static void GenPadding(const FieldDef &field,
const std::function<void (int bits)> &f) {
if (field.padding) {
for (int i = 0; i < 4; i++)
if (static_cast<int>(field.padding) & (1 << i))
@@ -427,7 +447,7 @@ static void GenPadding(const FieldDef &field, const std::function<void (int bits
// Generate an accessor struct with constructor for a flatbuffers struct.
static void GenStruct(const Parser &parser, StructDef &struct_def,
std::string *code_ptr) {
const GeneratorOptions &opts, std::string *code_ptr) {
if (struct_def.generated) return;
std::string &code = *code_ptr;
@@ -502,14 +522,30 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
++it) {
auto &field = **it;
GenComment(field.doc_comment, code_ptr, nullptr, " ");
auto is_scalar = IsScalar(field.value.type.base_type);
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " &",
true);
code += field.name + "() const { return ";
code += GenUnderlyingCast(parser, field, true,
IsScalar(field.value.type.base_type)
is_scalar
? "flatbuffers::EndianScalar(" + field.name + "_)"
: field.name + "_");
code += "; }\n";
if (opts.mutable_buffer) {
if (is_scalar) {
code += " void mutate_" + field.name + "(";
code += GenTypeBasic(parser, field.value.type, true);
code += " " + field.name + ") { flatbuffers::WriteScalar(&";
code += field.name + "_, ";
code += GenUnderlyingCast(parser, field, false, field.name);
code += "); }\n";
} else {
code += " ";
code += GenTypeGet(parser, field.value.type, "", "", " &", true);
code += "mutable_" + field.name + "() { return " + field.name;
code += "_; }\n";
}
}
}
code += "};\nSTRUCT_END(" + struct_def.name + ", ";
code += NumToString(struct_def.bytesize) + ");\n\n";
@@ -581,7 +617,7 @@ std::string GenerateCPP(const Parser &parser,
std::string decl_code;
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
if ((**it).fixed) GenStruct(parser, **it, &decl_code);
if ((**it).fixed) GenStruct(parser, **it, opts, &decl_code);
}
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
@@ -654,6 +690,12 @@ std::string GenerateCPP(const Parser &parser,
code += name;
code += "(const void *buf) { return flatbuffers::GetRoot<";
code += name + ">(buf); }\n\n";
if (opts.mutable_buffer) {
code += "inline " + name + " *GetMutable";
code += name;
code += "(void *buf) { return flatbuffers::GetMutableRoot<";
code += name + ">(buf); }\n\n";
}
// The root verifier:
code += "inline bool Verify";