diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md index 6cf36d1fa..7867f4be4 100644 --- a/docs/source/CppUsage.md +++ b/docs/source/CppUsage.md @@ -35,7 +35,7 @@ The test code itself is located in [test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp). This test file is built alongside `flatc`. To review how to build the project, -please read the [Building](@ref flatbuffers_guide_building) documenation. +please read the [Building](@ref flatbuffers_guide_building) documentation. To run the tests, execute `flattests` from the root `flatbuffers/` directory. For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply @@ -546,21 +546,63 @@ locale-independent or locale-narrow functions `strtof_l`, `strtod_l`, These functions use specified locale rather than the global or per-thread locale instead. They are part of POSIX-2008 but not part of the C/C++ standard library, therefore, may be missing on some platforms. - The Flatbuffers library try to detect these functions at configuration and compile time: -- `_MSC_VER >= 1900`: check MSVC2012 or higher for MSVC buid -- `_XOPEN_SOURCE>=700`: check POSIX-2008 for GCC/Clang build -- `check_cxx_symbol_exists(strtof_l stdlib.h)`: CMake check of `strtod_f` +- CMake `"CMakeLists.txt"`: + - Check existence of `strtol_l` and `strtod_l` in the ``. +- Compile-time `"/include/base.h"`: + - `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC. + - `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang. After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be set to `0` or `1`. +To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}` +or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol. -It is possible to test the compatibility of the Flatbuffers library with -a specific locale using the environment variable `FLATBUFFERS_TEST_LOCALE`: +To test the compatibility of the Flatbuffers library with +a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`: ```sh >FLATBUFFERS_TEST_LOCALE="" ./flattests >FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests ``` +## Support of floating-point numbers +The Flatbuffers library assumes that a C++ compiler and a CPU are +compatible with the `IEEE-754` floating-point standard. +The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active. + +### Support of hexadecimal and special floating-point numbers +According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files +may use hexadecimal and special (`NaN`, `Inf`) floating-point literals. +The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point +literals. The Flatbuffers library has a code to detect a compiler compatibility +with the literals. If necessary conditions are met the preprocessor constant +`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`. +The support of floating-point literals will be limited at compile time +if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`. +In this case, schemas with hexadecimal or special literals cannot be used. + +### Comparison of floating-point NaN values +The floating-point `NaN` (`not a number`) is special value which +representing an undefined or unrepresentable value. +`NaN` may be explicitly assigned to variables, typically as a representation +for missing values or may be a result of a mathematical operation. +The `IEEE-754` defines two kind of `NaNs`: +- Quiet NaNs, or `qNaNs`. +- Signaling NaNs, or `sNaNs`. + +According to the `IEEE-754`, a comparison with `NaN` always returns +an unordered result even when compared with itself. As a result, a whole +Flatbuffers object will be not equal to itself if has one or more `NaN`. +Flatbuffers scalar fields that have the default value are not actually stored +in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)). +Scalar fields with `NaN` defaults break this behavior. +If a schema has a lot of `NaN` defaults the Flatbuffers can override +the unordered comparison by the ordered: `(NaN==NaN)->true`. +This ordered comparison is enabled when compiling a program with the symbol +`FLATBUFFERS_NAN_DEFAULTS` defined. +Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap +if GCC or Clang used. These compilers have a compile-time implementation +of `isnan` checking which MSVC does not. +
diff --git a/docs/source/Internals.md b/docs/source/Internals.md index e8f453a87..d2064ca61 100644 --- a/docs/source/Internals.md +++ b/docs/source/Internals.md @@ -15,6 +15,12 @@ all commonly used CPUs today. FlatBuffers will also work on big-endian machines, but will be slightly slower because of additional byte-swap intrinsics. +It is assumed that the following conditions are met, to ensure +cross-platform interoperability: +- The binary `IEEE-754` format is used for floating-point numbers. +- The `two's complemented` representation is used for signed integers. +- The endianness is the same for floating-point numbers as for integers. + On purpose, the format leaves a lot of details about where exactly things live in memory undefined, e.g. fields in a table can have any order, and objects to some extent can be stored in many orders. This is diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index 58bedae6a..403aebbe0 100644 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -439,14 +439,19 @@ numerical literals: For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals. - The format of float-point numbers is fully compatible with C/C++ format. If a modern C++ compiler is used the parser accepts hexadecimal and special - float-point literals as well: + floating-point literals as well: `[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`. - The exponent suffix of hexadecimal float-point number is mandatory. - Extended float-point support was tested with: + The following conventions for floating-point numbers are used: + - The exponent suffix of hexadecimal floating-point number is mandatory. + - Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value. + + Extended floating-point support was tested with: - x64 Windows: `MSVC2015` and higher. - x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher. + For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section. + - For compatibility with a JSON lint tool all numeric literals of scalar fields can be wrapped to quoted string: `"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`. diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 02a191047..21896f6bd 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -25,16 +25,21 @@ namespace flatbuffers { // Generic 'operator==' with conditional specialisations. +// T e - new value of a scalar field. +// T def - default of scalar (is known at compile-time). template inline bool IsTheSameAs(T e, T def) { return e == def; } #if defined(FLATBUFFERS_NAN_DEFAULTS) && \ - (!defined(_MSC_VER) || _MSC_VER >= 1800) + defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) // Like `operator==(e, def)` with weak NaN if T=(float|double). +template inline bool IsFloatTheSameAs(T e, T def) { + return (e == def) || ((def != def) && (e != e)); +} template<> inline bool IsTheSameAs(float e, float def) { - return (e == def) || (std::isnan(def) && std::isnan(e)); + return IsFloatTheSameAs(e, def); } template<> inline bool IsTheSameAs(double e, double def) { - return (e == def) || (std::isnan(def) && std::isnan(e)); + return IsFloatTheSameAs(e, def); } #endif diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 794165f79..adc80ccd6 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include "flatbuffers/idl.h" #include "flatbuffers/util.h" @@ -1525,6 +1525,21 @@ CheckedError Parser::TokenError() { return Error("cannot parse value starting with: " + TokenToStringId(token_)); } +// Re-pack helper (ParseSingleValue) to normalize defaults of scalars. +template 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) +// Normilaze defaults NaN to unsigned quiet-NaN(0). +static inline void SingleValueRepack(Value& e, float val) { + if (val != val) e.constant = "nan"; +} +static inline void SingleValueRepack(Value& e, double val) { + if (val != val) e.constant = "nan"; +} +#endif + CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, bool check_now) { // First see if this could be a conversion function: @@ -1569,96 +1584,94 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, } auto match = false; + const auto in_type = e.type.base_type; // clang-format off - #define TRY_ECHECK(force, dtoken, check, req) \ + #define IF_ECHECK_(force, dtoken, check, req) \ if (!match && ((check) || IsConstTrue(force))) \ ECHECK(TryTypedValue(name, dtoken, check, e, req, &match)) + #define TRY_ECHECK(dtoken, check, req) IF_ECHECK_(false, dtoken, check, req) + #define FORCE_ECHECK(dtoken, check, req) IF_ECHECK_(true, dtoken, check, req) // clang-format on if (token_ == kTokenStringConstant || token_ == kTokenIdentifier) { const auto kTokenStringOrIdent = token_; // The string type is a most probable type, check it first. - TRY_ECHECK(false, kTokenStringConstant, - e.type.base_type == BASE_TYPE_STRING, BASE_TYPE_STRING); + TRY_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING, + BASE_TYPE_STRING); // avoid escaped and non-ascii in the string - if ((token_ == kTokenStringConstant) && IsScalar(e.type.base_type) && + if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type) && !attr_is_trivial_ascii_string_) { return Error( std::string("type mismatch or invalid value, an initializer of " "non-string field must be trivial ASCII string: type: ") + - kTypeNames[e.type.base_type] + ", name: " + (name ? *name : "") + + kTypeNames[in_type] + ", name: " + (name ? *name : "") + ", value: " + attribute_); } // A boolean as true/false. Boolean as Integer check below. - if (!match && IsBool(e.type.base_type)) { + if (!match && IsBool(in_type)) { auto is_true = attribute_ == "true"; if (is_true || attribute_ == "false") { attribute_ = is_true ? "1" : "0"; // accepts both kTokenStringConstant and kTokenIdentifier - TRY_ECHECK(false, kTokenStringOrIdent, IsBool(e.type.base_type), - BASE_TYPE_BOOL); + TRY_ECHECK(kTokenStringOrIdent, IsBool(in_type), BASE_TYPE_BOOL); } } // Check if this could be a string/identifier enum value. // Enum can have only true integer base type. - if (!match && IsInteger(e.type.base_type) && !IsBool(e.type.base_type) && + if (!match && IsInteger(in_type) && !IsBool(in_type) && IsIdentifierStart(*attribute_.c_str())) { ECHECK(ParseEnumFromString(e.type, &e.constant)); NEXT(); match = true; } - // float/integer number in string - if ((token_ == kTokenStringConstant) && IsScalar(e.type.base_type)) { + // Parse a float/integer number from the string. + if (!match) check_now = true; // Re-pack if parsed from string literal. + if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type)) { // remove trailing whitespaces from attribute_ auto last = attribute_.find_last_not_of(' '); if (std::string::npos != last) // has non-whitespace attribute_.resize(last + 1); } // Float numbers or nan, inf, pi, etc. - TRY_ECHECK(false, kTokenStringOrIdent, IsFloat(e.type.base_type), - BASE_TYPE_FLOAT); + TRY_ECHECK(kTokenStringOrIdent, IsFloat(in_type), BASE_TYPE_FLOAT); // An integer constant in string. - TRY_ECHECK(false, kTokenStringOrIdent, IsInteger(e.type.base_type), - BASE_TYPE_INT); + TRY_ECHECK(kTokenStringOrIdent, IsInteger(in_type), BASE_TYPE_INT); // Unknown tokens will be interpreted as string type. - TRY_ECHECK(true, kTokenStringConstant, e.type.base_type == BASE_TYPE_STRING, + FORCE_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING, BASE_TYPE_STRING); } else { // Try a float number. - TRY_ECHECK(false, kTokenFloatConstant, IsFloat(e.type.base_type), - BASE_TYPE_FLOAT); + TRY_ECHECK(kTokenFloatConstant, IsFloat(in_type), BASE_TYPE_FLOAT); // Integer token can init any scalar (integer of float). - TRY_ECHECK(true, kTokenIntegerConstant, IsScalar(e.type.base_type), - BASE_TYPE_INT); + FORCE_ECHECK(kTokenIntegerConstant, IsScalar(in_type), BASE_TYPE_INT); } - #undef TRY_ECHECK +#undef FORCE_ECHECK +#undef TRY_ECHECK +#undef IF_ECHECK_ if (!match) return TokenError(); - + const auto match_type = e.type.base_type; // may differ from in_type // The check_now flag must be true when parse a fbs-schema. // This flag forces to check default scalar values or metadata of field. // For JSON parser the flag should be false. // If it is set for JSON each value will be checked twice (see ParseTable). - if (check_now && IsScalar(e.type.base_type)) { - // "re-pack" an integer scalar to remove any ambiguities like leading zeros - // which can be treated as octal-literal (idl_gen_cpp/GenDefaultConstant). - const auto repack = IsInteger(e.type.base_type); - switch (e.type.base_type) { + if (check_now && IsScalar(match_type)) { // clang-format off + switch (match_type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: {\ CTYPE val; \ ECHECK(atot(e.constant.c_str(), *this, &val)); \ - if(repack) e.constant = NumToString(val); \ + SingleValueRepack(e, val); \ break; } FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); #undef FLATBUFFERS_TD default: break; - // clang-format on } + // clang-format on } return NoError(); } @@ -3031,7 +3044,7 @@ static Namespace *GetNamespace( for (;;) { dot = qualified_name.find('.', pos); if (dot == std::string::npos) { break; } - ns->components.push_back(qualified_name.substr(pos, dot-pos)); + ns->components.push_back(qualified_name.substr(pos, dot - pos)); pos = dot + 1; } } diff --git a/tests/MyGame/MonsterExtra.cs b/tests/MyGame/MonsterExtra.cs index 0a26a347e..570639047 100644 --- a/tests/MyGame/MonsterExtra.cs +++ b/tests/MyGame/MonsterExtra.cs @@ -19,73 +19,83 @@ public struct MonsterExtra : IFlatbufferObject public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _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 float TestfVec(int j) { int o = __p.__offset(16); return o != 0 ? __p.bb.GetFloat(__p.__vector(o) + j * 4) : (float)0; } - public int TestfVecLength { get { int o = __p.__offset(16); return o != 0 ? __p.__vector_len(o) : 0; } } + public double D0 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.NaN; } } + public bool MutateD0(double d0) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, d0); return true; } else { return false; } } + public double D1 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.NaN; } } + public bool MutateD1(double d1) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, d1); return true; } else { return false; } } + public double D2 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.PositiveInfinity; } } + public bool MutateD2(double d2) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, d2); return true; } else { return false; } } + public double D3 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)Double.NegativeInfinity; } } + public bool MutateD3(double d3) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, d3); return true; } else { return false; } } + public float F0 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.NaN; } } + public bool MutateF0(float f0) { int o = __p.__offset(12); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, f0); return true; } else { return false; } } + public float F1 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.NaN; } } + public bool MutateF1(float f1) { int o = __p.__offset(14); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, f1); return true; } else { return false; } } + public float F2 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateF2(float f2) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, f2); return true; } else { return false; } } + public float F3 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateF3(float f3) { int o = __p.__offset(18); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, f3); return true; } else { return false; } } + public double Dvec(int j) { int o = __p.__offset(20); return o != 0 ? __p.bb.GetDouble(__p.__vector(o) + j * 8) : (double)0; } + public int DvecLength { get { int o = __p.__offset(20); return o != 0 ? __p.__vector_len(o) : 0; } } #if ENABLE_SPAN_T - public Span GetTestfVecBytes() { return __p.__vector_as_span(16); } + public Span GetDvecBytes() { return __p.__vector_as_span(20); } #else - public ArraySegment? GetTestfVecBytes() { return __p.__vector_as_arraysegment(16); } + public ArraySegment? GetDvecBytes() { return __p.__vector_as_arraysegment(20); } #endif - public float[] GetTestfVecArray() { return __p.__vector_as_array(16); } - public bool MutateTestfVec(int j, float testf_vec) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutFloat(__p.__vector(o) + j * 4, testf_vec); return true; } else { return false; } } - public double TestdVec(int j) { int o = __p.__offset(18); return o != 0 ? __p.bb.GetDouble(__p.__vector(o) + j * 8) : (double)0; } - public int TestdVecLength { get { int o = __p.__offset(18); return o != 0 ? __p.__vector_len(o) : 0; } } + public double[] GetDvecArray() { return __p.__vector_as_array(20); } + public bool MutateDvec(int j, double dvec) { int o = __p.__offset(20); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, dvec); return true; } else { return false; } } + public float Fvec(int j) { int o = __p.__offset(22); return o != 0 ? __p.bb.GetFloat(__p.__vector(o) + j * 4) : (float)0; } + public int FvecLength { get { int o = __p.__offset(22); return o != 0 ? __p.__vector_len(o) : 0; } } #if ENABLE_SPAN_T - public Span GetTestdVecBytes() { return __p.__vector_as_span(18); } + public Span GetFvecBytes() { return __p.__vector_as_span(22); } #else - public ArraySegment? GetTestdVecBytes() { return __p.__vector_as_arraysegment(18); } + public ArraySegment? GetFvecBytes() { return __p.__vector_as_arraysegment(22); } #endif - public double[] GetTestdVecArray() { return __p.__vector_as_array(18); } - public bool MutateTestdVec(int j, double testd_vec) { int o = __p.__offset(18); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, testd_vec); return true; } else { return false; } } + public float[] GetFvecArray() { return __p.__vector_as_array(22); } + public bool MutateFvec(int j, float fvec) { int o = __p.__offset(22); if (o != 0) { __p.bb.PutFloat(__p.__vector(o) + j * 4, fvec); 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, - VectorOffset testf_vecOffset = default(VectorOffset), - VectorOffset testd_vecOffset = default(VectorOffset)) { - builder.StartTable(8); - MonsterExtra.AddTestdNinf(builder, testd_ninf); - MonsterExtra.AddTestdPinf(builder, testd_pinf); - MonsterExtra.AddTestdNan(builder, testd_nan); - MonsterExtra.AddTestdVec(builder, testd_vecOffset); - MonsterExtra.AddTestfVec(builder, testf_vecOffset); - MonsterExtra.AddTestfNinf(builder, testf_ninf); - MonsterExtra.AddTestfPinf(builder, testf_pinf); - MonsterExtra.AddTestfNan(builder, testf_nan); + double d0 = Double.NaN, + double d1 = Double.NaN, + double d2 = Double.PositiveInfinity, + double d3 = Double.NegativeInfinity, + float f0 = Single.NaN, + float f1 = Single.NaN, + float f2 = Single.PositiveInfinity, + float f3 = Single.NegativeInfinity, + VectorOffset dvecOffset = default(VectorOffset), + VectorOffset fvecOffset = default(VectorOffset)) { + builder.StartTable(10); + MonsterExtra.AddD3(builder, d3); + MonsterExtra.AddD2(builder, d2); + MonsterExtra.AddD1(builder, d1); + MonsterExtra.AddD0(builder, d0); + MonsterExtra.AddFvec(builder, fvecOffset); + MonsterExtra.AddDvec(builder, dvecOffset); + MonsterExtra.AddF3(builder, f3); + MonsterExtra.AddF2(builder, f2); + MonsterExtra.AddF1(builder, f1); + MonsterExtra.AddF0(builder, f0); return MonsterExtra.EndMonsterExtra(builder); } - public static void StartMonsterExtra(FlatBufferBuilder builder) { builder.StartTable(8); } - 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 void AddTestfVec(FlatBufferBuilder builder, VectorOffset testfVecOffset) { builder.AddOffset(6, testfVecOffset.Value, 0); } - public static VectorOffset CreateTestfVecVector(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddFloat(data[i]); return builder.EndVector(); } - public static VectorOffset CreateTestfVecVectorBlock(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } - public static void StartTestfVecVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } - public static void AddTestdVec(FlatBufferBuilder builder, VectorOffset testdVecOffset) { builder.AddOffset(7, testdVecOffset.Value, 0); } - public static VectorOffset CreateTestdVecVector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); } - public static VectorOffset CreateTestdVecVectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); } - public static void StartTestdVecVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void StartMonsterExtra(FlatBufferBuilder builder) { builder.StartTable(10); } + public static void AddD0(FlatBufferBuilder builder, double d0) { builder.AddDouble(0, d0, Double.NaN); } + public static void AddD1(FlatBufferBuilder builder, double d1) { builder.AddDouble(1, d1, Double.NaN); } + public static void AddD2(FlatBufferBuilder builder, double d2) { builder.AddDouble(2, d2, Double.PositiveInfinity); } + public static void AddD3(FlatBufferBuilder builder, double d3) { builder.AddDouble(3, d3, Double.NegativeInfinity); } + public static void AddF0(FlatBufferBuilder builder, float f0) { builder.AddFloat(4, f0, Single.NaN); } + public static void AddF1(FlatBufferBuilder builder, float f1) { builder.AddFloat(5, f1, Single.NaN); } + public static void AddF2(FlatBufferBuilder builder, float f2) { builder.AddFloat(6, f2, Single.PositiveInfinity); } + public static void AddF3(FlatBufferBuilder builder, float f3) { builder.AddFloat(7, f3, Single.NegativeInfinity); } + public static void AddDvec(FlatBufferBuilder builder, VectorOffset dvecOffset) { builder.AddOffset(8, dvecOffset.Value, 0); } + public static VectorOffset CreateDvecVector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); } + public static VectorOffset CreateDvecVectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); } + public static void StartDvecVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddFvec(FlatBufferBuilder builder, VectorOffset fvecOffset) { builder.AddOffset(9, fvecOffset.Value, 0); } + public static VectorOffset CreateFvecVector(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddFloat(data[i]); return builder.EndVector(); } + public static VectorOffset CreateFvecVectorBlock(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static void StartFvecVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } public static Offset EndMonsterExtra(FlatBufferBuilder builder) { int o = builder.EndTable(); return new Offset(o); diff --git a/tests/MyGame/MonsterExtra.java b/tests/MyGame/MonsterExtra.java index bf1065f52..3022596b2 100644 --- a/tests/MyGame/MonsterExtra.java +++ b/tests/MyGame/MonsterExtra.java @@ -16,63 +16,73 @@ public final class MonsterExtra extends Table { public void __init(int _i, ByteBuffer _bb) { __reset(_i, _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 float testfVec(int j) { int o = __offset(16); return o != 0 ? bb.getFloat(__vector(o) + j * 4) : 0; } - public int testfVecLength() { int o = __offset(16); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer testfVecAsByteBuffer() { return __vector_as_bytebuffer(16, 4); } - public ByteBuffer testfVecInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 16, 4); } - public boolean mutateTestfVec(int j, float testf_vec) { int o = __offset(16); if (o != 0) { bb.putFloat(__vector(o) + j * 4, testf_vec); return true; } else { return false; } } - public double testdVec(int j) { int o = __offset(18); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } - public int testdVecLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer testdVecAsByteBuffer() { return __vector_as_bytebuffer(18, 8); } - public ByteBuffer testdVecInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 8); } - public boolean mutateTestdVec(int j, double testd_vec) { int o = __offset(18); if (o != 0) { bb.putDouble(__vector(o) + j * 8, testd_vec); return true; } else { return false; } } + public double d0() { int o = __offset(4); return o != 0 ? bb.getDouble(o + bb_pos) : Double.NaN; } + public boolean mutateD0(double d0) { int o = __offset(4); if (o != 0) { bb.putDouble(o + bb_pos, d0); return true; } else { return false; } } + public double d1() { int o = __offset(6); return o != 0 ? bb.getDouble(o + bb_pos) : Double.NaN; } + public boolean mutateD1(double d1) { int o = __offset(6); if (o != 0) { bb.putDouble(o + bb_pos, d1); return true; } else { return false; } } + public double d2() { int o = __offset(8); return o != 0 ? bb.getDouble(o + bb_pos) : Double.POSITIVE_INFINITY; } + public boolean mutateD2(double d2) { int o = __offset(8); if (o != 0) { bb.putDouble(o + bb_pos, d2); return true; } else { return false; } } + public double d3() { int o = __offset(10); return o != 0 ? bb.getDouble(o + bb_pos) : Double.NEGATIVE_INFINITY; } + public boolean mutateD3(double d3) { int o = __offset(10); if (o != 0) { bb.putDouble(o + bb_pos, d3); return true; } else { return false; } } + public float f0() { int o = __offset(12); return o != 0 ? bb.getFloat(o + bb_pos) : Float.NaN; } + public boolean mutateF0(float f0) { int o = __offset(12); if (o != 0) { bb.putFloat(o + bb_pos, f0); return true; } else { return false; } } + public float f1() { int o = __offset(14); return o != 0 ? bb.getFloat(o + bb_pos) : Float.NaN; } + public boolean mutateF1(float f1) { int o = __offset(14); if (o != 0) { bb.putFloat(o + bb_pos, f1); return true; } else { return false; } } + public float f2() { int o = __offset(16); return o != 0 ? bb.getFloat(o + bb_pos) : Float.POSITIVE_INFINITY; } + public boolean mutateF2(float f2) { int o = __offset(16); if (o != 0) { bb.putFloat(o + bb_pos, f2); return true; } else { return false; } } + public float f3() { int o = __offset(18); return o != 0 ? bb.getFloat(o + bb_pos) : Float.NEGATIVE_INFINITY; } + public boolean mutateF3(float f3) { int o = __offset(18); if (o != 0) { bb.putFloat(o + bb_pos, f3); return true; } else { return false; } } + public double dvec(int j) { int o = __offset(20); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } + public int dvecLength() { int o = __offset(20); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer dvecAsByteBuffer() { return __vector_as_bytebuffer(20, 8); } + public ByteBuffer dvecInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 8); } + public boolean mutateDvec(int j, double dvec) { int o = __offset(20); if (o != 0) { bb.putDouble(__vector(o) + j * 8, dvec); return true; } else { return false; } } + public float fvec(int j) { int o = __offset(22); return o != 0 ? bb.getFloat(__vector(o) + j * 4) : 0; } + public int fvecLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer fvecAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } + public ByteBuffer fvecInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } + public boolean mutateFvec(int j, float fvec) { int o = __offset(22); if (o != 0) { bb.putFloat(__vector(o) + j * 4, fvec); 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, - int testf_vecOffset, - int testd_vecOffset) { - builder.startTable(8); - MonsterExtra.addTestdNinf(builder, testd_ninf); - MonsterExtra.addTestdPinf(builder, testd_pinf); - MonsterExtra.addTestdNan(builder, testd_nan); - MonsterExtra.addTestdVec(builder, testd_vecOffset); - MonsterExtra.addTestfVec(builder, testf_vecOffset); - MonsterExtra.addTestfNinf(builder, testf_ninf); - MonsterExtra.addTestfPinf(builder, testf_pinf); - MonsterExtra.addTestfNan(builder, testf_nan); + double d0, + double d1, + double d2, + double d3, + float f0, + float f1, + float f2, + float f3, + int dvecOffset, + int fvecOffset) { + builder.startTable(10); + MonsterExtra.addD3(builder, d3); + MonsterExtra.addD2(builder, d2); + MonsterExtra.addD1(builder, d1); + MonsterExtra.addD0(builder, d0); + MonsterExtra.addFvec(builder, fvecOffset); + MonsterExtra.addDvec(builder, dvecOffset); + MonsterExtra.addF3(builder, f3); + MonsterExtra.addF2(builder, f2); + MonsterExtra.addF1(builder, f1); + MonsterExtra.addF0(builder, f0); return MonsterExtra.endMonsterExtra(builder); } - public static void startMonsterExtra(FlatBufferBuilder builder) { builder.startTable(8); } - 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 void addTestfVec(FlatBufferBuilder builder, int testfVecOffset) { builder.addOffset(6, testfVecOffset, 0); } - public static int createTestfVecVector(FlatBufferBuilder builder, float[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addFloat(data[i]); return builder.endVector(); } - public static void startTestfVecVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTestdVec(FlatBufferBuilder builder, int testdVecOffset) { builder.addOffset(7, testdVecOffset, 0); } - public static int createTestdVecVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } - public static void startTestdVecVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } + public static void startMonsterExtra(FlatBufferBuilder builder) { builder.startTable(10); } + public static void addD0(FlatBufferBuilder builder, double d0) { builder.addDouble(0, d0, Double.NaN); } + public static void addD1(FlatBufferBuilder builder, double d1) { builder.addDouble(1, d1, Double.NaN); } + public static void addD2(FlatBufferBuilder builder, double d2) { builder.addDouble(2, d2, Double.POSITIVE_INFINITY); } + public static void addD3(FlatBufferBuilder builder, double d3) { builder.addDouble(3, d3, Double.NEGATIVE_INFINITY); } + public static void addF0(FlatBufferBuilder builder, float f0) { builder.addFloat(4, f0, Float.NaN); } + public static void addF1(FlatBufferBuilder builder, float f1) { builder.addFloat(5, f1, Float.NaN); } + public static void addF2(FlatBufferBuilder builder, float f2) { builder.addFloat(6, f2, Float.POSITIVE_INFINITY); } + public static void addF3(FlatBufferBuilder builder, float f3) { builder.addFloat(7, f3, Float.NEGATIVE_INFINITY); } + public static void addDvec(FlatBufferBuilder builder, int dvecOffset) { builder.addOffset(8, dvecOffset, 0); } + public static int createDvecVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } + public static void startDvecVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } + public static void addFvec(FlatBufferBuilder builder, int fvecOffset) { builder.addOffset(9, fvecOffset, 0); } + public static int createFvecVector(FlatBufferBuilder builder, float[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addFloat(data[i]); return builder.endVector(); } + public static void startFvecVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endMonsterExtra(FlatBufferBuilder builder) { int o = builder.endTable(); return o; diff --git a/tests/MyGame/MonsterExtra.py b/tests/MyGame/MonsterExtra.py index 768fb5744..5fcace064 100644 --- a/tests/MyGame/MonsterExtra.py +++ b/tests/MyGame/MonsterExtra.py @@ -19,100 +19,116 @@ class MonsterExtra(object): self._tab = flatbuffers.table.Table(buf, pos) # MonsterExtra - def TestfNan(self): + def D0(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 self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) return float('nan') # MonsterExtra - def TestfPinf(self): + def D1(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 self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return float('nan') + + # MonsterExtra + def D2(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, 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): + def D3(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') # MonsterExtra - def TestfVec(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) + def F0(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12)) if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Float32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4)) - return 0 + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('nan') # MonsterExtra - def TestfVecAsNumpy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) + def F1(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14)) if o != 0: - return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o) - return 0 + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('nan') # MonsterExtra - def TestfVecLength(self): + def F2(self): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) if o != 0: - return self._tab.VectorLen(o) - return 0 + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('inf') # MonsterExtra - def TestdVec(self, j): + def F3(self): o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return float('-inf') + + # MonsterExtra + def Dvec(self, j): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20)) if o != 0: a = self._tab.Vector(o) return self._tab.Get(flatbuffers.number_types.Float64Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8)) return 0 # MonsterExtra - def TestdVecAsNumpy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18)) + def DvecAsNumpy(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20)) if o != 0: return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float64Flags, o) return 0 # MonsterExtra - def TestdVecLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18)) + def DvecLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20)) if o != 0: return self._tab.VectorLen(o) return 0 -def MonsterExtraStart(builder): builder.StartObject(8) -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 MonsterExtraAddTestfVec(builder, testfVec): builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(testfVec), 0) -def MonsterExtraStartTestfVecVector(builder, numElems): return builder.StartVector(4, numElems, 4) -def MonsterExtraAddTestdVec(builder, testdVec): builder.PrependUOffsetTRelativeSlot(7, flatbuffers.number_types.UOffsetTFlags.py_type(testdVec), 0) -def MonsterExtraStartTestdVecVector(builder, numElems): return builder.StartVector(8, numElems, 8) + # MonsterExtra + def Fvec(self, j): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) + if o != 0: + a = self._tab.Vector(o) + return self._tab.Get(flatbuffers.number_types.Float32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4)) + return 0 + + # MonsterExtra + def FvecAsNumpy(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) + if o != 0: + return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o) + return 0 + + # MonsterExtra + def FvecLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + +def MonsterExtraStart(builder): builder.StartObject(10) +def MonsterExtraAddD0(builder, d0): builder.PrependFloat64Slot(0, d0, float('nan')) +def MonsterExtraAddD1(builder, d1): builder.PrependFloat64Slot(1, d1, float('nan')) +def MonsterExtraAddD2(builder, d2): builder.PrependFloat64Slot(2, d2, float('inf')) +def MonsterExtraAddD3(builder, d3): builder.PrependFloat64Slot(3, d3, float('-inf')) +def MonsterExtraAddF0(builder, f0): builder.PrependFloat32Slot(4, f0, float('nan')) +def MonsterExtraAddF1(builder, f1): builder.PrependFloat32Slot(5, f1, float('nan')) +def MonsterExtraAddF2(builder, f2): builder.PrependFloat32Slot(6, f2, float('inf')) +def MonsterExtraAddF3(builder, f3): builder.PrependFloat32Slot(7, f3, float('-inf')) +def MonsterExtraAddDvec(builder, dvec): builder.PrependUOffsetTRelativeSlot(8, flatbuffers.number_types.UOffsetTFlags.py_type(dvec), 0) +def MonsterExtraStartDvecVector(builder, numElems): return builder.StartVector(8, numElems, 8) +def MonsterExtraAddFvec(builder, fvec): builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(fvec), 0) +def MonsterExtraStartFvecVector(builder, numElems): return builder.StartVector(4, numElems, 4) def MonsterExtraEnd(builder): return builder.EndObject() diff --git a/tests/monster_extra.fbs b/tests/monster_extra.fbs index 60a9ab99c..d0fc7feb4 100644 --- a/tests/monster_extra.fbs +++ b/tests/monster_extra.fbs @@ -3,14 +3,16 @@ namespace MyGame; // Not all programming languages support this extra table. table MonsterExtra { // Float-point values with NaN and Inf defaults. - testf_nan:float = nan; - testf_pinf:float = +inf; - testf_ninf:float = -inf; - testd_nan:double = nan; - testd_pinf:double = +inf; - testd_ninf:double = -inf; - testf_vec : [float]; - testd_vec : [double]; + d0:double = nan; + d1:double = -nan; // parser must ignore sign of NaN + d2:double = +inf; + d3:double = -inf; + f0:float = -nan; // parser must ignore sign of NaN + f1:float = +nan; + f2:float = +inf; + f3:float = -inf; + dvec : [double]; + fvec : [float]; } root_type MonsterExtra; diff --git a/tests/monster_extra_generated.h b/tests/monster_extra_generated.h index 13d8a8beb..d7ff90022 100644 --- a/tests/monster_extra_generated.h +++ b/tests/monster_extra_generated.h @@ -18,34 +18,40 @@ inline const flatbuffers::TypeTable *MonsterExtraTypeTable(); 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; - std::vector testf_vec; - std::vector testd_vec; + double d0; + double d1; + double d2; + double d3; + float f0; + float f1; + float f2; + float f3; + std::vector dvec; + std::vector fvec; MonsterExtraT() - : testf_nan(std::numeric_limits::quiet_NaN()), - testf_pinf(std::numeric_limits::infinity()), - testf_ninf(-std::numeric_limits::infinity()), - testd_nan(std::numeric_limits::quiet_NaN()), - testd_pinf(std::numeric_limits::infinity()), - testd_ninf(-std::numeric_limits::infinity()) { + : d0(std::numeric_limits::quiet_NaN()), + d1(std::numeric_limits::quiet_NaN()), + d2(std::numeric_limits::infinity()), + d3(-std::numeric_limits::infinity()), + f0(std::numeric_limits::quiet_NaN()), + f1(std::numeric_limits::quiet_NaN()), + f2(std::numeric_limits::infinity()), + f3(-std::numeric_limits::infinity()) { } }; inline bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs) { return - (lhs.testf_nan == rhs.testf_nan) && - (lhs.testf_pinf == rhs.testf_pinf) && - (lhs.testf_ninf == rhs.testf_ninf) && - (lhs.testd_nan == rhs.testd_nan) && - (lhs.testd_pinf == rhs.testd_pinf) && - (lhs.testd_ninf == rhs.testd_ninf) && - (lhs.testf_vec == rhs.testf_vec) && - (lhs.testd_vec == rhs.testd_vec); + (lhs.d0 == rhs.d0) && + (lhs.d1 == rhs.d1) && + (lhs.d2 == rhs.d2) && + (lhs.d3 == rhs.d3) && + (lhs.f0 == rhs.f0) && + (lhs.f1 == rhs.f1) && + (lhs.f2 == rhs.f2) && + (lhs.f3 == rhs.f3) && + (lhs.dvec == rhs.dvec) && + (lhs.fvec == rhs.fvec); } inline bool operator!=(const MonsterExtraT &lhs, const MonsterExtraT &rhs) { @@ -59,75 +65,91 @@ struct MonsterExtra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return MonsterExtraTypeTable(); } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_TESTF_NAN = 4, - VT_TESTF_PINF = 6, - VT_TESTF_NINF = 8, - VT_TESTD_NAN = 10, - VT_TESTD_PINF = 12, - VT_TESTD_NINF = 14, - VT_TESTF_VEC = 16, - VT_TESTD_VEC = 18 + VT_D0 = 4, + VT_D1 = 6, + VT_D2 = 8, + VT_D3 = 10, + VT_F0 = 12, + VT_F1 = 14, + VT_F2 = 16, + VT_F3 = 18, + VT_DVEC = 20, + VT_FVEC = 22 }; - float testf_nan() const { - return GetField(VT_TESTF_NAN, std::numeric_limits::quiet_NaN()); + double d0() const { + return GetField(VT_D0, std::numeric_limits::quiet_NaN()); } - bool mutate_testf_nan(float _testf_nan) { - return SetField(VT_TESTF_NAN, _testf_nan, std::numeric_limits::quiet_NaN()); + bool mutate_d0(double _d0) { + return SetField(VT_D0, _d0, std::numeric_limits::quiet_NaN()); } - float testf_pinf() const { - return GetField(VT_TESTF_PINF, std::numeric_limits::infinity()); + double d1() const { + return GetField(VT_D1, std::numeric_limits::quiet_NaN()); } - bool mutate_testf_pinf(float _testf_pinf) { - return SetField(VT_TESTF_PINF, _testf_pinf, std::numeric_limits::infinity()); + bool mutate_d1(double _d1) { + return SetField(VT_D1, _d1, std::numeric_limits::quiet_NaN()); } - float testf_ninf() const { - return GetField(VT_TESTF_NINF, -std::numeric_limits::infinity()); + double d2() const { + return GetField(VT_D2, std::numeric_limits::infinity()); } - bool mutate_testf_ninf(float _testf_ninf) { - return SetField(VT_TESTF_NINF, _testf_ninf, -std::numeric_limits::infinity()); + bool mutate_d2(double _d2) { + return SetField(VT_D2, _d2, std::numeric_limits::infinity()); } - double testd_nan() const { - return GetField(VT_TESTD_NAN, std::numeric_limits::quiet_NaN()); + double d3() const { + return GetField(VT_D3, -std::numeric_limits::infinity()); } - bool mutate_testd_nan(double _testd_nan) { - return SetField(VT_TESTD_NAN, _testd_nan, std::numeric_limits::quiet_NaN()); + bool mutate_d3(double _d3) { + return SetField(VT_D3, _d3, -std::numeric_limits::infinity()); } - double testd_pinf() const { - return GetField(VT_TESTD_PINF, std::numeric_limits::infinity()); + float f0() const { + return GetField(VT_F0, std::numeric_limits::quiet_NaN()); } - bool mutate_testd_pinf(double _testd_pinf) { - return SetField(VT_TESTD_PINF, _testd_pinf, std::numeric_limits::infinity()); + bool mutate_f0(float _f0) { + return SetField(VT_F0, _f0, std::numeric_limits::quiet_NaN()); } - double testd_ninf() const { - return GetField(VT_TESTD_NINF, -std::numeric_limits::infinity()); + float f1() const { + return GetField(VT_F1, std::numeric_limits::quiet_NaN()); } - bool mutate_testd_ninf(double _testd_ninf) { - return SetField(VT_TESTD_NINF, _testd_ninf, -std::numeric_limits::infinity()); + bool mutate_f1(float _f1) { + return SetField(VT_F1, _f1, std::numeric_limits::quiet_NaN()); } - const flatbuffers::Vector *testf_vec() const { - return GetPointer *>(VT_TESTF_VEC); + float f2() const { + return GetField(VT_F2, std::numeric_limits::infinity()); } - flatbuffers::Vector *mutable_testf_vec() { - return GetPointer *>(VT_TESTF_VEC); + bool mutate_f2(float _f2) { + return SetField(VT_F2, _f2, std::numeric_limits::infinity()); } - const flatbuffers::Vector *testd_vec() const { - return GetPointer *>(VT_TESTD_VEC); + float f3() const { + return GetField(VT_F3, -std::numeric_limits::infinity()); } - flatbuffers::Vector *mutable_testd_vec() { - return GetPointer *>(VT_TESTD_VEC); + bool mutate_f3(float _f3) { + return SetField(VT_F3, _f3, -std::numeric_limits::infinity()); + } + const flatbuffers::Vector *dvec() const { + return GetPointer *>(VT_DVEC); + } + flatbuffers::Vector *mutable_dvec() { + return GetPointer *>(VT_DVEC); + } + const flatbuffers::Vector *fvec() const { + return GetPointer *>(VT_FVEC); + } + flatbuffers::Vector *mutable_fvec() { + return GetPointer *>(VT_FVEC); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, VT_TESTF_NAN) && - VerifyField(verifier, VT_TESTF_PINF) && - VerifyField(verifier, VT_TESTF_NINF) && - VerifyField(verifier, VT_TESTD_NAN) && - VerifyField(verifier, VT_TESTD_PINF) && - VerifyField(verifier, VT_TESTD_NINF) && - VerifyOffset(verifier, VT_TESTF_VEC) && - verifier.VerifyVector(testf_vec()) && - VerifyOffset(verifier, VT_TESTD_VEC) && - verifier.VerifyVector(testd_vec()) && + VerifyField(verifier, VT_D0) && + VerifyField(verifier, VT_D1) && + VerifyField(verifier, VT_D2) && + VerifyField(verifier, VT_D3) && + VerifyField(verifier, VT_F0) && + VerifyField(verifier, VT_F1) && + VerifyField(verifier, VT_F2) && + VerifyField(verifier, VT_F3) && + VerifyOffset(verifier, VT_DVEC) && + verifier.VerifyVector(dvec()) && + VerifyOffset(verifier, VT_FVEC) && + verifier.VerifyVector(fvec()) && verifier.EndTable(); } MonsterExtraT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -138,29 +160,35 @@ struct MonsterExtra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct MonsterExtraBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_testf_nan(float testf_nan) { - fbb_.AddElement(MonsterExtra::VT_TESTF_NAN, testf_nan, std::numeric_limits::quiet_NaN()); + void add_d0(double d0) { + fbb_.AddElement(MonsterExtra::VT_D0, d0, std::numeric_limits::quiet_NaN()); } - void add_testf_pinf(float testf_pinf) { - fbb_.AddElement(MonsterExtra::VT_TESTF_PINF, testf_pinf, std::numeric_limits::infinity()); + void add_d1(double d1) { + fbb_.AddElement(MonsterExtra::VT_D1, d1, std::numeric_limits::quiet_NaN()); } - void add_testf_ninf(float testf_ninf) { - fbb_.AddElement(MonsterExtra::VT_TESTF_NINF, testf_ninf, -std::numeric_limits::infinity()); + void add_d2(double d2) { + fbb_.AddElement(MonsterExtra::VT_D2, d2, std::numeric_limits::infinity()); } - void add_testd_nan(double testd_nan) { - fbb_.AddElement(MonsterExtra::VT_TESTD_NAN, testd_nan, std::numeric_limits::quiet_NaN()); + void add_d3(double d3) { + fbb_.AddElement(MonsterExtra::VT_D3, d3, -std::numeric_limits::infinity()); } - void add_testd_pinf(double testd_pinf) { - fbb_.AddElement(MonsterExtra::VT_TESTD_PINF, testd_pinf, std::numeric_limits::infinity()); + void add_f0(float f0) { + fbb_.AddElement(MonsterExtra::VT_F0, f0, std::numeric_limits::quiet_NaN()); } - void add_testd_ninf(double testd_ninf) { - fbb_.AddElement(MonsterExtra::VT_TESTD_NINF, testd_ninf, -std::numeric_limits::infinity()); + void add_f1(float f1) { + fbb_.AddElement(MonsterExtra::VT_F1, f1, std::numeric_limits::quiet_NaN()); } - void add_testf_vec(flatbuffers::Offset> testf_vec) { - fbb_.AddOffset(MonsterExtra::VT_TESTF_VEC, testf_vec); + void add_f2(float f2) { + fbb_.AddElement(MonsterExtra::VT_F2, f2, std::numeric_limits::infinity()); } - void add_testd_vec(flatbuffers::Offset> testd_vec) { - fbb_.AddOffset(MonsterExtra::VT_TESTD_VEC, testd_vec); + void add_f3(float f3) { + fbb_.AddElement(MonsterExtra::VT_F3, f3, -std::numeric_limits::infinity()); + } + void add_dvec(flatbuffers::Offset> dvec) { + fbb_.AddOffset(MonsterExtra::VT_DVEC, dvec); + } + void add_fvec(flatbuffers::Offset> fvec) { + fbb_.AddOffset(MonsterExtra::VT_FVEC, fvec); } explicit MonsterExtraBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { @@ -176,48 +204,56 @@ struct MonsterExtraBuilder { inline flatbuffers::Offset CreateMonsterExtra( flatbuffers::FlatBufferBuilder &_fbb, - float testf_nan = std::numeric_limits::quiet_NaN(), - float testf_pinf = std::numeric_limits::infinity(), - float testf_ninf = -std::numeric_limits::infinity(), - double testd_nan = std::numeric_limits::quiet_NaN(), - double testd_pinf = std::numeric_limits::infinity(), - double testd_ninf = -std::numeric_limits::infinity(), - flatbuffers::Offset> testf_vec = 0, - flatbuffers::Offset> testd_vec = 0) { + double d0 = std::numeric_limits::quiet_NaN(), + double d1 = std::numeric_limits::quiet_NaN(), + double d2 = std::numeric_limits::infinity(), + double d3 = -std::numeric_limits::infinity(), + float f0 = std::numeric_limits::quiet_NaN(), + float f1 = std::numeric_limits::quiet_NaN(), + float f2 = std::numeric_limits::infinity(), + float f3 = -std::numeric_limits::infinity(), + flatbuffers::Offset> dvec = 0, + flatbuffers::Offset> fvec = 0) { MonsterExtraBuilder builder_(_fbb); - builder_.add_testd_ninf(testd_ninf); - builder_.add_testd_pinf(testd_pinf); - builder_.add_testd_nan(testd_nan); - builder_.add_testd_vec(testd_vec); - builder_.add_testf_vec(testf_vec); - builder_.add_testf_ninf(testf_ninf); - builder_.add_testf_pinf(testf_pinf); - builder_.add_testf_nan(testf_nan); + builder_.add_d3(d3); + builder_.add_d2(d2); + builder_.add_d1(d1); + builder_.add_d0(d0); + builder_.add_fvec(fvec); + builder_.add_dvec(dvec); + builder_.add_f3(f3); + builder_.add_f2(f2); + builder_.add_f1(f1); + builder_.add_f0(f0); return builder_.Finish(); } inline flatbuffers::Offset CreateMonsterExtraDirect( flatbuffers::FlatBufferBuilder &_fbb, - float testf_nan = std::numeric_limits::quiet_NaN(), - float testf_pinf = std::numeric_limits::infinity(), - float testf_ninf = -std::numeric_limits::infinity(), - double testd_nan = std::numeric_limits::quiet_NaN(), - double testd_pinf = std::numeric_limits::infinity(), - double testd_ninf = -std::numeric_limits::infinity(), - const std::vector *testf_vec = nullptr, - const std::vector *testd_vec = nullptr) { - auto testf_vec__ = testf_vec ? _fbb.CreateVector(*testf_vec) : 0; - auto testd_vec__ = testd_vec ? _fbb.CreateVector(*testd_vec) : 0; + double d0 = std::numeric_limits::quiet_NaN(), + double d1 = std::numeric_limits::quiet_NaN(), + double d2 = std::numeric_limits::infinity(), + double d3 = -std::numeric_limits::infinity(), + float f0 = std::numeric_limits::quiet_NaN(), + float f1 = std::numeric_limits::quiet_NaN(), + float f2 = std::numeric_limits::infinity(), + float f3 = -std::numeric_limits::infinity(), + const std::vector *dvec = nullptr, + const std::vector *fvec = nullptr) { + auto dvec__ = dvec ? _fbb.CreateVector(*dvec) : 0; + auto fvec__ = fvec ? _fbb.CreateVector(*fvec) : 0; return MyGame::CreateMonsterExtra( _fbb, - testf_nan, - testf_pinf, - testf_ninf, - testd_nan, - testd_pinf, - testd_ninf, - testf_vec__, - testd_vec__); + d0, + d1, + d2, + d3, + f0, + f1, + f2, + f3, + dvec__, + fvec__); } flatbuffers::Offset CreateMonsterExtra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -231,14 +267,16 @@ inline MonsterExtraT *MonsterExtra::UnPack(const flatbuffers::resolver_function_ 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; }; - { auto _e = testf_pinf(); _o->testf_pinf = _e; }; - { auto _e = testf_ninf(); _o->testf_ninf = _e; }; - { auto _e = testd_nan(); _o->testd_nan = _e; }; - { auto _e = testd_pinf(); _o->testd_pinf = _e; }; - { auto _e = testd_ninf(); _o->testd_ninf = _e; }; - { auto _e = testf_vec(); if (_e) { _o->testf_vec.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testf_vec[_i] = _e->Get(_i); } } }; - { auto _e = testd_vec(); if (_e) { _o->testd_vec.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testd_vec[_i] = _e->Get(_i); } } }; + { auto _e = d0(); _o->d0 = _e; }; + { auto _e = d1(); _o->d1 = _e; }; + { auto _e = d2(); _o->d2 = _e; }; + { auto _e = d3(); _o->d3 = _e; }; + { auto _e = f0(); _o->f0 = _e; }; + { auto _e = f1(); _o->f1 = _e; }; + { auto _e = f2(); _o->f2 = _e; }; + { auto _e = f3(); _o->f3 = _e; }; + { auto _e = dvec(); if (_e) { _o->dvec.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->dvec[_i] = _e->Get(_i); } } }; + { auto _e = fvec(); if (_e) { _o->fvec.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fvec[_i] = _e->Get(_i); } } }; } inline flatbuffers::Offset MonsterExtra::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT* _o, const flatbuffers::rehasher_function_t *_rehasher) { @@ -249,49 +287,57 @@ inline flatbuffers::Offset CreateMonsterExtra(flatbuffers::FlatBuf (void)_rehasher; (void)_o; 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; - auto _testf_vec = _o->testf_vec.size() ? _fbb.CreateVector(_o->testf_vec) : 0; - auto _testd_vec = _o->testd_vec.size() ? _fbb.CreateVector(_o->testd_vec) : 0; + auto _d0 = _o->d0; + auto _d1 = _o->d1; + auto _d2 = _o->d2; + auto _d3 = _o->d3; + auto _f0 = _o->f0; + auto _f1 = _o->f1; + auto _f2 = _o->f2; + auto _f3 = _o->f3; + auto _dvec = _o->dvec.size() ? _fbb.CreateVector(_o->dvec) : 0; + auto _fvec = _o->fvec.size() ? _fbb.CreateVector(_o->fvec) : 0; return MyGame::CreateMonsterExtra( _fbb, - _testf_nan, - _testf_pinf, - _testf_ninf, - _testd_nan, - _testd_pinf, - _testd_ninf, - _testf_vec, - _testd_vec); + _d0, + _d1, + _d2, + _d3, + _f0, + _f1, + _f2, + _f3, + _dvec, + _fvec); } inline const flatbuffers::TypeTable *MonsterExtraTypeTable() { static const flatbuffers::TypeCode type_codes[] = { - { flatbuffers::ET_FLOAT, 0, -1 }, - { flatbuffers::ET_FLOAT, 0, -1 }, - { flatbuffers::ET_FLOAT, 0, -1 }, { flatbuffers::ET_DOUBLE, 0, -1 }, { flatbuffers::ET_DOUBLE, 0, -1 }, { flatbuffers::ET_DOUBLE, 0, -1 }, - { flatbuffers::ET_FLOAT, 1, -1 }, - { flatbuffers::ET_DOUBLE, 1, -1 } + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_DOUBLE, 1, -1 }, + { flatbuffers::ET_FLOAT, 1, -1 } }; static const char * const names[] = { - "testf_nan", - "testf_pinf", - "testf_ninf", - "testd_nan", - "testd_pinf", - "testd_ninf", - "testf_vec", - "testd_vec" + "d0", + "d1", + "d2", + "d3", + "f0", + "f1", + "f2", + "f3", + "dvec", + "fvec" }; static const flatbuffers::TypeTable tt = { - flatbuffers::ST_TABLE, 8, type_codes, nullptr, nullptr, names + flatbuffers::ST_TABLE, 10, type_codes, nullptr, nullptr, names }; return &tt; } diff --git a/tests/monsterdata_extra.json b/tests/monsterdata_extra.json index e290d478c..53045cdd5 100644 --- a/tests/monsterdata_extra.json +++ b/tests/monsterdata_extra.json @@ -1,11 +1,15 @@ { - // Float-point values with NaN and Inf defaults. - testf_nan : nan, - testf_pinf : +inf, - testf_ninf : -inf, - testd_nan : nan, - testd_pinf : +inf, - testd_ninf : -inf, - testf_vec : [-1.0, 2.0, -inf, +inf, nan], - testd_vec : [-1.0, 4.0, -inf, +inf, nan] + // Initialize with non-default values. + d0 : -nan, // match with default + d1 : +inf, + d2 : -inf, + d3: nan, + f0 : +nan, // match with default + f1 : -nan, // match with default + f2 : +inf, // match with default + f3 : -inf, // match with default + // Values should have exact binary representation + // to avoid rounding effects in tests. + dvec : [2.0, +inf, -inf, nan,], + fvec : [1.0, -inf, +inf, nan], } diff --git a/tests/py_test.py b/tests/py_test.py index e7f72782e..d640d3b3f 100644 --- a/tests/py_test.py +++ b/tests/py_test.py @@ -1412,13 +1412,13 @@ class TestAllCodePathsOfMonsterExtraSchema(unittest.TestCase): 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.F1())) + self.assertEqual(self.mon.F2(), float("inf")) + self.assertEqual(self.mon.F3(), float("-inf")) - self.assertTrue(math.isnan(self.mon.TestdNan())) - self.assertEqual(self.mon.TestdPinf(), float("inf")) - self.assertEqual(self.mon.TestdNinf(), float("-inf")) + self.assertTrue(math.isnan(self.mon.D1())) + self.assertEqual(self.mon.D2(), float("inf")) + self.assertEqual(self.mon.D3(), float("-inf")) class TestVtableDeduplication(unittest.TestCase): diff --git a/tests/test.cpp b/tests/test.cpp index c70bbeb28..903c58df7 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -41,6 +41,25 @@ #include "flatbuffers/flexbuffers.h" +// clang-format off +// Check that char* and uint8_t* are interoperable types. +// The reinterpret_cast<> between the pointers are used to simplify data loading. +static_assert(flatbuffers::is_same::value || + flatbuffers::is_same::value, + "unexpected uint8_t type"); + +#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) + // Ensure IEEE-754 support if tests of floats with NaN/Inf will run. + static_assert(std::numeric_limits::is_iec559 && + std::numeric_limits::is_iec559, + "IEC-559 (IEEE-754) standard required"); +#endif +// clang-format on + +// Shortcuts for the infinity. +static const auto infinityf = std::numeric_limits::infinity(); +static const auto infinityd = std::numeric_limits::infinity(); + using namespace MyGame::Example; void FlatBufferBuilderTest(); @@ -601,36 +620,105 @@ void JsonDefaultTest() { TEST_EQ(std::string::npos != jsongen.find("testf: 3.14159"), true); } -#if defined(FLATBUFFERS_HAS_NEW_STRTOD) +#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) +// The IEEE-754 quiet_NaN is not simple binary constant. +// All binary NaN bit strings have all the bits of the biased exponent field E +// set to 1. A quiet NaN bit string should be encoded with the first bit d[1] +// of the trailing significand field T being 1 (d[0] is implicit bit). +// It is assumed that endianness of floating-point is same as integer. +template bool is_quiet_nan_impl(T v) { + static_assert(sizeof(T) == sizeof(U), "unexpected"); + U b = 0; + std::memcpy(&b, &v, sizeof(T)); + return ((b & qnan_base) == qnan_base); +} +static bool is_quiet_nan(float v) { + return is_quiet_nan_impl(v); +} +static bool is_quiet_nan(double v) { + return is_quiet_nan_impl(v); +} + void TestMonsterExtraFloats() { + TEST_EQ(is_quiet_nan(1.0), false); + TEST_EQ(is_quiet_nan(infinityd), false); + TEST_EQ(is_quiet_nan(-infinityf), false); + TEST_EQ(is_quiet_nan(std::numeric_limits::quiet_NaN()), true); + TEST_EQ(is_quiet_nan(std::numeric_limits::quiet_NaN()), true); + + using namespace flatbuffers; using namespace MyGame; // Load FlatBuffer schema (.fbs) from disk. std::string schemafile; - TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_extra.fbs").c_str(), - false, &schemafile), + TEST_EQ(LoadFile((test_data_path + "monster_extra.fbs").c_str(), false, + &schemafile), true); // Parse schema first, so we can use it to parse the data after. - flatbuffers::Parser parser; - auto include_test_path = - flatbuffers::ConCatPathFileName(test_data_path, "include_test"); + Parser parser; + auto include_test_path = ConCatPathFileName(test_data_path, "include_test"); const char *include_directories[] = { test_data_path.c_str(), include_test_path.c_str(), nullptr }; TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true); // Create empty extra and store to json. parser.opts.output_default_scalars_in_json = true; parser.opts.output_enum_identifiers = true; - flatbuffers::FlatBufferBuilder builder; - MonsterExtraBuilder extra(builder); - FinishMonsterExtraBuffer(builder, extra.Finish()); + FlatBufferBuilder builder; + const auto def_root = MonsterExtraBuilder(builder).Finish(); + FinishMonsterExtraBuffer(builder, def_root); + const auto def_obj = builder.GetBufferPointer(); + const auto def_extra = GetMonsterExtra(def_obj); + TEST_NOTNULL(def_extra); + TEST_EQ(is_quiet_nan(def_extra->f0()), true); + TEST_EQ(is_quiet_nan(def_extra->f1()), true); + TEST_EQ(def_extra->f2(), +infinityf); + TEST_EQ(def_extra->f3(), -infinityf); + TEST_EQ(is_quiet_nan(def_extra->d0()), true); + TEST_EQ(is_quiet_nan(def_extra->d1()), true); + TEST_EQ(def_extra->d2(), +infinityd); + TEST_EQ(def_extra->d3(), -infinityd); std::string jsongen; - auto result = GenerateText(parser, builder.GetBufferPointer(), &jsongen); + auto result = GenerateText(parser, def_obj, &jsongen); TEST_EQ(result, true); - TEST_EQ(std::string::npos != jsongen.find("testf_nan: nan"), true); - TEST_EQ(std::string::npos != jsongen.find("testf_pinf: inf"), true); - TEST_EQ(std::string::npos != jsongen.find("testf_ninf: -inf"), true); - TEST_EQ(std::string::npos != jsongen.find("testd_nan: nan"), true); - TEST_EQ(std::string::npos != jsongen.find("testd_pinf: inf"), true); - TEST_EQ(std::string::npos != jsongen.find("testd_ninf: -inf"), true); + // Check expected default values. + TEST_EQ(std::string::npos != jsongen.find("f0: nan"), true); + TEST_EQ(std::string::npos != jsongen.find("f1: nan"), true); + TEST_EQ(std::string::npos != jsongen.find("f2: inf"), true); + TEST_EQ(std::string::npos != jsongen.find("f3: -inf"), true); + TEST_EQ(std::string::npos != jsongen.find("d0: nan"), true); + TEST_EQ(std::string::npos != jsongen.find("d1: nan"), true); + TEST_EQ(std::string::npos != jsongen.find("d2: inf"), true); + TEST_EQ(std::string::npos != jsongen.find("d3: -inf"), true); + // Parse 'mosterdata_extra.json'. + const auto extra_base = test_data_path + "monsterdata_extra"; + jsongen = ""; + TEST_EQ(LoadFile((extra_base + ".json").c_str(), false, &jsongen), true); + TEST_EQ(parser.Parse(jsongen.c_str()), true); + const auto test_file = parser.builder_.GetBufferPointer(); + const auto test_size = parser.builder_.GetSize(); + Verifier verifier(test_file, test_size); + TEST_ASSERT(VerifyMonsterExtraBuffer(verifier)); + const auto extra = GetMonsterExtra(test_file); + TEST_NOTNULL(extra); + TEST_EQ(is_quiet_nan(extra->f0()), true); + TEST_EQ(is_quiet_nan(extra->f1()), true); + TEST_EQ(extra->f2(), +infinityf); + TEST_EQ(extra->f3(), -infinityf); + TEST_EQ(is_quiet_nan(extra->d0()), true); + TEST_EQ(extra->d1(), +infinityd); + TEST_EQ(extra->d2(), -infinityd); + TEST_EQ(is_quiet_nan(extra->d3()), true); + TEST_NOTNULL(extra->fvec()); + TEST_EQ(extra->fvec()->size(), 4); + TEST_EQ(extra->fvec()->Get(0), 1.0f); + TEST_EQ(extra->fvec()->Get(1), -infinityf); + TEST_EQ(extra->fvec()->Get(2), +infinityf); + TEST_EQ(is_quiet_nan(extra->fvec()->Get(3)), true); + TEST_NOTNULL(extra->dvec()); + TEST_EQ(extra->dvec()->size(), 4); + TEST_EQ(extra->dvec()->Get(0), 2.0); + TEST_EQ(extra->dvec()->Get(1), +infinityd); + TEST_EQ(extra->dvec()->Get(2), -infinityd); + TEST_EQ(is_quiet_nan(extra->dvec()->Get(3)), true); } #else void TestMonsterExtraFloats() {} @@ -1663,8 +1751,6 @@ void IntegerBoundaryTest() { } void ValidFloatTest() { - const auto infinityf = flatbuffers::numeric_limits::infinity(); - const auto infinityd = flatbuffers::numeric_limits::infinity(); // check rounding to infinity TEST_EQ(TestValue("{ Y:+3.4029e+38 }", "float"), +infinityf); TEST_EQ(TestValue("{ Y:-3.4029e+38 }", "float"), -infinityf); @@ -1694,7 +1780,7 @@ void ValidFloatTest() { TEST_EQ(TestValue("{ Y:5 }", "float"), 5.0f); TEST_EQ(TestValue("{ Y:\"5\" }", "float"), 5.0f); - #if defined(FLATBUFFERS_HAS_NEW_STRTOD) + #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) // Old MSVC versions may have problem with this check. // https://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ TEST_EQ(TestValue("{ Y:6.9294956446009195e15 }", "double"), @@ -1740,7 +1826,7 @@ void ValidFloatTest() { #else // FLATBUFFERS_HAS_NEW_STRTOD TEST_OUTPUT_LINE("FLATBUFFERS_HAS_NEW_STRTOD tests skipped"); -#endif // FLATBUFFERS_HAS_NEW_STRTOD +#endif // !FLATBUFFERS_HAS_NEW_STRTOD } void InvalidFloatTest() {