Skip to content

Commit 842e9ac

Browse files
committed
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.
1 parent 5c5628a commit 842e9ac

9 files changed

Lines changed: 253 additions & 76 deletions

File tree

NEWS.txt

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,38 @@
1818
initialization/destruction order issues (bug #2934500).
1919
The DefaultValueAllocator has been inlined in code.
2020

21-
- Added support for 64 bits integer. Json::Int and Json::UInt are
22-
now 64 bits integers on system that support them (more precisely
23-
they are of the size of long long, so if it is 128 bits it will
24-
also work).
21+
- Added support for 64 bits integer:
22+
23+
Types Json::Int64 and Json::UInt64 have been added. They are aliased
24+
to 64 bits integers on system that support them (based on __int64 on
25+
Microsoft Visual Studio platform, and long long on other platforms).
26+
27+
Types Json::LargestInt and Json::LargestUInt have been added. They are
28+
aliased to the largest integer type supported:
29+
either Json::Int/Json::UInt or Json::Int64/Json::UInt64 respectively.
30+
31+
Json::Value::asInt() and Json::Value::asUInt() still returns plain
32+
"int" based types, but asserts if an attempt is made to retrieve
33+
a 64 bits value that can not represented as the return type.
34+
35+
Json::Value::asInt64() and Json::Value::asUInt64() have been added
36+
to obtain the 64 bits integer value.
37+
38+
Json::Value::asLargestInt() and Json::Value::asLargestUInt() returns
39+
the integer as a LargestInt/LargestUInt respectively. Those functions
40+
functions are typically used when implementing writer.
41+
42+
The reader attempts to read number as 64 bits integer, and fall back
43+
to reading a double if the number is not in the range of 64 bits
44+
integer.
2545

2646
Warning: Json::Value::asInt() and Json::Value::asUInt() now returns
2747
long long. This changes break code that was passing the return value
2848
to *printf() function.
29-
30-
Notes: you can switch back to the 32 bits only behavior by defining the
31-
macro JSON_NO_INT64 (se include/json/config.h).
49+
50+
Support for 64 bits integer can be disabled by defining the macro
51+
JSON_NO_INT64 (uncomment it in json/config.h for example), though
52+
it should have no impact on existing usage.
3253

3354
- The type Json::ArrayIndex is used for indexes of a JSON value array. It
3455
is an unsigned int (typically 32 bits).

include/json/config.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
# endif
4747

4848
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
49-
// Storages.
49+
// Storages, and 64 bits integer support is disabled.
5050
// #define JSON_NO_INT64 1
5151

5252
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
@@ -57,18 +57,24 @@
5757

5858

5959
namespace Json {
60-
# if defined(JSON_NO_INT64)
6160
typedef int Int;
6261
typedef unsigned int UInt;
62+
# if defined(JSON_NO_INT64)
63+
typedef int LargestInt;
64+
typedef unsigned int LargestUInt;
65+
# undef JSON_HAS_INT64
6366
# else // if defined(JSON_NO_INT64)
6467
// For Microsoft Visual use specific types as long long is not supported
6568
# if defined(_MSC_VER) // Microsoft Visual Studio
66-
typedef __int64 Int;
67-
typedef unsigned __int64 UInt;
69+
typedef __int64 Int64;
70+
typedef unsigned __int64 UInt64;
6871
# else // if defined(_MSC_VER) // Other platforms, use long long
69-
typedef long long int Int;
70-
typedef unsigned long long int UInt;
72+
typedef long long int Int64;
73+
typedef unsigned long long int UInt64;
7174
# endif // if defined(_MSC_VER)
75+
typedef Int64 LargestInt;
76+
typedef UInt64 LargestUInt;
77+
# define JSON_HAS_INT64
7278
# endif // if defined(JSON_NO_INT64)
7379
} // end namespace Json
7480

include/json/value.h

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,36 @@ namespace Json {
126126
typedef ValueConstIterator const_iterator;
127127
typedef Json::UInt UInt;
128128
typedef Json::Int Int;
129+
# if defined(JSON_HAS_INT64)
130+
typedef Json::UInt64 UInt64;
131+
typedef Json::Int64 Int64;
132+
#endif // defined(JSON_HAS_INT64)
133+
typedef Json::LargestInt LargestInt;
134+
typedef Json::LargestUInt LargestUInt;
129135
typedef Json::ArrayIndex ArrayIndex;
130136

131137
static const Value null;
132-
static const Int minInt;
138+
/// Minimum signed integer value that can be stored in a Json::Value.
139+
static const LargestInt minLargestInt;
140+
/// Maximum signed integer value that can be stored in a Json::Value.
141+
static const LargestInt maxLargestInt;
142+
/// Maximum unsigned integer value that can be stored in a Json::Value.
143+
static const LargestUInt maxLargestUInt;
144+
145+
/// Minimum signed int value that can be stored in a Json::Value.
146+
static const Int minInt;
147+
/// Maximum signed int value that can be stored in a Json::Value.
133148
static const Int maxInt;
149+
/// Maximum unsigned int value that can be stored in a Json::Value.
134150
static const UInt maxUInt;
135151

152+
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
153+
static const Int64 minInt64;
154+
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
155+
static const Int64 maxInt64;
156+
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
157+
static const UInt64 maxUInt64;
158+
136159
private:
137160
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
138161
# ifndef JSON_VALUE_USE_INTERNAL_MAP
@@ -187,12 +210,12 @@ namespace Json {
187210
\endcode
188211
*/
189212
Value( ValueType type = nullValue );
190-
#if !defined(JSON_NO_INT64)
191-
Value( int value );
192-
Value( ArrayIndex value );
193-
#endif // if !defined(JSON_NO_INT64)
194213
Value( Int value );
195214
Value( UInt value );
215+
#if defined(JSON_HAS_INT64)
216+
Value( Int64 value );
217+
Value( UInt64 value );
218+
#endif // if defined(JSON_HAS_INT64)
196219
Value( double value );
197220
Value( const char *value );
198221
Value( const char *beginValue, const char *endValue );
@@ -240,6 +263,10 @@ namespace Json {
240263
# endif
241264
Int asInt() const;
242265
UInt asUInt() const;
266+
Int64 asInt64() const;
267+
UInt64 asUInt64() const;
268+
LargestInt asLargestInt() const;
269+
LargestUInt asLargestUInt() const;
243270
float asFloat() const;
244271
double asDouble() const;
245272
bool asBool() const;
@@ -448,8 +475,8 @@ namespace Json {
448475

449476
union ValueHolder
450477
{
451-
Int int_;
452-
UInt uint_;
478+
LargestInt int_;
479+
LargestUInt uint_;
453480
double real_;
454481
bool bool_;
455482
char *string_;

include/json/writer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,12 @@ namespace Json {
162162
bool addChildValues_;
163163
};
164164

165+
# if defined(JSON_HAS_INT64)
165166
std::string JSON_API valueToString( Int value );
166167
std::string JSON_API valueToString( UInt value );
168+
# endif // if defined(JSON_HAS_INT64)
169+
std::string JSON_API valueToString( LargestInt value );
170+
std::string JSON_API valueToString( LargestUInt value );
167171
std::string JSON_API valueToString( double value );
168172
std::string JSON_API valueToString( bool value );
169173
std::string JSON_API valueToQuotedString( const char *value );

src/jsontestrunner/main.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
4444
fprintf( fout, "%s=null\n", path.c_str() );
4545
break;
4646
case Json::intValue:
47-
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asInt() ).c_str() );
47+
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestInt() ).c_str() );
4848
break;
4949
case Json::uintValue:
50-
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asUInt() ).c_str() );
50+
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestUInt() ).c_str() );
5151
break;
5252
case Json::realValue:
5353
fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );
@@ -224,37 +224,45 @@ int main( int argc, const char *argv[] )
224224
return exitCode;
225225
}
226226

