mirror of
https://github.com/DaveGamble/cJSON.git
synced 2023-08-10 21:13:26 +03:00
Merge pull request #123 from DaveGamble/trim-numbers
Remove traling zeroes when printing floating point numbers
This commit is contained in:
commit
0aea75fbda
97
cJSON.c
97
cJSON.c
@ -324,55 +324,90 @@ static void update_offset(printbuffer * const buffer)
|
|||||||
buffer->offset += strlen((const char*)buffer_pointer);
|
buffer->offset += strlen((const char*)buffer_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Removes trailing zeroes from the end of a printed number */
|
||||||
|
static unsigned char *trim_trailing_zeroes(printbuffer * const buffer)
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
unsigned char *content = NULL;
|
||||||
|
|
||||||
|
if ((buffer == NULL) || (buffer->buffer == NULL) || (buffer->offset < 1))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = buffer->offset - 1;
|
||||||
|
content = buffer->buffer;
|
||||||
|
|
||||||
|
while ((offset > 0) && (content[offset] == '0'))
|
||||||
|
{
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
|
if ((offset > 0) && (content[offset] == '.'))
|
||||||
|
{
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
content[offset] = '\0';
|
||||||
|
|
||||||
|
buffer->offset = offset;
|
||||||
|
|
||||||
|
return content + offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* Render the number nicely from the given item into a string. */
|
/* Render the number nicely from the given item into a string. */
|
||||||
static unsigned char *print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
|
static unsigned char *print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
|
||||||
{
|
{
|
||||||
unsigned char *output_pointer = NULL;
|
unsigned char *output_pointer = NULL;
|
||||||
double d = item->valuedouble;
|
double d = item->valuedouble;
|
||||||
|
int length = 0;
|
||||||
|
cjbool trim_zeroes = true; /* should at the end be removed? */
|
||||||
|
|
||||||
if (output_buffer == NULL)
|
if (output_buffer == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* value is an int */
|
/* This is a nice tradeoff. */
|
||||||
if ((fabs(((double)item->valueint) - d) <= DBL_EPSILON) && (d <= INT_MAX) && (d >= INT_MIN))
|
output_pointer = ensure(output_buffer, 64, hooks);
|
||||||
|
if (output_pointer != NULL)
|
||||||
{
|
{
|
||||||
/* 2^64+1 can be represented in 21 chars. */
|
/* This checks for NaN and Infinity */
|
||||||
output_pointer = ensure(output_buffer, 21, hooks);
|
if ((d * 0) != 0)
|
||||||
if (output_pointer != NULL)
|
|
||||||
{
|
{
|
||||||
sprintf((char*)output_pointer, "%d", item->valueint);
|
length = sprintf((char*)output_pointer, "null");
|
||||||
}
|
}
|
||||||
}
|
else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
|
||||||
/* value is a floating point number */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is a nice tradeoff. */
|
|
||||||
output_pointer = ensure(output_buffer, 64, hooks);
|
|
||||||
if (output_pointer != NULL)
|
|
||||||
{
|
{
|
||||||
/* This checks for NaN and Infinity */
|
/* integer */
|
||||||
if ((d * 0) != 0)
|
length = sprintf((char*)output_pointer, "%.0f", d);
|
||||||
{
|
trim_zeroes = false; /* don't remove zeroes for "big integers" */
|
||||||
sprintf((char*)output_pointer, "null");
|
}
|
||||||
}
|
else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
|
||||||
else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
|
{
|
||||||
{
|
length = sprintf((char*)output_pointer, "%e", d);
|
||||||
sprintf((char*)output_pointer, "%.0f", d);
|
trim_zeroes = false; /* don't remove zeroes in engineering notation */
|
||||||
}
|
}
|
||||||
else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
|
else
|
||||||
{
|
{
|
||||||
sprintf((char*)output_pointer, "%e", d);
|
length = sprintf((char*)output_pointer, "%f", d);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf((char*)output_pointer, "%f", d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output_pointer;
|
/* sprintf failed */
|
||||||
|
if (length < 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_buffer->offset += (size_t)length;
|
||||||
|
|
||||||
|
if (trim_zeroes)
|
||||||
|
{
|
||||||
|
return trim_trailing_zeroes(output_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output_buffer->buffer + output_buffer->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse 4 digit hexadecimal number */
|
/* parse 4 digit hexadecimal number */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[{
|
[{
|
||||||
"precision": "zip",
|
"precision": "zip",
|
||||||
"Latitude": 37.766800,
|
"Latitude": 37.7668,
|
||||||
"Longitude": -122.395900,
|
"Longitude": -122.3959,
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"City": "SAN FRANCISCO",
|
"City": "SAN FRANCISCO",
|
||||||
"State": "CA",
|
"State": "CA",
|
||||||
@ -10,7 +10,7 @@
|
|||||||
}, {
|
}, {
|
||||||
"precision": "zip",
|
"precision": "zip",
|
||||||
"Latitude": 37.371991,
|
"Latitude": 37.371991,
|
||||||
"Longitude": -122.026020,
|
"Longitude": -122.02602,
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"City": "SUNNYVALE",
|
"City": "SUNNYVALE",
|
||||||
"State": "CA",
|
"State": "CA",
|
||||||
|
@ -62,7 +62,7 @@ static void print_number_should_print_positive_integers(void)
|
|||||||
|
|
||||||
static void print_number_should_print_positive_reals(void)
|
static void print_number_should_print_positive_reals(void)
|
||||||
{
|
{
|
||||||
assert_print_number("0.123000", 0.123);
|
assert_print_number("0.123", 0.123);
|
||||||
assert_print_number("1.000000e-09", 10e-10);
|
assert_print_number("1.000000e-09", 10e-10);
|
||||||
assert_print_number("1000000000000", 10e11);
|
assert_print_number("1000000000000", 10e11);
|
||||||
assert_print_number("1.230000e+129", 123e+127);
|
assert_print_number("1.230000e+129", 123e+127);
|
||||||
@ -71,7 +71,7 @@ static void print_number_should_print_positive_reals(void)
|
|||||||
|
|
||||||
static void print_number_should_print_negative_reals(void)
|
static void print_number_should_print_negative_reals(void)
|
||||||
{
|
{
|
||||||
assert_print_number("-0.012300", -0.0123);
|
assert_print_number("-0.0123", -0.0123);
|
||||||
assert_print_number("-1.000000e-09", -10e-10);
|
assert_print_number("-1.000000e-09", -10e-10);
|
||||||
assert_print_number("-1000000000000000000000", -10e20);
|
assert_print_number("-1000000000000000000000", -10e20);
|
||||||
assert_print_number("-1.230000e+129", -123e+127);
|
assert_print_number("-1.230000e+129", -123e+127);
|
||||||
@ -87,6 +87,22 @@ static void print_number_should_print_non_number(void)
|
|||||||
/* assert_print_number("null", -INFTY); */
|
/* assert_print_number("null", -INFTY); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void trim_trailing_zeroes_should_trim_trailing_zeroes(void)
|
||||||
|
{
|
||||||
|
printbuffer buffer;
|
||||||
|
unsigned char number[100];
|
||||||
|
unsigned char *pointer = NULL;
|
||||||
|
buffer.length = sizeof(number);
|
||||||
|
buffer.buffer = number;
|
||||||
|
|
||||||
|
strcpy((char*)number, "10.00");
|
||||||
|
buffer.offset = sizeof("10.00") - 1;
|
||||||
|
pointer = trim_trailing_zeroes(&buffer);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8('\0', *pointer);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("10", number);
|
||||||
|
TEST_ASSERT_EQUAL_UINT(sizeof("10") - 1, buffer.offset);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
/* initialize cJSON item */
|
/* initialize cJSON item */
|
||||||
@ -98,6 +114,7 @@ int main(void)
|
|||||||
RUN_TEST(print_number_should_print_positive_reals);
|
RUN_TEST(print_number_should_print_positive_reals);
|
||||||
RUN_TEST(print_number_should_print_negative_reals);
|
RUN_TEST(print_number_should_print_negative_reals);
|
||||||
RUN_TEST(print_number_should_print_non_number);
|
RUN_TEST(print_number_should_print_non_number);
|
||||||
|
RUN_TEST(trim_trailing_zeroes_should_trim_trailing_zeroes);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ static void print_value_should_print_false(void)
|
|||||||
|
|
||||||
static void print_value_should_print_number(void)
|
static void print_value_should_print_number(void)
|
||||||
{
|
{
|
||||||
assert_print_value("1.500000");
|
assert_print_value("1.5");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_value_should_print_string(void)
|
static void print_value_should_print_string(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user