mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-16 01:07:29 +00:00
Add default NaN/Inf to C#, Java, Python (#5107)
* Add default NaN/Inf to C#, Java, Python * Python NaN/Inf test added * Remove MSVC2010/13 dependent code
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
46208b1e91
commit
4fa4d36706
@@ -188,6 +188,94 @@ std::string FloatConstantGenerator::GenFloatConstant(
|
||||
};
|
||||
}
|
||||
|
||||
TypedFloatConstantGenerator::TypedFloatConstantGenerator(
|
||||
const char *double_prefix, const char *single_prefix,
|
||||
const char *nan_number, const char *pos_inf_number,
|
||||
const char *neg_inf_number)
|
||||
: double_prefix_(double_prefix),
|
||||
single_prefix_(single_prefix),
|
||||
nan_number_(nan_number),
|
||||
pos_inf_number_(pos_inf_number),
|
||||
neg_inf_number_(neg_inf_number) {}
|
||||
|
||||
std::string TypedFloatConstantGenerator::MakeNaN(
|
||||
const std::string &prefix) const {
|
||||
return prefix + nan_number_;
|
||||
}
|
||||
std::string TypedFloatConstantGenerator::MakeInf(
|
||||
bool neg, const std::string &prefix) const {
|
||||
if (neg)
|
||||
return !neg_inf_number_.empty() ? (prefix + neg_inf_number_)
|
||||
: ("-" + prefix + pos_inf_number_);
|
||||
else
|
||||
return prefix + pos_inf_number_;
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::Value(double v,
|
||||
const std::string &src) const {
|
||||
(void)v;
|
||||
return src;
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::Inf(double v) const {
|
||||
return MakeInf(v < 0, double_prefix_);
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::NaN(double v) const {
|
||||
(void)v;
|
||||
return MakeNaN(double_prefix_);
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::Value(float v,
|
||||
const std::string &src) const {
|
||||
(void)v;
|
||||
return src + "f";
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::Inf(float v) const {
|
||||
return MakeInf(v < 0, single_prefix_);
|
||||
}
|
||||
|
||||
std::string TypedFloatConstantGenerator::NaN(float v) const {
|
||||
(void)v;
|
||||
return MakeNaN(single_prefix_);
|
||||
}
|
||||
|
||||
SimpleFloatConstantGenerator::SimpleFloatConstantGenerator(
|
||||
const char *nan_number, const char *pos_inf_number,
|
||||
const char *neg_inf_number)
|
||||
: nan_number_(nan_number),
|
||||
pos_inf_number_(pos_inf_number),
|
||||
neg_inf_number_(neg_inf_number) {}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::Value(double v,
|
||||
const std::string &src) const {
|
||||
(void)v;
|
||||
return src;
|
||||
}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::Inf(double v) const {
|
||||
return (v < 0) ? neg_inf_number_ : pos_inf_number_;
|
||||
}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::NaN(double v) const {
|
||||
(void)v;
|
||||
return nan_number_;
|
||||
}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::Value(float v,
|
||||
const std::string &src) const {
|
||||
return this->Value(static_cast<double>(v), src);
|
||||
}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::Inf(float v) const {
|
||||
return this->Inf(static_cast<double>(v));
|
||||
}
|
||||
|
||||
std::string SimpleFloatConstantGenerator::NaN(float v) const {
|
||||
return this->NaN(static_cast<double>(v));
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
@@ -34,50 +34,15 @@ static std::string GeneratedFileName(const std::string &path,
|
||||
}
|
||||
|
||||
namespace cpp {
|
||||
class CppFloatConstantGenerator : public FloatConstantGenerator {
|
||||
protected:
|
||||
std::string Value(double v,
|
||||
const std::string &src) const FLATBUFFERS_OVERRIDE {
|
||||
(void)v;
|
||||
return src;
|
||||
};
|
||||
|
||||
std::string Value(float v,
|
||||
const std::string &src) const FLATBUFFERS_OVERRIDE {
|
||||
(void)v;
|
||||
return src + "f";
|
||||
}
|
||||
|
||||
std::string NaN(double v) const FLATBUFFERS_OVERRIDE {
|
||||
(void)v;
|
||||
return "std::numeric_limits<double>::quiet_NaN()";
|
||||
}
|
||||
std::string NaN(float v) const FLATBUFFERS_OVERRIDE {
|
||||
(void)v;
|
||||
return "std::numeric_limits<float>::quiet_NaN()";
|
||||
}
|
||||
|
||||
std::string Inf(double v) const FLATBUFFERS_OVERRIDE {
|
||||
if(v < 0)
|
||||
return "-std::numeric_limits<double>::infinity()";
|
||||
else
|
||||
return "std::numeric_limits<double>::infinity()";
|
||||
}
|
||||
|
||||
std::string Inf(float v) const FLATBUFFERS_OVERRIDE {
|
||||
if (v < 0)
|
||||
return "-std::numeric_limits<float>::infinity()";
|
||||
else
|
||||
return "std::numeric_limits<float>::infinity()";
|
||||
}
|
||||
};
|
||||
|
||||
class CppGenerator : public BaseGenerator {
|
||||
public:
|
||||
CppGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
: BaseGenerator(parser, path, file_name, "", "::"),
|
||||
cur_name_space_(nullptr) {
|
||||
cur_name_space_(nullptr),
|
||||
float_const_gen_("std::numeric_limits<double>::",
|
||||
"std::numeric_limits<float>::", "quiet_NaN()",
|
||||
"infinity()") {
|
||||
static const char * const keywords[] = {
|
||||
"alignas",
|
||||
"alignof",
|
||||
@@ -2785,7 +2750,7 @@ class CppGenerator : public BaseGenerator {
|
||||
cur_name_space_ = ns;
|
||||
}
|
||||
|
||||
const CppFloatConstantGenerator float_const_gen_;
|
||||
const TypedFloatConstantGenerator float_const_gen_;
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
|
||||
@@ -58,9 +58,16 @@ struct LanguageParameters {
|
||||
std::string class_annotation;
|
||||
std::string generated_type_annotation;
|
||||
CommentConfig comment_config;
|
||||
const FloatConstantGenerator *float_gen;
|
||||
};
|
||||
|
||||
const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
|
||||
static TypedFloatConstantGenerator CSharpFloatGen(
|
||||
"Double.", "Single.", "NaN", "PositiveInfinity", "NegativeInfinity");
|
||||
|
||||
static TypedFloatConstantGenerator JavaFloatGen(
|
||||
"Double.", "Float.", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY");
|
||||
|
||||
static const LanguageParameters language_parameters[] = {
|
||||
{
|
||||
IDLOptions::kJava,
|
||||
@@ -95,6 +102,7 @@ const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
|
||||
" *",
|
||||
" */",
|
||||
},
|
||||
&JavaFloatGen
|
||||
},
|
||||
{
|
||||
IDLOptions::kCSharp,
|
||||
@@ -128,6 +136,7 @@ const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
|
||||
"///",
|
||||
nullptr,
|
||||
},
|
||||
&CSharpFloatGen
|
||||
},
|
||||
};
|
||||
|
||||
@@ -429,7 +438,8 @@ class GeneralGenerator : public BaseGenerator {
|
||||
return SourceCastBasic(type, true);
|
||||
}
|
||||
|
||||
std::string GenEnumDefaultValue(const Value &value) const {
|
||||
std::string GenEnumDefaultValue(const FieldDef &field) const {
|
||||
auto& value = field.value;
|
||||
auto enum_def = value.type.enum_def;
|
||||
auto vec = enum_def->vals.vec;
|
||||
auto default_value = StringToInt(value.constant.c_str());
|
||||
@@ -446,19 +456,19 @@ class GeneralGenerator : public BaseGenerator {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GenDefaultValue(const Value &value, bool enableLangOverrides) const {
|
||||
std::string GenDefaultValue(const FieldDef &field, bool enableLangOverrides) const {
|
||||
auto& value = field.value;
|
||||
if (enableLangOverrides) {
|
||||
// handles both enum case and vector of enum case
|
||||
if (lang_.language == IDLOptions::kCSharp &&
|
||||
value.type.enum_def != nullptr &&
|
||||
value.type.base_type != BASE_TYPE_UNION) {
|
||||
return GenEnumDefaultValue(value);
|
||||
return GenEnumDefaultValue(field);
|
||||
}
|
||||
}
|
||||
|
||||
auto longSuffix = lang_.language == IDLOptions::kJava ? "L" : "";
|
||||
switch (value.type.base_type) {
|
||||
case BASE_TYPE_FLOAT: return value.constant + "f";
|
||||
case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
|
||||
case BASE_TYPE_ULONG: {
|
||||
if (lang_.language != IDLOptions::kJava) return value.constant;
|
||||
@@ -468,16 +478,21 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
case BASE_TYPE_UINT:
|
||||
case BASE_TYPE_LONG: return value.constant + longSuffix;
|
||||
default: return value.constant;
|
||||
default:
|
||||
if(IsFloat(value.type.base_type))
|
||||
return lang_.float_gen->GenFloatConstant(field);
|
||||
else
|
||||
return value.constant;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenDefaultValue(const Value &value) const {
|
||||
return GenDefaultValue(value, true);
|
||||
std::string GenDefaultValue(const FieldDef &field) const {
|
||||
return GenDefaultValue(field, true);
|
||||
}
|
||||
|
||||
std::string GenDefaultValueBasic(const Value &value,
|
||||
std::string GenDefaultValueBasic(const FieldDef &field,
|
||||
bool enableLangOverrides) const {
|
||||
auto& value = field.value;
|
||||
if (!IsScalar(value.type.base_type)) {
|
||||
if (enableLangOverrides) {
|
||||
if (lang_.language == IDLOptions::kCSharp) {
|
||||
@@ -493,11 +508,11 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
return GenDefaultValue(value, enableLangOverrides);
|
||||
return GenDefaultValue(field, enableLangOverrides);
|
||||
}
|
||||
|
||||
std::string GenDefaultValueBasic(const Value &value) const {
|
||||
return GenDefaultValueBasic(value, true);
|
||||
std::string GenDefaultValueBasic(const FieldDef &field) const {
|
||||
return GenDefaultValueBasic(field, true);
|
||||
}
|
||||
|
||||
void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
|
||||
@@ -956,7 +971,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
code += offset_prefix + getter;
|
||||
code += "(o + " + lang_.accessor_prefix + "bb_pos)" + dest_mask;
|
||||
code += " : " + default_cast;
|
||||
code += GenDefaultValue(field.value);
|
||||
code += GenDefaultValue(field);
|
||||
}
|
||||
} else {
|
||||
switch (field.value.type.base_type) {
|
||||
@@ -1278,7 +1293,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// supply all arguments, and thus won't compile when fields are added.
|
||||
if (lang_.language != IDLOptions::kJava) {
|
||||
code += " = ";
|
||||
code += GenDefaultValueBasic(field.value);
|
||||
code += GenDefaultValueBasic(field);
|
||||
}
|
||||
}
|
||||
code += ") {\n builder.";
|
||||
@@ -1338,7 +1353,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
code += ", ";
|
||||
if (lang_.language == IDLOptions::kJava)
|
||||
code += SourceCastBasic(field.value.type);
|
||||
code += GenDefaultValue(field.value, false);
|
||||
code += GenDefaultValue(field, false);
|
||||
code += "); }\n";
|
||||
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
auto vector_type = field.value.type.VectorType();
|
||||
|
||||
@@ -36,7 +36,8 @@ class PythonGenerator : public BaseGenerator {
|
||||
PythonGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
: BaseGenerator(parser, path, file_name, "" /* not used */,
|
||||
"" /* not used */){
|
||||
"" /* not used */),
|
||||
float_const_gen_("float('nan')", "float('inf')", "float('-inf')") {
|
||||
static const char * const keywords[] = {
|
||||
"False",
|
||||
"None",
|
||||
@@ -191,7 +192,7 @@ class PythonGenerator : public BaseGenerator {
|
||||
code += "(self):";
|
||||
code += OffsetPrefix(field);
|
||||
getter += "o + self._tab.Pos)";
|
||||
auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
|
||||
auto is_bool = IsBool(field.value.type.base_type);
|
||||
if (is_bool) {
|
||||
getter = "bool(" + getter + ")";
|
||||
}
|
||||
@@ -200,7 +201,9 @@ class PythonGenerator : public BaseGenerator {
|
||||
if (is_bool) {
|
||||
default_value = field.value.constant == "0" ? "False" : "True";
|
||||
} else {
|
||||
default_value = field.value.constant;
|
||||
default_value = IsFloat(field.value.type.base_type)
|
||||
? float_const_gen_.GenFloatConstant(field)
|
||||
: field.value.constant;
|
||||
}
|
||||
code += Indent + Indent + "return " + default_value + "\n\n";
|
||||
}
|
||||
@@ -452,7 +455,10 @@ class PythonGenerator : public BaseGenerator {
|
||||
} else {
|
||||
code += MakeCamel(NormalizedName(field), false);
|
||||
}
|
||||
code += ", " + field.value.constant;
|
||||
code += ", ";
|
||||
code += IsFloat(field.value.type.base_type)
|
||||
? float_const_gen_.GenFloatConstant(field)
|
||||
: field.value.constant;
|
||||
code += ")\n";
|
||||
}
|
||||
|
||||
@@ -715,6 +721,7 @@ class PythonGenerator : public BaseGenerator {
|
||||
}
|
||||
private:
|
||||
std::unordered_set<std::string> keywords_;
|
||||
const SimpleFloatConstantGenerator float_const_gen_;
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
|
||||
Reference in New Issue
Block a user