Reworked the type conversion system again, so that:A

*  isFoo methods determine exact representability.
 *  asFoo methods cause casting when safe.
 *  isConvertibleTo indicates whether casting is safe.

See NEWS.txt for details.
This commit is contained in:
Aaron Jacobs 2011-05-26 02:46:28 +00:00
parent b0ec41c3e3
commit c025697ea5
4 changed files with 518 additions and 91 deletions

View File

@ -1,22 +1,36 @@
New in SVN:
-----------
New in SVN
----------
* Value
* Updated the type system's behavior, in order to better support backwards
compatibility with code that was written before 64-bit integer support was
introduced. Here's how it works now:
- Updated the Value::isFoo methods to work as follows:
* isInt, isInt64, isUInt, and isUInt64 return true if and only if the
value can be exactly represented as that type. In particular, a value
constructed with a double like 17.0 will now return true for all of
these methods.
* isInt, isInt64, isUInt, and isUInt64 return true if and only if the
value can be exactly representable as that type. In particular, a value
constructed with a double like 17.0 will now return true for all of
these methods.
* isDouble and isFloat now return true for all numeric values, since all
numeric values can be converted to a double or float without
truncation. Note however that the conversion may not be exact -- for
example, doubles cannot exactly represent all integers above 2^53 + 1.
* isDouble and isFloat now return true for all numeric values, since all
numeric values can be converted to a double or float without
truncation. Note that the conversion may not be exact -- for example,
doubles cannot exactly represent integers above 2^53.
* isBool, isNull, isString, isArray, and isObject now return true if and
only if the value is of that type.
* isConvertibleTo(fooValue) indicates that it is safe to call asFoo.
(For each type foo, isFoo always implies isConvertibleTo(fooValue).)
asFoo returns an approximate or exact representation as appropriate.
For example, a double value may be truncated when asInt is called.
* For backwards compatibility with old code, isConvertibleTo(intValue)
may return false even if type() == intValue. This is because the value
may have been constructed with a 64-bit integer larger than maxInt,
and calling asInt() would cause an exception. If you're writing new
code, use isInt64 to find out whether the value is exactly
representable using an Int64, or asDouble() combined with minInt64 and
maxInt64 to figure out whether it is approximately representable.
* isBool, isNull, isString, isArray, and isObject now return true if and
only if the value is of that type.
New in JsonCpp 0.6.0:
---------------------

View File

