- Moved definition of Json::Int and Json::UInt to config.h which compiler detection logic to define them to 64 bits integer if JSON_NO_INT64 is not defined.
- Added Json::ArrayIndex as an unsigned int to forwards.h
- Modified Json::Value to consistently use Json::ArrayIndex.
- Added int/unsigned int constructor overload to Json::Value to avoid ambiguous constructor call.
- Modified jsontestrunner/main.cpp to use Json::valueToString for Value::asInt() conversion to string.
- Modified Json::Reader to only overflow to double when the number is too large (previous code relied on the fact that an int fitted in a double without precision loss).
- Generalized uintToString() helpers and buffer size to automatically adapt to the precision of Json::UInt.
- Added specific conversion logic for UInt to double conversion on Microsoft Visual Studio 6 which only support __int64 to double conversion (unsigned __int64 conversion is not supported)
- Added test for 64 bits parsing/writing. Notes: those will fail when compiled with JSON_NO_INT64 (more dev required to adapt).
diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp
index 231ee0c..3e6cd5d 100644
--- a/src/jsontestrunner/main.cpp
+++ b/src/jsontestrunner/main.cpp
@@ -35,10 +35,10 @@
       fprintf( fout, "%s=null\n", path.c_str() );
       break;
    case Json::intValue:
-      fprintf( fout, "%s=%d\n", path.c_str(), value.asInt() );
+      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asInt() ).c_str() );
       break;
    case Json::uintValue:
-      fprintf( fout, "%s=%u\n", path.c_str(), value.asUInt() );
+      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asUInt() ).c_str() );
       break;
    case Json::realValue:
       fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );
@@ -148,6 +148,19 @@
    return path.substr( 0, path.length() - extension.length() );
 }
 
+
+static void
+printConfig()
+{
+   // Print the configuration used to compile JsonCpp
+#if defined(JSON_NO_INT64)
+   printf( "JSON_NO_INT64=1\n" );
+#else
+   printf( "JSON_NO_INT64=0\n" );
+#endif
+}
+
+
 static int 
 printUsage( const char *argv[] )
 {
@@ -175,6 +188,12 @@
       ++index;
    }
 
+   if ( std::string(argv[1]) == "--json-config" )
+   {
+      printConfig();
+      return 3;
+   }
+
    if ( index == argc  ||  index + 1 < argc )
    {
       return printUsage( argv );
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index da8e83b..2bd38f0 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -555,21 +555,36 @@
    }
    if ( isDouble )
       return decodeDouble( token );
+   // Attempts to parse the number as an integer. If the number is
+   // larger than the maximum supported value of an integer then
+   // we decode the number as a double.
    Location current = token.start_;
    bool isNegative = *current == '-';
    if ( isNegative )
       ++current;
-   Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) 
-                                       : Value::maxUInt) / 10;
+   Value::UInt maxIntegerValue = isNegative ? Value::UInt(-Value::minInt) 
+                                            : Value::maxUInt;
+   Value::UInt threshold = maxIntegerValue / 10;
+   Value::UInt lastDigitThreshold = maxIntegerValue % 10;
+   assert( lastDigitThreshold >=0  &&  lastDigitThreshold <= 9 );
    Value::UInt value = 0;
    while ( current < token.end_ )
    {
       Char c = *current++;
       if ( c < '0'  ||  c > '9' )
          return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+      Value::UInt digit(c - '0');
       if ( value >= threshold )
-         return decodeDouble( token );
-      value = value * 10 + Value::UInt(c - '0');
+      {
+         // If the current digit is not the last one, or if it is
+         // greater than the last digit of the maximum integer value,
+         // the parse the number as a double.
+         if ( current != token.end_  ||  digit > lastDigitThreshold )
+         {
+            return decodeDouble( token );
+         }
+      }
+      value = value * 10 + digit;
    }
    if ( isNegative )
       currentValue() = -Value::Int( value );
diff --git a/src/lib_json/json_tool.h b/src/lib_json/json_tool.h
index ca4ea4f..5ffc2de 100644
--- a/src/lib_json/json_tool.h
+++ b/src/lib_json/json_tool.h
@@ -56,18 +56,28 @@
 }

 

 

+enum { 

+   /// Constant that specify the size of the buffer that must be passed to uintToString.

+   uintToStringBufferSize = 3*sizeof(UInt)+1 

+};

+

+// Defines a char buffer for use with uintToString().

+typedef char UIntToStringBuffer[uintToStringBufferSize];

+

+

 /** Converts an unsigned integer to string.

  * @param value Unsigned interger to convert to string

- * @param current Input/Output string buffer. Must have at least 10 chars free.

+ * @param current Input/Output string buffer. 

+ *        Must have at least uintToStringBufferSize chars free.

  */

 static inline void 

