diff options
Diffstat (limited to '')
| -rw-r--r-- | lua_cjson.c | 36 | 
1 files changed, 21 insertions, 15 deletions
| 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); | 
