mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-03 20:31:23 +00:00
Add CodeWriter utility class.
Helps simplify code generation code. Instead of this:
code += "inline const " + cpp_qualified_name + " *Get";
code += name;
code += "(const void *buf) {\n return flatbuffers::GetRoot<";
code += cpp_qualified_name + ">(buf);\n}\n\n";
You do this:
code.SetValue("NAME", struct_def.name);
code.SetValue("CPP_NAME", cpp_qualified_name);
code += "inline const {{CPP_NAME}} *Get{{NAME}}(const void *buf) {";
code += " return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
code += "}";
code += "";
Updated the CPP code generator to use the CodeWriter class. Most of the
changes in the generated code are white-space changes, esp. around new
lines (since the code generator class automatically appends new lines
when appending a string). Actual code changes include:
* Renamed "rehasher" to "_rehasher" for consistency with other args in
Pack function.
* Renamed "union_obj" to "obj: in UnPack function.
* Always do "(void)_o;" to prevent unused variable warning in Create
function (instead of only doing it if there are no fields) in order
to avoid two-passes.
* Renamed padding variables from __paddingX to paddingX__.
"Each name that contains a double underscore (_ _) [...] is reserved
to the implementation for any use." C++ standards 17.4.3.1.2.
* Add braces around switch cases.
* Calculate index as a separate statement in EnumName function, eg.
const size_t index = ...;
return EnumNamesX()[index];
vs.
return EnumNamesX()[...];
* Stored end table offset in variable in Finish() functions, eg.
const auto end = fbb_.EndTable(start_, ...);
auto o = flatbuffers::Offset<T>(end);
vs.
auto o = flatbuffers::Offset<T>(fbb_.EndTable(start, ...));
* Separate reinterpret_cast calls from function calls in Union
functions, eg.
auto ptr = reinterpret_cast<const T *>(obj);
return ptr->UnPack(resolver);
vs.
return reinterpret_cast<const T *>(obj)->UnPack(resolver);
* Removed unecessary (void)(padding__X) no-ops from constructors, eg.
Test(int16_t a, int8_t b) : ... {
(void)__padding0; // <-- Removed this line.
}
In the idl_gen_cpp.cpp file itself, I refactored some code generation into
new functions: GenParam, GenNativeTable, GenVerifyCall, GenBuilders,
GenUnpackFieldStatement, and GenCreateParam.
Change-Id: I727b1bd8719d05b7ce33cbce00eb58fda817b25d
This commit is contained in:
@@ -17,25 +17,63 @@
|
||||
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
|
||||
#define FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Utility class to assist in generating code through use of text templates.
|
||||
//
|
||||
// Example code:
|
||||
// CodeWriter code;
|
||||
// code.SetValue("NAME", "Foo");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// code.SetValue("NAME", "Bar");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// std::cout << code.ToString() << std::endl;
|
||||
//
|
||||
// Output:
|
||||
// void Foo() { printf("%s", "Foo"); }
|
||||
// void Bar() { printf("%s", "Bar"); }
|
||||
class CodeWriter {
|
||||
public:
|
||||
CodeWriter() {}
|
||||
|
||||
// Clears the current "written" code.
|
||||
void Clear() {
|
||||
stream_.str("");
|
||||
stream_.clear();
|
||||
}
|
||||
|
||||
// Associates a key with a value. All subsequent calls to operator+=, where
|
||||
// the specified key is contained in {{ and }} delimiters will be replaced by
|
||||
// the given value.
|
||||
void SetValue(const std::string& key, const std::string& value) {
|
||||
value_map_[key] = value;
|
||||
}
|
||||
|
||||
// Appends the given text to the generated code as well as a newline
|
||||
// character. Any text within {{ and }} delimeters is replaced by values
|
||||
// previously stored in the CodeWriter by calling SetValue above. The newline
|
||||
// will be suppressed if the text ends with the \\ character.
|
||||
void operator+=(std::string text);
|
||||
|
||||
// Returns the current contents of the CodeWriter as a std::string.
|
||||
std::string ToString() const { return stream_.str(); }
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> value_map_;
|
||||
std::stringstream stream_;
|
||||
};
|
||||
|
||||
class BaseGenerator {
|
||||
public:
|
||||
virtual bool generate() = 0;
|
||||
|
||||
static std::string NamespaceDir(const Parser &parser,
|
||||
const std::string &path,
|
||||
const Namespace &ns) {
|
||||
EnsureDirExists(path.c_str());
|
||||
if (parser.opts.one_file) return path;
|
||||
std::string namespace_dir = path; // Either empty or ends in separator.
|
||||
auto &namespaces = ns.components;
|
||||
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
|
||||
namespace_dir += *it + kPathSeparator;
|
||||
EnsureDirExists(namespace_dir.c_str());
|
||||
}
|
||||
return namespace_dir;
|
||||
}
|
||||
const Namespace &ns);
|
||||
|
||||
protected:
|
||||
BaseGenerator(const Parser &parser, const std::string &path,
|
||||
@@ -53,43 +91,15 @@ class BaseGenerator {
|
||||
BaseGenerator &operator=(const BaseGenerator &);
|
||||
BaseGenerator(const BaseGenerator &);
|
||||
|
||||
std::string NamespaceDir(const Namespace &ns) const {
|
||||
return BaseGenerator::NamespaceDir(parser_, path_, ns);
|
||||
}
|
||||
std::string NamespaceDir(const Namespace &ns) const;
|
||||
|
||||
const char *FlatBuffersGeneratedWarning() {
|
||||
return "automatically generated by the FlatBuffers compiler,"
|
||||
" do not modify\n\n";
|
||||
}
|
||||
static const char *FlatBuffersGeneratedWarning();
|
||||
|
||||
bool IsEverythingGenerated() const {
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
++it) {
|
||||
if (!(*it)->generated) return false;
|
||||
}
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
if (!(*it)->generated) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool IsEverythingGenerated() const;
|
||||
|
||||
static std::string FullNamespace(const char *separator, const Namespace &ns) {
|
||||
std::string namespace_name;
|
||||
auto &namespaces = ns.components;
|
||||
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
|
||||
if (namespace_name.length()) namespace_name += separator;
|
||||
namespace_name += *it;
|
||||
}
|
||||
return namespace_name;
|
||||
}
|
||||
static std::string FullNamespace(const char *separator, const Namespace &ns);
|
||||
|
||||
static std::string LastNamespacePart(const Namespace &ns) {
|
||||
if (!ns.components.empty())
|
||||
return ns.components.back();
|
||||
else
|
||||
return std::string("");
|
||||
}
|
||||
static std::string LastNamespacePart(const Namespace &ns);
|
||||
|
||||
// tracks the current namespace for early exit in WrapInNameSpace
|
||||
// c++, java and csharp returns a different namespace from
|
||||
@@ -100,17 +110,9 @@ class BaseGenerator {
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) const {
|
||||
if (CurrentNameSpace() == ns) return name;
|
||||
std::string qualified_name = qualifying_start_;
|
||||
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
|
||||
qualified_name += *it + qualifying_separator_;
|
||||
return qualified_name + name;
|
||||
}
|
||||
const std::string &name) const;
|
||||
|
||||
std::string WrapInNameSpace(const Definition &def) const {
|
||||
return WrapInNameSpace(def.defined_namespace, def.name);
|
||||
}
|
||||
std::string WrapInNameSpace(const Definition &def) const;
|
||||
|
||||
const Parser &parser_;
|
||||
const std::string &path_;
|
||||
@@ -119,6 +121,17 @@ class BaseGenerator {
|
||||
const std::string qualifying_separator_;
|
||||
};
|
||||
|
||||
struct CommentConfig {
|
||||
const char *first_line;
|
||||
const char *content_line_prefix;
|
||||
const char *last_line;
|
||||
};
|
||||
|
||||
extern void GenComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr,
|
||||
const CommentConfig *config,
|
||||
const char *prefix = "");
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
Reference in New Issue
Block a user