-uintToString( unsigned int value, 

+uintToString( UInt value, 

               char *&current )

 {

    *--current = 0;

    do

    {

-      *--current = (value % 10) + '0';

+      *--current = char(value % 10) + '0';

       value /= 10;

    }

    while ( value != 0 );

diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 1ccf70f..60362ad 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -119,7 +119,7 @@
 // Notes: index_ indicates if the string was allocated when
 // a string is stored.
 
-Value::CZString::CZString( int index )
+Value::CZString::CZString( ArrayIndex index )
    : cstr_( 0 )
    , index_( index )
 {
@@ -179,7 +179,7 @@
 }
 
 
-int 
+ArrayIndex 
 Value::CZString::index() const
 {
    return index_;
@@ -257,6 +257,30 @@
 }
 
 
+#if !defined(JSON_NO_INT64)
+Value::Value( ArrayIndex value )
+   : type_( uintValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   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 )
@@ -310,7 +334,7 @@
 #endif
 {
    value_.string_ = duplicateStringValue( beginValue, 
-                                          UInt(endValue - beginValue) );
+                                          (unsigned int)(endValue - beginValue) );
 }
 
 
@@ -722,9 +746,13 @@
    case nullValue:
       return 0.0;
    case intValue:
-      return value_.int_;
+      return static_cast<double>( value_.int_ );
    case uintValue:
-      return value_.uint_;
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<double>( value_.uint_ );
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<double>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
    case realValue:
       return value_.real_;
    case booleanValue:
@@ -817,7 +845,7 @@
 
 
 /// Number of values in array or object
-Value::UInt 
+ArrayIndex 
 Value::size() const
 {
    switch ( type_ )
@@ -839,7 +867,7 @@
       }
       return 0;
    case objectValue:
-      return Int( value_.map_->size() );
+      return ArrayIndex( value_.map_->size() );
 #else
    case arrayValue:
       return Int( value_.array_->size() );
@@ -896,21 +924,23 @@
 }
 
 void 
-Value::resize( UInt newSize )
+Value::resize( ArrayIndex newSize )
 {
    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
    if ( type_ == nullValue )
       *this = Value( arrayValue );
 #ifndef JSON_VALUE_USE_INTERNAL_MAP
-   UInt oldSize = size();
+   ArrayIndex oldSize = size();
    if ( newSize == 0 )
       clear();
    else if ( newSize > oldSize )
       (*this)[ newSize - 1 ];
    else
    {
-      for ( UInt index = newSize; index < oldSize; ++index )
+      for ( ArrayIndex index = newSize; index < oldSize; ++index )
+      {
          value_.map_->erase( index );
+      }
       assert( size() == newSize );
    }
 #else
@@ -920,7 +950,7 @@
 
 
 Value &
-Value::operator[]( UInt index )
+Value::operator[]( ArrayIndex index )
 {
    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
    if ( type_ == nullValue )
@@ -941,7 +971,7 @@
 
 
 const Value &
-Value::operator[]( UInt index ) const
+Value::operator[]( ArrayIndex index ) const
 {
    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
    if ( type_ == nullValue )
@@ -991,7 +1021,7 @@
 
 
 Value 
-Value::get( UInt index, 
+Value::get( ArrayIndex index, 
             const Value &defaultValue ) const
 {
    const Value *value = &((*this)[index]);
@@ -1000,7 +1030,7 @@
 
 
 bool 
-Value::isValidIndex( UInt index ) const
+Value::isValidIndex( ArrayIndex index ) const
 {
    return index < size();
 }
@@ -1463,7 +1493,7 @@
 }
 
 
-PathArgument::PathArgument( Value::UInt index )
+PathArgument::PathArgument( ArrayIndex index )
    : index_( index )
    , kind_( kindIndex )
 {
@@ -1519,9 +1549,9 @@
             addPathInArg( path, in, itInArg, PathArgument::kindIndex );
          else
          {
-            Value::UInt index = 0;
+            ArrayIndex index = 0;
             for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
-               index = index * 10 + Value::UInt(*current - '0');
+               index = index * 10 + ArrayIndex(*current - '0');
             args_.push_back( index );
          }
          if ( current == end  ||  *current++ != ']' )
diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp
index 3b926e6..92782db 100644
--- a/src/lib_json/json_writer.cpp
+++ b/src/lib_json/json_writer.cpp
@@ -26,7 +26,7 @@
 
 std::string valueToString( Int value )
 {
-   char buffer[32];
+   UIntToStringBuffer buffer;
    char *current = buffer + sizeof(buffer);
    bool isNegative = value < 0;
    if ( isNegative )
@@ -41,7 +41,7 @@
 
 std::string valueToString( UInt value )
 {
-   char buffer[32];
+   UIntToStringBuffer buffer;
    char *current = buffer + sizeof(buffer);
    uintToString( value, current );
    assert( current >= buffer );