227-
std::string input = readInputTestFile( path.c_str() );
228-
if ( input.empty() )
227+
try
229228
{
230-
printf( "Failed to read input or empty input: %s\n", path.c_str() );
231-
return 3;
232-
}
229+
std::string input = readInputTestFile( path.c_str() );
230+
if ( input.empty() )
231+
{
232+
printf( "Failed to read input or empty input: %s\n", path.c_str() );
233+
return 3;
234+
}
233235

234-
std::string basePath = removeSuffix( argv[1], ".json" );
235-
if ( !parseOnly && basePath.empty() )
236-
{
237-
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
238-
return 3;
239-
}
236+
std::string basePath = removeSuffix( argv[1], ".json" );
237+
if ( !parseOnly && basePath.empty() )
238+
{
239+
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
240+
return 3;
241+
}
240242

241-
std::string actualPath = basePath + ".actual";
242-
std::string rewritePath = basePath + ".rewrite";
243-
std::string rewriteActualPath = basePath + ".actual-rewrite";
243+
std::string actualPath = basePath + ".actual";
244+
std::string rewritePath = basePath + ".rewrite";
245+
std::string rewriteActualPath = basePath + ".actual-rewrite";
244246

245-
Json::Value root;
246-
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
247-
if ( exitCode == 0 && !parseOnly )
248-
{
249-
std::string rewrite;
250-
exitCode = rewriteValueTree( rewritePath, root, rewrite );
251-
if ( exitCode == 0 )
247+
Json::Value root;
248+
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
249+
if ( exitCode == 0 && !parseOnly )
252250
{
253-
Json::Value rewriteRoot;
254-
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
255-
"rewrite", rewriteRoot, features, parseOnly );
251+
std::string rewrite;
252+
exitCode = rewriteValueTree( rewritePath, root, rewrite );
253+
if ( exitCode == 0 )
254+
{
255+
Json::Value rewriteRoot;
256+
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
257+
"rewrite", rewriteRoot, features, parseOnly );
258+
}
256259
}
257260
}
261+
catch ( const std::exception &e )
262+
{
263+
printf( "Unhandled exception:\n%s\n", e.what() );
264+
exitCode = 1;
265+
}
258266

