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 * isDouble and isFloat now return true for all numeric values, since all
value can be exactly representable as that type. In particular, a value numeric values can be converted to a double or float without
constructed with a double like 17.0 will now return true for all of truncation. Note however that the conversion may not be exact -- for
these methods. example, doubles cannot exactly represent all integers above 2^53 + 1.
* isDouble and isFloat now return true for all numeric values, since all * isBool, isNull, isString, isArray, and isObject now return true if and
numeric values can be converted to a double or float without only if the value is of that type.
truncation. Note that the conversion may not be exact -- for example,
doubles cannot exactly represent integers above 2^53. * 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: New in JsonCpp 0.6.0:
--------------------- ---------------------

View File

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

View File

@ -121,6 +121,23 @@ JSONTEST_FIXTURE( ValueTest, objects )
JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type()); 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 // Access through const reference
const Json::Value &constObject = object1_; const Json::Value &constObject = object1_;
@ -148,6 +165,23 @@ JSONTEST_FIXTURE( ValueTest, arrays )
JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type()); 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 // Access through const reference
const Json::Value &constArray = array1_; const Json::Value &constArray = array1_;
JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]); JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]);
@ -170,6 +204,23 @@ JSONTEST_FIXTURE( ValueTest, null )
IsCheck checks; IsCheck checks;
checks.isNull_ = true; checks.isNull_ = true;
JSONTEST_ASSERT_PRED( checkIs( null_, checks ) ); 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( string_, checks ) );
JSONTEST_ASSERT_PRED( checkIs( string1_, 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_.asString());
JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString()); 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( false_, checks ) );
JSONTEST_ASSERT_PRED( checkIs( true_, 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(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(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; IsCheck checks;
Json::Value val; 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 // Default int
val = Json::Value(Json::intValue); val = Json::Value(Json::intValue);
@ -222,12 +338,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt()); JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default uint // Default uint
val = Json::Value(Json::uintValue); val = Json::Value(Json::uintValue);
@ -244,18 +366,28 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt()); JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default real // Default real
val = Json::Value(Json::realValue); val = Json::Value(Json::realValue);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); 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 = IsCheck();
checks.isInt_ = true; checks.isInt_ = true;
checks.isInt64_ = true; checks.isInt64_ = true;
@ -272,6 +404,8 @@ JSONTEST_FIXTURE( ValueTest, integers )
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (signed constructor arg) // Zero (signed constructor arg)
val = Json::Value(0); val = Json::Value(0);
@ -288,12 +422,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt()); JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (unsigned constructor arg) // Zero (unsigned constructor arg)
val = Json::Value(0u); val = Json::Value(0u);
@ -310,12 +450,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt()); JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); 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) // Zero (floating-point constructor arg)
val = Json::Value(0.0); val = Json::Value(0.0);
@ -332,12 +478,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt()); JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); 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) // 2^20 (signed constructor arg)
val = Json::Value(1 << 20); val = Json::Value(1 << 20);
@ -354,12 +506,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); 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) // 2^20 (unsigned constructor arg)
val = Json::Value(1u << 20); val = Json::Value(1u << 20);
@ -376,12 +534,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); 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) // 2^20 (floating-point constructor arg)
val = Json::Value((1 << 20) / 1.0); val = Json::Value((1 << 20) / 1.0);
@ -398,12 +562,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.04858e+06", val.asString());
// -2^20 // -2^20
val = Json::Value(-(1 << 20)); val = Json::Value(-(1 << 20));
@ -418,10 +588,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt()); JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble()); JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat()); JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString());
// int32 max // int32 max
val = Json::Value(kint32max); val = Json::Value(kint32max);
@ -438,12 +614,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt()); JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble()); JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kint32max, val.asFloat()); JSONTEST_ASSERT_EQUAL(kint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString());
// int32 min // int32 min
val = Json::Value(kint32min); val = Json::Value(kint32min);
@ -458,10 +640,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble()); JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble());
JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat()); JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString());
// uint32 max // uint32 max
val = Json::Value(kuint32max); val = Json::Value(kuint32max);
@ -477,6 +665,10 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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 #ifndef JSON_NO_INT64
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt());
#endif #endif
@ -484,6 +676,8 @@ JSONTEST_FIXTURE( ValueTest, integers )
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble()); JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asFloat()); JSONTEST_ASSERT_EQUAL(kuint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString());
#ifdef JSON_NO_INT64 #ifdef JSON_NO_INT64
// int64 max // int64 max
@ -496,8 +690,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.22337204e18", val.asString());
// int64 min // int64 min
val = Json::Value(double(kint64min)); val = Json::Value(double(kint64min));
@ -509,8 +709,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.22337204e18", val.asString());
// uint64 max // uint64 max
val = Json::Value(double(kuint64max)); val = Json::Value(double(kuint64max));
@ -522,8 +728,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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(double(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat()); 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 #else // ifdef JSON_NO_INT64
// 2^40 (signed constructor arg) // 2^40 (signed constructor arg)
val = Json::Value(1LL << 40); val = Json::Value(1LL << 40);
@ -538,12 +750,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat()); 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) // 2^40 (unsigned constructor arg)
val = Json::Value(1ULL << 40); val = Json::Value(1ULL << 40);
@ -558,12 +776,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat()); 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) // 2^40 (floating-point constructor arg)
val = Json::Value((1LL << 40) / 1.0); val = Json::Value((1LL << 40) / 1.0);
@ -578,12 +802,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat()); JSONTEST_ASSERT_EQUAL((1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.09951e+12", val.asString());
// -2^40 // -2^40
val = Json::Value(-(1LL << 40)); val = Json::Value(-(1LL << 40));
@ -597,10 +827,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asLargestInt()); JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asDouble()); JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asFloat()); JSONTEST_ASSERT_EQUAL(-(1LL << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString());
// int64 max // int64 max
val = Json::Value(Json::Int64(kint64max)); val = Json::Value(Json::Int64(kint64max));
@ -615,12 +851,18 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64()); JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); 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 // int64 max (floating point constructor). Note that kint64max is not exactly
// representable as a double, and will be rounded up to be higher. // representable as a double, and will be rounded up to be higher.
@ -635,10 +877,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asUInt64());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asDouble()); JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asDouble());
JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asFloat()); JSONTEST_ASSERT_EQUAL(9223372036854775808ULL, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString());
// int64 min // int64 min
val = Json::Value(Json::Int64(kint64min)); val = Json::Value(Json::Int64(kint64min));
@ -652,10 +900,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asInt64());
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); 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 // int64 min (floating point constructor). Note that kint64min *is* exactly
// representable as a double. // representable as a double.
@ -670,10 +924,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(-9223372036854775808LL, val.asInt64()); JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT_EQUAL(-9223372036854775808LL, val.asLargestInt()); 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.asDouble());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString());
// uint64 max // uint64 max
val = Json::Value(Json::UInt64(kuint64max)); val = Json::Value(Json::UInt64(kuint64max));
@ -687,10 +947,16 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asUInt64());
JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt()); JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble()); JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat()); 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 // uint64 max (floating point constructor). Note that kuint64max is not
// exactly representable as a double, and will be rounded up to be higher. // exactly representable as a double, and will be rounded up to be higher.
@ -703,8 +969,14 @@ JSONTEST_FIXTURE( ValueTest, integers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); 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.asDouble());
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString());
#endif #endif
} }
@ -714,8 +986,8 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
IsCheck checks; IsCheck checks;
Json::Value val; Json::Value val;
// Positive number // Small positive number
val = Json::Value(0.25); val = Json::Value(1.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
@ -724,11 +996,26 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(0.25, val.asDouble()); JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT_EQUAL(0.25, val.asFloat()); 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 JSONTEST_ASSERT_EQUAL(1.5, val.asDouble());
val = Json::Value(-0.25); 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()); JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
@ -737,8 +1024,105 @@ JSONTEST_FIXTURE( ValueTest, nonIntegers )
checks.isNumeric_ = true; checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED( checkIs( val, checks ) ); JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
JSONTEST_ASSERT_EQUAL(-0.25, val.asDouble()); JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT_EQUAL(-0.25, val.asFloat()); 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());
} }