diff options
Diffstat (limited to '')
| -rw-r--r-- | lua_cjson.c | 141 | 
1 files changed, 94 insertions, 47 deletions
| diff --git a/lua_cjson.c b/lua_cjson.c index cab1922..df3b71c 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
| @@ -85,7 +85,11 @@ static const char *json_token_type_name[] = { | |||
| 85 | 85 | ||
| 86 | typedef struct { | 86 | typedef struct { | 
| 87 | json_token_type_t ch2token[256]; | 87 | json_token_type_t ch2token[256]; | 
| 88 | char ch2escape[256]; | 88 | char escape2char[256]; /* Decoding */ | 
| 89 | #if 0 | ||
| 90 | char escapes[35][8]; /* Pre-generated escape string buffer */ | ||
| 91 | char *char2escape[256]; /* Encoding */ | ||
| 92 | #endif | ||
| 89 | strbuf_t encode_buf; | 93 | strbuf_t encode_buf; | 
| 90 | int sparse_ratio; | 94 | int sparse_ratio; | 
| 91 | int max_depth; | 95 | int max_depth; | 
| @@ -111,10 +115,49 @@ typedef struct { | |||
| 111 | int string_len; | 115 | int string_len; | 
| 112 | } json_token_t; | 116 | } json_token_t; | 
| 113 | 117 | ||
| 114 | /* ===== CONFIGURATION ===== */ | 118 | static const char *char2escape[256] = { | 
| 119 | "\\u0000", "\\u0001", "\\u0002", "\\u0003", | ||
| 120 | "\\u0004", "\\u0005", "\\u0006", "\\u0007", | ||
| 121 | "\\b", "\\t", "\\n", "\\u000b", | ||
| 122 | "\\f", "\\r", "\\u000e", "\\u000f", | ||
| 123 | "\\u0010", "\\u0011", "\\u0012", "\\u0013", | ||
| 124 | "\\u0014", "\\u0015", "\\u0016", "\\u0017", | ||
| 125 | "\\u0018", "\\u0019", "\\u001a", "\\u001b", | ||
| 126 | "\\u001c", "\\u001d", "\\u001e", "\\u001f", | ||
| 127 | NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL, | ||
| 128 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 129 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 130 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 131 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 132 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 133 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 134 | NULL, NULL, NULL, NULL, "\\\\", NULL, NULL, NULL, | ||
| 135 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 136 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 137 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 138 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\u007f", | ||
| 139 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 140 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 141 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 142 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 143 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 144 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 145 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 146 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 147 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 148 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 149 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 150 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 151 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 152 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 153 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 154 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 155 | }; | ||
| 115 | 156 | ||
| 116 | static int json_config_key; | 157 | static int json_config_key; | 
| 117 | 158 | ||
| 159 | /* ===== CONFIGURATION ===== */ | ||
| 160 | |||
| 118 | static json_config_t *json_fetch_config(lua_State *l) | 161 | static json_config_t *json_fetch_config(lua_State *l) | 
| 119 | { | 162 | { | 
| 120 | json_config_t *cfg; | 163 | json_config_t *cfg; | 
| @@ -201,6 +244,12 @@ static void json_create_config(lua_State *l) | |||
| 201 | 244 | ||
| 202 | cfg = lua_newuserdata(l, sizeof(*cfg)); | 245 | cfg = lua_newuserdata(l, sizeof(*cfg)); | 
| 203 | 246 | ||
| 247 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; | ||
| 248 | cfg->max_depth = DEFAULT_MAX_DEPTH; | ||
| 249 | cfg->strict_numbers = 1; | ||
| 250 | |||
| 251 | /* Decoding init */ | ||
| 252 | |||
| 204 | /* Tag all characters as an error */ | 253 | /* Tag all characters as an error */ | 
| 205 | for (i = 0; i < 256; i++) | 254 | for (i = 0; i < 256; i++) | 
| 206 | cfg->ch2token[i] = T_ERROR; | 255 | cfg->ch2token[i] = T_ERROR; | 
| @@ -233,22 +282,45 @@ static void json_create_config(lua_State *l) | |||
| 233 | 282 | ||
| 234 | /* Lookup table for parsing escape characters */ | 283 | /* Lookup table for parsing escape characters */ | 
| 235 | for (i = 0; i < 256; i++) | 284 | for (i = 0; i < 256; i++) | 
| 236 | cfg->ch2escape[i] = 0; /* String error */ | 285 | cfg->escape2char[i] = 0; /* String error */ | 
| 237 | cfg->ch2escape['"'] = '"'; | 286 | cfg->escape2char['"'] = '"'; | 
| 238 | cfg->ch2escape['\\'] = '\\'; | 287 | cfg->escape2char['\\'] = '\\'; | 
| 239 | cfg->ch2escape['/'] = '/'; | 288 | cfg->escape2char['/'] = '/'; | 
| 240 | cfg->ch2escape['b'] = '\b'; | 289 | cfg->escape2char['b'] = '\b'; | 
| 241 | cfg->ch2escape['t'] = '\t'; | 290 | cfg->escape2char['t'] = '\t'; | 
| 242 | cfg->ch2escape['n'] = '\n'; | 291 | cfg->escape2char['n'] = '\n'; | 
| 243 | cfg->ch2escape['f'] = '\f'; | 292 | cfg->escape2char['f'] = '\f'; | 
| 244 | cfg->ch2escape['r'] = '\r'; | 293 | cfg->escape2char['r'] = '\r'; | 
| 245 | cfg->ch2escape['u'] = 'u'; /* Unicode parsing required */ | 294 | cfg->escape2char['u'] = 'u'; /* Unicode parsing required */ | 
| 246 | 295 | ||
| 247 | cfg->sparse_ratio = DEFAULT_SPARSE_RATIO; | 296 | /* Encoding init */ | 
| 248 | cfg->max_depth = DEFAULT_MAX_DEPTH; | ||
| 249 | cfg->strict_numbers = 1; | ||
| 250 | 297 | ||
| 251 | strbuf_init(&cfg->encode_buf, 0); | 298 | strbuf_init(&cfg->encode_buf, 0); | 
| 299 | |||
| 300 | #if 0 | ||
| 301 | /* Initialise separate storage for pre-generated escape codes. | ||
| 302 | * Escapes 0-31 map directly, 34, 92, 127 follow afterwards to | ||
| 303 | * save memory. */ | ||
| 304 | for (i = 0 ; i < 32; i++) | ||
| 305 | sprintf(cfg->escapes[i], "\\u%04x", i); | ||
| 306 | strcpy(cfg->escapes[8], "\b"); /* Override simpler escapes */ | ||
| 307 | strcpy(cfg->escapes[9], "\t"); | ||
| 308 | strcpy(cfg->escapes[10], "\n"); | ||
| 309 | strcpy(cfg->escapes[12], "\f"); | ||
| 310 | strcpy(cfg->escapes[13], "\r"); | ||
| 311 | strcpy(cfg->escapes[32], "\\\""); /* chr(34) */ | ||
| 312 | strcpy(cfg->escapes[33], "\\\\"); /* chr(92) */ | ||
| 313 | sprintf(cfg->escapes[34], "\\u%04x", 127); /* char(127) */ | ||
| 314 | |||
| 315 | /* Initialise encoding escape lookup table */ | ||
| 316 | for (i = 0; i < 32; i++) | ||
| 317 | cfg->char2escape[i] = cfg->escapes[i]; | ||
| 318 | for (i = 32; i < 256; i++) | ||
| 319 | cfg->char2escape[i] = NULL; | ||
| 320 | cfg->char2escape[34] = cfg->escapes[32]; | ||
| 321 | cfg->char2escape[92] = cfg->escapes[33]; | ||
| 322 | cfg->char2escape[127] = cfg->escapes[34]; | ||
| 323 | #endif | ||
| 252 | } | 324 | } | 
| 253 | 325 | ||
| 254 | /* ===== ENCODING ===== */ | 326 | /* ===== ENCODING ===== */ | 
| @@ -259,31 +331,6 @@ static void json_encode_exception(lua_State *l, int lindex, const char *reason) | |||
| 259 | lua_typename(l, lua_type(l, lindex)), reason); | 331 | lua_typename(l, lua_type(l, lindex)), reason); | 
| 260 | } | 332 | } | 
| 261 | 333 | ||
| 262 | /* JSON escape a character if required, or return NULL */ | ||
| 263 | static inline char *json_escape_char(int c) | ||
| 264 | { | ||
| 265 | switch(c) { | ||
| 266 | case 0: | ||
| 267 | return "\\u0000"; | ||
| 268 | case '\\': | ||
| 269 | return "\\\\"; | ||
| 270 | case '"': | ||
| 271 | return "\\\""; | ||
| 272 | case '\b': | ||
| 273 | return "\\b"; | ||
| 274 | case '\t': | ||
| 275 | return "\\t"; | ||
| 276 | case '\n': | ||
| 277 | return "\\n"; | ||
| 278 | case '\f': | ||
| 279 | return "\\f"; | ||
| 280 | case '\r': | ||
| 281 | return "\\r"; | ||
| 282 | } | ||
| 283 | |||
| 284 | return NULL; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* json_append_string args: | 334 | /* json_append_string args: | 
| 288 | * - lua_State | 335 | * - lua_State | 
| 289 | * - JSON strbuf | 336 | * - JSON strbuf | 
| @@ -292,7 +339,7 @@ static inline char *json_escape_char(int c) | |||
| 292 | * Returns nothing. Doesn't remove string from Lua stack */ | 339 | * Returns nothing. Doesn't remove string from Lua stack */ | 
| 293 | static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | 340 | static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | 
| 294 | { | 341 | { | 
| 295 | const char *p; | 342 | const char *escstr; | 
| 296 | int i; | 343 | int i; | 
| 297 | const char *str; | 344 | const char *str; | 
| 298 | size_t len; | 345 | size_t len; | 
| @@ -307,9 +354,9 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | |||
| 307 | 354 | ||
| 308 | strbuf_append_char_unsafe(json, '\"'); | 355 | strbuf_append_char_unsafe(json, '\"'); | 
| 309 | for (i = 0; i < len; i++) { | 356 | for (i = 0; i < len; i++) { | 
| 310 | p = json_escape_char(str[i]); | 357 | escstr = char2escape[(unsigned char)str[i]]; | 
| 311 | if (p) | 358 | if (escstr) | 
| 312 | strbuf_append_string(json, p); | 359 | strbuf_append_string(json, escstr); | 
| 313 | else | 360 | else | 
| 314 | strbuf_append_char_unsafe(json, str[i]); | 361 | strbuf_append_char_unsafe(json, str[i]); | 
| 315 | } | 362 | } | 
| @@ -625,7 +672,7 @@ static void json_set_token_error(json_token_t *token, json_parse_t *json, | |||
| 625 | 672 | ||
| 626 | static void json_next_string_token(json_parse_t *json, json_token_t *token) | 673 | static void json_next_string_token(json_parse_t *json, json_token_t *token) | 
| 627 | { | 674 | { | 
| 628 | char *ch2escape = json->cfg->ch2escape; | 675 | char *escape2char = json->cfg->escape2char; | 
| 629 | char ch; | 676 | char ch; | 
| 630 | 677 | ||
| 631 | /* Caller must ensure a string is next */ | 678 | /* Caller must ensure a string is next */ | 
| @@ -650,7 +697,7 @@ static void json_next_string_token(json_parse_t *json, json_token_t *token) | |||
| 650 | ch = json->data[json->index + 1]; | 697 | ch = json->data[json->index + 1]; | 
| 651 | 698 | ||
| 652 | /* Translate escape code and append to tmp string */ | 699 | /* Translate escape code and append to tmp string */ | 
| 653 | ch = ch2escape[(unsigned char)ch]; | 700 | ch = escape2char[(unsigned char)ch]; | 
| 654 | if (ch == 'u') { | 701 | if (ch == 'u') { | 
| 655 | if (json_append_unicode_escape(json) == 0) | 702 | if (json_append_unicode_escape(json) == 0) | 
| 656 | continue; | 703 | continue; | 
