aboutsummaryrefslogtreecommitdiff
path: root/lua_cjson.c
diff options
context:
space:
mode:
Diffstat (limited to 'lua_cjson.c')
-rw-r--r--lua_cjson.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/lua_cjson.c b/lua_cjson.c
index f765883..151fa39 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -44,7 +44,30 @@
44 44
45#include "strbuf.h" 45#include "strbuf.h"
46 46
47#ifdef USE_POSIX_LOCALE
48/* Reset locale to POSIX for strtod() / sprintf().
49 * Some locales use comma as a decimal separator. This breaks JSON. */
50
51/* unistd.h defines _POSIX_VERSION */
52#include <unistd.h>
53#if _POSIX_VERSION >= 200809L
54/* POSIX.1-2008 adds threadsafe locale support */
55#include <locale.h>
56#elif defined(_POSIX_VERSION)
57/* Some pre-POSIX.1-2008 operating systems use xlocale.h instead */
58#include <xlocale.h>
59#else
60#error Missing _POSIX_VERSION define
61#endif
62#define LOCALE_SET_POSIX(x) (x)->saved_locale = uselocale((x)->posix_locale)
63#define LOCALE_RESTORE(x) uselocale((x)->saved_locale)
64#else
65#define LOCALE_SET_POSIX(x) do { } while(0)
66#define LOCALE_RESTORE(x) do { } while(0)
67#endif
68
47#ifdef MISSING_ISINF 69#ifdef MISSING_ISINF
70/* Some Solaris platforms are missing isinf(). Define here. */
48#define isinf(x) (!isnan(x) && isnan((x) - (x))) 71#define isinf(x) (!isnan(x) && isnan((x) - (x)))
49#endif 72#endif
50 73
@@ -99,6 +122,10 @@ typedef struct {
99 char *char2escape[256]; /* Encoding */ 122 char *char2escape[256]; /* Encoding */
100#endif 123#endif
101 strbuf_t encode_buf; 124 strbuf_t encode_buf;
125#if USE_POSIX_LOCALE
126 locale_t saved_locale;
127 locale_t posix_locale;
128#endif
102 char number_fmt[8]; /* "%.XXg\0" */ 129 char number_fmt[8]; /* "%.XXg\0" */
103 int current_depth; 130 int current_depth;
104 131
@@ -342,6 +369,10 @@ static int json_destroy_config(lua_State *l)
342 json_config_t *cfg; 369 json_config_t *cfg;
343 370
344 cfg = lua_touserdata(l, 1); 371 cfg = lua_touserdata(l, 1);
372#ifdef USE_POSIX_LOCALE
373 if (cfg->posix_locale)
374 freelocale(cfg->posix_locale);
375#endif
345 if (cfg) 376 if (cfg)
346 strbuf_free(&cfg->encode_buf); 377 strbuf_free(&cfg->encode_buf);
347 cfg = NULL; 378 cfg = NULL;
@@ -363,6 +394,13 @@ static void json_create_config(lua_State *l)
363 lua_setmetatable(l, -2); 394 lua_setmetatable(l, -2);
364 395
365 strbuf_init(&cfg->encode_buf, 0); 396 strbuf_init(&cfg->encode_buf, 0);
397#if USE_POSIX_LOCALE
398 cfg->saved_locale = NULL;
399 /* Must not lua_error() before cfg->posix_locale has been initialised */
400 cfg->posix_locale = newlocale(LC_ALL_MASK, "C", NULL);
401 if (!cfg->posix_locale)
402 luaL_error(l, "Failed to create POSIX locale for JSON");
403#endif
366 404
367 cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT; 405 cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;
368 cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO; 406 cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;
@@ -452,6 +490,7 @@ static void json_encode_exception(lua_State *l, json_config_t *cfg, int lindex,
452{ 490{
453 if (!cfg->encode_keep_buffer) 491 if (!cfg->encode_keep_buffer)
454 strbuf_free(&cfg->encode_buf); 492 strbuf_free(&cfg->encode_buf);
493 LOCALE_RESTORE(cfg);
455 luaL_error(l, "Cannot serialise %s: %s", 494 luaL_error(l, "Cannot serialise %s: %s",
456 lua_typename(l, lua_type(l, lindex)), reason); 495 lua_typename(l, lua_type(l, lindex)), reason);
457} 496}
@@ -542,6 +581,7 @@ static void json_encode_descend(lua_State *l, json_config_t *cfg)
542 if (cfg->current_depth > cfg->encode_max_depth) { 581 if (cfg->current_depth > cfg->encode_max_depth) {
543 if (!cfg->encode_keep_buffer) 582 if (!cfg->encode_keep_buffer)
544 strbuf_free(&cfg->encode_buf); 583 strbuf_free(&cfg->encode_buf);
584 LOCALE_RESTORE(cfg);
545 luaL_error(l, "Cannot serialise, excessive nesting (%d)", 585 luaL_error(l, "Cannot serialise, excessive nesting (%d)",
546 cfg->current_depth); 586 cfg->current_depth);
547 } 587 }
@@ -701,9 +741,13 @@ static int json_encode(lua_State *l)
701 else 741 else
702 strbuf_init(&cfg->encode_buf, 0); 742 strbuf_init(&cfg->encode_buf, 0);
703 743
744 LOCALE_SET_POSIX(cfg);
745
704 json_append_data(l, cfg, &cfg->encode_buf); 746 json_append_data(l, cfg, &cfg->encode_buf);
705 json = strbuf_string(&cfg->encode_buf, &len); 747 json = strbuf_string(&cfg->encode_buf, &len);
706 748
749 LOCALE_RESTORE(cfg);
750
707 lua_pushlstring(l, json, len); 751 lua_pushlstring(l, json, len);
708 752
709 if (!cfg->encode_keep_buffer) 753 if (!cfg->encode_keep_buffer)
@@ -1084,6 +1128,8 @@ static void json_throw_parse_error(lua_State *l, json_parse_t *json,
1084 else 1128 else
1085 found = json_token_type_name[token->type]; 1129 found = json_token_type_name[token->type];
1086 1130
1131 LOCALE_RESTORE(json->cfg);
1132
1087 /* Note: token->index is 0 based, display starting from 1 */ 1133 /* Note: token->index is 0 based, display starting from 1 */
1088 luaL_error(l, "Expected %s but found %s at character %d", 1134 luaL_error(l, "Expected %s but found %s at character %d",
1089 exp, found, token->index + 1); 1135 exp, found, token->index + 1);
@@ -1095,6 +1141,7 @@ static void json_decode_checkstack(lua_State *l, json_parse_t *json, int n)
1095 return; 1141 return;
1096 1142
1097 strbuf_free(json->tmp); 1143 strbuf_free(json->tmp);
1144 LOCALE_RESTORE(json->cfg);
1098 luaL_error(l, "Too many nested data structures"); 1145 luaL_error(l, "Too many nested data structures");
1099} 1146}
1100 1147
@@ -1224,6 +1271,8 @@ static void lua_json_decode(lua_State *l, const char *json_text, int json_len)
1224 * string must be smaller than the entire json string */ 1271 * string must be smaller than the entire json string */
1225 json.tmp = strbuf_new(json_len); 1272 json.tmp = strbuf_new(json_len);
1226 1273
1274 LOCALE_SET_POSIX(json.cfg);
1275
1227 json_next_token(&json, &token); 1276 json_next_token(&json, &token);
1228 json_process_value(l, &json, &token); 1277 json_process_value(l, &json, &token);
1229 1278
@@ -1233,6 +1282,8 @@ static void lua_json_decode(lua_State *l, const char *json_text, int json_len)
1233 if (token.type != T_END) 1282 if (token.type != T_END)
1234 json_throw_parse_error(l, &json, "the end", &token); 1283 json_throw_parse_error(l, &json, "the end", &token);
1235 1284
1285 LOCALE_RESTORE(json.cfg);
1286
1236 strbuf_free(json.tmp); 1287 strbuf_free(json.tmp);
1237} 1288}
1238 1289