parent
3cb5733ec0
commit
8b4c999888
@ -788,6 +788,29 @@ public:
|
||||
bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
|
||||
bool IsString() const { return (flags_ & kStringFlag) != 0; }
|
||||
|
||||
// Checks whether a number can be losslessly converted to a double.
|
||||
bool IsLosslessDouble() const {
|
||||
if (!IsNumber()) return false;
|
||||
if (IsUint64()) return static_cast<uint64_t>(static_cast<double>(GetUint64())) == GetUint64();
|
||||
if (IsInt64()) return static_cast< int64_t>(static_cast<double>(GetInt64())) == GetInt64();
|
||||
return true; // double, int, uint are always lossless
|
||||
}
|
||||
|
||||
// Checks whether a number is a float (possible lossy).
|
||||
bool IsFloat() const {
|
||||
if ((flags_ & kDoubleFlag) == 0)
|
||||
return false;
|
||||
double d = GetDouble();
|
||||
return d >= -3.4028234e38 && d <= 3.4028234e38;
|
||||
}
|
||||
// Checks whether a number can be losslessly converted to a float.
|
||||
bool IsLosslessFloat() const {
|
||||
if (!IsNumber()) return false;
|
||||
double a = GetDouble();
|
||||
double b = static_cast<double>(static_cast<float>(a));
|
||||
return a >= b && a <= b; // Prevent -Wfloat-equal
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Null
|
||||
@ -1445,6 +1468,9 @@ public:
|
||||
int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
|
||||
uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
|
||||
|
||||
//! Get the value as double type.
|
||||
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
|
||||
*/
|
||||
double GetDouble() const {
|
||||
RAPIDJSON_ASSERT(IsNumber());
|
||||
if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
|
||||
@ -1454,11 +1480,19 @@ public:
|
||||
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
|
||||
}
|
||||
|
||||
//! Get the value as double type.
|
||||
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
|
||||
*/
|
||||
double GetFloat() const {
|
||||
return static_cast<float>(GetDouble());
|
||||
}
|
||||
|
||||
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
|
||||
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
|
||||
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
|
||||
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
|
||||
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
|
||||
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
|
@ -579,6 +579,54 @@ TEST(Value, Double) {
|
||||
EXPECT_NEAR(56.78, z.GetDouble(), 0.0);
|
||||
}
|
||||
|
||||
TEST(Value, Float) {
|
||||
// Constructor with double
|
||||
Value x(12.34f);
|
||||
EXPECT_EQ(kNumberType, x.GetType());
|
||||
EXPECT_NEAR(12.34f, x.GetFloat(), 0.0);
|
||||
EXPECT_TRUE(x.IsNumber());
|
||||
EXPECT_TRUE(x.IsDouble());
|
||||
EXPECT_TRUE(x.IsFloat());
|
||||
|
||||
EXPECT_FALSE(x.IsInt());
|
||||
EXPECT_FALSE(x.IsNull());
|
||||
EXPECT_FALSE(x.IsBool());
|
||||
EXPECT_FALSE(x.IsFalse());
|
||||
EXPECT_FALSE(x.IsTrue());
|
||||
EXPECT_FALSE(x.IsString());
|
||||
EXPECT_FALSE(x.IsObject());
|
||||
EXPECT_FALSE(x.IsArray());
|
||||
|
||||
// SetFloat()
|
||||
Value z;
|
||||
z.SetFloat(12.34f);
|
||||
EXPECT_NEAR(12.34f, z.GetFloat(), 0.0f);
|
||||
|
||||
z = 56.78f;
|
||||
EXPECT_NEAR(56.78f, z.GetFloat(), 0.0f);
|
||||
}
|
||||
|
||||
TEST(Value, IsLosslessDouble) {
|
||||
EXPECT_TRUE(Value(12.34).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(-123).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(2147483648u).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble());
|
||||
|
||||
EXPECT_FALSE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble());
|
||||
EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble());
|
||||
}
|
||||
|
||||
TEST(Value, IsLosslessFloat) {
|
||||
EXPECT_TRUE(Value(12.25).IsLosslessFloat());
|
||||
EXPECT_TRUE(Value(-123).IsLosslessFloat());
|
||||
EXPECT_TRUE(Value(2147483648u).IsLosslessFloat());
|
||||
EXPECT_TRUE(Value(3.4028234e38f).IsLosslessFloat());
|
||||
EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessFloat());
|
||||
EXPECT_FALSE(Value(3.4028235e38).IsLosslessFloat());
|
||||
EXPECT_FALSE(Value(0.3).IsLosslessFloat());
|
||||
}
|
||||
|
||||
TEST(Value, String) {
|
||||
// Construction with const string
|
||||
Value x("Hello", 5); // literal
|
||||
|
Loading…
x
Reference in New Issue
Block a user