From f0232f21bd026ebbf57261f0f87b28a1602a0994 Mon Sep 17 00:00:00 2001 From: Hironobu Ishii Date: Mon, 8 May 2023 22:31:27 +0900 Subject: [PATCH 1/2] Fix build error in print_string.c when using MSVC --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d34969d3..882a17873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS) /W4 /wd4001 /D_CRT_SECURE_NO_WARNINGS + /utf-8 ) endif() endif() From decce2ce6f963d8b0983927943a7cb3c1e340cc4 Mon Sep 17 00:00:00 2001 From: Hironobu Ishii Date: Mon, 8 May 2023 22:49:20 +0900 Subject: [PATCH 2/2] Fix an issue where 16-digit integers ending with 0 are printed in exponential format --- cJSON.c | 24 ++++++++++++++++++++---- tests/print_number.c | 6 ++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/cJSON.c b/cJSON.c index 524ba4641..ee2166dd2 100644 --- a/cJSON.c +++ b/cJSON.c @@ -541,6 +541,15 @@ static cJSON_bool compare_double(double a, double b) return (fabs(a - b) <= maxVal * DBL_EPSILON); } +/* check if the double value is in the range [-(2^53-1), 2^53-1] and has no fractional part */ +#define Number_MAX_SAFE_INTEGER (9007199254740991.0) /* 2^53-1 (double constant) */ +static cJSON_bool is_safe_integer(double d) +{ + double abs_d = fabs(d); + double trunc_d = d >= 0 ? floor(d) : -floor(-d); + return (abs_d <= Number_MAX_SAFE_INTEGER && (fabs(d - trunc_d) <= abs_d * DBL_EPSILON)); +} + /* Render the number nicely from the given item into a string. */ static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) { @@ -562,10 +571,17 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out { length = sprintf((char*)number_buffer, "null"); } - else if(d == (double)item->valueint) - { - length = sprintf((char*)number_buffer, "%d", item->valueint); - } + else if (d == (double)item->valueint) + { + length = sprintf((char*)number_buffer, "%d", item->valueint); + } + else if (is_safe_integer(d)) + { + /* Avoid exponential expression in case of integer between + * Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER + */ + length = sprintf((char*)number_buffer, "%.0f", d); + } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ diff --git a/tests/print_number.c b/tests/print_number.c index 3fbf9cb64..89f87d5cd 100644 --- a/tests/print_number.c +++ b/tests/print_number.c @@ -72,6 +72,8 @@ static void print_number_should_print_negative_integers(void) assert_print_number("-1", -1.0); assert_print_number("-32768", -32768.0); assert_print_number("-2147483648", -2147483648.0); + assert_print_number("-9007199254740990", -9007199254740990.0); + assert_print_number("-9007199254740991", -9007199254740991.0); } static void print_number_should_print_positive_integers(void) @@ -79,6 +81,8 @@ static void print_number_should_print_positive_integers(void) assert_print_number("1", 1.0); assert_print_number("32767", 32767.0); assert_print_number("2147483647", 2147483647.0); + assert_print_number("9007199254740990", 9007199254740990.0); + assert_print_number("9007199254740991", 9007199254740991.0); } static void print_number_should_print_positive_reals(void) @@ -89,6 +93,7 @@ static void print_number_should_print_positive_reals(void) assert_print_number("1.23e+129", 123e+127); assert_print_number("1.23e-126", 123e-128); assert_print_number("3.1415926535897931", 3.1415926535897931); + assert_print_number("9.10719925474099e+15", 9107199254740991.5); } static void print_number_should_print_negative_reals(void) @@ -98,6 +103,7 @@ static void print_number_should_print_negative_reals(void) assert_print_number("-1e+21", -10e20); assert_print_number("-1.23e+129", -123e+127); assert_print_number("-1.23e-126", -123e-128); + assert_print_number("-9.10719925474099e+15", -9107199254740991.5); } static void print_number_should_print_non_number(void)