From e5df03c2774748db89fdee7e67f8aa0010b22d3d Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Thu, 11 Oct 2018 20:17:52 +0800 Subject: [PATCH] feat(cjson): Add function to encode json number when "sprintf" not support float Newlib use nano mode as default. When enable nano mode, cjson use internal function to encode for float data. Otherwise using "sprintf" to encode float data. --- components/cjson/cJSON/cJSON.c | 47 +++++++++++++++++++++++++++++++++- components/cjson/component.mk | 4 +++ components/newlib/Kconfig | 2 +- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/components/cjson/cJSON/cJSON.c b/components/cjson/cJSON/cJSON.c index 15d3fef4..cbc62a21 100644 --- a/components/cjson/cJSON/cJSON.c +++ b/components/cjson/cJSON/cJSON.c @@ -56,6 +56,10 @@ #pragma GCC visibility pop #endif +#ifndef CJSON_SPRINTF_FLOAT +#define CJSON_SPRINTF_FLOAT 0 +#endif + #include "cJSON.h" /* define our own boolean type */ @@ -480,7 +484,6 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out size_t i = 0; unsigned char number_buffer[26]; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); - double test; if (output_buffer == NULL) { @@ -494,6 +497,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } else { +#if CJSON_SPRINTF_FLOAT + double test; + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ length = sprintf((char*)number_buffer, "%1.15g", d); @@ -503,6 +509,45 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out /* If not, print with 17 decimal places of precision */ length = sprintf((char*)number_buffer, "%1.17g", d); } +#else + long d32 = (long)d; + + length = sprintf((char*)number_buffer, "%ld", d32); + + if ((double)d32 != d) { + size_t precision = 14; + unsigned char *pbuf = number_buffer; + + if (d < 0.0) { + d = (double)d32 - d + 0.00000000000001; + } else { + d = d - (double)d32; + } + + pbuf = &number_buffer[length]; + *pbuf++ = '.'; + length++; + + while (d > 0.0 && precision--) { + d *= 10.0; + unsigned char tmp = (unsigned char)d; + + *pbuf++ = tmp + '0'; + length++; + + d -= (double)tmp; + } + + pbuf = &number_buffer[length - 1]; + + while (*pbuf == '0') { + pbuf--; + length--; + } + + *++pbuf = 0; + } +#endif } /* sprintf failed or buffer overrun occured */ diff --git a/components/cjson/component.mk b/components/cjson/component.mk index e404f24c..9b2da22a 100644 --- a/components/cjson/component.mk +++ b/components/cjson/component.mk @@ -4,3 +4,7 @@ COMPONENT_ADD_INCLUDEDIRS += cJSON COMPONENT_SRCDIRS := cJSON + +ifdef CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL +CFLAGS += -DCJSON_SPRINTF_FLOAT=1 +endif diff --git a/components/newlib/Kconfig b/components/newlib/Kconfig index 565d1947..527130f4 100644 --- a/components/newlib/Kconfig +++ b/components/newlib/Kconfig @@ -11,7 +11,7 @@ config NEWLIB_ENABLE choice NEWLIB_LIBRARY_LEVEL prompt "newlib level" - default NEWLIB_LIBRARY_LEVEL_NORMAL + default NEWLIB_LIBRARY_LEVEL_NANO depends on NEWLIB_ENABLE help Choose newlib library level.