259267
return exitCode;
260268
}

src/lib_json/json_reader.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -567,12 +567,12 @@ Reader::decodeNumber( Token &token )
567567
bool isNegative = *current == '-';
568568
if ( isNegative )
569569
++current;
570-
Value::UInt maxIntegerValue = isNegative ? Value::UInt(-Value::minInt)
571-
: Value::maxUInt;
572-
Value::UInt threshold = maxIntegerValue / 10;
573-
Value::UInt lastDigitThreshold = maxIntegerValue % 10;
570+
Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
571+
: Value::maxLargestUInt;
572+
Value::LargestUInt threshold = maxIntegerValue / 10;
573+
Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
574574
assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 );
575-
Value::UInt value = 0;
575+
Value::LargestUInt value = 0;
576576
while ( current < token.end_ )
577577
{
578578
Char c = *current++;
@@ -592,9 +592,9 @@ Reader::decodeNumber( Token &token )
592592
value = value * 10 + digit;
593593
}
594594
if ( isNegative )
595-
currentValue() = -Value::Int( value );
596-
else if ( value <= Value::UInt(Value::maxInt) )
597-
currentValue() = Value::Int( value );
595+
currentValue() = -Value::LargestInt( value );
596+
else if ( value <= Value::LargestUInt(Value::maxInt) )
597+
currentValue() = Value::LargestInt( value );
598598
else
599599
currentValue() = value;
600600
return true;

src/lib_json/json_tool.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ isControlCharacter(char ch)
6363

6464
enum {
6565
/// Constant that specify the size of the buffer that must be passed to uintToString.
66-
uintToStringBufferSize = 3*sizeof(UInt)+1
66+
uintToStringBufferSize = 3*sizeof(LargestUInt)+1
6767
};
6868

6969
// Defines a char buffer for use with uintToString().
@@ -76,7 +76,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
7676
* Must have at least uintToStringBufferSize chars free.
7777
*/
7878
static inline void
79-
uintToString( UInt value,
79+
uintToString( LargestUInt value,
8080
char *&current )
8181
{
8282
*--current = 0;

0 commit comments

Comments
 (0)