00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "config.h"
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <ctype.h>
00017 #include <string.h>
00018 #include <strings.h>
00019
00020 #include "bits.h"
00021 #include "debug.h"
00022 #include "printbuf.h"
00023 #include "arraylist.h"
00024 #include "json_object.h"
00025 #include "json_tokener.h"
00026
00027
00028 #if !HAVE_STRNCASECMP && defined(_MSC_VER)
00029
00030 # define strncasecmp _strnicmp
00031 #elif !HAVE_STRNCASECMP
00032
00033 #endif
00034
00035
00036 static const char* json_null_str = "null";
00037 static const char* json_true_str = "true";
00038 static const char* json_false_str = "false";
00039
00040 const char* json_tokener_errors[] = {
00041 "success",
00042 "continue",
00043 "nesting to deep",
00044 "unexpected end of data",
00045 "unexpected character",
00046 "null expected",
00047 "boolean expected",
00048 "number expected",
00049 "array value separator ',' expected",
00050 "quoted object property name expected",
00051 "object property name separator ':' expected",
00052 "object value separator ',' expected",
00053 "invalid string sequence",
00054 "expected comment",
00055 };
00056
00057
00058 struct json_tokener* json_tokener_new()
00059 {
00060 struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
00061 tok->pb = printbuf_new();
00062 json_tokener_reset(tok);
00063 return tok;
00064 }
00065
00066 void json_tokener_free(struct json_tokener *tok)
00067 {
00068 json_tokener_reset(tok);
00069 if(tok) printbuf_free(tok->pb);
00070 free(tok);
00071 }
00072
00073 static void json_tokener_reset_level(struct json_tokener *tok, int depth)
00074 {
00075 tok->stack[depth].state = json_tokener_state_eatws;
00076 tok->stack[depth].saved_state = json_tokener_state_start;
00077 json_object_put(tok->stack[depth].current);
00078 tok->stack[depth].current = NULL;
00079 free(tok->stack[depth].obj_field_name);
00080 tok->stack[depth].obj_field_name = NULL;
00081 }
00082
00083 void json_tokener_reset(struct json_tokener *tok)
00084 {
00085 int i;
00086 for(i = tok->depth; i >= 0; i--)
00087 json_tokener_reset_level(tok, i);
00088 tok->depth = 0;
00089 tok->err = json_tokener_success;
00090 }
00091
00092 struct json_object* json_tokener_parse(const char *str)
00093 {
00094 struct json_tokener* tok;
00095 struct json_object* obj;
00096
00097 tok = json_tokener_new();
00098 obj = json_tokener_parse_ex(tok, str, -1);
00099 if(tok->err != json_tokener_success)
00100 obj = error_ptr(-tok->err);
00101 json_tokener_free(tok);
00102 return obj;
00103 }
00104
00105
00106
00107
00108 char* json_c_strndup(const char* str, size_t n)
00109 {
00110 if(str) {
00111 size_t len = strlen(str);
00112 size_t nn = min(len,n);
00113 char* s = (char*)malloc(sizeof(char) * (nn + 1));
00114
00115 if(s) {
00116 memcpy(s, str, nn);
00117 s[nn] = '\0';
00118 }
00119
00120 return s;
00121 }
00122
00123 return NULL;
00124 }
00125
00126
00127
00128 #define state tok->stack[tok->depth].state
00129 #define saved_state tok->stack[tok->depth].saved_state
00130 #define current tok->stack[tok->depth].current
00131 #define obj_field_name tok->stack[tok->depth].obj_field_name
00132
00133 struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
00134 const char *str, int len)
00135 {
00136 struct json_object *obj = NULL;
00137 char c;
00138
00139 tok->char_offset = 0;
00140 tok->err = json_tokener_success;
00141
00142 do {
00143 if(tok->char_offset == len) {
00144 if(tok->depth == 0 && state == json_tokener_state_eatws &&
00145 saved_state == json_tokener_state_finish)
00146 tok->err = json_tokener_success;
00147 else
00148 tok->err = json_tokener_continue;
00149 goto out;
00150 }
00151
00152 c = *str;
00153 redo_char:
00154 switch(state) {
00155
00156 case json_tokener_state_eatws:
00157 if(isspace(c)) {
00158
00159 } else if(c == '/') {
00160 printbuf_reset(tok->pb);
00161 printbuf_memappend(tok->pb, &c, 1);
00162 state = json_tokener_state_comment_start;
00163 } else {
00164 state = saved_state;
00165 goto redo_char;
00166 }
00167 break;
00168
00169 case json_tokener_state_start:
00170 switch(c) {
00171 case '{':
00172 state = json_tokener_state_eatws;
00173 saved_state = json_tokener_state_object_field_start;
00174 current = json_object_new_object();
00175 break;
00176 case '[':
00177 state = json_tokener_state_eatws;
00178 saved_state = json_tokener_state_array;
00179 current = json_object_new_array();
00180 break;
00181 case 'N':
00182 case 'n':
00183 state = json_tokener_state_null;
00184 printbuf_reset(tok->pb);
00185 tok->st_pos = 0;
00186 goto redo_char;
00187 case '"':
00188 case '\'':
00189 state = json_tokener_state_string;
00190 printbuf_reset(tok->pb);
00191 tok->quote_char = c;
00192 break;
00193 case 'T':
00194 case 't':
00195 case 'F':
00196 case 'f':
00197 state = json_tokener_state_boolean;
00198 printbuf_reset(tok->pb);
00199 tok->st_pos = 0;
00200 goto redo_char;
00201 #if 0
00202 case '0' ... '9':
00203 #else
00204 case '0':
00205 case '1':
00206 case '2':
00207 case '3':
00208 case '4':
00209 case '5':
00210 case '6':
00211 case '7':
00212 case '8':
00213 case '9':
00214 #endif
00215 case '-':
00216 state = json_tokener_state_number;
00217 printbuf_reset(tok->pb);
00218 tok->is_double = 0;
00219 goto redo_char;
00220 default:
00221 tok->err = json_tokener_error_parse_unexpected;
00222 goto out;
00223 }
00224 break;
00225
00226 case json_tokener_state_finish:
00227 if(tok->depth == 0) goto out;
00228 obj = json_object_get(current);
00229 json_tokener_reset_level(tok, tok->depth);
00230 tok->depth--;
00231 goto redo_char;
00232
00233 case json_tokener_state_null:
00234 printbuf_memappend(tok->pb, &c, 1);
00235 if(strncasecmp(json_null_str, tok->pb->buf,
00236 min( (size_t) (tok->st_pos+1), strlen(json_null_str))) == 0) {
00237 if( ((size_t) tok->st_pos) == strlen(json_null_str)) {
00238 current = NULL;
00239 saved_state = json_tokener_state_finish;
00240 state = json_tokener_state_eatws;
00241 goto redo_char;
00242 }
00243 } else {
00244 tok->err = json_tokener_error_parse_null;
00245 goto out;
00246 }
00247 tok->st_pos++;
00248 break;
00249
00250 case json_tokener_state_comment_start:
00251 if(c == '*') {
00252 state = json_tokener_state_comment;
00253 } else if(c == '/') {
00254 state = json_tokener_state_comment_eol;
00255 } else {
00256 tok->err = json_tokener_error_parse_comment;
00257 goto out;
00258 }
00259 printbuf_memappend(tok->pb, &c, 1);
00260 break;
00261
00262 case json_tokener_state_comment:
00263 if(c == '*') state = json_tokener_state_comment_end;
00264 printbuf_memappend(tok->pb, &c, 1);
00265 break;
00266
00267 case json_tokener_state_comment_eol:
00268 if(c == '\n') {
00269 mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
00270 state = json_tokener_state_eatws;
00271 } else {
00272 printbuf_memappend(tok->pb, &c, 1);
00273 }
00274 break;
00275
00276 case json_tokener_state_comment_end:
00277 printbuf_memappend(tok->pb, &c, 1);
00278 if(c == '/') {
00279 mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
00280 state = json_tokener_state_eatws;
00281 } else {
00282 state = json_tokener_state_comment;
00283 }
00284 break;
00285
00286 case json_tokener_state_string:
00287 if(c == tok->quote_char) {
00288 current = json_object_new_string(tok->pb->buf);
00289 saved_state = json_tokener_state_finish;
00290 state = json_tokener_state_eatws;
00291 } else if(c == '\\') {
00292 saved_state = json_tokener_state_string;
00293 state = json_tokener_state_string_escape;
00294 } else {
00295 printbuf_memappend(tok->pb, &c, 1);
00296 }
00297 break;
00298
00299 case json_tokener_state_string_escape:
00300 switch(c) {
00301 case '"':
00302 case '\\':
00303 case '/':
00304 printbuf_memappend(tok->pb, &c, 1);
00305 state = saved_state;
00306 break;
00307 case 'b':
00308 case 'n':
00309 case 'r':
00310 case 't':
00311 if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
00312 else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
00313 else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
00314 else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
00315 state = saved_state;
00316 break;
00317 case 'u':
00318 tok->ucs_char = 0;
00319 tok->st_pos = 0;
00320 state = json_tokener_state_escape_unicode;
00321 break;
00322 default:
00323 tok->err = json_tokener_error_parse_string;
00324 goto out;
00325 }
00326 break;
00327
00328 case json_tokener_state_escape_unicode:
00329 if(strchr(json_hex_chars, c)) {
00330 tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
00331 if(tok->st_pos == 4) {
00332 unsigned char utf_out[3];
00333 if (tok->ucs_char < 0x80) {
00334 utf_out[0] = tok->ucs_char;
00335 printbuf_memappend(tok->pb, (char*)utf_out, 1);
00336 } else if (tok->ucs_char < 0x800) {
00337 utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
00338 utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
00339 printbuf_memappend(tok->pb, (char*)utf_out, 2);
00340 } else {
00341 utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
00342 utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
00343 utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
00344 printbuf_memappend(tok->pb, (char*)utf_out, 3);
00345 }
00346 state = saved_state;
00347 }
00348 } else {
00349 tok->err = json_tokener_error_parse_string;
00350 goto out;
00351 }
00352 break;
00353
00354 case json_tokener_state_boolean:
00355 printbuf_memappend(tok->pb, &c, 1);
00356 if(strncasecmp(json_true_str, tok->pb->buf,
00357 min( (size_t)(tok->st_pos+1), strlen(json_true_str))) == 0) {
00358 if(((size_t) tok->st_pos) == strlen(json_true_str)) {
00359 current = json_object_new_boolean(1);
00360 saved_state = json_tokener_state_finish;
00361 state = json_tokener_state_eatws;
00362 goto redo_char;
00363 }
00364 } else if(strncasecmp(json_false_str, tok->pb->buf,
00365 min((size_t)(tok->st_pos+1), strlen(json_false_str))) == 0) {
00366 if(( (size_t) tok->st_pos) == strlen(json_false_str)) {
00367 current = json_object_new_boolean(0);
00368 saved_state = json_tokener_state_finish;
00369 state = json_tokener_state_eatws;
00370 goto redo_char;
00371 }
00372 } else {
00373 tok->err = json_tokener_error_parse_boolean;
00374 goto out;
00375 }
00376 tok->st_pos++;
00377 break;
00378
00379 case json_tokener_state_number:
00380 if(c && strchr(json_number_chars, c)) {
00381 printbuf_memappend(tok->pb, &c, 1);
00382 if(c == '.' || c == 'e') tok->is_double = 1;
00383 } else {
00384 int numi;
00385 double numd;
00386 if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
00387 current = json_object_new_int(numi);
00388 } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
00389 current = json_object_new_double(numd);
00390 } else {
00391 tok->err = json_tokener_error_parse_number;
00392 goto out;
00393 }
00394 saved_state = json_tokener_state_finish;
00395 state = json_tokener_state_eatws;
00396 goto redo_char;
00397 }
00398 break;
00399
00400 case json_tokener_state_array:
00401 if(c == ']') {
00402 saved_state = json_tokener_state_finish;
00403 state = json_tokener_state_eatws;
00404 } else {
00405 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
00406 tok->err = json_tokener_error_depth;
00407 goto out;
00408 }
00409 state = json_tokener_state_array_add;
00410 tok->depth++;
00411 json_tokener_reset_level(tok, tok->depth);
00412 goto redo_char;
00413 }
00414 break;
00415
00416 case json_tokener_state_array_add:
00417 json_object_array_add(current, obj);
00418 saved_state = json_tokener_state_array_sep;
00419 state = json_tokener_state_eatws;
00420 goto redo_char;
00421
00422 case json_tokener_state_array_sep:
00423 if(c == ']') {
00424 saved_state = json_tokener_state_finish;
00425 state = json_tokener_state_eatws;
00426 } else if(c == ',') {
00427 saved_state = json_tokener_state_array;
00428 state = json_tokener_state_eatws;
00429 } else {
00430 tok->err = json_tokener_error_parse_array;
00431 goto out;
00432 }
00433 break;
00434
00435 case json_tokener_state_object_field_start:
00436 if(c == '}') {
00437 saved_state = json_tokener_state_finish;
00438 state = json_tokener_state_eatws;
00439 } else if (c == '"' || c == '\'') {
00440 tok->quote_char = c;
00441 printbuf_reset(tok->pb);
00442 state = json_tokener_state_object_field;
00443 } else {
00444 tok->err = json_tokener_error_parse_object_key_name;
00445 goto out;
00446 }
00447 break;
00448
00449 case json_tokener_state_object_field:
00450 if(c == tok->quote_char) {
00451 obj_field_name = strdup(tok->pb->buf);
00452 saved_state = json_tokener_state_object_field_end;
00453 state = json_tokener_state_eatws;
00454 } else if(c == '\\') {
00455 saved_state = json_tokener_state_object_field;
00456 state = json_tokener_state_string_escape;
00457 } else {
00458 printbuf_memappend(tok->pb, &c, 1);
00459 }
00460 break;
00461
00462 case json_tokener_state_object_field_end:
00463 if(c == ':') {
00464 saved_state = json_tokener_state_object_value;
00465 state = json_tokener_state_eatws;
00466 } else {
00467 tok->err = json_tokener_error_parse_object_key_sep;
00468 goto out;
00469 }
00470 break;
00471
00472 case json_tokener_state_object_value:
00473 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
00474 tok->err = json_tokener_error_depth;
00475 goto out;
00476 }
00477 state = json_tokener_state_object_value_add;
00478 tok->depth++;
00479 json_tokener_reset_level(tok, tok->depth);
00480 goto redo_char;
00481
00482 case json_tokener_state_object_value_add:
00483 json_object_object_add(current, obj_field_name, obj);
00484 free(obj_field_name);
00485 obj_field_name = NULL;
00486 saved_state = json_tokener_state_object_sep;
00487 state = json_tokener_state_eatws;
00488 goto redo_char;
00489
00490 case json_tokener_state_object_sep:
00491 if(c == '}') {
00492 saved_state = json_tokener_state_finish;
00493 state = json_tokener_state_eatws;
00494 } else if(c == ',') {
00495 saved_state = json_tokener_state_object_field_start;
00496 state = json_tokener_state_eatws;
00497 } else {
00498 tok->err = json_tokener_error_parse_object_value_sep;
00499 goto out;
00500 }
00501 break;
00502
00503 }
00504 str++;
00505 tok->char_offset++;
00506 } while(c);
00507
00508 if(state != json_tokener_state_finish &&
00509 saved_state != json_tokener_state_finish)
00510 tok->err = json_tokener_error_parse_eof;
00511
00512 out:
00513 if(tok->err == json_tokener_success) return json_object_get(current);
00514 mc_debug("json_tokener_parse_ex: error %s at offset %d\n",
00515 json_tokener_errors[tok->err], tok->char_offset);
00516 return NULL;
00517 }