From 4fa4d367069748c318bfff041d71184dc1199270 Mon Sep 17 00:00:00 2001 From: Vladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com> Date: Tue, 15 Jan 2019 00:23:42 +0700 Subject: [PATCH] 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 --- include/flatbuffers/code_generators.h | 67 ++++++++++++++++---- src/code_generators.cpp | 88 +++++++++++++++++++++++++++ src/idl_gen_cpp.cpp | 45 ++------------ src/idl_gen_general.cpp | 43 ++++++++----- src/idl_gen_python.cpp | 15 +++-- tests/JavaTest.java | 1 + tests/MyGame/MonsterExtra.cs | 64 +++++++++++++++++++ tests/MyGame/MonsterExtra.java | 58 ++++++++++++++++++ tests/MyGame/MonsterExtra.py | 70 +++++++++++++++++++++ tests/generate_code.bat | 2 +- tests/generate_code.sh | 2 +- tests/monster_extra.fbs | 2 +- tests/monster_extra_generated.h | 74 +++++++++++----------- tests/py_test.py | 24 +++++++- 14 files changed, 443 insertions(+), 112 deletions(-) create mode 100644 tests/MyGame/MonsterExtra.cs create mode 100644 tests/MyGame/MonsterExtra.java create mode 100644 tests/MyGame/MonsterExtra.py diff --git a/include/flatbuffers/code_generators.h b/include/flatbuffers/code_generators.h index 8077d3003..df09ca01d 100644 --- a/include/flatbuffers/code_generators.h +++ b/include/flatbuffers/code_generators.h @@ -136,27 +136,68 @@ class FloatConstantGenerator { std::string GenFloatConstant(const FieldDef &field) const; private: + virtual std::string Value(double v, const std::string &src) const = 0; virtual std::string Inf(double v) const = 0; virtual std::string NaN(double v) const = 0; - virtual std::string Value(double v, const std::string &src) const { - (void)v; - return src; - } - virtual std::string Inf(float v) const { - return this->Inf(static_cast(v)); - } - virtual std::string NaN(float v) const { - return this->NaN(static_cast(v)); - } - virtual std::string Value(float v, const std::string &src) const { - return this->Value(static_cast(v), src); - } + virtual std::string Value(float v, const std::string &src) const = 0; + virtual std::string Inf(float v) const = 0; + virtual std::string NaN(float v) const = 0; template std::string GenFloatConstantImpl(const FieldDef &field) const; }; +class SimpleFloatConstantGenerator : public FloatConstantGenerator { + public: + SimpleFloatConstantGenerator(const char *nan_number, + const char *pos_inf_number, + const char *neg_inf_number); + + private: + std::string Value(double v, + const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(double v) const FLATBUFFERS_OVERRIDE; + std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + + std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(float v) const FLATBUFFERS_OVERRIDE; + std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + + const std::string nan_number_; + const std::string pos_inf_number_; + const std::string neg_inf_number_; +}; + +// C++, C#, Java like generator. +class TypedFloatConstantGenerator : public FloatConstantGenerator { + public: + TypedFloatConstantGenerator(const char *double_prefix, + const char *single_prefix, const char *nan_number, + const char *pos_inf_number, + const char *neg_inf_number = ""); + + private: + std::string Value(double v, + const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(double v) const FLATBUFFERS_OVERRIDE; + + std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + + std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(float v) const FLATBUFFERS_OVERRIDE; + std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + + std::string MakeNaN(const std::string &prefix) const; + std::string MakeInf(bool neg, const std::string &prefix) const; + + const std::string double_prefix_; + const std::string single_prefix_; + const std::string nan_number_; + const std::string pos_inf_number_; + const std::string neg_inf_number_; +}; + } // namespace flatbuffers #endif // FLATBUFFERS_CODE_GENERATORS_H_ diff --git a/src/code_generators.cpp b/src/code_generators.cpp index b78b5ca1d..3b10db7f5 100644 --- a/src/code_generators.cpp +++ b/src/code_generators.cpp @@ -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(v), src); +} + +std::string SimpleFloatConstantGenerator::Inf(float v) const { + return this->Inf(static_cast(v)); +} + +std::string SimpleFloatConstantGenerator::NaN(float v) const { + return this->NaN(static_cast(v)); +} + } // namespace flatbuffers #if defined(_MSC_VER) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 06896d9c6..9884081ad 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -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::quiet_NaN()"; - } - std::string NaN(float v) const FLATBUFFERS_OVERRIDE { - (void)v; - return "std::numeric_limits::quiet_NaN()"; - } - - std::string Inf(double v) const FLATBUFFERS_OVERRIDE { - if(v < 0) - return "-std::numeric_limits::infinity()"; - else - return "std::numeric_limits::infinity()"; - } - - std::string Inf(float v) const FLATBUFFERS_OVERRIDE { - if (v < 0) - return "-std::numeric_limits::infinity()"; - else - return "std::numeric_limits::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::", + "std::numeric_limits::", "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 diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 66984da0c..7c34ee28d 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.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(); diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index 11491c00d..fbb0805cb 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -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 keywords_; + const SimpleFloatConstantGenerator float_const_gen_; }; } // namespace python diff --git a/tests/JavaTest.java b/tests/JavaTest.java index 3aead2917..7d96f0656 100644 --- a/tests/JavaTest.java +++ b/tests/JavaTest.java @@ -24,6 +24,7 @@ import NamespaceA.NamespaceB.*; import com.google.flatbuffers.ByteBufferUtil; import static com.google.flatbuffers.Constants.*; import com.google.flatbuffers.FlatBufferBuilder; +import MyGame.MonsterExtra; class JavaTest { public static void main(String[] args) { diff --git a/tests/MyGame/MonsterExtra.cs b/tests/MyGame/MonsterExtra.cs new file mode 100644 index 000000000..fc9a32348 --- /dev/null +++ b/tests/MyGame/MonsterExtra.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame +{ + +using global::System; +using global::FlatBuffers; + +public struct MonsterExtra : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static MonsterExtra GetRootAsMonsterExtra(ByteBuffer _bb) { return GetRootAsMonsterExtra(_bb, new MonsterExtra()); } + public static MonsterExtra GetRootAsMonsterExtra(ByteBuffer _bb, MonsterExtra obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; } + public MonsterExtra __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float TestfNan { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.NaN; } } + public bool MutateTestfNan(float testf_nan) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf_nan); return true; } else { return false; } } + public float TestfPinf { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateTestfPinf(float testf_pinf) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf_pinf); return true; } else { return false; } } + public float TestfNinf { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateTestfNinf(float testf_ninf) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf_ninf); return true; } else { return false; } } + public double TestdNan { get { int o = __p.__offset(10); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.NaN; } } + public bool MutateTestdNan(double testd_nan) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, testd_nan); return true; } else { return false; } } + public double TestdPinf { get { int o = __p.__offset(12); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.PositiveInfinity; } } + public bool MutateTestdPinf(double testd_pinf) { int o = __p.__offset(12); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, testd_pinf); return true; } else { return false; } } + public double TestdNinf { get { int o = __p.__offset(14); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.NegativeInfinity; } } + public bool MutateTestdNinf(double testd_ninf) { int o = __p.__offset(14); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, testd_ninf); return true; } else { return false; } } + + public static Offset CreateMonsterExtra(FlatBufferBuilder builder, + float testf_nan = Single.NaN, + float testf_pinf = Single.PositiveInfinity, + float testf_ninf = Single.NegativeInfinity, + double testd_nan = Double.NaN, + double testd_pinf = Double.PositiveInfinity, + double testd_ninf = Double.NegativeInfinity) { + builder.StartObject(6); + MonsterExtra.AddTestdNinf(builder, testd_ninf); + MonsterExtra.AddTestdPinf(builder, testd_pinf); + MonsterExtra.AddTestdNan(builder, testd_nan); + MonsterExtra.AddTestfNinf(builder, testf_ninf); + MonsterExtra.AddTestfPinf(builder, testf_pinf); + MonsterExtra.AddTestfNan(builder, testf_nan); + return MonsterExtra.EndMonsterExtra(builder); + } + + public static void StartMonsterExtra(FlatBufferBuilder builder) { builder.StartObject(6); } + public static void AddTestfNan(FlatBufferBuilder builder, float testfNan) { builder.AddFloat(0, testfNan, Single.NaN); } + public static void AddTestfPinf(FlatBufferBuilder builder, float testfPinf) { builder.AddFloat(1, testfPinf, Single.PositiveInfinity); } + public static void AddTestfNinf(FlatBufferBuilder builder, float testfNinf) { builder.AddFloat(2, testfNinf, Single.NegativeInfinity); } + public static void AddTestdNan(FlatBufferBuilder builder, double testdNan) { builder.AddDouble(3, testdNan, Double.NaN); } + public static void AddTestdPinf(FlatBufferBuilder builder, double testdPinf) { builder.AddDouble(4, testdPinf, Double.PositiveInfinity); } + public static void AddTestdNinf(FlatBufferBuilder builder, double testdNinf) { builder.AddDouble(5, testdNinf, Double.NegativeInfinity); } + public static Offset EndMonsterExtra(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return new Offset(o); + } +}; + + +} diff --git a/tests/MyGame/MonsterExtra.java b/tests/MyGame/MonsterExtra.java new file mode 100644 index 000000000..6070efdcf --- /dev/null +++ b/tests/MyGame/MonsterExtra.java @@ -0,0 +1,58 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused")public final class MonsterExtra extends Table { + public static MonsterExtra getRootAsMonsterExtra(ByteBuffer _bb) { return getRootAsMonsterExtra(_bb, new MonsterExtra()); } + public static MonsterExtra getRootAsMonsterExtra(ByteBuffer _bb, MonsterExtra obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; } + public MonsterExtra __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float testfNan() { int o = __offset(4); return o != 0 ? bb.getFloat(o + bb_pos) : Float.NaN; } + public boolean mutateTestfNan(float testf_nan) { int o = __offset(4); if (o != 0) { bb.putFloat(o + bb_pos, testf_nan); return true; } else { return false; } } + public float testfPinf() { int o = __offset(6); return o != 0 ? bb.getFloat(o + bb_pos) : Float.POSITIVE_INFINITY; } + public boolean mutateTestfPinf(float testf_pinf) { int o = __offset(6); if (o != 0) { bb.putFloat(o + bb_pos, testf_pinf); return true; } else { return false; } } + public float testfNinf() { int o = __offset(8); return o != 0 ? bb.getFloat(o + bb_pos) : Float.NEGATIVE_INFINITY; } + public boolean mutateTestfNinf(float testf_ninf) { int o = __offset(8); if (o != 0) { bb.putFloat(o + bb_pos, testf_ninf); return true; } else { return false; } } + public double testdNan() { int o = __offset(10); return o != 0 ? bb.getDouble(o + bb_pos) : Double.NaN; } + public boolean mutateTestdNan(double testd_nan) { int o = __offset(10); if (o != 0) { bb.putDouble(o + bb_pos, testd_nan); return true; } else { return false; } } + public double testdPinf() { int o = __offset(12); return o != 0 ? bb.getDouble(o + bb_pos) : Double.POSITIVE_INFINITY; } + public boolean mutateTestdPinf(double testd_pinf) { int o = __offset(12); if (o != 0) { bb.putDouble(o + bb_pos, testd_pinf); return true; } else { return false; } } + public double testdNinf() { int o = __offset(14); return o != 0 ? bb.getDouble(o + bb_pos) : Double.NEGATIVE_INFINITY; } + public boolean mutateTestdNinf(double testd_ninf) { int o = __offset(14); if (o != 0) { bb.putDouble(o + bb_pos, testd_ninf); return true; } else { return false; } } + + public static int createMonsterExtra(FlatBufferBuilder builder, + float testf_nan, + float testf_pinf, + float testf_ninf, + double testd_nan, + double testd_pinf, + double testd_ninf) { + builder.startObject(6); + MonsterExtra.addTestdNinf(builder, testd_ninf); + MonsterExtra.addTestdPinf(builder, testd_pinf); + MonsterExtra.addTestdNan(builder, testd_nan); + MonsterExtra.addTestfNinf(builder, testf_ninf); + MonsterExtra.addTestfPinf(builder, testf_pinf); + MonsterExtra.addTestfNan(builder, testf_nan); + return MonsterExtra.endMonsterExtra(builder); + } + + public static void startMonsterExtra(FlatBufferBuilder builder) { builder.startObject(6); } + public static void addTestfNan(FlatBufferBuilder builder, float testfNan) { builder.addFloat(0, testfNan, Float.NaN); } + public static void addTestfPinf(FlatBufferBuilder builder, float testfPinf) { builder.addFloat(1, testfPinf, Float.POSITIVE_INFINITY); } + public static void addTestfNinf(FlatBufferBuilder builder, float testfNinf) { builder.addFloat(2, testfNinf, Float.NEGATIVE_INFINITY); } + public static void addTestdNan(FlatBufferBuilder builder, double testdNan) { builder.addDouble(3, testdNan, Double.NaN); } + public static void addTestdPinf(FlatBufferBuilder builder, double testdPinf) { builder.addDouble(4, testdPinf, Double.POSITIVE_INFINITY); } + public static void addTestdNinf(FlatBufferBuilder builder, double testdNinf) { builder.addDouble(5, testdNinf, Double.NEGATIVE_INFINITY); } + public static int endMonsterExtra(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/tests/MyGame/MonsterExtra.py b/tests/MyGame/MonsterExtra.py new file mode 100644 index 000000000..3e8b26d30 --- /dev/null +++ b/tests/MyGame/MonsterExtra.py @@ -0,0 +1,70 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: MyGame + +import flatbuffers + +class MonsterExtra(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAsMonsterExtra(cls, buf, offset): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = MonsterExtra() + x.Init(buf, n + offset) + return x + + # MonsterExtra + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # MonsterExtra + def TestfNan(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('nan') + + # MonsterExtra + def TestfPinf(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('inf') + + # MonsterExtra + def TestfNinf(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('-inf') + + # MonsterExtra + def TestdNan(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return float('nan') + + # MonsterExtra + def TestdPinf(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return float('inf') + + # MonsterExtra + def TestdNinf(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return float('-inf') + +def MonsterExtraStart(builder): builder.StartObject(6) +def MonsterExtraAddTestfNan(builder, testfNan): builder.PrependFloat32Slot(0, testfNan, float('nan')) +def MonsterExtraAddTestfPinf(builder, testfPinf): builder.PrependFloat32Slot(1, testfPinf, float('inf')) +def MonsterExtraAddTestfNinf(builder, testfNinf): builder.PrependFloat32Slot(2, testfNinf, float('-inf')) +def MonsterExtraAddTestdNan(builder, testdNan): builder.PrependFloat64Slot(3, testdNan, float('nan')) +def MonsterExtraAddTestdPinf(builder, testdPinf): builder.PrependFloat64Slot(4, testdPinf, float('inf')) +def MonsterExtraAddTestdNinf(builder, testdNinf): builder.PrependFloat64Slot(5, testdNinf, float('-inf')) +def MonsterExtraEnd(builder): return builder.EndObject() diff --git a/tests/generate_code.bat b/tests/generate_code.bat index d2e836428..fed9c766f 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -23,7 +23,7 @@ if "%1"=="-b" set buildtype=%2 IF NOT "%MONSTER_EXTRA%"=="skip" ( @echo Generate MosterExtra - ..\%buildtype%\flatc.exe --cpp --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs || goto FAIL + ..\%buildtype%\flatc.exe --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs || goto FAIL ) else ( @echo monster_extra.fbs skipped (the strtod function from MSVC2013 or older doesn't support NaN/Inf arguments) ) diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 6a3a8f854..499e31ac6 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -20,7 +20,7 @@ set -e ../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs -../flatc --cpp --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs || goto FAIL +../flatc --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs || goto FAIL cd ../samples ../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs ../flatc -b --schema --bfbs-comments --bfbs-builtins monster.fbs diff --git a/tests/monster_extra.fbs b/tests/monster_extra.fbs index 2518f5b17..89f1cc8d0 100644 --- a/tests/monster_extra.fbs +++ b/tests/monster_extra.fbs @@ -1,7 +1,7 @@ namespace MyGame; // Not all programmining languages support this extra table. -table MonsterExra { +table MonsterExtra { // Float-point values with NaN and Inf defaults. testf_nan:float = nan; testf_pinf:float = +inf; diff --git a/tests/monster_extra_generated.h b/tests/monster_extra_generated.h index 0dad3b057..ac316d6f9 100644 --- a/tests/monster_extra_generated.h +++ b/tests/monster_extra_generated.h @@ -8,22 +8,22 @@ namespace MyGame { -struct MonsterExra; -struct MonsterExraT; +struct MonsterExtra; +struct MonsterExtraT; -bool operator==(const MonsterExraT &lhs, const MonsterExraT &rhs); +bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs); -inline const flatbuffers::TypeTable *MonsterExraTypeTable(); +inline const flatbuffers::TypeTable *MonsterExtraTypeTable(); -struct MonsterExraT : public flatbuffers::NativeTable { - typedef MonsterExra TableType; +struct MonsterExtraT : public flatbuffers::NativeTable { + typedef MonsterExtra TableType; float testf_nan; float testf_pinf; float testf_ninf; double testd_nan; double testd_pinf; double testd_ninf; - MonsterExraT() + MonsterExtraT() : testf_nan(std::numeric_limits::quiet_NaN()), testf_pinf(std::numeric_limits::infinity()), testf_ninf(-std::numeric_limits::infinity()), @@ -33,7 +33,7 @@ struct MonsterExraT : public flatbuffers::NativeTable { } }; -inline bool operator==(const MonsterExraT &lhs, const MonsterExraT &rhs) { +inline bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs) { return (lhs.testf_nan == rhs.testf_nan) && (lhs.testf_pinf == rhs.testf_pinf) && @@ -43,10 +43,10 @@ inline bool operator==(const MonsterExraT &lhs, const MonsterExraT &rhs) { (lhs.testd_ninf == rhs.testd_ninf); } -struct MonsterExra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - typedef MonsterExraT NativeTableType; +struct MonsterExtra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MonsterExtraT NativeTableType; static const flatbuffers::TypeTable *MiniReflectTypeTable() { - return MonsterExraTypeTable(); + return MonsterExtraTypeTable(); } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_TESTF_NAN = 4, @@ -102,45 +102,45 @@ struct MonsterExra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_TESTD_NINF) && verifier.EndTable(); } - MonsterExraT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; - void UnPackTo(MonsterExraT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; - static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExraT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + MonsterExtraT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MonsterExtraT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); }; -struct MonsterExraBuilder { +struct MonsterExtraBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; void add_testf_nan(float testf_nan) { - fbb_.AddElement(MonsterExra::VT_TESTF_NAN, testf_nan, std::numeric_limits::quiet_NaN()); + fbb_.AddElement(MonsterExtra::VT_TESTF_NAN, testf_nan, std::numeric_limits::quiet_NaN()); } void add_testf_pinf(float testf_pinf) { - fbb_.AddElement(MonsterExra::VT_TESTF_PINF, testf_pinf, std::numeric_limits::infinity()); + fbb_.AddElement(MonsterExtra::VT_TESTF_PINF, testf_pinf, std::numeric_limits::infinity()); } void add_testf_ninf(float testf_ninf) { - fbb_.AddElement(MonsterExra::VT_TESTF_NINF, testf_ninf, -std::numeric_limits::infinity()); + fbb_.AddElement(MonsterExtra::VT_TESTF_NINF, testf_ninf, -std::numeric_limits::infinity()); } void add_testd_nan(double testd_nan) { - fbb_.AddElement(MonsterExra::VT_TESTD_NAN, testd_nan, std::numeric_limits::quiet_NaN()); + fbb_.AddElement(MonsterExtra::VT_TESTD_NAN, testd_nan, std::numeric_limits::quiet_NaN()); } void add_testd_pinf(double testd_pinf) { - fbb_.AddElement(MonsterExra::VT_TESTD_PINF, testd_pinf, std::numeric_limits::infinity()); + fbb_.AddElement(MonsterExtra::VT_TESTD_PINF, testd_pinf, std::numeric_limits::infinity()); } void add_testd_ninf(double testd_ninf) { - fbb_.AddElement(MonsterExra::VT_TESTD_NINF, testd_ninf, -std::numeric_limits::infinity()); + fbb_.AddElement(MonsterExtra::VT_TESTD_NINF, testd_ninf, -std::numeric_limits::infinity()); } - explicit MonsterExraBuilder(flatbuffers::FlatBufferBuilder &_fbb) + explicit MonsterExtraBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - MonsterExraBuilder &operator=(const MonsterExraBuilder &); - flatbuffers::Offset Finish() { + MonsterExtraBuilder &operator=(const MonsterExtraBuilder &); + flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset(end); + auto o = flatbuffers::Offset(end); return o; } }; -inline flatbuffers::Offset CreateMonsterExra( +inline flatbuffers::Offset CreateMonsterExtra( flatbuffers::FlatBufferBuilder &_fbb, float testf_nan = std::numeric_limits::quiet_NaN(), float testf_pinf = std::numeric_limits::infinity(), @@ -148,7 +148,7 @@ inline flatbuffers::Offset CreateMonsterExra( double testd_nan = std::numeric_limits::quiet_NaN(), double testd_pinf = std::numeric_limits::infinity(), double testd_ninf = -std::numeric_limits::infinity()) { - MonsterExraBuilder builder_(_fbb); + MonsterExtraBuilder builder_(_fbb); builder_.add_testd_ninf(testd_ninf); builder_.add_testd_pinf(testd_pinf); builder_.add_testd_nan(testd_nan); @@ -158,15 +158,15 @@ inline flatbuffers::Offset CreateMonsterExra( return builder_.Finish(); } -flatbuffers::Offset CreateMonsterExra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +flatbuffers::Offset CreateMonsterExtra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); -inline MonsterExraT *MonsterExra::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterExraT(); +inline MonsterExtraT *MonsterExtra::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new MonsterExtraT(); UnPackTo(_o, _resolver); return _o; } -inline void MonsterExra::UnPackTo(MonsterExraT *_o, const flatbuffers::resolver_function_t *_resolver) const { +inline void MonsterExtra::UnPackTo(MonsterExtraT *_o, const flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; { auto _e = testf_nan(); _o->testf_nan = _e; }; @@ -177,21 +177,21 @@ inline void MonsterExra::UnPackTo(MonsterExraT *_o, const flatbuffers::resolver_ { auto _e = testd_ninf(); _o->testd_ninf = _e; }; } -inline flatbuffers::Offset MonsterExra::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExraT* _o, const flatbuffers::rehasher_function_t *_rehasher) { - return CreateMonsterExra(_fbb, _o, _rehasher); +inline flatbuffers::Offset MonsterExtra::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMonsterExtra(_fbb, _o, _rehasher); } -inline flatbuffers::Offset CreateMonsterExra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExraT *_o, const flatbuffers::rehasher_function_t *_rehasher) { +inline flatbuffers::Offset CreateMonsterExtra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; - struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterExraT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterExtraT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _testf_nan = _o->testf_nan; auto _testf_pinf = _o->testf_pinf; auto _testf_ninf = _o->testf_ninf; auto _testd_nan = _o->testd_nan; auto _testd_pinf = _o->testd_pinf; auto _testd_ninf = _o->testd_ninf; - return MyGame::CreateMonsterExra( + return MyGame::CreateMonsterExtra( _fbb, _testf_nan, _testf_pinf, @@ -201,7 +201,7 @@ inline flatbuffers::Offset CreateMonsterExra(flatbuffers::FlatBuffe _testd_ninf); } -inline const flatbuffers::TypeTable *MonsterExraTypeTable() { +inline const flatbuffers::TypeTable *MonsterExtraTypeTable() { static const flatbuffers::TypeCode type_codes[] = { { flatbuffers::ET_FLOAT, 0, -1 }, { flatbuffers::ET_FLOAT, 0, -1 }, diff --git a/tests/py_test.py b/tests/py_test.py index 268efbe7b..54f044660 100644 --- a/tests/py_test.py +++ b/tests/py_test.py @@ -20,10 +20,10 @@ PY_VERSION = sys.version_info[:2] import ctypes from collections import defaultdict +import math import timeit import unittest - from flatbuffers import compat from flatbuffers import util from flatbuffers.compat import range_func as compat_range @@ -40,6 +40,7 @@ import MyGame.Example.Monster # refers to generated code import MyGame.Example.Test # refers to generated code import MyGame.Example.Stat # refers to generated code import MyGame.Example.Vec3 # refers to generated code +import MyGame.MonsterExtra # refers to generated code def assertRaises(test_case, fn, exception_class): @@ -1395,6 +1396,27 @@ class TestAllCodePathsOfExampleSchema(unittest.TestCase): self.assertEqual(12345, stat2.Count()) +class TestAllCodePathsOfMonsterExtraSchema(unittest.TestCase): + def setUp(self, *args, **kwargs): + super(TestAllCodePathsOfMonsterExtraSchema, self).setUp(*args, **kwargs) + + b = flatbuffers.Builder(0) + MyGame.MonsterExtra.MonsterExtraStart(b) + gen_mon = MyGame.MonsterExtra.MonsterExtraEnd(b) + b.Finish(gen_mon) + + self.mon = MyGame.MonsterExtra.MonsterExtra.GetRootAsMonsterExtra(b.Bytes, b.Head()) + + def test_default_nan_inf(self): + self.assertTrue(math.isnan(self.mon.TestfNan())) + self.assertEqual(self.mon.TestfPinf(), float("inf")) + self.assertEqual(self.mon.TestfNinf(), float("-inf")) + + self.assertTrue(math.isnan(self.mon.TestdNan())) + self.assertEqual(self.mon.TestdPinf(), float("inf")) + self.assertEqual(self.mon.TestdNinf(), float("-inf")) + + class TestVtableDeduplication(unittest.TestCase): ''' TestVtableDeduplication verifies that vtables are deduplicated. '''