Major rework of 64 integer support: 64 bits integer are only returned when explicitly request via Json::Value::asInt64(), unlike previous implementation where Json::Value::asInt() returned a 64 bits integer. 

This eases porting portable code and does not break compatibility with the previous release.

Json::Value::asLargestInt() has also be added to ease writing portable code independent of 64 bits integer support. It is typically used to implement writers.
diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp
index 67344e0..2da3ede 100644
--- a/src/jsontestrunner/main.cpp
+++ b/src/jsontestrunner/main.cpp
@@ -44,10 +44,10 @@
       fprintf( fout, "%s=null\n", path.c_str() );
       break;
    case Json::intValue:
-      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asInt() ).c_str() );
+      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestInt() ).c_str() );
       break;
    case Json::uintValue:
-      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asUInt() ).c_str() );
+      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestUInt() ).c_str() );
       break;
    case Json::realValue:
       fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );
@@ -224,36 +224,44 @@
       return exitCode;
    }
 
-   std::string input = readInputTestFile( path.c_str() );
-   if ( input.empty() )
+   try
    {
-      printf( "Failed to read input or empty input: %s\n", path.c_str() );
-      return 3;
-   }
-
-   std::string basePath = removeSuffix( argv[1], ".json" );
-   if ( !parseOnly  &&  basePath.empty() )
-   {
-      printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
-      return 3;
-   }
-
-   std::string actualPath = basePath + ".actual";
-   std::string rewritePath = basePath + ".rewrite";
-   std::string rewriteActualPath = basePath + ".actual-rewrite";
-
-   Json::Value root;
-   exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
-   if ( exitCode == 0  &&  !parseOnly )
-   {
-      std::string rewrite;
-      exitCode = rewriteValueTree( rewritePath, root, rewrite );
-      if ( exitCode == 0 )
+      std::string input = readInputTestFile( path.c_str() );
+      if ( input.empty() )
       {
-         Json::Value rewriteRoot;
-         exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath, 
-            "rewrite", rewriteRoot, features, parseOnly );
+         printf( "Failed to read input or empty input: %s\n", path.c_str() );
+         return 3;
       }
+
+      std::string basePath = removeSuffix( argv[1], ".json" );
+      if ( !parseOnly  &&  basePath.empty() )
+      {
+         printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
+         return 3;
+      }
+
+      std::string actualPath = basePath + ".actual";
+      std::string rewritePath = basePath + ".rewrite";
+      std::string rewriteActualPath = basePath + ".actual-rewrite";
+
+      Json::Value root;
+      exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
+      if ( exitCode == 0  &&  !parseOnly )
+      {
+         std::string rewrite;
+         exitCode = rewriteValueTree( rewritePath, root, rewrite );
+         if ( exitCode == 0 )
+         {
+            Json::Value rewriteRoot;
+            exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath, 
+               "rewrite", rewriteRoot, features, parseOnly );
+         }
+      }
+   }
+   catch ( const std::exception &e )
+   {
+      printf( "Unhandled exception:\n%s\n", e.what() );
+      exitCode = 1;
    }
 
    return exitCode;
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index d2c255c..60dc4c9 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -567,12 +567,12 @@
    bool isNegative = *current == '-';
    if ( isNegative )
       ++current;
-   Value::UInt maxIntegerValue = isNegative ? Value::UInt(-Value::minInt) 
-                                            : Value::maxUInt;
-   Value::UInt threshold = maxIntegerValue / 10;
-   Value::UInt lastDigitThreshold = maxIntegerValue % 10;
+   Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) 
+                                                   : Value::maxLargestUInt;
+   Value::LargestUInt threshold = maxIntegerValue / 10;
+   Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
    assert( lastDigitThreshold >=0  &&  lastDigitThreshold <= 9 );
-   Value::UInt value = 0;
+   Value::LargestUInt value = 0;
    while ( current < token.end_ )
    {
       Char c = *current++;
@@ -592,9 +592,9 @@
       value = value * 10 + digit;
    }
    if ( isNegative )
-      currentValue() = -Value::Int( value );
-   else if ( value <= Value::UInt(Value::maxInt) )
-      currentValue() = Value::Int( value );
+      currentValue() = -Value::LargestInt( value );
+   else if ( value <= Value::LargestUInt(Value::maxInt) )
+      currentValue() = Value::LargestInt( value );
    else
       currentValue() = value;
    return true;
diff --git a/src/lib_json/json_tool.h b/src/lib_json/json_tool.h
index c20639d..658031b 100644
--- a/src/lib_json/json_tool.h
+++ b/src/lib_json/json_tool.h
@@ -63,7 +63,7 @@
 
 enum { 
    /// Constant that specify the size of the buffer that must be passed to uintToString.
-   uintToStringBufferSize = 3*sizeof(UInt)+1 
+   uintToStringBufferSize = 3*sizeof(LargestUInt)+1 
 };
 
 // Defines a char buffer for use with uintToString().
@@ -76,7 +76,7 @@
  *        Must have at least uintToStringBufferSize chars free.
  */
 static inline void 
-uintToString( UInt value, 
+uintToString( LargestUInt value, 
               char *&current )
 {
    *--current = 0;
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 15a1140..218c127 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -28,6 +28,13 @@
 const Int Value::minInt = Int( ~(UInt(-1)/2) );
 const Int Value::maxInt = Int( UInt(-1)/2 );
 const UInt Value::maxUInt = UInt(-1);
+const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
+const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
+const UInt64 Value::maxUInt64 = UInt64(-1);
+const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
+const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
 
 /// Unknown size marker
 enum { unknown = (unsigned)-1 };
@@ -262,8 +269,8 @@
 }
 
 
-#if !defined(JSON_NO_INT64)
-Value::Value( ArrayIndex value )
+#if defined(JSON_HAS_INT64)
+Value::Value( UInt value )
    : type_( uintValue )
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
@@ -273,19 +280,6 @@
    value_.uint_ = value;
 }
 
