diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 214ce267b71c27ffacc774a66fe37fe5a0a8efab..c1550f75ecfed55031629b32330b9b7aeb790bb8 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1664,13 +1664,14 @@ const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) { /// This function is UNDEFINED for FlatBuffers whose schema does not include /// a file_identifier (likely points at padding or the start of a the root /// vtable). -inline const char *GetBufferIdentifier(const void *buf) { - return reinterpret_cast<const char *>(buf) + sizeof(uoffset_t); +inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) { + return reinterpret_cast<const char *>(buf) + + ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); } // Helper to see if the identifier in a buffer has the expected value. -inline bool BufferHasIdentifier(const void *buf, const char *identifier) { - return strncmp(GetBufferIdentifier(buf), identifier, +inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) { + return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, FlatBufferBuilder::kFileIdentifierLength) == 0; } diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 77e7422a471149bb73e03fbb098149e38e89fe50..4f569071037948952a97e0db93de922d1072c76a 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -387,6 +387,7 @@ struct IDLOptions { std::string go_namespace; bool reexport_ts_modules; bool protobuf_ascii_alike; + bool size_prefixed; // Possible options for the more general generator below. enum Language { @@ -442,6 +443,7 @@ struct IDLOptions { skip_flatbuffers_import(false), reexport_ts_modules(true), protobuf_ascii_alike(false), + size_prefixed(false), lang(IDLOptions::kJava), mini_reflect(IDLOptions::kNone), lang_to_generate(0) {} diff --git a/src/flatc.cpp b/src/flatc.cpp index 7b430a9217a93316209fdad046a25bff3bd84169..a164550e05e5b92c06ee3760ec5253818b787292 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -100,6 +100,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { " (default is \"github.com/google/flatbuffers/go\")\n" " --raw-binary Allow binaries without file_indentifier to be read.\n" " This may crash flatc given a mismatched schema.\n" + " --size-prefixed Input binaries are size prefixed buffers.\n" " --proto Input is a .proto, translate to .fbs.\n" " --oneof-union Translate .proto oneofs to flatbuffer unions.\n" " --grpc Generate GRPC interfaces for the specified languages\n" @@ -233,6 +234,8 @@ int FlatCompiler::Compile(int argc, const char **argv) { opts.one_file = true; } else if (arg == "--raw-binary") { raw_binary = true; + } else if (arg == "--size-prefixed") { + opts.size_prefixed = true; } else if (arg == "--") { // Separator between text and binary inputs. binary_files_from = filenames.size(); } else if (arg == "--proto") { @@ -325,7 +328,7 @@ int FlatCompiler::Compile(int argc, const char **argv) { "\" matches the schema, use --raw-binary to read this file" " anyway."); } else if (!flatbuffers::BufferHasIdentifier( - contents.c_str(), parser->file_identifier_.c_str())) { + contents.c_str(), parser->file_identifier_.c_str(), opts.size_prefixed)) { Error("binary \"" + filename + "\" does not have expected file_identifier \"" + parser->file_identifier_ + diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index 40afbf40ea89fab93f366c51abb20bb65beb6c35..6ef7f09678538b0f78fa268859fdfda2ce622ee9 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -263,8 +263,9 @@ bool GenerateText(const Parser &parser, const void *flatbuffer, std::string &text = *_text; assert(parser.root_struct_def_); // call SetRootType() text.reserve(1024); // Reduce amount of inevitable reallocs. - if (!GenStruct(*parser.root_struct_def_, GetRoot<Table>(flatbuffer), 0, - parser.opts, _text)) { + auto root = parser.opts.size_prefixed ? + GetSizePrefixedRoot<Table>(flatbuffer) : GetRoot<Table>(flatbuffer); + if (!GenStruct(*parser.root_struct_def_, root, 0, parser.opts, _text)) { return false; } text += NewLine(parser.opts); diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 89e6e80d8969ecfec966ecaace9a6e48e42e910e..2607c0cd049b0d9e94ff40f1b1f55dc1ff2ff801 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2412,9 +2412,15 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, } uoffset_t toff; ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); - builder_.Finish(Offset<Table>(toff), file_identifier_.length() - ? file_identifier_.c_str() - : nullptr); + if (opts.size_prefixed) { + builder_.FinishSizePrefixed(Offset<Table>(toff), file_identifier_.length() + ? file_identifier_.c_str() + : nullptr); + } else { + builder_.Finish(Offset<Table>(toff), file_identifier_.length() + ? file_identifier_.c_str() + : nullptr); + } } else if (IsIdent("enum")) { ECHECK(ParseEnum(false, nullptr)); } else if (IsIdent("union")) { @@ -2521,7 +2527,11 @@ void Parser::Serialize() { builder_.CreateString(file_identifier_), builder_.CreateString(file_extension_), root_struct_def_ ? root_struct_def_->serialized_location : 0); - builder_.Finish(schema_offset, reflection::SchemaIdentifier()); + if (opts.size_prefixed) { + builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier()); + } else { + builder_.Finish(schema_offset, reflection::SchemaIdentifier()); + } } Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,