mirror of
https://github.com/DaveGamble/cJSON.git
synced 2023-08-10 21:13:26 +03:00
long long fixes, enhancements, tests
This commit is contained in:
parent
586762189b
commit
a1efa1e77f
23
cJSON.c
23
cJSON.c
@ -70,7 +70,7 @@
|
||||
#define false ((cJSON_bool)0)
|
||||
|
||||
/* define our own int max and min */
|
||||
#if defined(CJSON_INT_USE_LONGLONG) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
#define CJSON_INT_MAX LLONG_MAX
|
||||
#define CJSON_INT_MIN LLONG_MIN
|
||||
#define strtoint(s) strtoll((const char*)(s), NULL, 0)
|
||||
@ -82,7 +82,7 @@
|
||||
#define intfmt "%d"
|
||||
#endif
|
||||
|
||||
#define isint(d) (d == floor(d))
|
||||
#define has_no_decimals(d) (d == floor(d))
|
||||
|
||||
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
|
||||
#ifndef isinf
|
||||
@ -320,7 +320,7 @@ typedef struct
|
||||
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
|
||||
{
|
||||
double number = 0;
|
||||
cJSON_bool integer = cJSON_True;
|
||||
cJSON_bool is_integer = cJSON_True;
|
||||
unsigned char *after_end = NULL;
|
||||
unsigned char number_c_string[64];
|
||||
unsigned char decimal_point = get_decimal_point();
|
||||
@ -355,12 +355,12 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
integer = cJSON_False;
|
||||
is_integer = cJSON_False;
|
||||
number_c_string[i] = buffer_at_offset(input_buffer)[i];
|
||||
break;
|
||||
|
||||
case '.':
|
||||
integer = cJSON_False;
|
||||
is_integer = cJSON_False;
|
||||
number_c_string[i] = decimal_point;
|
||||
break;
|
||||
|
||||
@ -380,7 +380,8 @@ loop_end:
|
||||
item->valuedouble = number;
|
||||
|
||||
/* use saturation in case of overflow */
|
||||
if (number >= CJSON_INT_MAX)
|
||||
/* note that even float has range beyond long long (though inexactly) */
|
||||
if (number >= (double)CJSON_INT_MAX)
|
||||
{
|
||||
item->valueint = CJSON_INT_MAX;
|
||||
}
|
||||
@ -388,9 +389,9 @@ loop_end:
|
||||
{
|
||||
item->valueint = CJSON_INT_MIN;
|
||||
}
|
||||
else if (integer == cJSON_True)
|
||||
else if (is_integer == cJSON_True)
|
||||
{
|
||||
/* parse again to handle the very big integer */
|
||||
/* integer is in range, parse as integer to prevent float inexactness */
|
||||
item->valueint = strtoint(number_c_string);
|
||||
}
|
||||
else
|
||||
@ -407,7 +408,7 @@ loop_end:
|
||||
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
|
||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
|
||||
{
|
||||
if (number >= CJSON_INT_MAX)
|
||||
if (number >= (double)CJSON_INT_MAX)
|
||||
{
|
||||
object->valueint = CJSON_INT_MAX;
|
||||
}
|
||||
@ -588,8 +589,8 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "null");
|
||||
}
|
||||
else if (isint(d) && ((item->valueint != CJSON_INT_MAX &&
|
||||
item->valueint != CJSON_INT_MIN) || d == (double)item->valueint))
|
||||
else if (has_no_decimals(d) && item->valueint != CJSON_INT_MAX &&
|
||||
item->valueint != CJSON_INT_MIN && d == (double)item->valueint)
|
||||
{
|
||||
length = sprintf((char*)number_buffer, intfmt, item->valueint);
|
||||
}
|
||||
|
5
cJSON.h
5
cJSON.h
@ -100,8 +100,11 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
|
||||
#define cJSON_StringIsConst 512
|
||||
|
||||
#define notCJSON_INT_USE_LONGLONG
|
||||
// Note: Default cmake rules will force C89 and prevent long long.
|
||||
// To use long long, delete build tree, then run:
|
||||
// CFLAGS="-Wall -Werror" cmake -DENABLE_CUSTOM_COMPILER_FLAGS=Off <sourcedir>
|
||||
|
||||
#if defined(CJSON_INT_USE_LONGLONG) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
typedef long long cJSON_int;
|
||||
#else
|
||||
typedef int cJSON_int;
|
||||
|
@ -231,13 +231,13 @@ static void cjson_set_number_value_should_set_numbers(void)
|
||||
TEST_ASSERT_EQUAL(-1, number->valueint);
|
||||
TEST_ASSERT_EQUAL_DOUBLE(-1.5, number->valuedouble);
|
||||
|
||||
cJSON_SetNumberValue(number, 1 + (double)INT_MAX);
|
||||
TEST_ASSERT_EQUAL(INT_MAX, number->valueint);
|
||||
TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble);
|
||||
cJSON_SetNumberValue(number, 1.0 + (double)CJSON_INT_MAX);
|
||||
TEST_ASSERT_EQUAL(CJSON_INT_MAX, number->valueint);
|
||||
TEST_ASSERT_EQUAL_DOUBLE(1.0 + (double)CJSON_INT_MAX, number->valuedouble);
|
||||
|
||||
cJSON_SetNumberValue(number, -1 + (double)INT_MIN);
|
||||
TEST_ASSERT_EQUAL(INT_MIN, number->valueint);
|
||||
TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
|
||||
cJSON_SetNumberValue(number, -1.0 + (double)CJSON_INT_MIN);
|
||||
TEST_ASSERT_EQUAL(CJSON_INT_MIN, number->valueint);
|
||||
TEST_ASSERT_EQUAL_DOUBLE(-1.0 + (double)CJSON_INT_MIN, number->valuedouble);
|
||||
}
|
||||
|
||||
static void cjson_detach_item_via_pointer_should_detach_items(void)
|
||||
|
@ -43,7 +43,7 @@ static void assert_is_number(cJSON *number_item)
|
||||
assert_has_no_string(number_item);
|
||||
}
|
||||
|
||||
static void assert_parse_number(const char *string, int integer, double real)
|
||||
static void assert_parse_number(const char *string, cJSON_int integer, double real)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
buffer.content = (const unsigned char*)string;
|
||||
@ -51,7 +51,11 @@ static void assert_parse_number(const char *string, int integer, double real)
|
||||
|
||||
TEST_ASSERT_TRUE(parse_number(item, &buffer));
|
||||
assert_is_number(item);
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
TEST_ASSERT_EQUAL_INT64(integer, item->valueint);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL_INT(integer, item->valueint);
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL_DOUBLE(real, item->valuedouble);
|
||||
}
|
||||
|
||||
@ -66,14 +70,24 @@ static void parse_number_should_parse_negative_integers(void)
|
||||
{
|
||||
assert_parse_number("-1", -1, -1);
|
||||
assert_parse_number("-32768", -32768, -32768.0);
|
||||
assert_parse_number("-2147483648", (int)-2147483648.0, -2147483648.0);
|
||||
assert_parse_number("-2147483648", -2147483648, -2147483648.0);
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
assert_parse_number("-8765432101234567", -8765432101234567LL, -8765432101234567.0);
|
||||
#else
|
||||
assert_parse_number("-8765432101234567", CJSON_INT_MIN, -8765432101234567.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void parse_number_should_parse_positive_integers(void)
|
||||
{
|
||||
assert_parse_number("1", 1, 1);
|
||||
assert_parse_number("32767", 32767, 32767.0);
|
||||
assert_parse_number("2147483647", (int)2147483647.0, 2147483647.0);
|
||||
assert_parse_number("2147483647", 2147483647, 2147483647.0);
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
assert_parse_number("8765432101234567", 8765432101234567LL, 8765432101234567.0);
|
||||
#else
|
||||
assert_parse_number("8765432101234567", CJSON_INT_MAX, 8765432101234567.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void parse_number_should_parse_positive_reals(void)
|
||||
@ -81,8 +95,11 @@ static void parse_number_should_parse_positive_reals(void)
|
||||
assert_parse_number("0.001", 0, 0.001);
|
||||
assert_parse_number("10e-10", 0, 10e-10);
|
||||
assert_parse_number("10E-10", 0, 10e-10);
|
||||
assert_parse_number("10e10", INT_MAX, 10e10);
|
||||
assert_parse_number("123e+127", INT_MAX, 123e127);
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
assert_parse_number("10e10", 100000000000LL, 10e10);
|
||||
#endif
|
||||
assert_parse_number("10e20", CJSON_INT_MAX, 10e20);
|
||||
assert_parse_number("123e+127", CJSON_INT_MAX, 123e127);
|
||||
assert_parse_number("123e-128", 0, 123e-128);
|
||||
}
|
||||
|
||||
@ -91,8 +108,11 @@ static void parse_number_should_parse_negative_reals(void)
|
||||
assert_parse_number("-0.001", 0, -0.001);
|
||||
assert_parse_number("-10e-10", 0, -10e-10);
|
||||
assert_parse_number("-10E-10", 0, -10e-10);
|
||||
assert_parse_number("-10e20", INT_MIN, -10e20);
|
||||
assert_parse_number("-123e+127", INT_MIN, -123e127);
|
||||
#ifdef CJSON_INT_USE_LONGLONG
|
||||
assert_parse_number("-10e10", -100000000000LL, -10e10);
|
||||
#endif
|
||||
assert_parse_number("-10e20", CJSON_INT_MIN, -10e20);
|
||||
assert_parse_number("-123e+127", CJSON_INT_MIN, -123e127);
|
||||
assert_parse_number("-123e-128", 0, -123e-128);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user