diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md index c1df15965..87a11c8bd 100755 --- a/docs/source/CppUsage.md +++ b/docs/source/CppUsage.md @@ -103,7 +103,7 @@ To use: cout << monsterobj->name; // This is now a std::string! monsterobj->name = "Bob"; // Change the name. FlatBufferBuilder fbb; - CreateMonster(fbb, monsterobj->get()); // Serialize into new buffer. + CreateMonster(fbb, monsterobj.get()); // Serialize into new buffer. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Reflection (& Resizing) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 1f4501629..25706e84f 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -347,6 +347,7 @@ struct IDLOptions { bool generate_name_strings; bool escape_proto_identifiers; bool generate_object_based_api; + bool union_value_namespacing; // Possible options for the more general generator below. enum Language { kJava, kCSharp, kGo, kMAX }; @@ -368,6 +369,7 @@ struct IDLOptions { generate_name_strings(false), escape_proto_identifiers(false), generate_object_based_api(false), + union_value_namespacing(true), lang(IDLOptions::kJava) {} }; diff --git a/src/flatc.cpp b/src/flatc.cpp index a568bbb24..b174cbd43 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -195,6 +195,8 @@ int main(int argc, const char *argv[]) { } else if(arg == "--scoped-enums") { opts.prefixed_enums = false; opts.scoped_enums = true; + } else if (arg == "--no-union-value-namespacing") { + opts.union_value_namespacing = false; } else if(arg == "--gen-mutable") { opts.mutable_buffer = true; } else if(arg == "--gen-name-strings") { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index ad20b36cb..6eaab1445 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -975,8 +975,10 @@ class CppGenerator : public BaseGenerator { if (invector) { return "*" + val; } else { - return "std::unique_ptr<" + type.struct_def->name + - ">(new " + type.struct_def->name + "(*" + val + "))"; + return "std::unique_ptr<" + + WrapInNameSpace (*type.struct_def) + + ">(new " + + WrapInNameSpace (*type.struct_def) + "(*" + val + "))"; } } else { return val + "->UnPack()"; diff --git a/src/idl_gen_js.cpp b/src/idl_gen_js.cpp index d7c913e50..fec578029 100644 --- a/src/idl_gen_js.cpp +++ b/src/idl_gen_js.cpp @@ -79,7 +79,7 @@ class JsGenerator : public BaseGenerator { for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; - GenStruct(struct_def, decl_code_ptr, exports_code_ptr); + GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr); } } void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) { @@ -361,7 +361,7 @@ static void GenStructBody(const StructDef &struct_def, } // Generate an accessor struct with constructor for a flatbuffers struct. -void GenStruct(StructDef &struct_def, std::string *code_ptr, std::string *exports_ptr) { +void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_ptr, std::string *exports_ptr) { if (struct_def.generated) return; std::string &code = *code_ptr; std::string &exports = *exports_ptr; @@ -550,6 +550,22 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr, std::string *export } code += "};\n\n"; + // Adds the mutable scalar value to the output + if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) { + std::string annotations = "@param {" + GenTypeName(field.value.type, true) + "} value\n"; + GenDocComment(code_ptr, annotations + + "@returns {boolean}"); + + code += object_name + ".prototype.mutate_" + field.name + " = function(value) {\n"; + code += " var offset = this.bb.__offset(this.bb_pos, " + NumToString(field.value.offset) + ")\n\n"; + code += " if (offset === 0) {\n"; + code += " return false;\n"; + code += " }\n\n"; + code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, value);\n"; + code += " return true;\n"; + code += "}\n\n"; + } + // Emit vector helpers if (field.value.type.base_type == BASE_TYPE_VECTOR) { // Emit a length helper diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index fc2136757..b03655c92 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1216,10 +1216,12 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { EXPECT(kTokenIdentifier); if (is_union) { ECHECK(ParseNamespacing(&full_name, &value_name)); - // Since we can't namespace the actual enum identifiers, turn - // namespace parts into part of the identifier. - value_name = full_name; - std::replace(value_name.begin(), value_name.end(), '.', '_'); + if (opts.union_value_namespacing) { + // Since we can't namespace the actual enum identifiers, turn + // namespace parts into part of the identifier. + value_name = full_name; + std::replace(value_name.begin(), value_name.end(), '.', '_'); + } } auto prevsize = enum_def.vals.vec.size(); auto value = enum_def.vals.vec.size() diff --git a/tests/JavaScriptTest.js b/tests/JavaScriptTest.js index c89ae85d7..c97ed2d08 100644 --- a/tests/JavaScriptTest.js +++ b/tests/JavaScriptTest.js @@ -64,7 +64,10 @@ function main() { fs.writeFileSync('monsterdata_javascript_wire.mon', new Buffer(fbb.asUint8Array())); - // Test it: + // Tests mutation first. This will verify that we did not trample any other + // part of the byte buffer. + testMutation(fbb.dataBuffer()); + testBuffer(fbb.dataBuffer()); test64bit(); @@ -74,6 +77,21 @@ function main() { console.log('FlatBuffers test: completed successfully'); } +function testMutation(bb) { + var monster = MyGame.Example.Monster.getRootAsMonster(bb); + + monster.mutate_hp(120); + assert.strictEqual(monster.hp(), 120); + + monster.mutate_hp(80); + assert.strictEqual(monster.hp(), 80); + + var manaRes = monster.mutate_mana(10); + assert.strictEqual(manaRes, false); // Field was NOT present, because default value. + + // TODO: There is not the availability to mutate structs or vectors. +} + function testBuffer(bb) { assert.ok(MyGame.Example.Monster.bufferHasIdentifier(bb)); diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index 7c4c28f82..774882d7c 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -127,6 +127,21 @@ MyGame.Example.Test.prototype.a = function() { return this.bb.readInt16(this.bb_pos); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Test.prototype.mutate_a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 0) + + if (offset === 0) { + return false; + } + + this.bb.writeInt16(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -134,6 +149,21 @@ MyGame.Example.Test.prototype.b = function() { return this.bb.readInt8(this.bb_pos + 2); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Test.prototype.mutate_b = function(value) { + var offset = this.bb.__offset(this.bb_pos, 2) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Builder} builder * @param {number} a @@ -191,6 +221,21 @@ MyGame.Example.TestSimpleTableWithEnum.prototype.color = function() { return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Green; }; +/** + * @param {MyGame.Example.Color} value + * @returns {boolean} + */ +MyGame.Example.TestSimpleTableWithEnum.prototype.mutate_color = function(value) { + var offset = this.bb.__offset(this.bb_pos, 4) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Builder} builder */ @@ -248,6 +293,21 @@ MyGame.Example.Vec3.prototype.x = function() { return this.bb.readFloat32(this.bb_pos); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Vec3.prototype.mutate_x = function(value) { + var offset = this.bb.__offset(this.bb_pos, 0) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -255,6 +315,21 @@ MyGame.Example.Vec3.prototype.y = function() { return this.bb.readFloat32(this.bb_pos + 4); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Vec3.prototype.mutate_y = function(value) { + var offset = this.bb.__offset(this.bb_pos, 4) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -262,6 +337,21 @@ MyGame.Example.Vec3.prototype.z = function() { return this.bb.readFloat32(this.bb_pos + 8); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Vec3.prototype.mutate_z = function(value) { + var offset = this.bb.__offset(this.bb_pos, 8) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -269,6 +359,21 @@ MyGame.Example.Vec3.prototype.test1 = function() { return this.bb.readFloat64(this.bb_pos + 16); }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Vec3.prototype.mutate_test1 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 16) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat64(this.bb_pos + offset, value); + return true; +} + /** * @returns {MyGame.Example.Color} */ @@ -276,6 +381,21 @@ MyGame.Example.Vec3.prototype.test2 = function() { return /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + 24)); }; +/** + * @param {MyGame.Example.Color} value + * @returns {boolean} + */ +MyGame.Example.Vec3.prototype.mutate_test2 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 24) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @param {MyGame.Example.Test=} obj * @returns {MyGame.Example.Test} @@ -364,6 +484,21 @@ MyGame.Example.Stat.prototype.val = function() { return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0); }; +/** + * @param {flatbuffers.Long} value + * @returns {boolean} + */ +MyGame.Example.Stat.prototype.mutate_val = function(value) { + var offset = this.bb.__offset(this.bb_pos, 6) + + if (offset === 0) { + return false; + } + + this.bb.writeInt64(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -372,6 +507,21 @@ MyGame.Example.Stat.prototype.count = function() { return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Stat.prototype.mutate_count = function(value) { + var offset = this.bb.__offset(this.bb_pos, 8) + + if (offset === 0) { + return false; + } + + this.bb.writeUint16(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Builder} builder */ @@ -474,6 +624,21 @@ MyGame.Example.Monster.prototype.mana = function() { return offset ? this.bb.readInt16(this.bb_pos + offset) : 150; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_mana = function(value) { + var offset = this.bb.__offset(this.bb_pos, 6) + + if (offset === 0) { + return false; + } + + this.bb.writeInt16(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -482,6 +647,21 @@ MyGame.Example.Monster.prototype.hp = function() { return offset ? this.bb.readInt16(this.bb_pos + offset) : 100; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_hp = function(value) { + var offset = this.bb.__offset(this.bb_pos, 8) + + if (offset === 0) { + return false; + } + + this.bb.writeInt16(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Encoding=} optionalEncoding * @returns {string|Uint8Array} @@ -524,6 +704,21 @@ MyGame.Example.Monster.prototype.color = function() { return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Blue; }; +/** + * @param {MyGame.Example.Color} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_color = function(value) { + var offset = this.bb.__offset(this.bb_pos, 16) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @returns {MyGame.Example.Any} */ @@ -532,6 +727,21 @@ MyGame.Example.Monster.prototype.testType = function() { return offset ? /** @type {MyGame.Example.Any} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.Any.NONE; }; +/** + * @param {MyGame.Example.Any} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_test_type = function(value) { + var offset = this.bb.__offset(this.bb_pos, 18) + + if (offset === 0) { + return false; + } + + this.bb.writeUint8(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Table} obj * @returns {?flatbuffers.Table} @@ -649,6 +859,21 @@ MyGame.Example.Monster.prototype.testbool = function() { return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; }; +/** + * @param {boolean} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testbool = function(value) { + var offset = this.bb.__offset(this.bb_pos, 34) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -657,6 +882,21 @@ MyGame.Example.Monster.prototype.testhashs32Fnv1 = function() { return offset ? this.bb.readInt32(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashs32_fnv1 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 36) + + if (offset === 0) { + return false; + } + + this.bb.writeInt32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -665,6 +905,21 @@ MyGame.Example.Monster.prototype.testhashu32Fnv1 = function() { return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashu32_fnv1 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 38) + + if (offset === 0) { + return false; + } + + this.bb.writeUint32(this.bb_pos + offset, value); + return true; +} + /** * @returns {flatbuffers.Long} */ @@ -673,6 +928,21 @@ MyGame.Example.Monster.prototype.testhashs64Fnv1 = function() { return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0); }; +/** + * @param {flatbuffers.Long} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashs64_fnv1 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 40) + + if (offset === 0) { + return false; + } + + this.bb.writeInt64(this.bb_pos + offset, value); + return true; +} + /** * @returns {flatbuffers.Long} */ @@ -681,6 +951,21 @@ MyGame.Example.Monster.prototype.testhashu64Fnv1 = function() { return offset ? this.bb.readUint64(this.bb_pos + offset) : this.bb.createLong(0, 0); }; +/** + * @param {flatbuffers.Long} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashu64_fnv1 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 42) + + if (offset === 0) { + return false; + } + + this.bb.writeUint64(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -689,6 +974,21 @@ MyGame.Example.Monster.prototype.testhashs32Fnv1a = function() { return offset ? this.bb.readInt32(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashs32_fnv1a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 44) + + if (offset === 0) { + return false; + } + + this.bb.writeInt32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -697,6 +997,21 @@ MyGame.Example.Monster.prototype.testhashu32Fnv1a = function() { return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashu32_fnv1a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 46) + + if (offset === 0) { + return false; + } + + this.bb.writeUint32(this.bb_pos + offset, value); + return true; +} + /** * @returns {flatbuffers.Long} */ @@ -705,6 +1020,21 @@ MyGame.Example.Monster.prototype.testhashs64Fnv1a = function() { return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0); }; +/** + * @param {flatbuffers.Long} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashs64_fnv1a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 48) + + if (offset === 0) { + return false; + } + + this.bb.writeInt64(this.bb_pos + offset, value); + return true; +} + /** * @returns {flatbuffers.Long} */ @@ -713,6 +1043,21 @@ MyGame.Example.Monster.prototype.testhashu64Fnv1a = function() { return offset ? this.bb.readUint64(this.bb_pos + offset) : this.bb.createLong(0, 0); }; +/** + * @param {flatbuffers.Long} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testhashu64_fnv1a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 50) + + if (offset === 0) { + return false; + } + + this.bb.writeUint64(this.bb_pos + offset, value); + return true; +} + /** * @param {number} index * @returns {boolean} @@ -746,6 +1091,21 @@ MyGame.Example.Monster.prototype.testf = function() { return offset ? this.bb.readFloat32(this.bb_pos + offset) : 3.14159; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testf = function(value) { + var offset = this.bb.__offset(this.bb_pos, 54) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -754,6 +1114,21 @@ MyGame.Example.Monster.prototype.testf2 = function() { return offset ? this.bb.readFloat32(this.bb_pos + offset) : 3.0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testf2 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 56) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -762,6 +1137,21 @@ MyGame.Example.Monster.prototype.testf3 = function() { return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; }; +/** + * @param {number} value + * @returns {boolean} + */ +MyGame.Example.Monster.prototype.mutate_testf3 = function(value) { + var offset = this.bb.__offset(this.bb_pos, 58) + + if (offset === 0) { + return false; + } + + this.bb.writeFloat32(this.bb_pos + offset, value); + return true; +} + /** * @param {number} index * @param {flatbuffers.Encoding=} optionalEncoding diff --git a/tests/namespace_test/namespace_test1_generated.js b/tests/namespace_test/namespace_test1_generated.js index e6390567f..a8fea9ea6 100644 --- a/tests/namespace_test/namespace_test1_generated.js +++ b/tests/namespace_test/namespace_test1_generated.js @@ -64,6 +64,21 @@ NamespaceA.NamespaceB.TableInNestedNS.prototype.foo = function() { return offset ? this.bb.readInt32(this.bb_pos + offset) : 0; }; +/** + * @param {number} value + * @returns {boolean} + */ +NamespaceA.NamespaceB.TableInNestedNS.prototype.mutate_foo = function(value) { + var offset = this.bb.__offset(this.bb_pos, 4) + + if (offset === 0) { + return false; + } + + this.bb.writeInt32(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Builder} builder */ @@ -121,6 +136,21 @@ NamespaceA.NamespaceB.StructInNestedNS.prototype.a = function() { return this.bb.readInt32(this.bb_pos); }; +/** + * @param {number} value + * @returns {boolean} + */ +NamespaceA.NamespaceB.StructInNestedNS.prototype.mutate_a = function(value) { + var offset = this.bb.__offset(this.bb_pos, 0) + + if (offset === 0) { + return false; + } + + this.bb.writeInt32(this.bb_pos + offset, value); + return true; +} + /** * @returns {number} */ @@ -128,6 +158,21 @@ NamespaceA.NamespaceB.StructInNestedNS.prototype.b = function() { return this.bb.readInt32(this.bb_pos + 4); }; +/** + * @param {number} value + * @returns {boolean} + */ +NamespaceA.NamespaceB.StructInNestedNS.prototype.mutate_b = function(value) { + var offset = this.bb.__offset(this.bb_pos, 4) + + if (offset === 0) { + return false; + } + + this.bb.writeInt32(this.bb_pos + offset, value); + return true; +} + /** * @param {flatbuffers.Builder} builder * @param {number} a diff --git a/tests/namespace_test/namespace_test2_generated.js b/tests/namespace_test/namespace_test2_generated.js index f76d5a95a..856bbff92 100644 --- a/tests/namespace_test/namespace_test2_generated.js +++ b/tests/namespace_test/namespace_test2_generated.js @@ -70,6 +70,21 @@ NamespaceA.TableInFirstNS.prototype.fooEnum = function() { return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb.readInt8(this.bb_pos + offset)) : NamespaceA.NamespaceB.EnumInNestedNS.A; }; +/** + * @param {NamespaceA.NamespaceB.EnumInNestedNS} value + * @returns {boolean} + */ +NamespaceA.TableInFirstNS.prototype.mutate_foo_enum = function(value) { + var offset = this.bb.__offset(this.bb_pos, 6) + + if (offset === 0) { + return false; + } + + this.bb.writeInt8(this.bb_pos + offset, value); + return true; +} + /** * @param {NamespaceA.NamespaceB.StructInNestedNS=} obj * @returns {NamespaceA.NamespaceB.StructInNestedNS}