Sync from upstream

This commit is contained in:
吴凡
2016-07-01 11:03:25 +08:00
296 changed files with 16524 additions and 8059 deletions

View File

@@ -17,6 +17,9 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <limits>
#define FLATC_VERSION "1.3.0 (" __DATE__ ")"
static void Error(const std::string &err, bool usage = false,
bool show_exe_name = true);
@@ -26,22 +29,26 @@ static void Error(const std::string &err, bool usage = false,
struct Generator {
bool (*generate)(const flatbuffers::Parser &parser,
const std::string &path,
<<<<<<< HEAD
const std::string &file_name,
const flatbuffers::GeneratorOptions &opts);
=======
const std::string &file_name);
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
flatbuffers::GeneratorOptions::Language lang;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;
std::string (*make_rule)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name,
const flatbuffers::GeneratorOptions &opts);
const std::string &file_name);
};
const Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
<<<<<<< HEAD
flatbuffers::GeneratorOptions::kMAX,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
@@ -75,8 +82,47 @@ const Generator generators[] = {
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
flatbuffers::GeneratorOptions::kMAX,
=======
flatbuffers::IDLOptions::kMAX,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
flatbuffers::IDLOptions::kMAX,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::IDLOptions::kMAX,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
flatbuffers::IDLOptions::kMAX,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
flatbuffers::IDLOptions::kMAX,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
flatbuffers::IDLOptions::kMAX,
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGRPC, nullptr, "--grpc", "GRPC",
flatbuffers::IDLOptions::kMAX,
"Generate GRPC interfaces",
flatbuffers::CPPMakeRule },
};
const char *program_name = nullptr;
@@ -95,28 +141,33 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
: " ",
generators[i].generator_help);
printf(
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n"
" --strict-json Strict JSON: field names must be / will be quoted,\n"
" no trailing commas in tables/vectors.\n"
" --defaults-json Output fields whose value is the default when\n"
" writing JSON\n"
" --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
" --scoped-enums Use C++11 style scoped and strongly typed enums.\n"
" also implies --no-prefix.\n"
" --gen-includes (deprecated), this is the default behavior.\n"
" If the original behavior is required (no include\n"
" statements) use --no-includes.\n"
" --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C#\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --schema Serialize schemas instead of JSON (use with -b)\n"
"FILEs may depend on declarations in earlier files.\n"
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n"
" --version Print the version number of flatc and exit.\n"
" --strict-json Strict JSON: field names must be / will be quoted,\n"
" no trailing commas in tables/vectors.\n"
" --defaults-json Output fields whose value is the default when\n"
" writing JSON\n"
" --unknown-json Allow fields in JSON that are not defined in the\n"
" schema. These fields will be discared when generating\n"
" binaries.\n"
" --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
" --scoped-enums Use C++11 style scoped and strongly typed enums.\n"
" also implies --no-prefix.\n"
" --gen-includes (deprecated), this is the default behavior.\n"
" If the original behavior is required (no include\n"
" statements) use --no-includes.\n"
" --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C#\n"
" --gen-name-strings Generate type name functions for C++.\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --schema Serialize schemas instead of JSON (use with -b)\n"
"FILEs may be schemas, or JSON files (conforming to preceding schema)\n"
"FILEs after the -- must be binary flatbuffer format files.\n"
"Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n"
@@ -129,13 +180,12 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
int main(int argc, const char *argv[]) {
program_name = argv[0];
flatbuffers::GeneratorOptions opts;
flatbuffers::IDLOptions opts;
std::string output_path;
const size_t num_generators = sizeof(generators) / sizeof(generators[0]);
bool generator_enabled[num_generators] = { false };
bool any_generator = false;
bool print_make_rules = false;
bool proto_mode = false;
bool raw_binary = false;
bool schema_binary = false;
std::vector<std::string> filenames;
@@ -158,6 +208,8 @@ int main(int argc, const char *argv[]) {
opts.skip_js_exports = true;
} else if(arg == "--defaults-json") {
opts.output_default_scalars_in_json = true;
} else if (arg == "--unknown-json") {
opts.skip_unexpected_fields_in_json = true;
} else if(arg == "--no-prefix") {
opts.prefixed_enums = false;
} else if(arg == "--scoped-enums") {
@@ -165,6 +217,11 @@ int main(int argc, const char *argv[]) {
opts.scoped_enums = true;
} else if(arg == "--gen-mutable") {
opts.mutable_buffer = true;
} else if(arg == "--gen-name-strings") {
opts.generate_name_strings = true;
} else if(arg == "--gen-all") {
opts.generate_all = true;
opts.include_dependence_headers = false;
} else if(arg == "--gen-includes") {
// Deprecated, remove this option some time in the future.
printf("warning: --gen-includes is deprecated (it is now default)\n");
@@ -177,12 +234,14 @@ int main(int argc, const char *argv[]) {
} else if(arg == "--") { // Separator between text and binary inputs.
binary_files_from = filenames.size();
} else if(arg == "--proto") {
proto_mode = true;
any_generator = true;
opts.proto_mode = true;
} else if(arg == "--schema") {
schema_binary = true;
} else if(arg == "-M") {
print_make_rules = true;
} else if(arg == "--version") {
printf("flatc version %s\n", FLATC_VERSION);
exit(0);
} else {
for (size_t i = 0; i < num_generators; ++i) {
if (arg == generators[i].generator_opt_long ||
@@ -203,11 +262,19 @@ int main(int argc, const char *argv[]) {
if (!filenames.size()) Error("missing input files", false, true);
if (!any_generator)
Error("no options: specify one of -c -g -j -t -b etc.", true);
if (opts.proto_mode) {
if (any_generator)
Error("cannot generate code directly from .proto files", true);
} else if (!any_generator) {
Error("no options: specify at least one generator.", true);
}
// Now process the files:
<<<<<<< HEAD
parser = new flatbuffers::Parser(opts.strict_json, proto_mode);
=======
parser = new flatbuffers::Parser(opts);
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
for (auto file_it = filenames.begin();
file_it != filenames.end();
++file_it) {
@@ -243,12 +310,23 @@ int main(int argc, const char *argv[]) {
}
}
} else {
<<<<<<< HEAD
=======
// Check if file contains 0 bytes.
if (contents.length() != strlen(contents.c_str())) {
Error("input file appears to be binary: " + *file_it, true);
}
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
if (flatbuffers::GetExtension(*file_it) == "fbs") {
// If we're processing multiple schemas, make sure to start each
// one from scratch. If it depends on previous schemas it must do
// so explicitly using an include.
delete parser;
<<<<<<< HEAD
parser = new flatbuffers::Parser(opts.strict_json, proto_mode);
=======
parser = new flatbuffers::Parser(opts);
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
}
auto local_include_directory = flatbuffers::StripFileName(*file_it);
include_directories.push_back(local_include_directory.c_str());
@@ -268,11 +346,15 @@ int main(int argc, const char *argv[]) {
flatbuffers::StripExtension(*file_it));
for (size_t i = 0; i < num_generators; ++i) {
opts.lang = generators[i].lang;
parser->opts.lang = generators[i].lang;
if (generator_enabled[i]) {
if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path);
<<<<<<< HEAD
if (!generators[i].generate(*parser, output_path, filebase, opts)) {
=======
if (!generators[i].generate(*parser, output_path, filebase)) {
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
Error(std::string("Unable to generate ") +
generators[i].lang_name +
" for " +
@@ -280,7 +362,11 @@ int main(int argc, const char *argv[]) {
}
} else {
std::string make_rule = generators[i].make_rule(
<<<<<<< HEAD
*parser, output_path, *file_it, opts);
=======
*parser, output_path, *file_it);
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap(
make_rule, 80, " ", " \\").c_str());
@@ -288,7 +374,15 @@ int main(int argc, const char *argv[]) {
}
}
<<<<<<< HEAD
if (proto_mode) GenerateFBS(*parser, output_path, filebase, opts);
=======
if (opts.proto_mode) GenerateFBS(*parser, output_path, filebase);
// We do not want to generate code for the definitions in this file
// in any files coming up next.
parser->MarkGenerated();
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
}
delete parser;

File diff suppressed because it is too large Load Diff

View File

@@ -52,8 +52,7 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
}
// Generate a flatbuffer schema from the Parser's internal representation.
std::string GenerateFBS(const Parser &parser, const std::string &file_name,
const GeneratorOptions &opts) {
std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
// Proto namespaces may clash with table names, so we have to prefix all:
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
++it) {
@@ -65,7 +64,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name,
std::string schema;
schema += "// Generated from " + file_name + ".proto\n\n";
if (opts.include_dependence_headers) {
if (parser.opts.include_dependence_headers) {
#ifdef FBS_GEN_INCLUDES // TODO: currently all in one file.
int num_includes = 0;
for (auto it = parser.included_files_.begin();
@@ -120,10 +119,9 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name,
bool GenerateFBS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts) {
const std::string &file_name) {
return SaveFile((path + file_name + ".fbs").c_str(),
GenerateFBS(parser, file_name, opts), false);
GenerateFBS(parser, file_name), false);
}
} // namespace flatbuffers

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,7 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
#ifdef _WIN32
#include <direct.h>
@@ -52,20 +53,6 @@ std::string OffsetPrefix(const FieldDef &field) {
"))\n\tif o != 0 {\n";
}
// Begin by declaring namespace and imports.
static void BeginFile(const std::string name_space_name,
const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "// automatically generated, do not modify\n\n";
code += "package " + name_space_name + "\n\n";
if (needs_imports) {
code += "import (\n";
code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
code += ")\n";
}
}
// Begin a class declaration.
static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -588,32 +575,6 @@ static std::string GenMethod(const FieldDef &field) {
: (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
}
// Save out the generated code for a Go Table type.
static bool SaveType(const Parser &parser, const Definition &def,
const std::string &classcode, const std::string &path,
bool needs_imports) {
if (!classcode.length()) return true;
std::string namespace_name;
std::string namespace_dir = path; // Either empty or ends in separator.
auto &namespaces = parser.namespaces_.back()->components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) {
namespace_name += ".";
}
namespace_name = *it;
namespace_dir += *it + kPathSeparator;
}
EnsureDirExists(namespace_dir);
std::string code = "";
BeginFile(namespace_name, needs_imports, &code);
code += classcode;
std::string filename = namespace_dir + def.name + ".go";
return SaveFile(filename.c_str(), code, false);
}
static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
@@ -660,29 +621,63 @@ static void GenStructBuilder(const StructDef &struct_def,
EndBuilderBody(code_ptr);
}
class GoGenerator : public BaseGenerator {
public:
GoGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "" /* not used*/,
"" /* not used */){};
bool generate() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
std::string enumcode;
go::GenEnum(**it, &enumcode);
if (!SaveType(**it, enumcode, false)) return false;
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
std::string declcode;
go::GenStruct(**it, &declcode, parser_.root_struct_def_);
if (!SaveType(**it, declcode, true)) return false;
}
return true;
}
private:
// Begin by declaring namespace and imports.
void BeginFile(const std::string name_space_name, const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code = code + "// " + FlatBuffersGeneratedWarning();
code += "package " + name_space_name + "\n\n";
if (needs_imports) {
code += "import (\n";
code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
code += ")\n";
}
}
// Save out the generated code for a Go Table type.
bool SaveType(const Definition &def, const std::string &classcode,
bool needs_imports) {
if (!classcode.length()) return true;
std::string code = "";
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
code += classcode;
std::string filename =
NamespaceDir(*def.defined_namespace) + def.name + ".go";
return SaveFile(filename.c_str(), code, false);
}
};
} // namespace go
bool GenerateGo(const Parser &parser,
const std::string &path,
const std::string & /*file_name*/,
const GeneratorOptions & /*opts*/) {
for (auto it = parser.enums_.vec.begin();
it != parser.enums_.vec.end(); ++it) {
std::string enumcode;
go::GenEnum(**it, &enumcode);
if (!go::SaveType(parser, **it, enumcode, path, false))
return false;
}
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
std::string declcode;
go::GenStruct(**it, &declcode, parser.root_struct_def_);
if (!go::SaveType(parser, **it, declcode, path, true))
return false;
}
return true;
bool GenerateGo(const Parser &parser, const std::string &path,
const std::string &file_name) {
go::GoGenerator generator(parser, path, file_name);
return generator.generate();
}
} // namespace flatbuffers

216
src/idl_gen_grpc.cpp Normal file
View File

@@ -0,0 +1,216 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "src/compiler/cpp_generator.h"
namespace flatbuffers {
class FlatBufMethod : public grpc_cpp_generator::Method {
public:
enum Streaming { kNone, kClient, kServer, kBiDi };
FlatBufMethod(const RPCCall *method)
: method_(method) {
streaming_ = kNone;
auto val = method_->attributes.Lookup("streaming");
if (val) {
if (val->constant == "client") streaming_ = kClient;
if (val->constant == "server") streaming_ = kServer;
if (val->constant == "bidi") streaming_ = kBiDi;
}
}
std::string name() const { return method_->name; }
std::string GRPCType(const StructDef &sd) const {
return "flatbuffers::BufferRef<" + sd.name + ">";
}
std::string input_type_name() const {
return GRPCType(*method_->request);
}
std::string output_type_name() const {
return GRPCType(*method_->response);
}
bool NoStreaming() const { return streaming_ == kNone; }
bool ClientOnlyStreaming() const { return streaming_ == kClient; }
bool ServerOnlyStreaming() const { return streaming_ == kServer; }
bool BidiStreaming() const { return streaming_ == kBiDi; }
private:
const RPCCall *method_;
Streaming streaming_;
};
class FlatBufService : public grpc_cpp_generator::Service {
public:
FlatBufService(const ServiceDef *service) : service_(service) {}
std::string name() const { return service_->name; }
int method_count() const {
return static_cast<int>(service_->calls.vec.size());
};
std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Method>(
new FlatBufMethod(service_->calls.vec[i]));
};
private:
const ServiceDef *service_;
};
class FlatBufPrinter : public grpc_cpp_generator::Printer {
public:
FlatBufPrinter(std::string *str)
: str_(str), escape_char_('$'), indent_(0) {}
void Print(const std::map<std::string, std::string> &vars,
const char *string_template) {
std::string s = string_template;
// Replace any occurrences of strings in "vars" that are surrounded
// by the escape character by what they're mapped to.
size_t pos;
while ((pos = s.find(escape_char_)) != std::string::npos) {
// Found an escape char, must also find the closing one.
size_t pos2 = s.find(escape_char_, pos + 1);
// If placeholder not closed, ignore.
if (pos2 == std::string::npos) break;
auto it = vars.find(s.substr(pos + 1, pos2 - pos - 1));
// If unknown placeholder, ignore.
if (it == vars.end()) break;
// Subtitute placeholder.
s.replace(pos, pos2 - pos + 1, it->second);
}
Print(s.c_str());
}
void Print(const char *s) {
// Add this string, but for each part separated by \n, add indentation.
for (;;) {
// Current indentation.
str_->insert(str_->end(), indent_ * 2, ' ');
// See if this contains more than one line.
auto lf = strchr(s, '\n');
if (lf) {
(*str_) += std::string(s, lf + 1);
s = lf + 1;
if (!*s) break; // Only continue if there's more lines.
} else {
(*str_) += s;
break;
}
}
}
void Indent() { indent_++; }
void Outdent() { indent_--; assert(indent_ >= 0); }
private:
std::string *str_;
char escape_char_;
int indent_;
};
class FlatBufFile : public grpc_cpp_generator::File {
public:
FlatBufFile(const Parser &parser, const std::string &file_name)
: parser_(parser), file_name_(file_name) {}
std::string filename() const { return file_name_; }
std::string filename_without_ext() const {
return StripExtension(file_name_);
}
std::string message_header_ext() const { return "_generated.h"; }
std::string service_header_ext() const { return ".grpc.fb.h"; }
std::string package() const {
return parser_.namespaces_.back()->GetFullyQualifiedName("");
}
std::vector<std::string> package_parts() const {
return parser_.namespaces_.back()->components;
}
std::string additional_headers() const {
return "#include \"flatbuffers/grpc.h\"\n";
}
int service_count() const {
return static_cast<int>(parser_.services_.vec.size());
};
std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Service> (
new FlatBufService(parser_.services_.vec[i]));
}
std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(std::string *str) const {
return std::unique_ptr<grpc_cpp_generator::Printer>(
new FlatBufPrinter(str));
}
private:
const Parser &parser_;
const std::string &file_name_;
};
bool GenerateGRPC(const Parser &parser,
const std::string &/*path*/,
const std::string &file_name) {
int nservices = 0;
for (auto it = parser.services_.vec.begin();
it != parser.services_.vec.end(); ++it) {
if (!(*it)->generated) nservices++;
}
if (!nservices) return true;
grpc_cpp_generator::Parameters generator_parameters;
// TODO(wvo): make the other parameters in this struct configurable.
generator_parameters.use_system_headers = true;
FlatBufFile fbfile(parser, file_name);
std::string header_code =
grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) +
grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) +
grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) +
grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters);
std::string source_code =
grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) +
grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) +
grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) +
grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters);
return flatbuffers::SaveFile((file_name + ".grpc.fb.h").c_str(),
header_code, false) &&
flatbuffers::SaveFile((file_name + ".grpc.fb.cc").c_str(),
source_code, false);
}
} // namespace flatbuffers

