diff options
author | Mark Pulford <mark@kyne.com.au> | 2011-05-01 16:29:11 +0930 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2011-05-01 16:29:11 +0930 |
commit | a875deda45983379fabf07a4b60064d33dd70d57 (patch) | |
tree | ed7edc06b3e121d1b99bd0f4c063f7664954ac24 | |
parent | bc94292b70be41cecd2bd151b1fffcfa59480118 (diff) | |
download | lua-cjson-a875deda45983379fabf07a4b60064d33dd70d57.tar.gz lua-cjson-a875deda45983379fabf07a4b60064d33dd70d57.tar.bz2 lua-cjson-a875deda45983379fabf07a4b60064d33dd70d57.zip |
Throw error on Inf/NaN by default when encoding
Add runtime configuration for generating Inf/NaN encoding errors through
cjson.strict_numbers().
-rw-r--r-- | lua_cjson.c | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index e5e7d1c..e339d51 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | #include "strbuf.h" | 31 | #include "strbuf.h" |
32 | 32 | ||
33 | |||
34 | #define CJSON_CONFIG_KEY "cjson_configdata" | 33 | #define CJSON_CONFIG_KEY "cjson_configdata" |
35 | #define DEFAULT_SPARSE_RATIO 2 | 34 | #define DEFAULT_SPARSE_RATIO 2 |
36 | #define DEFAULT_MAX_DEPTH 20 | 35 | #define DEFAULT_MAX_DEPTH 20 |
@@ -76,6 +75,7 @@ typedef struct { | |||
76 | int sparse_ratio; | 75 | int sparse_ratio; |
77 | int max_depth; | 76 | int max_depth; |
78 | int current_depth; | 77 | int current_depth; |
78 | int strict_numbers; | ||
79 | } json_config_t; | 79 | } json_config_t; |
80 | 80 | ||
81 | typedef struct { | 81 | typedef struct { |
@@ -112,18 +112,26 @@ static json_config_t *json_fetch_config(lua_State *l) | |||
112 | return cfg; | 112 | return cfg; |
113 | } | 113 | } |
114 | 114 | ||
115 | static int json_sparse_ratio(lua_State *l) | 115 | /* Checks whether a config variable needs to be updated. |
116 | * Also return cfg pointer */ | ||
117 | static int cfg_update_requested(lua_State *l, json_config_t **cfg) | ||
116 | { | 118 | { |
117 | json_config_t *cfg; | ||
118 | int sparse_ratio; | ||
119 | int args; | 119 | int args; |
120 | 120 | ||
121 | args = lua_gettop(l); | 121 | args = lua_gettop(l); |
122 | luaL_argcheck(l, args <= 1, 2, "found too many arguments"); | 122 | luaL_argcheck(l, args <= 1, 2, "found too many arguments"); |
123 | 123 | ||
124 | cfg = json_fetch_config(l); | 124 | *cfg = json_fetch_config(l); |
125 | |||
126 | return args; | ||
127 | } | ||
128 | |||
129 | static int json_sparse_ratio(lua_State *l) | ||
130 | { | ||
131 | json_config_t *cfg; | ||
132 | int sparse_ratio; | ||
125 | 133 | ||
126 | if (args == 1) { | 134 | if (cfg_update_requested(l, &cfg)) { |
127 | sparse_ratio = luaL_checkinteger(l, 1); | 135 | sparse_ratio = luaL_checkinteger(l, 1); |
128 | luaL_argcheck(l, sparse_ratio >= 0, 1, | 136 | luaL_argcheck(l, sparse_ratio >= 0, 1, |
129 | "expected zero or positive integer"); | 137 | "expected zero or positive integer"); |
@@ -139,14 +147,8 @@ static int json_max_depth(lua_State *l) | |||
139 | { | 147 | { |
140 | json_config_t *cfg; | 148 | json_config_t *cfg; |
141 | int max_depth; | 149 | int max_depth; |
142 | int args; | ||
143 | |||
144 | args = lua_gettop(l); | ||
145 | luaL_argcheck(l, args <= 1, 2, "found too many arguments"); | ||
146 | 150 | ||
147 | cfg = json_fetch_config(l); | 151 | if (cfg_update_requested(l, &cfg)) { |
148 | |||
149 | if (args == 1) { | ||
150 | max_depth = luaL_checkinteger(l, 1); | 152 | max_depth = luaL_checkinteger(l, 1); |
151 | luaL_argcheck(l, max_depth > 0, 1, "expected positive integer"); | 153 | luaL_argcheck(l, max_depth > 0, 1, "expected positive integer"); |
152 | cfg->max_depth = max_depth; | 154 | cfg->max_depth = max_depth; |
@@ -157,6 +159,20 @@ static int json_max_depth(lua_State *l) | |||
157 | return 1; | 159 | return 1; |
158 | } | 160 | } |
159 | 161 | ||
162 | static int json_strict_numbers(lua_State *l) | ||
163 | { | ||
164 | json_config_t *cfg; | ||
165 | |||
166 | if (cfg_update_requested(l, &cfg)) { | ||
167 | luaL_argcheck(l, lua_isboolean(l, 1), 1, "expected boolean"); | ||
168 | cfg->strict_numbers = lua_toboolean(l, 1); | ||
169 | } | ||
170 | |||
171 | lua_pushboolean(l, cfg->strict_numbers); | ||
172 | |||
173 | return 1; | ||
174 | } | ||
175 | |||
160 | static void json_create_config(lua_State *l) | 176 | static void json_create_config(lua_State *l) |
161 | { | 177 | { |
162 | json_config_t *cfg; | 178 | json_config_t *cfg; |
@@ -205,6 +221,7 @@ static void json_create_config(lua_State *l) | |||
205 | 221 | ||
206 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; | 222 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; |
207 | cfg->max_depth = DEFAULT_MAX_DEPTH; | 223 | cfg->max_depth = DEFAULT_MAX_DEPTH; |
224 | cfg->strict_numbers = 1; | ||
208 | } | 225 | } |
209 | 226 | ||
210 | /* ===== ENCODING ===== */ | 227 | /* ===== ENCODING ===== */ |
@@ -360,6 +377,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, strbuf_t *json, | |||
360 | cfg->current_depth--; | 377 | cfg->current_depth--; |
361 | } | 378 | } |
362 | 379 | ||
380 | static void json_append_number(lua_State *l, strbuf_t *json, int index, | ||
381 | int strict) | ||
382 | { | ||
383 | double num = lua_tonumber(l, index); | ||
384 | |||
385 | if (strict && (isinf(num) || isnan(num))) | ||
386 | json_encode_exception(l, json, index, "must not be NaN of Inf"); | ||
387 | |||
388 | strbuf_append_fmt(json, LUA_NUMBER_FMT, num); | ||
389 | } | ||
390 | |||
363 | static void json_append_object(lua_State *l, json_config_t *cfg, | 391 | static void json_append_object(lua_State *l, json_config_t *cfg, |
364 | strbuf_t *json) | 392 | strbuf_t *json) |
365 | { | 393 | { |
@@ -382,8 +410,12 @@ static void json_append_object(lua_State *l, json_config_t *cfg, | |||
382 | /* table, key, value */ | 410 | /* table, key, value */ |
383 | keytype = lua_type(l, -2); | 411 | keytype = lua_type(l, -2); |
384 | if (keytype == LUA_TNUMBER) { | 412 | if (keytype == LUA_TNUMBER) { |
385 | strbuf_append_fmt(json, "\"" LUA_NUMBER_FMT "\": ", | 413 | /* Can't just use json_append_string() below since it would |
386 | lua_tonumber(l, -2)); | 414 | * convert the value in the callers data structure, and it |
415 | * does not support strict numbers */ | ||
416 | strbuf_append_char(json, '"'); | ||
417 | json_append_number(l, json, -2, cfg->strict_numbers); | ||
418 | strbuf_append_string(json, "\": "); | ||
387 | } else if (keytype == LUA_TSTRING) { | 419 | } else if (keytype == LUA_TSTRING) { |
388 | json_append_string(l, json, -2); | 420 | json_append_string(l, json, -2); |
389 | strbuf_append_string(json, ": "); | 421 | strbuf_append_string(json, ": "); |
@@ -414,7 +446,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json) | |||
414 | json_append_string(l, json, -1); | 446 | json_append_string(l, json, -1); |
415 | break; | 447 | break; |
416 | case LUA_TNUMBER: | 448 | case LUA_TNUMBER: |
417 | strbuf_append_fmt(json, "%lf", lua_tonumber(l, -1)); | 449 | json_append_number(l, json, -1, cfg->strict_numbers); |
418 | break; | 450 | break; |
419 | case LUA_TBOOLEAN: | 451 | case LUA_TBOOLEAN: |
420 | if (lua_toboolean(l, -1)) | 452 | if (lua_toboolean(l, -1)) |
@@ -893,6 +925,7 @@ int luaopen_cjson(lua_State *l) | |||
893 | { "decode", json_decode }, | 925 | { "decode", json_decode }, |
894 | { "sparse_ratio", json_sparse_ratio }, | 926 | { "sparse_ratio", json_sparse_ratio }, |
895 | { "max_depth", json_max_depth }, | 927 | { "max_depth", json_max_depth }, |
928 | { "strict_numbers", json_strict_numbers }, | ||
896 | { NULL, NULL } | 929 | { NULL, NULL } |
897 | }; | 930 | }; |
898 | 931 | ||