mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-22 14:48:53 +00:00
Audit and fixups for GCC and Clang (#7212)
Added (for compiler versions that support it): -Wmissing-declarations -Wzero-as-null-pointer-constant Then, fixes to problems identified by the extra warnings Tested only on GCC 9.4.0 Adjusted the CPP code generator to output nullptr where appropriate, to satisfy -Wzero-as-null-pointer-constant Added a lot of 'static' declarations in front of functions, to satisfy -Wmissing-declarations, and wrap static function defs in anonymous namespaces. There are advantages to both anonymous namespaces and static, it seems that marking a function as static will not publish the name in the symbol table at all, thus giving the linker less work to do.
This commit is contained in:
@@ -24,19 +24,21 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
void ForAllEnums(
|
||||
namespace {
|
||||
|
||||
static void ForAllEnums(
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums,
|
||||
std::function<void(const reflection::Enum *)> func) {
|
||||
for (auto it = enums->cbegin(); it != enums->cend(); ++it) { func(*it); }
|
||||
}
|
||||
|
||||
void ForAllObjects(
|
||||
static void ForAllObjects(
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects,
|
||||
std::function<void(const reflection::Object *)> func) {
|
||||
for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
|
||||
}
|
||||
|
||||
void ForAllEnumValues(const reflection::Enum *enum_def,
|
||||
static void ForAllEnumValues(const reflection::Enum *enum_def,
|
||||
std::function<void(const reflection::EnumVal *)> func) {
|
||||
for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
|
||||
++it) {
|
||||
@@ -44,7 +46,7 @@ void ForAllEnumValues(const reflection::Enum *enum_def,
|
||||
}
|
||||
}
|
||||
|
||||
void ForAllDocumentation(
|
||||
static void ForAllDocumentation(
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
|
||||
*documentation,
|
||||
std::function<void(const flatbuffers::String *)> func) {
|
||||
@@ -89,6 +91,8 @@ static bool IsVector(const reflection::BaseType base_type) {
|
||||
return base_type == reflection::Vector;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// A concrete base Flatbuffer Generator that specific language generators can
|
||||
// derive from.
|
||||
class BaseBfbsGenerator : public BfbsGenerator {
|
||||
@@ -187,4 +191,4 @@ class BaseBfbsGenerator : public BfbsGenerator {
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BFBS_GEN_H_
|
||||
#endif // FLATBUFFERS_BFBS_GEN_H_
|
||||
|
||||
@@ -299,7 +299,10 @@ std::string SimpleFloatConstantGenerator::NaN(float v) const {
|
||||
return this->NaN(static_cast<double>(v));
|
||||
}
|
||||
|
||||
std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name) {
|
||||
const std::string file_extension = java ? ".java" : ".cs";
|
||||
@@ -331,6 +334,9 @@ std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
|
||||
return make_rule;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
std::string JavaMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name) {
|
||||
return JavaCSharpMakeRule(true, parser, path, file_name);
|
||||
@@ -340,12 +346,16 @@ std::string CSharpMakeRule(const Parser &parser, const std::string &path,
|
||||
return JavaCSharpMakeRule(false, parser, path, file_name);
|
||||
}
|
||||
|
||||
std::string BinaryFileName(const Parser &parser, const std::string &path,
|
||||
namespace {
|
||||
|
||||
static std::string BinaryFileName(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name) {
|
||||
auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
|
||||
return path + file_name + "." + ext;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool GenerateBinary(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name) {
|
||||
if (parser.opts.use_flexbuffers) {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
|
||||
static const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
|
||||
|
||||
void FlatCompiler::ParseFile(
|
||||
flatbuffers::Parser &parser, const std::string &filename,
|
||||
|
||||
@@ -27,7 +27,9 @@ namespace flatbuffers {
|
||||
|
||||
namespace dart {
|
||||
|
||||
Namer::Config DartDefaultConfig() {
|
||||
namespace {
|
||||
|
||||
static Namer::Config DartDefaultConfig() {
|
||||
return { /*types=*/Case::kUpperCamel,
|
||||
/*constants=*/Case::kScreamingSnake,
|
||||
/*methods=*/Case::kLowerCamel,
|
||||
@@ -50,7 +52,7 @@ Namer::Config DartDefaultConfig() {
|
||||
/*filename_extension=*/".dart" };
|
||||
}
|
||||
|
||||
std::set<std::string> DartKeywords() {
|
||||
static std::set<std::string> DartKeywords() {
|
||||
// see https://www.dartlang.org/guides/language/language-tour#keywords
|
||||
// yield*, async*, and sync* shouldn't be proble
|
||||
return {
|
||||
@@ -67,6 +69,7 @@ std::set<std::string> DartKeywords() {
|
||||
"dynamic", "implements", "set",
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const std::string _kFb = "fb";
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@ namespace flatbuffers {
|
||||
|
||||
namespace go {
|
||||
|
||||
namespace {
|
||||
|
||||
// see https://golang.org/ref/spec#Keywords
|
||||
std::set<std::string> GoKeywords() {
|
||||
static std::set<std::string> GoKeywords() {
|
||||
return {
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
@@ -49,7 +51,7 @@ std::set<std::string> GoKeywords() {
|
||||
};
|
||||
}
|
||||
|
||||
Namer::Config GoDefaultConfig() {
|
||||
static Namer::Config GoDefaultConfig() {
|
||||
// Note that the functions with user defined types in the name use
|
||||
// upper camel case for all but the user defined type itself, which is keep
|
||||
// cased. Despite being a function, we interpret it as a Type.
|
||||
@@ -75,6 +77,8 @@ Namer::Config GoDefaultConfig() {
|
||||
/*filename_extension=*/".go" };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class GoGenerator : public BaseGenerator {
|
||||
public:
|
||||
GoGenerator(const Parser &parser, const std::string &path,
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
namespace flatbuffers {
|
||||
namespace java {
|
||||
|
||||
Namer::Config JavaDefaultConfig() {
|
||||
namespace {
|
||||
|
||||
static Namer::Config JavaDefaultConfig() {
|
||||
return {
|
||||
/*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kScreamingSnake,
|
||||
@@ -50,7 +52,7 @@ Namer::Config JavaDefaultConfig() {
|
||||
};
|
||||
}
|
||||
|
||||
std::set<std::string> JavaKeywords() {
|
||||
static std::set<std::string> JavaKeywords() {
|
||||
return {
|
||||
"abstract", "continue", "for", "new", "switch",
|
||||
"assert", "default", "goto", "package", "synchronized",
|
||||
@@ -65,16 +67,18 @@ std::set<std::string> JavaKeywords() {
|
||||
};
|
||||
}
|
||||
|
||||
static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
|
||||
static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
|
||||
"POSITIVE_INFINITY",
|
||||
"NEGATIVE_INFINITY");
|
||||
|
||||
static CommentConfig comment_config = {
|
||||
static const CommentConfig comment_config = {
|
||||
"/**",
|
||||
" *",
|
||||
" */",
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class JavaGenerator : public BaseGenerator {
|
||||
struct FieldArrayLength {
|
||||
std::string name;
|
||||
|
||||
@@ -24,7 +24,10 @@ namespace flatbuffers {
|
||||
|
||||
namespace jsons {
|
||||
|
||||
template<class T> std::string GenFullName(const T *enum_def) {
|
||||
namespace {
|
||||
|
||||
template<class T>
|
||||
static std::string GenFullName(const T *enum_def) {
|
||||
std::string full_name;
|
||||
const auto &name_spaces = enum_def->defined_namespace->components;
|
||||
for (auto ns = name_spaces.cbegin(); ns != name_spaces.cend(); ++ns) {
|
||||
@@ -34,15 +37,16 @@ template<class T> std::string GenFullName(const T *enum_def) {
|
||||
return full_name;
|
||||
}
|
||||
|
||||
template<class T> std::string GenTypeRef(const T *enum_def) {
|
||||
template<class T>
|
||||
static std::string GenTypeRef(const T *enum_def) {
|
||||
return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
|
||||
}
|
||||
|
||||
std::string GenType(const std::string &name) {
|
||||
static std::string GenType(const std::string &name) {
|
||||
return "\"type\" : \"" + name + "\"";
|
||||
}
|
||||
|
||||
std::string GenType(BaseType type) {
|
||||
static std::string GenType(BaseType type) {
|
||||
switch (type) {
|
||||
case BASE_TYPE_BOOL: return "\"type\" : \"boolean\"";
|
||||
case BASE_TYPE_CHAR:
|
||||
@@ -84,13 +88,13 @@ std::string GenType(BaseType type) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenBaseType(const Type &type) {
|
||||
static std::string GenBaseType(const Type &type) {
|
||||
if (type.struct_def != nullptr) { return GenTypeRef(type.struct_def); }
|
||||
if (type.enum_def != nullptr) { return GenTypeRef(type.enum_def); }
|
||||
return GenType(type.base_type);
|
||||
}
|
||||
|
||||
std::string GenArrayType(const Type &type) {
|
||||
static std::string GenArrayType(const Type &type) {
|
||||
std::string element_type;
|
||||
if (type.struct_def != nullptr) {
|
||||
element_type = GenTypeRef(type.struct_def);
|
||||
@@ -103,7 +107,7 @@ std::string GenArrayType(const Type &type) {
|
||||
return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
|
||||
}
|
||||
|
||||
std::string GenType(const Type &type) {
|
||||
static std::string GenType(const Type &type) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BASE_TYPE_VECTOR: {
|
||||
@@ -136,6 +140,8 @@ std::string GenType(const Type &type) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class JsonSchemaGenerator : public BaseGenerator {
|
||||
private:
|
||||
std::string code_;
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace flatbuffers {
|
||||
|
||||
namespace kotlin {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::map<std::string, std::pair<std::string, std::string> > FbbParamMap;
|
||||
static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
|
||||
"POSITIVE_INFINITY",
|
||||
@@ -36,7 +38,7 @@ static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
|
||||
|
||||
static const CommentConfig comment_config = { "/**", " *", " */" };
|
||||
static const std::string ident_pad = " ";
|
||||
std::set<std::string> KotlinKeywords() {
|
||||
static std::set<std::string> KotlinKeywords() {
|
||||
return { "package", "as", "typealias", "class", "this", "super",
|
||||
"val", "var", "fun", "for", "null", "true",
|
||||
"false", "is", "in", "throw", "return", "break",
|
||||
@@ -44,7 +46,7 @@ std::set<std::string> KotlinKeywords() {
|
||||
"do", "when", "interface", "typeof", "Any", "Character" };
|
||||
}
|
||||
|
||||
Namer::Config KotlinDefaultConfig() {
|
||||
static Namer::Config KotlinDefaultConfig() {
|
||||
return { /*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kKeep,
|
||||
/*methods=*/Case::kLowerCamel,
|
||||
@@ -66,6 +68,7 @@ Namer::Config KotlinDefaultConfig() {
|
||||
/*filename_suffix=*/"",
|
||||
/*filename_extension=*/".kt" };
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class KotlinGenerator : public BaseGenerator {
|
||||
public:
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
namespace flatbuffers {
|
||||
namespace python {
|
||||
|
||||
std::set<std::string> PythonKeywords() {
|
||||
namespace {
|
||||
|
||||
static std::set<std::string> PythonKeywords() {
|
||||
return { "False", "None", "True", "and", "as", "assert",
|
||||
"break", "class", "continue", "def", "del", "elif",
|
||||
"else", "except", "finally", "for", "from", "global",
|
||||
@@ -40,7 +42,7 @@ std::set<std::string> PythonKeywords() {
|
||||
"while", "with", "yield" };
|
||||
}
|
||||
|
||||
Namer::Config PythonDefaultConfig() {
|
||||
static Namer::Config PythonDefaultConfig() {
|
||||
return { /*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kScreamingSnake,
|
||||
/*methods=*/Case::kUpperCamel,
|
||||
@@ -64,8 +66,10 @@ Namer::Config PythonDefaultConfig() {
|
||||
}
|
||||
|
||||
// Hardcode spaces per indentation.
|
||||
const CommentConfig def_comment = { nullptr, "#", nullptr };
|
||||
const std::string Indent = " ";
|
||||
static const CommentConfig def_comment = { nullptr, "#", nullptr };
|
||||
static const std::string Indent = " ";
|
||||
|
||||
} // namespace
|
||||
|
||||
class PythonGenerator : public BaseGenerator {
|
||||
public:
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
#include "idl_namer.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace {
|
||||
|
||||
Namer::Config RustDefaultConfig() {
|
||||
static Namer::Config RustDefaultConfig() {
|
||||
// Historical note: We've been using "keep" casing since the original
|
||||
// implementation, presumably because Flatbuffers schema style and Rust style
|
||||
// roughly align. We are not going to enforce proper casing since its an
|
||||
@@ -51,7 +52,7 @@ Namer::Config RustDefaultConfig() {
|
||||
/*filename_extension=*/".rs" };
|
||||
}
|
||||
|
||||
std::set<std::string> RustKeywords() {
|
||||
static std::set<std::string> RustKeywords() {
|
||||
return {
|
||||
// https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
|
||||
"as",
|
||||
@@ -173,7 +174,7 @@ enum FullType {
|
||||
};
|
||||
|
||||
// Convert a Type to a FullType (exhaustive).
|
||||
FullType GetFullType(const Type &type) {
|
||||
static FullType GetFullType(const Type &type) {
|
||||
// N.B. The order of these conditionals matters for some types.
|
||||
|
||||
if (IsString(type)) {
|
||||
@@ -263,15 +264,16 @@ FullType GetFullType(const Type &type) {
|
||||
return ftBool;
|
||||
}
|
||||
|
||||
bool IsBitFlagsEnum(const EnumDef &enum_def) {
|
||||
static bool IsBitFlagsEnum(const EnumDef &enum_def) {
|
||||
return enum_def.attributes.Lookup("bit_flags") != nullptr;
|
||||
}
|
||||
|
||||
// TableArgs make required non-scalars "Option<_>".
|
||||
// TODO(cneo): Rework how we do defaults and stuff.
|
||||
bool IsOptionalToBuilder(const FieldDef &field) {
|
||||
static bool IsOptionalToBuilder(const FieldDef &field) {
|
||||
return field.IsOptional() || !IsScalar(field.value.type.base_type);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool GenerateRustModuleRootFile(const Parser &parser,
|
||||
const std::string &output_dir) {
|
||||
|
||||
@@ -27,7 +27,9 @@ namespace flatbuffers {
|
||||
|
||||
namespace swift {
|
||||
|
||||
Namer::Config SwiftDefaultConfig() {
|
||||
namespace {
|
||||
|
||||
static Namer::Config SwiftDefaultConfig() {
|
||||
return { /*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kLowerCamel,
|
||||
/*methods=*/Case::kLowerCamel,
|
||||
@@ -50,7 +52,7 @@ Namer::Config SwiftDefaultConfig() {
|
||||
/*filename_extension=*/".swift" };
|
||||
}
|
||||
|
||||
std::set<std::string> SwiftKeywords() {
|
||||
static std::set<std::string> SwiftKeywords() {
|
||||
return {
|
||||
"associatedtype",
|
||||
"class",
|
||||
@@ -134,16 +136,18 @@ std::set<std::string> SwiftKeywords() {
|
||||
};
|
||||
}
|
||||
|
||||
inline std::string GenIndirect(const std::string &reading) {
|
||||
static std::string GenIndirect(const std::string &reading) {
|
||||
return "{{ACCESS}}.indirect(" + reading + ")";
|
||||
}
|
||||
|
||||
inline std::string GenArrayMainBody(const std::string &optional) {
|
||||
static std::string GenArrayMainBody(const std::string &optional) {
|
||||
return "{{ACCESS_TYPE}} func {{FIELDMETHOD}}(at index: Int32) -> "
|
||||
"{{VALUETYPE}}" +
|
||||
optional + " { ";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class SwiftGenerator : public BaseGenerator {
|
||||
private:
|
||||
CodeWriter code_;
|
||||
|
||||
@@ -36,7 +36,11 @@ const char *FLATBUFFERS_VERSION() {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
const double kPi = 3.14159265358979323846;
|
||||
namespace {
|
||||
|
||||
static const double kPi = 3.14159265358979323846;
|
||||
|
||||
} // namespace
|
||||
|
||||
// clang-format off
|
||||
const char *const kTypeNames[] = {
|
||||
@@ -55,6 +59,9 @@ const char kTypeSizes[] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// The enums in the reflection schema should match the ones we use internally.
|
||||
// Compare the last element to check if these go out of sync.
|
||||
static_assert(BASE_TYPE_UNION == static_cast<BaseType>(reflection::Union),
|
||||
@@ -93,13 +100,15 @@ static bool IsLowerSnakeCase(const std::string &str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeserializeDoc(std::vector<std::string> &doc,
|
||||
static void DeserializeDoc(std::vector<std::string> &doc,
|
||||
const Vector<Offset<String>> *documentation) {
|
||||
if (documentation == nullptr) return;
|
||||
for (uoffset_t index = 0; index < documentation->size(); index++)
|
||||
doc.push_back(documentation->Get(index)->str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Parser::Message(const std::string &msg) {
|
||||
if (!error_.empty()) error_ += "\n"; // log all warnings and errors
|
||||
error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
|
||||
@@ -128,7 +137,11 @@ CheckedError Parser::Error(const std::string &msg) {
|
||||
return CheckedError(true);
|
||||
}
|
||||
|
||||
inline CheckedError NoError() { return CheckedError(false); }
|
||||
namespace {
|
||||
|
||||
static CheckedError NoError() { return CheckedError(false); }
|
||||
|
||||
} // namespace
|
||||
|
||||
CheckedError Parser::RecurseError() {
|
||||
return Error("maximum parsing depth " + NumToString(parse_depth_counter_) +
|
||||
@@ -164,26 +177,38 @@ class Parser::ParseDepthGuard {
|
||||
const int caller_depth_;
|
||||
};
|
||||
|
||||
template<typename T> std::string TypeToIntervalString() {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
static std::string TypeToIntervalString() {
|
||||
return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
|
||||
NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// atot: template version of atoi/atof: convert a string to an instance of T.
|
||||
template<typename T>
|
||||
bool atot_scalar(const char *s, T *val, bool_constant<false>) {
|
||||
static bool atot_scalar(const char *s, T *val, bool_constant<false>) {
|
||||
return StringToNumber(s, val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool atot_scalar(const char *s, T *val, bool_constant<true>) {
|
||||
static bool atot_scalar(const char *s, T *val, bool_constant<true>) {
|
||||
// Normalize NaN parsed from fbs or json to unsigned NaN.
|
||||
if (false == StringToNumber(s, val)) return false;
|
||||
*val = (*val != *val) ? std::fabs(*val) : *val;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T> CheckedError atot(const char *s, Parser &parser, T *val) {
|
||||
template<typename T>
|
||||
static CheckedError atot(const char *s, Parser &parser, T *val) {
|
||||
auto done = atot_scalar(s, val, bool_constant<is_floating_point<T>::value>());
|
||||
if (done) return NoError();
|
||||
if (0 == *val)
|
||||
@@ -193,13 +218,15 @@ template<typename T> CheckedError atot(const char *s, Parser &parser, T *val) {
|
||||
", constant does not fit " + TypeToIntervalString<T>());
|
||||
}
|
||||
template<>
|
||||
inline CheckedError atot<Offset<void>>(const char *s, Parser &parser,
|
||||
CheckedError atot<Offset<void>>(const char *s, Parser &parser,
|
||||
Offset<void> *val) {
|
||||
(void)parser;
|
||||
*val = Offset<void>(atoi(s));
|
||||
return NoError();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
||||
size_t max_components) const {
|
||||
// Early exit if we don't have a defined namespace.
|
||||
@@ -217,8 +244,12 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
||||
return stream_str;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
template<typename T>
|
||||
T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
|
||||
static T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
|
||||
const Namespace ¤t_namespace, size_t skip_top) {
|
||||
const auto &components = current_namespace.components;
|
||||
if (table.dict.empty()) return nullptr;
|
||||
@@ -278,6 +309,9 @@ static std::string TokenToString(int t) {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
std::string Parser::TokenToStringId(int t) const {
|
||||
return t == kTokenIdentifier ? attribute_ : TokenToString(t);
|
||||
}
|
||||
@@ -307,10 +341,14 @@ CheckedError Parser::SkipByteOrderMark() {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
static inline bool IsIdentifierStart(char c) {
|
||||
namespace {
|
||||
|
||||
static bool IsIdentifierStart(char c) {
|
||||
return is_alpha(c) || (c == '_');
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CheckedError Parser::Next() {
|
||||
doc_comment_.clear();
|
||||
bool seen_newline = cursor_ == source_;
|
||||
@@ -1410,6 +1448,9 @@ CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
|
||||
const FieldDef &key) {
|
||||
switch (key.value.type.base_type) {
|
||||
@@ -1477,7 +1518,7 @@ static void SwapSerializedTables(Offset<Table> *a, Offset<Table> *b) {
|
||||
|
||||
// See below for why we need our own sort :(
|
||||
template<typename T, typename F, typename S>
|
||||
void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
|
||||
static void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
|
||||
if (end - begin <= static_cast<ptrdiff_t>(width)) return;
|
||||
auto l = begin + width;
|
||||
auto r = end;
|
||||
@@ -1495,6 +1536,11 @@ void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
|
||||
SimpleQsort(r, end, width, comparator, swapper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
|
||||
size_t min_align, size_t *align) {
|
||||
// Use uint8_t to avoid problems with size_t==`unsigned long` on LP64.
|
||||
@@ -1821,22 +1867,28 @@ CheckedError Parser::TokenError() {
|
||||
return Error("cannot parse value starting with: " + TokenToStringId(token_));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Re-pack helper (ParseSingleValue) to normalize defaults of scalars.
|
||||
template<typename T> inline void SingleValueRepack(Value &e, T val) {
|
||||
template<typename T>
|
||||
static inline void SingleValueRepack(Value &e, T val) {
|
||||
// Remove leading zeros.
|
||||
if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
|
||||
}
|
||||
|
||||
#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
|
||||
// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
|
||||
// hex-float literal.
|
||||
static inline void SingleValueRepack(Value &e, float val) {
|
||||
static void SingleValueRepack(Value &e, float val) {
|
||||
if (val != val) e.constant = "nan";
|
||||
}
|
||||
static inline void SingleValueRepack(Value &e, double val) {
|
||||
static void SingleValueRepack(Value &e, double val) {
|
||||
if (val != val) e.constant = "nan";
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
|
||||
ParseDepthGuard depth_guard(this);
|
||||
ECHECK(depth_guard.Check());
|
||||
@@ -2108,6 +2160,8 @@ const EnumVal *EnumDef::MaxValue() const {
|
||||
return vals.vec.empty() ? nullptr : vals.vec.back();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
|
||||
if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
|
||||
// Signed overflow may occur, use unsigned calculation.
|
||||
@@ -2115,6 +2169,8 @@ template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
|
||||
return static_cast<uint64_t>(e1) - static_cast<uint64_t>(e2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
uint64_t EnumDef::Distance(const EnumVal *v1, const EnumVal *v2) const {
|
||||
return IsUInt64() ? EnumDistanceImpl(v1->GetAsUInt64(), v2->GetAsUInt64())
|
||||
: EnumDistanceImpl(v1->GetAsInt64(), v2->GetAsInt64());
|
||||
@@ -2535,12 +2591,16 @@ std::string Parser::UnqualifiedName(const std::string &full_qualified_name) {
|
||||
return full_qualified_name.substr(previous, current - previous);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
|
||||
auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
|
||||
auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
|
||||
return a_id < b_id;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CheckedError Parser::ParseDecl(const char *filename) {
|
||||
std::vector<std::string> dc = doc_comment_;
|
||||
bool fixed = IsIdent("struct");
|
||||
@@ -3349,6 +3409,9 @@ CheckedError Parser::CheckPrivatelyLeakedFields(const Definition &def,
|
||||
return NoError();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Generate a unique hash for a file based on its name and contents (if any).
|
||||
static uint64_t HashFile(const char *source_filename, const char *source) {
|
||||
uint64_t hash = 0;
|
||||
@@ -3361,6 +3424,9 @@ static uint64_t HashFile(const char *source_filename, const char *source) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
const char *source_filename,
|
||||
const char *include_filename) {
|
||||
@@ -3574,18 +3640,24 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
|
||||
|
||||
// Schema serialization functionality:
|
||||
|
||||
template<typename T> bool compareName(const T *a, const T *b) {
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
static bool compareName(const T *a, const T *b) {
|
||||
return a->defined_namespace->GetFullyQualifiedName(a->name) <
|
||||
b->defined_namespace->GetFullyQualifiedName(b->name);
|
||||
}
|
||||
|
||||
template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
|
||||
template<typename T>
|
||||
static void AssignIndices(const std::vector<T *> &defvec) {
|
||||
// Pre-sort these vectors, such that we can set the correct indices for them.
|
||||
auto vec = defvec;
|
||||
std::sort(vec.begin(), vec.end(), compareName<T>);
|
||||
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Parser::Serialize() {
|
||||
builder_.Clear();
|
||||
AssignIndices(structs_.vec);
|
||||
@@ -3655,6 +3727,8 @@ void Parser::Serialize() {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static Namespace *GetNamespace(
|
||||
const std::string &qualified_name, std::vector<Namespace *> &namespaces,
|
||||
std::map<std::string, Namespace *> &namespaces_index) {
|
||||
@@ -3681,6 +3755,9 @@ static Namespace *GetNamespace(
|
||||
return ns;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const {
|
||||
std::vector<Offset<reflection::Field>> field_offsets;
|
||||
|
||||
@@ -384,13 +384,19 @@ const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
|
||||
return flatbuf.data() + insertion_point + root_offset;
|
||||
}
|
||||
|
||||
void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
|
||||
namespace {
|
||||
|
||||
static void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
|
||||
const Table &table, size_t align, size_t size) {
|
||||
fbb.Align(align);
|
||||
fbb.PushBytes(table.GetStruct<const uint8_t *>(fielddef.offset()), size);
|
||||
fbb.TrackField(fielddef.offset(), fbb.GetSize());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
||||
const reflection::Schema &schema,
|
||||
const reflection::Object &objectdef,
|
||||
@@ -515,7 +521,9 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
||||
}
|
||||
}
|
||||
|
||||
bool VerifyStruct(flatbuffers::Verifier &v,
|
||||
namespace {
|
||||
|
||||
static bool VerifyStruct(flatbuffers::Verifier &v,
|
||||
const flatbuffers::Table &parent_table,
|
||||
voffset_t field_offset, const reflection::Object &obj,
|
||||
bool required) {
|
||||
@@ -527,7 +535,7 @@ bool VerifyStruct(flatbuffers::Verifier &v,
|
||||
offset, obj.bytesize(), obj.minalign());
|
||||
}
|
||||
|
||||
bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
|
||||
static bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
|
||||
const flatbuffers::Table &parent_table,
|
||||
voffset_t field_offset,
|
||||
const reflection::Object &obj, bool required) {
|
||||
@@ -538,11 +546,11 @@ bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
|
||||
}
|
||||
|
||||
// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
|
||||
bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
const reflection::Object &obj,
|
||||
const flatbuffers::Table *table, bool required);
|
||||
|
||||
bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
static bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
uint8_t utype, const uint8_t *elem,
|
||||
const reflection::Field &union_field) {
|
||||
if (!utype) return true; // Not present.
|
||||
@@ -567,7 +575,7 @@ bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
}
|
||||
}
|
||||
|
||||
bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
static bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
const flatbuffers::Table &table,
|
||||
const reflection::Field &vec_field) {
|
||||
FLATBUFFERS_ASSERT(vec_field.type()->base_type() == reflection::Vector);
|
||||
@@ -645,7 +653,7 @@ bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
}
|
||||
}
|
||||
|
||||
bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
const reflection::Object &obj,
|
||||
const flatbuffers::Table *table, bool required) {
|
||||
if (!table) return !required;
|
||||
@@ -735,6 +743,9 @@ bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
|
||||
const uint8_t *const buf, const size_t length,
|
||||
const uoffset_t max_depth, const uoffset_t max_tables) {
|
||||
|
||||
25
src/util.cpp
25
src/util.cpp
@@ -56,12 +56,14 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
bool FileExistsRaw(const char *name) {
|
||||
namespace {
|
||||
|
||||
static bool FileExistsRaw(const char *name) {
|
||||
std::ifstream ifs(name);
|
||||
return ifs.good();
|
||||
}
|
||||
|
||||
bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
|
||||
static 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;
|
||||
@@ -81,8 +83,10 @@ bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
|
||||
return !ifs.bad();
|
||||
}
|
||||
|
||||
static LoadFileFunction g_load_file_function = LoadFileRaw;
|
||||
static FileExistsFunction g_file_exists_function = FileExistsRaw;
|
||||
LoadFileFunction g_load_file_function = LoadFileRaw;
|
||||
FileExistsFunction g_file_exists_function = FileExistsRaw;
|
||||
|
||||
} // namespace
|
||||
|
||||
bool LoadFile(const char *name, bool binary, std::string *buf) {
|
||||
FLATBUFFERS_ASSERT(g_load_file_function);
|
||||
@@ -365,14 +369,14 @@ static std::string ToSnakeCase(const std::string &input, bool screaming) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string ToAll(const std::string &input,
|
||||
std::string ToAll(const std::string &input,
|
||||
std::function<char(const char)> transform) {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < input.length(); i++) { s += transform(input[i]); }
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string CamelToSnake(const std::string &input) {
|
||||
std::string CamelToSnake(const std::string &input) {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
if (i == 0) {
|
||||
@@ -391,7 +395,7 @@ static std::string CamelToSnake(const std::string &input) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string DasherToSnake(const std::string &input) {
|
||||
std::string DasherToSnake(const std::string &input) {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
if (input[i] == '-') {
|
||||
@@ -403,7 +407,7 @@ static std::string DasherToSnake(const std::string &input) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string ToDasher(const std::string &input) {
|
||||
std::string ToDasher(const std::string &input) {
|
||||
std::string s;
|
||||
char p = 0;
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
@@ -424,10 +428,9 @@ static std::string ToDasher(const std::string &input) {
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Converts foo_bar_123baz_456 to foo_bar123_baz456
|
||||
static std::string SnakeToSnake2(const std::string &s) {
|
||||
std::string SnakeToSnake2(const std::string &s) {
|
||||
if (s.length() <= 1) return s;
|
||||
std::string result;
|
||||
result.reserve(s.size());
|
||||
@@ -447,6 +450,8 @@ static std::string SnakeToSnake2(const std::string &s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string ConvertCase(const std::string &input, Case output_case,
|
||||
Case input_case) {
|
||||
if (output_case == Case::kKeep) return input;
|
||||
|
||||
Reference in New Issue
Block a user