diff --git a/CMakeLists.txt b/CMakeLists.txt index c17239b..9bb5314 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ cmake_minimum_required(VERSION 2.6) option(USE_INTERNAL_FPCONV "Use internal strtod() / g_fmt() code for performance") option(MULTIPLE_THREADS "Support multi-threaded apps with internal fpconv - recommended" ON) +option(USE_ECMA_262 "Use ecma-262 formatting rules for internal g_fmt()") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING @@ -18,6 +19,10 @@ endif() find_package(Lua51 REQUIRED) include_directories(${LUA_INCLUDE_DIR}) +if(USE_ECMA_262) + add_definitions(-DUSE_ECMA_262) +endif() + if(NOT USE_INTERNAL_FPCONV) # Use libc number conversion routines (strtod(), sprintf()) set(FPCONV_SOURCES fpconv.c) diff --git a/Makefile b/Makefile index 2361028..35d4d20 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,10 @@ FPCONV_OBJS = fpconv.o #FPCONV_OBJS = g_fmt.o dtoa.o #CJSON_CFLAGS += -DUSE_INTERNAL_FPCONV +## Use ecma-262 formatting rules for internal number conversion +#FPCONV_OBJS = g_fmt.o dtoa.o +#CJSON_CFLAGS += -DUSE_INTERNAL_FPCONV -DUSE_ECMA_262 + ## Compile built in number conversion for big endian architectures #CJSON_CFLAGS += -DIEEE_BIG_ENDIAN diff --git a/g_fmt.c b/g_fmt.c index 50d6a1d..fcfc9f8 100644 --- a/g_fmt.c +++ b/g_fmt.c @@ -58,7 +58,11 @@ fpconv_g_fmt(char *b, double x, int precision) b--; goto done0; } +#ifdef USE_ECMA_262 + if (decpt <= -6 || decpt > 21) { +#else if (decpt <= -4 || decpt > precision) { +#endif *b++ = *s++; if (*s) { *b++ = '.'; @@ -106,6 +110,13 @@ fpconv_g_fmt(char *b, double x, int precision) freedtoa(s0); #ifdef IGNORE_ZERO_SIGN done: +#endif +#ifdef USE_ECMA_262 + int len = b - b0; + if (len >= 4 && b0[len - 4] == 'e' && b0[len-3] == '-' && b0[len-2] == '0') { + b0[len-2] = b0[len - 1]; + *--b = 0; + } #endif return b - b0; }