@ -13,6 +13,7 @@
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <math.h>
#include <iostream>
#include <sstream>
#include <utility>
#include <stdexcept>
#include <cstring>
@ -43,6 +44,11 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
/// Unknown size marker
static const unsigned int unknown = (unsigned)-1;
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
return d >= min && d <= max;
}
/** Duplicates the specified string value.
* @param value Pointer to the string to duplicate. Must be zero-terminated if
@ -663,6 +669,9 @@ Value::asCString() const
std::string
Value::asString() const
{
// Let the STL sort it out for numeric types.
std::ostringstream oss;
switch ( type_ )
{
case nullValue:
@ -672,15 +681,18 @@ Value::asString() const
case booleanValue:
return value_.bool_ ? "true" : "false";
case intValue:
oss << value_.int_;
break;
case uintValue:
oss << value_.uint_;
break;
case realValue:
case arrayValue:
case objectValue:
JSON_FAIL_MESSAGE( "Type is not convertible to string" );
oss << value_.real_;
break;
default:
JSON_ASSERT_UNREACHABLE;
JSON_FAIL_MESSAGE( "Type is not convertible to string" );
}
return ""; // unreachable
return oss.str();
}
# ifdef JSON_USE_CPPTL
@ -695,17 +707,23 @@ Value::asConstString() const
Value::Int
Value::asInt() const
{
JSON_ASSERT_MESSAGE(isInt(), "Value is not convertible to Int");
switch ( type_ )
{
case intValue:
JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
return Int(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
return Int(value_.uint_);
case realValue:
return Int( value_.real_ );
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), "double out of Int range");
return Int(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
JSON_FAIL_MESSAGE("Value is not convertible to Int.");
}
JSON_ASSERT_UNREACHABLE;
return 0;
@ -715,17 +733,23 @@ Value::asInt() const
Value::UInt
Value::asUInt() const
{
JSON_ASSERT_MESSAGE(isUInt(), "Value is not convertible to UInt");
switch ( type_ )
{
case intValue:
JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
return UInt(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
return UInt(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), "double out of UInt range");
return UInt( value_.real_ );
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
}
JSON_ASSERT_UNREACHABLE;
return 0;
@ -737,17 +761,22 @@ Value::asUInt() const
Value::Int64
Value::asInt64() const
{
JSON_ASSERT_MESSAGE(isInt64(), "Value is not convertible to Int64");
switch ( type_ )
{
case intValue:
return Int64(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
return Int64(value_.uint_);
case realValue:
return Int64( value_.real_ );
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), "double out of Int64 range");
return Int64(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
}
JSON_ASSERT_UNREACHABLE;
return 0;
@ -757,15 +786,20 @@ Value::asInt64() const
Value::UInt64
Value::asUInt64() const
{
JSON_ASSERT_MESSAGE(isUInt64(), "Value is not convertible to UInt64");
switch ( type_ )
{
case intValue:
JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
return UInt64(value_.int_);
case uintValue:
return UInt64(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), "double out of UInt64 range");
return UInt64( value_.real_ );
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
}
@ -814,13 +848,11 @@ Value::asDouble() const
case realValue:
return value_.real_;
case nullValue:
return 0.0;
case booleanValue:
case stringValue:
case arrayValue:
case objectValue:
JSON_FAIL_MESSAGE( "Value is not a double" );
return value_.bool_ ? 1.0 : 0.0;
default:
JSON_ASSERT_UNREACHABLE;
JSON_FAIL_MESSAGE("Value is not convertible to double.");
}
return 0; // unreachable;
}
@ -841,15 +873,14 @@ Value::asFloat() const
case realValue:
return static_cast<float>( value_.real_ );
case nullValue:
return 0.0;
case booleanValue:
case stringValue:
case arrayValue:
case objectValue:
JSON_FAIL_MESSAGE( "Value is not a float" );
return value_.bool_ ? 1.0 : 0.0;
default:
JSON_ASSERT_UNREACHABLE;
JSON_FAIL_MESSAGE("Value is not convertible to float.");
}
return 0.0f; // unreachable;
JSON_ASSERT_UNREACHABLE;
return 0.0f;
}
bool
@ -860,68 +891,67 @@ Value::asBool() const
case booleanValue:
return value_.bool_;
case nullValue:
return false;
case intValue:
return value_.int_ ? true : false;
case uintValue:
return value_.uint_ ? true : false;
case realValue:
case stringValue:
case arrayValue:
case objectValue:
JSON_FAIL_MESSAGE( "Value is not a bool" );
return value_.real_ ? true : false;
default:
JSON_ASSERT_UNREACHABLE;
JSON_FAIL_MESSAGE("Value is not convertible to bool.");
}
return false; // unreachable;
JSON_ASSERT_UNREACHABLE;
return false;
}
bool
Value::isConvertibleTo( ValueType other ) const
{
switch ( type_ )
switch ( other )
{
case nullValue:
return true;
return ( isNumeric() && asDouble() == 0.0 )
|| ( type_ == booleanValue && value_.bool_ == false )
|| ( type_ == stringValue && asString() == "" )
|| ( type_ == arrayValue && value_.map_->size() == 0 )
|| ( type_ == objectValue && value_.map_->size() == 0 )
|| type_ == nullValue;
case intValue:
return ( other == nullValue && value_.int_ == 0 )
|| other == intValue
|| ( other == uintValue && value_.int_ >= 0 )
|| other == realValue
|| other == stringValue
|| other == booleanValue;
return isInt()
|| (type_ == realValue && InRange(value_.real_, minInt, maxInt))
|| type_ == booleanValue
|| type_ == nullValue;
case uintValue:
return ( other == nullValue && value_.uint_ == 0 )
|| ( other == intValue && value_.uint_ <= (LargestUInt)maxInt )
|| other == uintValue
|| other == realValue
|| other == stringValue
|| other == booleanValue;
return isUInt()
|| (type_ == realValue && InRange(value_.real_, 0, maxUInt))
|| type_ == booleanValue
|| type_ == nullValue;
case realValue:
return ( other == nullValue && value_.real_ == 0.0 )
|| ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
|| ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
|| other == realValue
|| other == stringValue
|| other == booleanValue;
return isNumeric()
|| type_ == booleanValue
|| type_ == nullValue;
case booleanValue:
return ( other == nullValue && value_.bool_ == false )
|| other == intValue
|| other == uintValue
|| other == realValue
|| other == stringValue
|| other == booleanValue;
return isNumeric()
|| type_ == booleanValue
|| type_ == nullValue;
case stringValue:
return other == stringValue
|| ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
return isNumeric()
|| type_ == booleanValue
|| type_ == stringValue
|| type_ == nullValue;
case arrayValue:
return other == arrayValue
|| ( other == nullValue && value_.map_->size() == 0 );
return type_ == arrayValue
|| type_ == nullValue;
case objectValue:
return other == objectValue
|| ( other == nullValue && value_.map_->size() == 0 );
return type_ == objectValue
|| type_ == nullValue;
default:
JSON_ASSERT_UNREACHABLE;
break;
}
return false; // unreachable;
JSON_ASSERT_UNREACHABLE;
return false;
}

View File

@ -250,7 +250,6 @@ TestResult::addToLastFailure( const std::string &message )
}
// class TestCase
// //////////////////////////////////////////////////////////////////
@ -324,7 +323,7 @@ Runner::runTestAt( unsigned int index, TestResult &result ) const
catch ( const std::exception &e )
{
result.addFailure( __FILE__, __LINE__,
"Unexpected exception caugth:" ) << e.what();
"Unexpected exception caught:" ) << e.what();
}
#endif // if JSON_USE_EXCEPTION
delete test;

View File

@ -121,6 +121,23 @@ JSONTEST_FIXTURE( ValueTest, objects )
JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type());
// Empty object okay
JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::nullValue));
// Non-empty object not okay
JSONTEST_ASSERT(!object1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::objectValue));
// Never okay
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::stringValue));
// Access through const reference
const Json::Value &constObject = object1_;
@ -148,6 +165,23 @@ JSONTEST_FIXTURE( ValueTest, arrays )
JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type());
// Empty array okay
JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::nullValue));
// Non-empty array not okay
JSONTEST_ASSERT(!array1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::arrayValue));
// Never okay
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::stringValue));
// Access through const reference
const Json::Value &constArray = array1_;
JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]);
@ -170,6 +204,23 @@ JSONTEST_FIXTURE( ValueTest, null )
IsCheck checks;
checks.isNull_ = true;
JSONTEST_ASSERT_PRED( checkIs( null_, checks ) );
JSONTEST_ASSERT(null_.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(Json::Int(0), null_.asInt());
JSONTEST_ASSERT_EQUAL(Json::LargestInt(0), null_.asLargestInt());
JSONTEST_ASSERT_EQUAL(Json::UInt(0), null_.asUInt());
JSONTEST_ASSERT_EQUAL(Json::LargestUInt(0), null_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, null_.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat());
JSONTEST_ASSERT_STRING_EQUAL("", null_.asString());
}
@ -183,6 +234,22 @@ JSONTEST_FIXTURE( ValueTest, strings )
JSONTEST_ASSERT_PRED( checkIs( string_, checks ) );
JSONTEST_ASSERT_PRED( checkIs( string1_, checks ) );
// Empty string okay
JSONTEST_ASSERT(emptyString_.isConvertibleTo(Json::nullValue));
// Non-empty string not okay
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(string1_.isConvertibleTo(Json::stringValue));
// Never okay
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asString());
JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString());
}
@ -197,8 +264,38 @@ JSONTEST_FIXTURE( ValueTest, bools )
JSONTEST_ASSERT_PRED( checkIs( false_, checks ) );
JSONTEST_ASSERT_PRED( checkIs( true_, checks ) );
// False okay
JSONTEST_ASSERT(false_.isConvertibleTo(Json::nullValue));
// True not okay
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(true_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::stringValue));
// Never okay
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(true, true_.asBool());
JSONTEST_ASSERT_EQUAL(1, true_.asInt());
JSONTEST_ASSERT_EQUAL(1, true_.asLargestInt());
JSONTEST_ASSERT_EQUAL(1, true_.asUInt());
JSONTEST_ASSERT_EQUAL(1, true_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(1.0, true_.asDouble());
JSONTEST_ASSERT_EQUAL(1.0, true_.asFloat());
JSONTEST_ASSERT_EQUAL(false, false_.asBool());
JSONTEST_ASSERT_EQUAL(0, false_.asInt());
JSONTEST_ASSERT_EQUAL(0, false_.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, false_.asUInt());
JSONTEST_ASSERT_EQUAL(0, false_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, false_.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, false_.asFloat());
}
@ -207,6 +304,25 @@ JSONTEST_FIXTURE( ValueTest, integers )
IsCheck checks;
Json::Value val;
// Conversions that don't depend on the value.
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::objectValue));
// Default int
val = Json::Value(Json::intValue);
@ -222,12 +338,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default uint
val = Json::Value(Json::uintValue);
@ -244,18 +366,28 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default real
val = Json::Value(Json::realValue);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
@ -272,6 +404,8 @@ JSONTEST_FIXTURE( ValueTest, integers )
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (signed constructor arg)
val = Json::Value(0);
@ -288,12 +422,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (unsigned constructor arg)
val = Json::Value(0u);
@ -310,12 +450,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (floating-point constructor arg)
val = Json::Value(0.0);
@ -332,12 +478,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// 2^20 (signed constructor arg)
val = Json::Value(1 << 20);
@ -354,12 +506,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString());
// 2^20 (unsigned constructor arg)
val = Json::Value(1u << 20);
@ -376,12 +534,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString());
// 2^20 (floating-point constructor arg)
val = Json::Value((1 << 20) / 1.0);
@ -398,12 +562,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.04858e+06", val.asString());
// -2^20
val = Json::Value(-(1 << 20));
@ -418,10 +588,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString());
// int32 max
val = Json::Value(kint32max);
@ -438,12 +614,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint32max, val.asInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString());
// int32 min
val = Json::Value(kint32min);
@ -458,10 +640,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint32min, val.asInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble());
JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString());
// uint32 max
val = Json::Value(kuint32max);
@ -477,6 +665,10 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
#ifndef JSON_NO_INT64
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt());
#endif
@ -484,6 +676,8 @@ JSONTEST_FIXTURE( ValueTest, integers )
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString());
#ifdef JSON_NO_INT64
// int64 max
@ -496,8 +690,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.22337204e18", val.asString());
// int64 min
val = Json::Value(double(kint64min));
@ -509,8 +709,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.22337204e18", val.asString());
// uint64 max
val = Json::Value(double(kuint64max));
@ -522,8 +728,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.84467441e19", val.asString());
#else // ifdef JSON_NO_INT64
// 2^40 (signed constructor arg)
val = Json::Value(1LL << 40);
@ -538,12 +750,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString());
// 2^40 (unsigned constructor arg)
val = Json::Value(1ULL << 40);
@ -558,12 +776,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString());
// 2^40 (floating-point constructor arg)
val = Json::Value((1LL << 40) / 1.0);
@ -578,12 +802,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.09951e+12", val.asString());
// -2^40
val = Json::Value(-(1LL << 40));
@ -597,10 +827,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString());
// int64 max
val = Json::Value(Json::Int64(kint64max));
@ -615,12 +851,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64max, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9223372036854775807", val.asString());
// int64 max (floating point constructor). Note that kint64max is not exactly
// representable as a double, and will be rounded up to be higher.
@ -635,10 +877,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asUInt64());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asDouble());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString());
// int64 min
val = Json::Value(Json::Int64(kint64min));
@ -652,10 +900,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString());
// int64 min (floating point constructor). Note that kint64min *is* exactly
// representable as a double.
@ -670,10 +924,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(-9223372036854775808LL, val.asInt64());
JSONTEST_ASSERT_EQUAL(-9223372036854775808LL, val.asLargestInt());
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString());
// uint64 max
val = Json::Value(Json::UInt64(kuint64max));
@ -687,10 +947,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kuint64max, val.asUInt64());
JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("18446744073709551615", val.asString());
// uint64 max (floating point constructor). Note that kuint64max is not
// exactly representable as a double, and will be rounded up to be higher.
@ -703,8 +969,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString());
#endif
}
@ -714,8 +986,8 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
IsCheck checks;
Json::Value val;
// Positive number
val = Json::Value(0.25);
// Small positive number
val = Json::Value(1.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
@ -724,11 +996,26 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(0.25, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.25, val.asFloat());
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
// Negative number
val = Json::Value(-0.25);
JSONTEST_ASSERT_EQUAL(1.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(1.5, val.asFloat());
JSONTEST_ASSERT_EQUAL(1, val.asInt());
JSONTEST_ASSERT_EQUAL(1, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(1, val.asUInt());
JSONTEST_ASSERT_EQUAL(1, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("1.5", val.asString());
// Small negative number
val = Json::Value(-1.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
@ -737,8 +1024,105 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(-0.25, val.asDouble());
JSONTEST_ASSERT_EQUAL(-0.25, val.asFloat());
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(-1.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(-1.5, val.asFloat());
JSONTEST_ASSERT_EQUAL(-1, val.asInt());
JSONTEST_ASSERT_EQUAL(-1, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("-1.5", val.asString());
// A bit over int32 max
val = Json::Value(kint32max + 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(2147483647.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(2147483647.5), val.asFloat());
JSONTEST_ASSERT_EQUAL(2147483647U, val.asUInt());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(2147483647L, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(2147483647U, val.asLargestUInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("2.14748e+09", val.asString());
// A bit under int32 min
val = Json::Value(kint32min - 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(-2147483648LL, val.asLargestInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("-2.14748e+09", val.asString());
// A bit over uint32 max
val = Json::Value(kuint32max + 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(4294967295.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(4294967295.5), val.asFloat());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(4294967295LL, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(4294967295ULL, val.asLargestUInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("4.29497e+09", val.asString());
}