View File

@@ -19,16 +19,74 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
namespace flatbuffers {
namespace js {
static void GenNamespaces(const Parser &parser, std::string *code_ptr,
std::string *exports_ptr) {
static std::string GeneratedFileName(const std::string &path,
const std::string &file_name) {
return path + file_name + "_generated.js";
}
namespace js {
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
class JsGenerator : public BaseGenerator {
public:
JsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."){};
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
if (IsEverythingGenerated()) return true;
std::string enum_code, struct_code, exports_code, code;
generateEnums(&enum_code, &exports_code);
generateStructs(&struct_code, &exports_code);
code = code + "// " + FlatBuffersGeneratedWarning();
// Generate code for all the namespace declarations.
GenNamespaces(&code, &exports_code);
// Output the main declaration code from above.
code += enum_code;
code += struct_code;
if (!exports_code.empty() && !parser_.opts.skip_js_exports) {
code += "// Exports for Node.js and RequireJS\n";
code += exports_code;
}
return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false);
}
private:
// Generate code for all enums.
void generateEnums(std::string *enum_code_ptr,
std::string *exports_code_ptr) {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
GenEnum(enum_def, enum_code_ptr, exports_code_ptr);
}
}
// Generate code for all structs.
void generateStructs(std::string *decl_code_ptr,
std::string *exports_code_ptr) {
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);
}
}
void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) {
std::set<std::string> namespaces;
for (auto it = parser.namespaces_.begin();
it != parser.namespaces_.end(); ++it) {
for (auto it = parser_.namespaces_.begin();
it != parser_.namespaces_.end(); ++it) {
std::string namespace_so_far;
// Gather all parent namespaces for this namespace
@@ -61,22 +119,6 @@ static void GenNamespaces(const Parser &parser, std::string *code_ptr,
}
}
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
static std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) {
std::string qualified_name;
for (auto it = ns->components.begin();
it != ns->components.end(); ++it) {
qualified_name += *it + ".";
}
return qualified_name + name;
}
static std::string WrapInNameSpace(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, def.name);
}
// Generate a documentation comment, if available.
static void GenDocComment(const std::vector<std::string> &dc,
std::string *code_ptr,
@@ -122,7 +164,7 @@ static void GenDocComment(std::string *code_ptr,
}
// Generate an enum declaration and an enum string lookup table.
static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
void GenEnum(EnumDef &enum_def, std::string *code_ptr,
std::string *exports_ptr) {
if (enum_def.generated) return;
std::string &code = *code_ptr;
@@ -169,7 +211,7 @@ static std::string GenType(const Type &type) {
}
}
static std::string GenGetter(const Type &type, const std::string &arguments) {
std::string GenGetter(const Type &type, const std::string &arguments) {
switch (type.base_type) {
case BASE_TYPE_STRING: return "this.bb.__string" + arguments;
case BASE_TYPE_STRUCT: return "this.bb.__struct" + arguments;
@@ -189,7 +231,7 @@ static std::string GenGetter(const Type &type, const std::string &arguments) {
}
}
static std::string GenDefaultValue(const Value &value) {
std::string GenDefaultValue(const Value &value, const std::string &context) {
if (value.type.enum_def) {
if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) {
@@ -205,20 +247,18 @@ static std::string GenDefaultValue(const Value &value) {
return "null";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG:
if (value.constant != "0") {
int64_t constant = StringToInt(value.constant.c_str());
return "new flatbuffers.Long(" + NumToString((int32_t)constant) +
", " + NumToString((int32_t)(constant >> 32)) + ")";
}
return "flatbuffers.Long.ZERO";
case BASE_TYPE_ULONG: {
int64_t constant = StringToInt(value.constant.c_str());
return context + ".createLong(" + NumToString((int32_t)constant) +
", " + NumToString((int32_t)(constant >> 32)) + ")";
}
default:
return value.constant;
}
}
static std::string GenTypeName(const Type &type, bool input) {
std::string GenTypeName(const Type &type, bool input) {
if (!input) {
if (type.base_type == BASE_TYPE_STRING) {
return "string|Uint8Array";
@@ -270,7 +310,7 @@ static std::string MaybeScale(T value) {
return value != 1 ? " * " + NumToString(value) : "";
}
static void GenStructArgs(const StructDef &struct_def,
void GenStructArgs(const StructDef &struct_def,
std::string *annotations,
std::string *arguments,
const std::string &nameprefix) {
@@ -321,8 +361,7 @@ static void GenStructBody(const StructDef &struct_def,
}
// Generate an accessor struct with constructor for a flatbuffers struct.
static void GenStruct(const Parser &parser, StructDef &struct_def,
std::string *code_ptr, std::string *exports_ptr) {
void GenStruct(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;
@@ -376,13 +415,13 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
code += "};\n\n";
// Generate the identifier check method
if (parser.root_struct_def_ == &struct_def &&
!parser.file_identifier_.empty()) {
if (parser_.root_struct_def_ == &struct_def &&
!parser_.file_identifier_.empty()) {
GenDocComment(code_ptr,
"@param {flatbuffers.ByteBuffer} bb\n"
"@returns {boolean}");
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
code += " return bb.__has_identifier('" + parser.file_identifier_;
code += " return bb.__has_identifier('" + parser_.file_identifier_;
code += "');\n};\n\n";
}
}
@@ -417,7 +456,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
index += ", optionalEncoding";
}
code += offset_prefix + GenGetter(field.value.type,
"(" + index + ")") + " : " + GenDefaultValue(field.value);
"(" + index + ")") + " : " + GenDefaultValue(field.value, "this.bb");
code += ";\n";
}
}
@@ -485,7 +524,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
code += "false";
} else if (field.value.type.element == BASE_TYPE_LONG ||
field.value.type.element == BASE_TYPE_ULONG) {
code += "flatbuffers.Long.ZERO";
code += "this.bb.createLong(0, 0)";
} else if (IsScalar(field.value.type.element)) {
code += "0";
} else {
@@ -511,12 +550,24 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
}
code += "};\n\n";
// Emit a length helper
// Emit vector helpers
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
// Emit a length helper
GenDocComment(code_ptr, "@returns {number}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += "Length = function() {\n" + offset_prefix;
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
// For scalar types, emit a typed array helper
auto vectorType = field.value.type.VectorType();
if (IsScalar(vectorType.base_type)) {
GenDocComment(code_ptr, "@returns {" + GenType(vectorType) + "Array}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += "Array = function() {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(this.bb.bytes().buffer, "
"this.bb.__vector(this.bb_pos + offset), "
"this.bb.__vector_len(this.bb_pos + offset)) : null;\n};\n\n";
}
}
}
@@ -570,7 +621,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
if (field.value.type.base_type == BASE_TYPE_BOOL) {
code += "+";
}
code += GenDefaultValue(field.value);
code += GenDefaultValue(field.value, "builder");
}
code += ");\n};\n\n";
@@ -633,86 +684,33 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
code += "};\n\n";
// Generate the method to complete buffer construction
if (parser.root_struct_def_ == &struct_def) {
if (parser_.root_struct_def_ == &struct_def) {
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@param {flatbuffers.Offset} offset");
code += object_name + ".finish" + struct_def.name + "Buffer";
code += " = function(builder, offset) {\n";
code += " builder.finish(offset";
if (!parser.file_identifier_.empty()) {
code += ", '" + parser.file_identifier_ + "'";
if (!parser_.file_identifier_.empty()) {
code += ", '" + parser_.file_identifier_ + "'";
}
code += ");\n";
code += "};\n\n";
}
}
}
};
} // namespace js
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
std::string GenerateJS(const Parser &parser,
const GeneratorOptions &opts) {
using namespace js;
// Generate code for all the enum declarations.
std::string enum_code, exports_code;
for (auto it = parser.enums_.vec.begin();
it != parser.enums_.vec.end(); ++it) {
GenEnum(**it, &enum_code, &exports_code);
}
// Generate code for all structs, then all tables.
std::string decl_code;
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
GenStruct(parser, **it, &decl_code, &exports_code);
}
// Only output file-level code if there were any declarations.
if (enum_code.length() || decl_code.length()) {
std::string code;
code = "// automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
// Generate code for all the namespace declarations.
GenNamespaces(parser, &code, &exports_code);
// Output the main declaration code from above.
code += enum_code;
code += decl_code;
if (!exports_code.empty() && !opts.skip_js_exports) {
code += "// Exports for Node.js and RequireJS\n";
code += exports_code;
}
return code;
}
return std::string();
}
static std::string GeneratedFileName(const std::string &path,
const std::string &file_name) {
return path + file_name + "_generated.js";
}
bool GenerateJS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts) {
auto code = GenerateJS(parser, opts);
return !code.length() ||
SaveFile(GeneratedFileName(path, file_name).c_str(), code, false);
bool GenerateJS(const Parser &parser, const std::string &path,
const std::string &file_name) {
js::JsGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string JSMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions & /*opts*/) {
const std::string &file_name) {
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(file_name));
std::string make_rule = GeneratedFileName(path, filebase) + ": ";

View File

@@ -21,56 +21,78 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
namespace flatbuffers {
namespace php {
static std::string GenGetter(const Type &type);
static std::string GenDefaultValue(const Value &value);
static std::string GenMethod(const FieldDef &field);
static void GenStructBuilder(const StructDef &struct_def,
std::string *code_ptr);
static std::string GenTypeBasic(const Type &type);
static std::string GenTypeGet(const Type &type);
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
static std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) {
std::string qualified_name = "\\";
for (auto it = ns->components.begin();
it != ns->components.end(); ++it) {
qualified_name += *it + "\\";
}
return qualified_name + name;
}
static std::string WrapInNameSpace(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, def.name);
}
// Hardcode spaces per indentation.
const std::string Indent = " ";
// Begin by declaring namespace and imports.
static void BeginFile(const std::string name_space_name,
const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "<?php\n";
code += "// automatically generated, do not modify\n\n";
code += "namespace " + name_space_name + ";\n\n";
if (needs_imports) {
code += "use \\Google\\FlatBuffers\\Struct;\n";
code += "use \\Google\\FlatBuffers\\Table;\n";
code += "use \\Google\\FlatBuffers\\ByteBuffer;\n";
code += "use \\Google\\FlatBuffers\\FlatBufferBuilder;\n";
code += "\n";
class PhpGenerator : public BaseGenerator {
public:
PhpGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "\\", "\\"){};
bool generate() {
if (!generateEnums()) return false;
if (!generateStructs()) return false;
return true;
}
}
private:
bool generateEnums() {
for (auto it = parser_.enums_.vec.begin();
it != parser_.enums_.vec.end(); ++it) {
auto &enum_def = **it;
std::string enumcode;
GenEnum(enum_def, &enumcode);
if (!SaveType(enum_def, enumcode, false)) return false;
}
return true;
}
bool generateStructs() {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
std::string declcode;
GenStruct(struct_def, &declcode);
if (!SaveType(struct_def, declcode, true)) return false;
}
return true;
}
// Begin by declaring namespace and imports.
void BeginFile(const std::string name_space_name,
const bool needs_imports, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "<?php\n";
code = code + "// " + FlatBuffersGeneratedWarning();
code += "namespace " + name_space_name + ";\n\n";
if (needs_imports) {
code += "use \\Google\\FlatBuffers\\Struct;\n";
code += "use \\Google\\FlatBuffers\\Table;\n";
code += "use \\Google\\FlatBuffers\\ByteBuffer;\n";
code += "use \\Google\\FlatBuffers\\FlatBufferBuilder;\n";
code += "\n";
}
}
// Save out the generated code for a Php Table type.
bool SaveType(const Definition &def, const std::string &classcode,
bool needs_imports) {
if (!classcode.length()) return true;
std::string code = "";
BeginFile(FullNamespace("\\", *def.defined_namespace),
needs_imports, &code);
code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) +
kPathSeparator + def.name + ".php";
return SaveFile(filename.c_str(), code, false);
}
// Begin a class declaration.
static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -140,8 +162,8 @@ namespace php {
code += Indent + " * @return " + struct_def.name + "\n";
code += Indent + " **/\n";
code += Indent + "public function init($_i, ByteBuffer $_bb)\n";
code += Indent + "{\n";
code += Indent + Indent + "$this->bb_pos = $_i;\n";
code += Indent + "{\n";
code += Indent + Indent + "$this->bb_pos = $_i;\n";
code += Indent + Indent + "$this->bb = $_bb;\n";
code += Indent + Indent + "return $this;\n";
code += Indent + "}\n\n";
@@ -165,6 +187,22 @@ namespace php {
code += Indent + "}\n\n";
}
// Get a [ubyte] vector as a byte array.
static void GetUByte(const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "/**\n";
code += Indent + " * @return string\n";
code += Indent + " */\n";
code += Indent + "public function get";
code += MakeCamel(field.name) + "Bytes()\n";
code += Indent + "{\n";
code += Indent + Indent + "return $this->__vector_as_bytes(";
code += NumToString(field.value.offset) + ");\n";
code += Indent + "}\n\n";
}
// Get the value of a struct's scalar.
static void GetScalarFieldOfStruct(const FieldDef &field,
std::string *code_ptr) {
@@ -190,8 +228,7 @@ namespace php {
}
// Get the value of a table's scalar.
static void GetScalarFieldOfTable(const FieldDef &field,
std::string *code_ptr) {
void GetScalarFieldOfTable(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
@@ -214,8 +251,7 @@ namespace php {
// Get a struct by initializing an existing struct.
// Specific to Struct.
static void GetStructFieldOfStruct(const FieldDef &field,
std::string *code_ptr) {
void GetStructFieldOfStruct(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "/**\n";
@@ -234,14 +270,13 @@ namespace php {
// Get a struct by initializing an existing struct.
// Specific to Table.
static void GetStructFieldOfTable(const FieldDef &field,
std::string *code_ptr) {
void GetStructFieldOfTable(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "public function get";
code += MakeCamel(field.name);
code += "()\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$obj = new ";
code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
code += Indent + Indent +
@@ -249,21 +284,24 @@ namespace php {
NumToString(field.value.offset) +
");\n";
code += Indent + Indent;
code += "return $o != 0 ? $obj->init($o + $this->bb_pos, $this->bb) : ";
code += "return $o != 0 ? $obj->init(";
if (field.value.type.struct_def->fixed)
{
code += "$o + $this->bb_pos, $this->bb) : ";
} else {
code += "$this->__indirect($o + $this->bb_pos), $this->bb) : ";
}
code += GenDefaultValue(field.value) + ";\n";
code += Indent + "}\n\n";
}
// Get the value of a string.
static void GetStringField(const FieldDef &field,
std::string *code_ptr) {
void GetStringField(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "public function get";
code += MakeCamel(field.name);
code += "()\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent +
"$o = $this->__offset(" +
NumToString(field.value.offset) +
@@ -275,8 +313,7 @@ namespace php {
}
// Get the value of a union from an object.
static void GetUnionField(const FieldDef &field,
std::string *code_ptr) {
void GetUnionField(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "/**\n";
@@ -295,9 +332,8 @@ namespace php {
}
// Get the value of a vector's struct member.
static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
const FieldDef &field,
std::string *code_ptr) {
void GetMemberOfVectorOfStruct(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
@@ -307,7 +343,7 @@ namespace php {
code += Indent + "public function get";
code += MakeCamel(field.name);
code += "($j)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent +
"$o = $this->__offset(" +
NumToString(field.value.offset) +
@@ -359,7 +395,7 @@ namespace php {
// Get the value of a vector's non-struct member. Uses a named return
// argument to conveniently set the zero value for the result.
static void GetMemberOfVectorOfNonStruct(const FieldDef &field,
void GetMemberOfVectorOfNonStruct(const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
@@ -371,7 +407,7 @@ namespace php {
code += Indent + "public function get";
code += MakeCamel(field.name);
code += "($j)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent +
"$o = $this->__offset(" +
NumToString(field.value.offset) +
@@ -456,7 +492,7 @@ namespace php {
code += Indent + " */\n";
code += Indent + "public static function start" + struct_def.name;
code += "(FlatBufferBuilder $builder)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->StartObject(";
code += NumToString(struct_def.fields.vec.size());
code += ");\n";
@@ -528,7 +564,7 @@ namespace php {
code += "(FlatBufferBuilder $builder, ";
code += "$" + MakeCamel(field.name, false);
code += ")\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->add";
code += GenMethod(field) + "X(";
code += NumToString(offset) + ", ";
@@ -562,7 +598,7 @@ namespace php {
code += Indent + "public static function create";
code += MakeCamel(field.name);
code += "Vector(FlatBufferBuilder $builder, array $data)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->startVector(";
code += NumToString(elem_size);
code += ", count($data), " + NumToString(alignment);
@@ -591,7 +627,7 @@ namespace php {
code += Indent + "public static function start";
code += MakeCamel(field.name);
code += "Vector(FlatBufferBuilder $builder, $numElems)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->startVector(";
code += NumToString(elem_size);
code += ", $numElems, " + NumToString(alignment);
@@ -600,9 +636,7 @@ namespace php {
}
// Get the offset of the end of a table.
static void GetEndOffsetOnTable(const Parser &parser,
const StructDef &struct_def,
std::string *code_ptr) {
void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -612,7 +646,7 @@ namespace php {
code += Indent + " */\n";
code += Indent + "public static function end" + struct_def.name;
code += "(FlatBufferBuilder $builder)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $builder->endObject();\n";
@@ -629,7 +663,7 @@ namespace php {
code += Indent + Indent + "return $o;\n";
code += Indent + "}\n";
if (parser.root_struct_def_ == &struct_def) {
if (parser_.root_struct_def_ == &struct_def) {
code += "\n";
code += Indent + "public static function finish";
code += struct_def.name;
@@ -637,16 +671,15 @@ namespace php {
code += Indent + "{\n";
code += Indent + Indent + "$builder->finish($offset";
if (parser.file_identifier_.length())
code += ", \"" + parser.file_identifier_ + "\"";
if (parser_.file_identifier_.length())
code += ", \"" + parser_.file_identifier_ + "\"";
code += ");\n";
code += Indent + "}\n";
}
}
// Generate a struct field, conditioned on its child type(s).
static void GenStructAccessor(const StructDef &struct_def,
const FieldDef &field,
// Generate a struct field, conditioned on its child type(s).
void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, nullptr);
@@ -686,13 +719,14 @@ namespace php {
}
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
GetVectorLen(field, code_ptr);
if (field.value.type.element == BASE_TYPE_UCHAR) {
GetUByte(field, code_ptr);
}
}
}
// Generate table constructors, conditioned on its members' types.
static void GenTableBuilders(const Parser &parser,
const StructDef &struct_def,
std::string *code_ptr) {
void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
GetStartOfTable(struct_def, code_ptr);
for (auto it = struct_def.fields.vec.begin();
@@ -707,7 +741,7 @@ namespace php {
code += Indent + "public static function add";
code += MakeCamel(field.name);
code += "(FlatBufferBuilder $builder, $offset)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->addOffsetX(";
code += NumToString(offset) + ", $offset, 0);\n";
code += Indent + "}\n\n";
@@ -719,11 +753,11 @@ namespace php {
}
}
GetEndOffsetOnTable(parser, struct_def, code_ptr);
GetEndOffsetOnTable(struct_def, code_ptr);
}
// Generate struct or table methods.
static void GenStruct(const Parser &parser, const StructDef &struct_def,
void GenStruct(const StructDef &struct_def,
std::string *code_ptr) {
if (struct_def.generated) return;
@@ -738,13 +772,13 @@ namespace php {
std::string &code = *code_ptr;
if (!struct_def.fixed) {
if (parser.file_identifier_.length()) {
if (parser_.file_identifier_.length()) {
// Return the identifier
code += Indent + "public static function " + struct_def.name;
code += "Identifier()\n";
code += Indent + "{\n";
code += Indent + Indent + "return \"";
code += parser.file_identifier_ + "\";\n";
code += parser_.file_identifier_ + "\";\n";
code += Indent + "}\n\n";
// Check if a buffer has the identifier.
@@ -757,12 +791,12 @@ namespace php {
code += Indent + "}\n\n";
}
if (parser.file_extension_.length()) {
if (parser_.file_extension_.length()) {
// Return the extension
code += Indent + "public static function " + struct_def.name;
code += "Extension()\n";
code += Indent + "{\n";
code += Indent + Indent + "return \"" + parser.file_extension_;
code += Indent + Indent + "return \"" + parser_.file_extension_;
code += "\";\n";
code += Indent + "}\n\n";
}
@@ -785,7 +819,7 @@ namespace php {
GenStructBuilder(struct_def, code_ptr);
} else {
// Create a set of functions that allow table construction.
GenTableBuilders(parser, struct_def, code_ptr);
GenTableBuilders(struct_def, code_ptr);
}
EndClass(code_ptr);
}
@@ -815,7 +849,7 @@ namespace php {
code += Indent + ");\n\n";
code += Indent + "public static function Name($e)\n";
code += Indent + "{\n";
code += Indent + "{\n";
code += Indent + Indent + "if (!isset(self::$names[$e])) {\n";
code += Indent + Indent + Indent + "throw new \\Exception();\n";
code += Indent + Indent + "}\n";
@@ -843,35 +877,6 @@ namespace php {
: (IsStruct(field.value.type) ? "Struct" : "Offset");
}
// Save out the generated code for a Php Table type.
static bool SaveType(const Parser &parser, const Definition &def,
const std::string &classcode, const std::string &path,
bool needs_imports) {
if (!classcode.length()) return true;
std::string namespace_name;
std::string namespace_dir = path;
auto &namespaces = parser.namespaces_.back()->components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) {
namespace_name += "\\";
namespace_dir += kPathSeparator;
}
namespace_name += *it;
namespace_dir += *it;
EnsureDirExists(namespace_dir.c_str());
}
std::string code = "";
BeginFile(namespace_name, needs_imports, &code);
code += classcode;
std::string filename = namespace_dir + kPathSeparator + def.name + ".php";
return SaveFile(filename.c_str(), code, false);
}
static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
@@ -882,7 +887,7 @@ namespace php {
return ctypename[type.base_type];
}
static std::string GenDefaultValue(const Value &value) {
std::string GenDefaultValue(const Value &value) {
if (value.type.enum_def) {
if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) {
@@ -943,38 +948,20 @@ namespace php {
code += "(FlatBufferBuilder $builder";
StructBuilderArgs(struct_def, "", code_ptr);
code += ")\n";
code += Indent + "{\n";
code += Indent + "{\n";
StructBuilderBody(struct_def, "", code_ptr);
code += Indent + Indent + "return $builder->offset();\n";
code += Indent + "}\n";
}
};
} // namespace php
} // namespace php
bool GeneratePhp(const Parser &parser,
const std::string &path,
const std::string & /*file_name*/,
const GeneratorOptions & /*opts*/) {
for (auto it = parser.enums_.vec.begin();
it != parser.enums_.vec.end(); ++it) {
std::string enumcode;
php::GenEnum(**it, &enumcode);
if (!php::SaveType(parser, **it, enumcode, path, false))
return false;
bool GeneratePhp(const Parser &parser, const std::string &path,
const std::string &file_name) {
php::PhpGenerator generator(parser, path, file_name);
return generator.generate();
}
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
std::string declcode;
php::GenStruct(parser, **it, &declcode);
if (!php::SaveType(parser, **it, declcode, path, true))
return false;
}
return true;
}
} // namespace flatbuffers
} // namespace flatbuffers

View File

@@ -21,6 +21,7 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
namespace flatbuffers {
namespace python {
@@ -48,18 +49,6 @@ std::string OffsetPrefix(const FieldDef &field) {
"))\n" + Indent + Indent + "if o != 0:\n";
}
// Begin by declaring namespace and imports.
static void BeginFile(const std::string name_space_name,
const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "# automatically generated, do not modify\n\n";
code += "# namespace: " + name_space_name + "\n\n";
if (needs_imports) {
code += "import flatbuffers\n\n";
}
}
// Begin a class declaration.
static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -557,37 +546,6 @@ static std::string GenMethod(const FieldDef &field) {
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
}
// Save out the generated code for a Python Table type.
static bool SaveType(const Parser &parser, const Definition &def,
const std::string &classcode, const std::string &path,
bool needs_imports) {
if (!classcode.length()) return true;
std::string namespace_name;
std::string namespace_dir = path;
auto &namespaces = parser.namespaces_.back()->components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) {
namespace_name += ".";
namespace_dir += kPathSeparator;
}
namespace_name = *it;
namespace_dir += *it;
EnsureDirExists(namespace_dir.c_str());
std::string init_py_filename = namespace_dir + "/__init__.py";
SaveFile(init_py_filename.c_str(), "", false);
}
std::string code = "";
BeginFile(namespace_name, needs_imports, &code);
code += classcode;
std::string filename = namespace_dir + kPathSeparator + def.name + ".py";
return SaveFile(filename.c_str(), code, false);
}
static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
@@ -634,29 +592,81 @@ static void GenStructBuilder(const StructDef &struct_def,
EndBuilderBody(code_ptr);
}
class PythonGenerator : public BaseGenerator {
public:
PythonGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "" /* not used */,
"" /* not used */){};
bool generate() {
if (!generateEnums()) return false;
if (!generateStructs()) return false;
return true;
}
private:
bool generateEnums() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
std::string enumcode;
GenEnum(enum_def, &enumcode);
if (!SaveType(enum_def, enumcode, false)) return false;
}
return true;
}
bool generateStructs() {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
std::string declcode;
GenStruct(struct_def, &declcode, parser_.root_struct_def_);
if (!SaveType(struct_def, declcode, true)) return false;
}
return true;
}
// Begin by declaring namespace and imports.
void BeginFile(const std::string name_space_name, const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code = code + "# " + FlatBuffersGeneratedWarning();
code += "# namespace: " + name_space_name + "\n\n";
if (needs_imports) {
code += "import flatbuffers\n\n";
}
}
// Save out the generated code for a Python Table type.
bool SaveType(const Definition &def, const std::string &classcode,
bool needs_imports) {
if (!classcode.length()) return true;
std::string namespace_dir = path_;
auto &namespaces = parser_.namespaces_.back()->components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (it != namespaces.begin()) namespace_dir += kPathSeparator;
namespace_dir += *it;
std::string init_py_filename = namespace_dir + "/__init__.py";
SaveFile(init_py_filename.c_str(), "", false);
}
std::string code = "";
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) +
kPathSeparator + def.name + ".py";
return SaveFile(filename.c_str(), code, false);
}
};
} // namespace python
bool GeneratePython(const Parser &parser,
const std::string &path,
const std::string & /*file_name*/,
const GeneratorOptions & /*opts*/) {
for (auto it = parser.enums_.vec.begin();
it != parser.enums_.vec.end(); ++it) {
std::string enumcode;
python::GenEnum(**it, &enumcode);
if (!python::SaveType(parser, **it, enumcode, path, false))
return false;
}
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
std::string declcode;
python::GenStruct(**it, &declcode, parser.root_struct_def_);
if (!python::SaveType(parser, **it, declcode, path, true))
return false;
}
return true;
bool GeneratePython(const Parser &parser, const std::string &path,
const std::string &file_name) {
python::PythonGenerator generator(parser, path, file_name);
return generator.generate();
}
} // namespace flatbuffers

View File

@@ -23,21 +23,21 @@
namespace flatbuffers {
static void GenStruct(const StructDef &struct_def, const Table *table,
int indent, const GeneratorOptions &opts,
int indent, const IDLOptions &opts,
std::string *_text);
// If indentation is less than 0, that indicates we don't want any newlines
// either.
const char *NewLine(const GeneratorOptions &opts) {
const char *NewLine(const IDLOptions &opts) {
return opts.indent_step >= 0 ? "\n" : "";
}
int Indent(const GeneratorOptions &opts) {
int Indent(const IDLOptions &opts) {
return std::max(opts.indent_step, 0);
}
// Output an identifier with or without quotes depending on strictness.
void OutputIdentifier(const std::string &name, const GeneratorOptions &opts,
void OutputIdentifier(const std::string &name, const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
if (opts.strict_json) text += "\"";
@@ -50,7 +50,7 @@ void OutputIdentifier(const std::string &name, const GeneratorOptions &opts,
// The general case for scalars:
template<typename T> void Print(T val, Type type, int /*indent*/,
StructDef * /*union_sd*/,
const GeneratorOptions &opts,
const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
if (type.enum_def && opts.output_enum_identifiers) {
@@ -70,7 +70,7 @@ template<typename T> void Print(T val, Type type, int /*indent*/,
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
template<typename T> void PrintVector(const Vector<T> &v, Type type,
int indent, const GeneratorOptions &opts,
int indent, const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
text += "[";
@@ -136,7 +136,7 @@ static void EscapeString(const String &s, std::string *_text) {
template<> void Print<const void *>(const void *val,
Type type, int indent,
StructDef *union_sd,
const GeneratorOptions &opts,
const IDLOptions &opts,
std::string *_text) {
switch (type.base_type) {
case BASE_TYPE_UNION:
@@ -181,7 +181,7 @@ template<> void Print<const void *>(const void *val,
// Generate text for a scalar field.
template<typename T> static void GenField(const FieldDef &fd,
const Table *table, bool fixed,
const GeneratorOptions &opts,
const IDLOptions &opts,
int indent,
std::string *_text) {
Print(fixed ?
@@ -193,7 +193,7 @@ template<typename T> static void GenField(const FieldDef &fd,
// Generate text for non-scalar field.
static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, StructDef *union_sd,
const GeneratorOptions &opts, std::string *_text) {
const IDLOptions &opts, std::string *_text) {
const void *val = nullptr;
if (fixed) {
// The only non-scalar fields in structs are structs.
@@ -211,7 +211,7 @@ static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
// Generate text for a struct or table, values separated by commas, indented,
// and bracketed by "{}"
static void GenStruct(const StructDef &struct_def, const Table *table,
int indent, const GeneratorOptions &opts,
int indent, const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
text += "{";
@@ -273,16 +273,16 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
// Generate a text representation of a flatbuffer in JSON format.
void GenerateText(const Parser &parser, const void *flatbuffer,
const GeneratorOptions &opts, std::string *_text) {
std::string *_text) {
std::string &text = *_text;
assert(parser.root_struct_def_); // call SetRootType()
text.reserve(1024); // Reduce amount of inevitable reallocs.
GenStruct(*parser.root_struct_def_,
GetRoot<Table>(flatbuffer),
0,
opts,
parser.opts,
_text);
text += NewLine(opts);
text += NewLine(parser.opts);
}
std::string TextFileName(const std::string &path,
@@ -292,12 +292,10 @@ std::string TextFileName(const std::string &path,
bool GenerateTextFile(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts) {
const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
std::string text;
GenerateText(parser, parser.builder_.GetBufferPointer(), opts,
&text);
GenerateText(parser, parser.builder_.GetBufferPointer(), &text);
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(),
text,
false);
@@ -305,8 +303,7 @@ bool GenerateTextFile(const Parser &parser,
std::string TextMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions & /*opts*/) {
const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return "";
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(file_name));

File diff suppressed because it is too large Load Diff

View File

@@ -287,14 +287,17 @@ void SetString(const reflection::Schema &schema, const std::string &val,
const String *str, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table) {
auto delta = static_cast<int>(val.size()) - static_cast<int>(str->Length());
auto start = static_cast<uoffset_t>(reinterpret_cast<const uint8_t *>(str) -
flatbuf->data() +
sizeof(uoffset_t));
auto str_start = static_cast<uoffset_t>(
reinterpret_cast<const uint8_t *>(str) - flatbuf->data());
auto start = str_start + static_cast<uoffset_t>(sizeof(uoffset_t));
if (delta) {
// Clear the old string, since we don't want parts of it remaining.
memset(flatbuf->data() + start, 0, str->Length());
// Different size, we must expand (or contract).
ResizeContext(schema, start, delta, flatbuf, root_table);
// Set the new length.
WriteScalar(flatbuf->data() + str_start,
static_cast<uoffset_t>(val.size()));
}
// Copy new data. Safe because we created the right amount of space.
memcpy(flatbuf->data() + start, val.c_str(), val.size() + 1);
@@ -351,7 +354,8 @@ void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
const Table &table) {
const Table &table,
bool use_string_pooling) {
// Before we can construct the table, we have to first generate any
// subobjects, and collect their offsets.
std::vector<uoffset_t> offsets;
@@ -363,7 +367,9 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
uoffset_t offset = 0;
switch (fielddef.type()->base_type()) {
case reflection::String: {
offset = fbb.CreateString(GetFieldS(table, fielddef)).o;
offset = use_string_pooling
? fbb.CreateSharedString(GetFieldS(table, fielddef)).o
: fbb.CreateString(GetFieldS(table, fielddef)).o;
break;
}
case reflection::Obj: {
@@ -392,7 +398,9 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
std::vector<Offset<const String *>> elements(vec->size());
auto vec_s = reinterpret_cast<const Vector<Offset<String>> *>(vec);
for (uoffset_t i = 0; i < vec_s->size(); i++) {
elements[i] = fbb.CreateString(vec_s->Get(i)).o;
elements[i] = use_string_pooling
? fbb.CreateSharedString(vec_s->Get(i)).o
: fbb.CreateString(vec_s->Get(i)).o;
}
offset = fbb.CreateVector(elements).o;
break;

86
src/util.cpp Normal file
View File

@@ -0,0 +1,86 @@
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "flatbuffers/util.h"
namespace flatbuffers {
bool FileExistsRaw(const char *name) {
std::ifstream ifs(name);
return ifs.good();
}
bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
if (DirExists(name)) return false;
std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
if (!ifs.is_open()) return false;
if (binary) {
// The fastest way to read a file into a string.
ifs.seekg(0, std::ios::end);
auto size = ifs.tellg();
(*buf).resize(static_cast<size_t>(size));
ifs.seekg(0, std::ios::beg);
ifs.read(&(*buf)[0], (*buf).size());
} else {
// This is slower, but works correctly on all platforms for text files.
std::ostringstream oss;
oss << ifs.rdbuf();
*buf = oss.str();
}
return !ifs.bad();
}
static LoadFileFunction g_load_file_function = LoadFileRaw;
static FileExistsFunction g_file_exists_function = FileExistsRaw;
bool LoadFile(const char *name, bool binary, std::string *buf) {
assert(g_load_file_function);
return g_load_file_function(name, binary, buf);
}
bool FileExists(const char *name) {
assert(g_file_exists_function);
return g_file_exists_function(name);
}
bool DirExists(const char *name) {
#ifdef _WIN32
#define flatbuffers_stat _stat
#define FLATBUFFERS_S_IFDIR _S_IFDIR
#else
#define flatbuffers_stat stat
#define FLATBUFFERS_S_IFDIR S_IFDIR
#endif
struct flatbuffers_stat file_info;
if (flatbuffers_stat(name, &file_info) != 0) return false;
return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0;
}
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) {
LoadFileFunction previous_function = g_load_file_function;
g_load_file_function = load_file_function ? load_file_function : LoadFileRaw;
return previous_function;
}
FileExistsFunction SetFileExistsFunction(
FileExistsFunction file_exists_function) {
FileExistsFunction previous_function = g_file_exists_function;
g_file_exists_function = file_exists_function ?
file_exists_function : FileExistsRaw;
return previous_function;
}
} // namespace flatbuffers