Add NaN and Inf defaults to the C++ generated code. (#5102)

* Add `NaN` and `Inf` defaults to the C++ generated code.

* Refactoring: add FloatConstantGenerator

* Refactoring-2:

- remove isnan checking for all float/double values
- add most probable implementation of virtual methods of FloatConstantGenerator

* Add conditional (FLATBUFFERS_NAN_DEFAULTS) isnan checking
This commit is contained in:
Vladimir Glavnyy
2019-01-08 01:04:44 +07:00
committed by Wouter van Oortmerssen
parent 155c55900f
commit dd288f71f3
10 changed files with 379 additions and 5 deletions

View File

@@ -19,6 +19,8 @@
#include "flatbuffers/base.h"
#include "flatbuffers/util.h"
#include <cmath>
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4127) // C4127: conditional expression is constant
@@ -157,6 +159,35 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
}
}
template<typename T>
std::string FloatConstantGenerator::GenFloatConstantImpl(
const FieldDef &field) const {
const auto &constant = field.value.constant;
T v;
auto done = StringToNumber(constant.c_str(), &v);
FLATBUFFERS_ASSERT(done);
if (done) {
#if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
if (std::isnan(v)) return NaN(v);
if (std::isinf(v)) return Inf(v);
#endif
return Value(v, constant);
}
return "#"; // compile time error
}
std::string FloatConstantGenerator::GenFloatConstant(
const FieldDef &field) const {
switch (field.value.type.base_type) {
case BASE_TYPE_FLOAT: return GenFloatConstantImpl<float>(field);
case BASE_TYPE_DOUBLE: return GenFloatConstantImpl<double>(field);
default: {
FLATBUFFERS_ASSERT(false);
return "INVALID_BASE_TYPE";
}
};
}
} // namespace flatbuffers
#if defined(_MSC_VER)

View File

@@ -34,6 +34,44 @@ static std::string GeneratedFileName(const std::string &path,
}
namespace cpp {
class CppFloatConstantGenerator : public FloatConstantGenerator {
protected:
std::string Value(double v,
const std::string &src) const FLATBUFFERS_OVERRIDE {
(void)v;
return src;
};
std::string Value(float v,
const std::string &src) const FLATBUFFERS_OVERRIDE {
(void)v;
return src + "f";
}
std::string NaN(double v) const FLATBUFFERS_OVERRIDE {
(void)v;
return "std::numeric_limits<double>::quiet_NaN()";
}
std::string NaN(float v) const FLATBUFFERS_OVERRIDE {
(void)v;
return "std::numeric_limits<float>::quiet_NaN()";
}
std::string Inf(double v) const FLATBUFFERS_OVERRIDE {
if(v < 0)
return "-std::numeric_limits<double>::infinity()";
else
return "std::numeric_limits<double>::infinity()";
}
std::string Inf(float v) const FLATBUFFERS_OVERRIDE {
if (v < 0)
return "-std::numeric_limits<float>::infinity()";
else
return "std::numeric_limits<float>::infinity()";
}
};
class CppGenerator : public BaseGenerator {
public:
CppGenerator(const Parser &parser, const std::string &path,
@@ -1392,9 +1430,10 @@ class CppGenerator : public BaseGenerator {
}
std::string GenDefaultConstant(const FieldDef &field) {
return field.value.type.base_type == BASE_TYPE_FLOAT
? field.value.constant + "f"
: field.value.constant;
if(IsFloat(field.value.type.base_type))
return float_const_gen_.GenFloatConstant(field);
else
return field.value.constant;
}
std::string GetDefaultScalarValue(const FieldDef &field, bool is_ctor) {
@@ -2745,6 +2784,8 @@ class CppGenerator : public BaseGenerator {
cur_name_space_ = ns;
}
const CppFloatConstantGenerator float_const_gen_;
};
} // namespace cpp