diff options
Diffstat (limited to '')
-rw-r--r-- | lua-cjson-1.0devel-1.rockspec | 4 | ||||
-rw-r--r-- | lua_cjson.c | 36 |
2 files changed, 23 insertions, 17 deletions
diff --git a/lua-cjson-1.0devel-1.rockspec b/lua-cjson-1.0devel-1.rockspec index 3890ec1..fa20c53 100644 --- a/lua-cjson-1.0devel-1.rockspec +++ b/lua-cjson-1.0devel-1.rockspec | |||
@@ -23,11 +23,11 @@ build = { | |||
23 | type = "builtin", | 23 | type = "builtin", |
24 | modules = { | 24 | modules = { |
25 | cjson = { | 25 | cjson = { |
26 | sources = { "lua_cjson.c", "strbuf.c" }, | 26 | sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" }, |
27 | defines = { | ||
27 | -- Optional workaround: | 28 | -- Optional workaround: |
28 | -- USE_INTERNAL_ISINF: Provide internal isinf() implementation. Required | 29 | -- USE_INTERNAL_ISINF: Provide internal isinf() implementation. Required |
29 | -- on some Solaris platforms. | 30 | -- on some Solaris platforms. |
30 | defines = { | ||
31 | -- LuaRocks does not support platform specific configuration for Solaris. | 31 | -- LuaRocks does not support platform specific configuration for Solaris. |
32 | -- Uncomment the line below on Solaris platforms. | 32 | -- Uncomment the line below on Solaris platforms. |
33 | -- "USE_INTERNAL_ISINF" | 33 | -- "USE_INTERNAL_ISINF" |
diff --git a/lua_cjson.c b/lua_cjson.c index f5ea0dd..8e9b237 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <lauxlib.h> | 43 | #include <lauxlib.h> |
44 | 44 | ||
45 | #include "strbuf.h" | 45 | #include "strbuf.h" |
46 | #include "fpconv.h" | ||
46 | 47 | ||
47 | #ifndef CJSON_VERSION | 48 | #ifndef CJSON_VERSION |
48 | #define CJSON_VERSION "1.0devel" | 49 | #define CJSON_VERSION "1.0devel" |
@@ -60,6 +61,7 @@ | |||
60 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 | 61 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 |
61 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 | 62 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 |
62 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 | 63 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 |
64 | #define DEFAULT_ENCODE_NUMBER_PRECISION 14 | ||
63 | 65 | ||
64 | typedef enum { | 66 | typedef enum { |
65 | T_OBJ_BEGIN, | 67 | T_OBJ_BEGIN, |
@@ -104,7 +106,6 @@ typedef struct { | |||
104 | char *char2escape[256]; /* Encoding */ | 106 | char *char2escape[256]; /* Encoding */ |
105 | #endif | 107 | #endif |
106 | strbuf_t encode_buf; | 108 | strbuf_t encode_buf; |
107 | char number_fmt[8]; /* "%.XXg\0" */ | ||
108 | int current_depth; | 109 | int current_depth; |
109 | 110 | ||
110 | int encode_sparse_convert; | 111 | int encode_sparse_convert; |
@@ -253,12 +254,6 @@ static int json_cfg_encode_max_depth(lua_State *l) | |||
253 | return 1; | 254 | return 1; |
254 | } | 255 | } |
255 | 256 | ||
256 | static void json_set_number_precision(json_config_t *cfg, int prec) | ||
257 | { | ||
258 | cfg->encode_number_precision = prec; | ||
259 | sprintf(cfg->number_fmt, "%%.%dg", prec); | ||
260 | } | ||
261 | |||
262 | /* Configures number precision when converting doubles to text */ | 257 | /* Configures number precision when converting doubles to text */ |
263 | static int json_cfg_encode_number_precision(lua_State *l) | 258 | static int json_cfg_encode_number_precision(lua_State *l) |
264 | { | 259 | { |
@@ -272,7 +267,7 @@ static int json_cfg_encode_number_precision(lua_State *l) | |||
272 | precision = luaL_checkinteger(l, 1); | 267 | precision = luaL_checkinteger(l, 1); |
273 | luaL_argcheck(l, 1 <= precision && precision <= 14, 1, | 268 | luaL_argcheck(l, 1 <= precision && precision <= 14, 1, |
274 | "expected integer between 1 and 14"); | 269 | "expected integer between 1 and 14"); |
275 | json_set_number_precision(cfg, precision); | 270 | cfg->encode_number_precision = precision; |
276 | } | 271 | } |
277 | 272 | ||
278 | lua_pushinteger(l, cfg->encode_number_precision); | 273 | lua_pushinteger(l, cfg->encode_number_precision); |
@@ -342,6 +337,13 @@ static int json_cfg_refuse_invalid_numbers(lua_State *l) | |||
342 | return 1; | 337 | return 1; |
343 | } | 338 | } |
344 | 339 | ||
340 | static int json_update_locale(lua_State *l) | ||
341 | { | ||
342 | fpconv_update_locale(); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
345 | static int json_destroy_config(lua_State *l) | 347 | static int json_destroy_config(lua_State *l) |
346 | { | 348 | { |
347 | json_config_t *cfg; | 349 | json_config_t *cfg; |
@@ -376,7 +378,7 @@ static void json_create_config(lua_State *l) | |||
376 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; | 378 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; |
377 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; | 379 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; |
378 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; | 380 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; |
379 | json_set_number_precision(cfg, 14); | 381 | cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; |
380 | 382 | ||
381 | /* Decoding init */ | 383 | /* Decoding init */ |
382 | 384 | ||
@@ -562,6 +564,7 @@ static void json_append_number(lua_State *l, strbuf_t *json, int index, | |||
562 | json_config_t *cfg) | 564 | json_config_t *cfg) |
563 | { | 565 | { |
564 | double num = lua_tonumber(l, index); | 566 | double num = lua_tonumber(l, index); |
567 | int len; | ||
565 | 568 | ||
566 | if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num))) | 569 | if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num))) |
567 | json_encode_exception(l, cfg, index, "must not be NaN or Inf"); | 570 | json_encode_exception(l, cfg, index, "must not be NaN or Inf"); |
@@ -571,11 +574,10 @@ static void json_append_number(lua_State *l, strbuf_t *json, int index, | |||
571 | strbuf_append_mem(json, "nan", 3); | 574 | strbuf_append_mem(json, "nan", 3); |
572 | } else { | 575 | } else { |
573 | /* Longest double printed with %.14g is 21 characters long: | 576 | /* Longest double printed with %.14g is 21 characters long: |
574 | * -1.7976931348623e+308 | 577 | * -1.7976931348623e+308 */ |
575 | * | 578 | strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); |
576 | * Use 32 to include the \0, and a few extra just in case.. | 579 | len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision); |
577 | */ | 580 | strbuf_extend_length(json, len); |
578 | strbuf_append_fmt(json, 32, cfg->number_fmt, num); | ||
579 | } | 581 | } |
580 | } | 582 | } |
581 | 583 | ||
@@ -963,7 +965,7 @@ static void json_next_number_token(json_parse_t *json, json_token_t *token) | |||
963 | 965 | ||
964 | token->type = T_NUMBER; | 966 | token->type = T_NUMBER; |
965 | startptr = &json->data[json->index]; | 967 | startptr = &json->data[json->index]; |
966 | token->value.number = strtod(&json->data[json->index], &endptr); | 968 | token->value.number = fpconv_strtod(&json->data[json->index], &endptr); |
967 | if (startptr == endptr) | 969 | if (startptr == endptr) |
968 | json_set_token_error(token, json, "invalid number"); | 970 | json_set_token_error(token, json, "invalid number"); |
969 | else | 971 | else |
@@ -1254,9 +1256,13 @@ int luaopen_cjson(lua_State *l) | |||
1254 | { "encode_number_precision", json_cfg_encode_number_precision }, | 1256 | { "encode_number_precision", json_cfg_encode_number_precision }, |
1255 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, | 1257 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, |
1256 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, | 1258 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, |
1259 | { "update_locale", json_update_locale }, | ||
1257 | { NULL, NULL } | 1260 | { NULL, NULL } |
1258 | }; | 1261 | }; |
1259 | 1262 | ||
1263 | /* Update the current locale for g_fmt/strtod */ | ||
1264 | fpconv_update_locale(); | ||
1265 | |||
1260 | /* Use json_config_key as a pointer. | 1266 | /* Use json_config_key as a pointer. |
1261 | * It's faster than using a config string, and more unique */ | 1267 | * It's faster than using a config string, and more unique */ |
1262 | lua_pushlightuserdata(l, &json_config_key); | 1268 | lua_pushlightuserdata(l, &json_config_key); |