-Value::Value( int value )
-   : type_( intValue )
-   , comments_( 0 )
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-   , itemIsUsed_( 0 )
-#endif
-{
-   value_.int_ = value;
-}
-
-#endif // if !defined(JSON_NO_INT64)
-
-
 Value::Value( Int value )
    : type_( intValue )
    , comments_( 0 )
@@ -296,8 +290,21 @@
    value_.int_ = value;
 }
 
+#endif // if defined(JSON_HAS_INT64)
 
-Value::Value( UInt value )
+
+Value::Value( Int64 value )
+   : type_( intValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.int_ = value;
+}
+
+
+Value::Value( UInt64 value )
    : type_( uintValue )
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
@@ -689,6 +696,7 @@
 }
 # endif
 
+
 Value::Int 
 Value::asInt() const
 {
@@ -697,10 +705,11 @@
    case nullValue:
       return 0;
    case intValue:
-      return value_.int_;
+      JSON_ASSERT_MESSAGE( value_.int_ >= minInt  &&  value_.int_ <= maxInt, "unsigned integer out of signed int range" );
+      return Int(value_.int_);
    case uintValue:
-      JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
-      return value_.uint_;
+      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
+      return Int(value_.uint_);
    case realValue:
       JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
       return Int( value_.real_ );
@@ -716,6 +725,7 @@
    return 0; // unreachable;
 }
 
+
 Value::UInt 
 Value::asUInt() const
 {
@@ -725,9 +735,11 @@
       return 0;
    case intValue:
       JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
-      return value_.int_;
+      JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" );
+      return UInt(value_.int_);
    case uintValue:
-      return value_.uint_;
+      JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
+      return UInt(value_.uint_);
    case realValue:
       JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
       return UInt( value_.real_ );
@@ -743,6 +755,88 @@
    return 0; // unreachable;
 }
 
+
+# if defined(JSON_HAS_INT64)
+
+Value::Int64
+Value::asInt64() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= minInt64  &&  value_.real_ <= maxInt64, "Real out of Int64 range" );
+      return Int( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to Int64" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+Value::UInt64
+Value::asUInt64() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt64,  "Real out of UInt64 range" );
+      return UInt( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to UInt64" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+# endif // if defined(JSON_HAS_INT64)
+
+
+LargestInt 
+Value::asLargestInt() const
+{
+#if defined(JSON_NO_INT64)
+	return asInt();
+#else
+	return asInt64();
+#endif
+}
+
+
+LargestUInt 
+Value::asLargestUInt() const
+{
+#if defined(JSON_NO_INT64)
+	return asUInt();
+#else
+	return asUInt64();
+#endif
+}
+
+
 double 
 Value::asDouble() const
 {
diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp
index 7882acf..f101cbc 100644
--- a/src/lib_json/json_writer.cpp
+++ b/src/lib_json/json_writer.cpp
@@ -29,14 +29,15 @@
    return false;
 }
 
-std::string valueToString( Int value )
+
+std::string valueToString( LargestInt value )
 {
    UIntToStringBuffer buffer;
    char *current = buffer + sizeof(buffer);
    bool isNegative = value < 0;
    if ( isNegative )
       value = -value;
-   uintToString( UInt(value), current );
+   uintToString( LargestUInt(value), current );
    if ( isNegative )
       *--current = '-';
    assert( current >= buffer );
@@ -44,7 +45,7 @@
 }
 
 
-std::string valueToString( UInt value )
+std::string valueToString( LargestUInt value )
 {
    UIntToStringBuffer buffer;
    char *current = buffer + sizeof(buffer);
@@ -53,6 +54,22 @@
    return current;
 }
 
+#if defined(JSON_HAS_INT64)
+
+std::string valueToString( Int value )
+{
+   return valueToString( LargestInt(value) );
+}
+
+
+std::string valueToString( UInt value )
+{
+   return valueToString( LargestUInt(value) );
+}
+
+#endif // # if defined(JSON_HAS_INT64)
+
+
 std::string valueToString( double value )
 {
    char buffer[32];
@@ -203,10 +220,10 @@
       document_ += "null";
       break;
    case intValue:
-      document_ += valueToString( value.asInt() );
+      document_ += valueToString( value.asLargestInt() );
       break;
    case uintValue:
-      document_ += valueToString( value.asUInt() );
+      document_ += valueToString( value.asLargestUInt() );
       break;
    case realValue:
       document_ += valueToString( value.asDouble() );
@@ -286,10 +303,10 @@
       pushValue( "null" );
       break;
    case intValue:
-      pushValue( valueToString( value.asInt() ) );
+      pushValue( valueToString( value.asLargestInt() ) );
       break;
    case uintValue:
-      pushValue( valueToString( value.asUInt() ) );
+      pushValue( valueToString( value.asLargestUInt() ) );
       break;
    case realValue:
       pushValue( valueToString( value.asDouble() ) );
@@ -562,10 +579,10 @@
       pushValue( "null" );
       break;
    case intValue:
-      pushValue( valueToString( value.asInt() ) );
+      pushValue( valueToString( value.asLargestInt() ) );
       break;
    case uintValue:
-      pushValue( valueToString( value.asUInt() ) );
+      pushValue( valueToString( value.asLargestUInt() ) );
       break;
    case realValue:
       pushValue( valueToString( value.asDouble() ) );