• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/json-c/json_tokener.c

  1 /*
  2  * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
  3  *
  4  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
  5  * Michael Clark <michael@metaparadigm.com>
  6  *
  7  * This library is free software; you can redistribute it and/or modify
  8  * it under the terms of the MIT license. See COPYING for details.
  9  *
 10  *
 11  * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
 12  * The copyrights to the contents of this file are licensed under the MIT License
 13  * (http://www.opensource.org/licenses/mit-license.php)
 14  */
 15 
 16 #include "config.h"
 17 
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 #include <stddef.h>
 21 #include <ctype.h>
 22 #include <string.h>
 23 #include <limits.h>
 24 
 25 #include "bits.h"
 26 #include "debug.h"
 27 #include "printbuf.h"
 28 #include "arraylist.h"
 29 #include "json_inttypes.h"
 30 #include "json_object.h"
 31 #include "json_tokener.h"
 32 #include "json_util.h"
 33 
 34 #ifdef HAVE_LOCALE_H
 35 #include <locale.h>
 36 #endif /* HAVE_LOCALE_H */
 37 
 38 #if !HAVE_STRDUP && defined(_MSC_VER)
 39   /* MSC has the version as _strdup */
 40 # define strdup _strdup
 41 #elif !HAVE_STRDUP
 42 # error You do not have strdup on your system.
 43 #endif /* HAVE_STRDUP */
 44 
 45 #if !HAVE_STRNCASECMP && defined(_MSC_VER)
 46   /* MSC has the version as _strnicmp */
 47 # define strncasecmp _strnicmp
 48 #elif !HAVE_STRNCASECMP
 49 # error You do not have strncasecmp on your system.
 50 #endif /* HAVE_STRNCASECMP */
 51 
 52 static const char* json_null_str = "null";
 53 static const char* json_true_str = "true";
 54 static const char* json_false_str = "false";
 55 
 56 // XXX after v0.10 this array will become static:
 57 const char* json_tokener_errors[] = {
 58   "success",
 59   "continue",
 60   "nesting too deep",
 61   "unexpected end of data",
 62   "unexpected character",
 63   "null expected",
 64   "boolean expected",
 65   "number expected",
 66   "array value separator ',' expected",
 67   "quoted object property name expected",
 68   "object property name separator ':' expected",
 69   "object value separator ',' expected",
 70   "invalid string sequence",
 71   "expected comment",
 72 };
 73 
 74 const char *json_tokener_error_desc(enum json_tokener_error jerr)
 75 {
 76         int jerr_int = (int)jerr;
 77         if (jerr_int < 0 || jerr_int > (int)sizeof(json_tokener_errors))
 78                 return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
 79         return json_tokener_errors[jerr];
 80 }
 81 
 82 enum json_tokener_error json_tokener_get_error(json_tokener *tok)
 83 {
 84         return tok->err;
 85 }
 86 
 87 /* Stuff for decoding unicode sequences */
 88 #define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
 89 #define IS_LOW_SURROGATE(uc)  (((uc) & 0xFC00) == 0xDC00)
 90 #define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
 91 static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
 92 
 93 struct json_tokener* json_tokener_new_ex(int depth)
 94 {
 95   struct json_tokener *tok;
 96 
 97   tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
 98   if (!tok) return NULL;
 99   tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
100   if (!tok->stack) {
101     free(tok);
102     return NULL;
103   }
104   tok->pb = printbuf_new();
105   tok->max_depth = depth;
106   json_tokener_reset(tok);
107   return tok;
108 }
109 
110 struct json_tokener* json_tokener_new(void)
111 {
112   return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
113 }
114 
115 void json_tokener_free(struct json_tokener *tok)
116 {
117   json_tokener_reset(tok);
118   if (tok->pb) printbuf_free(tok->pb);
119   if (tok->stack) free(tok->stack);
120   free(tok);
121 }
122 
123 static void json_tokener_reset_level(struct json_tokener *tok, int depth)
124 {
125   tok->stack[depth].state = json_tokener_state_eatws;
126   tok->stack[depth].saved_state = json_tokener_state_start;
127   json_object_put(tok->stack[depth].current);
128   tok->stack[depth].current = NULL;
129   free(tok->stack[depth].obj_field_name);
130   tok->stack[depth].obj_field_name = NULL;
131 }
132 
133 void json_tokener_reset(struct json_tokener *tok)
134 {
135   int i;
136   if (!tok)
137     return;
138 
139   for(i = tok->depth; i >= 0; i--)
140     json_tokener_reset_level(tok, i);
141   tok->depth = 0;
142   tok->err = json_tokener_success;
143 }
144 
145 struct json_object* json_tokener_parse(const char *str)
146 {
147     enum json_tokener_error jerr_ignored;
148     struct json_object* obj;
149     obj = json_tokener_parse_verbose(str, &jerr_ignored);
150     return obj;
151 }
152 
153 struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
154 {
155     struct json_tokener* tok;
156     struct json_object* obj;
157 
158     tok = json_tokener_new();
159     if (!tok)
160       return NULL;
161     obj = json_tokener_parse_ex(tok, str, -1);
162     *error = tok->err;
163     if(tok->err != json_tokener_success) {
164                 if (obj != NULL)
165                         json_object_put(obj);
166         obj = NULL;
167     }
168 
169     json_tokener_free(tok);
170     return obj;
171 }
172 
173 
174 #if !HAVE_STRNDUP
175 /* CAW: compliant version of strndup() */
176 char* strndup(const char* str, size_t n)
177 {
178   if(str) {
179     size_t len = strlen(str);
180     size_t nn = json_min(len,n);
181     char* s = (char*)malloc(sizeof(char) * (nn + 1));
182 
183     if(s) {
184       memcpy(s, str, nn);
185       s[nn] = '\0';
186     }
187 
188     return s;
189   }
190 
191   return NULL;
192 }
193 #endif
194 
195 
196 #define state  tok->stack[tok->depth].state
197 #define saved_state  tok->stack[tok->depth].saved_state
198 #define current tok->stack[tok->depth].current
199 #define obj_field_name tok->stack[tok->depth].obj_field_name
200 
201 /* Optimization:
202  * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
203  * iterating character-by character.  A large performance boost is
204  * achieved by using tighter loops to locally handle units such as
205  * comments and strings.  Loops that handle an entire token within
206  * their scope also gather entire strings and pass them to
207  * printbuf_memappend() in a single call, rather than calling
208  * printbuf_memappend() one char at a time.
209  *
210  * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
211  * common to both the main loop and the tighter loops.
212  */
213 
214 /* PEEK_CHAR(dest, tok) macro:
215  *   Peeks at the current char and stores it in dest.
216  *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
217  *   Implicit inputs:  str, len vars
218  */
219 #define PEEK_CHAR(dest, tok)                                                  \
220   (((tok)->char_offset == len) ?                                          \
221    (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
222     (((tok)->err = json_tokener_success), 0)                              \
223     :                                                                   \
224     (((tok)->err = json_tokener_continue), 0)                             \
225     ) :                                                                 \
226    (((dest) = *str), 1)                                                 \
227    )
228 
229 /* ADVANCE_CHAR() macro:
230  *   Incrementes str & tok->char_offset.
231  *   For convenience of existing conditionals, returns the old value of c (0 on eof)
232  *   Implicit inputs:  c var
233  */
234 #define ADVANCE_CHAR(str, tok) \
235   ( ++(str), ((tok)->char_offset)++, c)
236 
237 
238 /* End optimization macro defs */
239 
240 
241 struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
242                                           const char *str, int len)
243 {
244   struct json_object *obj = NULL;
245   char c = '\1';
246 #ifdef HAVE_SETLOCALE
247   char *oldlocale=NULL, *tmplocale;
248 
249   tmplocale = setlocale(LC_NUMERIC, NULL);
250   if (tmplocale) oldlocale = strdup(tmplocale);
251   setlocale(LC_NUMERIC, "C");
252 #endif
253 
254   tok->char_offset = 0;
255   tok->err = json_tokener_success;
256 
257   while (PEEK_CHAR(c, tok)) {
258 
259   redo_char:
260     switch(state) {
261 
262     case json_tokener_state_eatws:
263       /* Advance until we change state */
264       while (isspace((int)c)) {
265         if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
266           goto out;
267       }
268       if(c == '/') {
269         printbuf_reset(tok->pb);
270         printbuf_memappend_fast(tok->pb, &c, 1);
271         state = json_tokener_state_comment_start;
272       } else {
273         state = saved_state;
274         goto redo_char;
275       }
276       break;
277 
278     case json_tokener_state_start:
279       switch(c) {
280       case '{':
281         state = json_tokener_state_eatws;
282         saved_state = json_tokener_state_object_field_start;
283         current = json_object_new_object();
284         break;
285       case '[':
286         state = json_tokener_state_eatws;
287         saved_state = json_tokener_state_array;
288         current = json_object_new_array();
289         break;
290       case 'N':
291       case 'n':
292         state = json_tokener_state_null;
293         printbuf_reset(tok->pb);
294         tok->st_pos = 0;
295         goto redo_char;
296       case '"':
297       case '\'':
298         state = json_tokener_state_string;
299         printbuf_reset(tok->pb);
300         tok->quote_char = c;
301         break;
302       case 'T':
303       case 't':
304       case 'F':
305       case 'f':
306         state = json_tokener_state_boolean;
307         printbuf_reset(tok->pb);
308         tok->st_pos = 0;
309         goto redo_char;
310 #if defined(__GNUC__)
311           case '' ... '9':
312 #else
313           case '':
314       case '1':
315       case '2':
316       case '3':
317       case '4':
318       case '5':
319       case '6':
320       case '7':
321       case '8':
322       case '9':
323 #endif
324       case '-':
325         state = json_tokener_state_number;
326         printbuf_reset(tok->pb);
327         tok->is_double = 0;
328         goto redo_char;
329       default:
330         tok->err = json_tokener_error_parse_unexpected;
331         goto out;
332       }
333       break;
334 
335     case json_tokener_state_finish:
336       if(tok->depth == 0) goto out;
337       obj = json_object_get(current);
338       json_tokener_reset_level(tok, tok->depth);
339       tok->depth--;
340       goto redo_char;
341 
342     case json_tokener_state_null:
343       printbuf_memappend_fast(tok->pb, &c, 1);
344       if(strncasecmp(json_null_str, tok->pb->buf,
345                      json_min(tok->st_pos+1, (int)strlen(json_null_str))) == 0) {
346         if(tok->st_pos == (int)strlen(json_null_str)) {
347           current = NULL;
348           saved_state = json_tokener_state_finish;
349           state = json_tokener_state_eatws;
350           goto redo_char;
351         }
352       } else {
353         tok->err = json_tokener_error_parse_null;
354         goto out;
355       }
356       tok->st_pos++;
357       break;
358 
359     case json_tokener_state_comment_start:
360       if(c == '*') {
361         state = json_tokener_state_comment;
362       } else if(c == '/') {
363         state = json_tokener_state_comment_eol;
364       } else {
365         tok->err = json_tokener_error_parse_comment;
366         goto out;
367       }
368       printbuf_memappend_fast(tok->pb, &c, 1);
369       break;
370 
371     case json_tokener_state_comment:
372               {
373           /* Advance until we change state */
374           const char *case_start = str;
375           while(c != '*') {
376             if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
377               printbuf_memappend_fast(tok->pb, case_start, str-case_start);
378               goto out;
379             }
380           }
381           printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
382           state = json_tokener_state_comment_end;
383         }
384             break;
385 
386     case json_tokener_state_comment_eol:
387       {
388         /* Advance until we change state */
389         const char *case_start = str;
390         while(c != '\n') {
391           if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
392             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
393             goto out;
394           }
395         }
396         printbuf_memappend_fast(tok->pb, case_start, str-case_start);
397         MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
398         state = json_tokener_state_eatws;
399       }
400       break;
401 
402     case json_tokener_state_comment_end:
403       printbuf_memappend_fast(tok->pb, &c, 1);
404       if(c == '/') {
405         MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
406         state = json_tokener_state_eatws;
407       } else {
408         state = json_tokener_state_comment;
409       }
410       break;
411 
412     case json_tokener_state_string:
413       {
414         /* Advance until we change state */
415         const char *case_start = str;
416         while(1) {
417           if(c == tok->quote_char) {
418             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
419             current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
420             saved_state = json_tokener_state_finish;
421             state = json_tokener_state_eatws;
422             break;
423           } else if(c == '\\') {
424             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
425             saved_state = json_tokener_state_string;
426             state = json_tokener_state_string_escape;
427             break;
428           }
429           if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
430             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
431             goto out;
432           }
433         }
434       }
435       break;
436 
437     case json_tokener_state_string_escape:
438       switch(c) {
439       case '"':
440       case '\\':
441       case '/':
442         printbuf_memappend_fast(tok->pb, &c, 1);
443         state = saved_state;
444         break;
445       case 'b':
446       case 'n':
447       case 'r':
448       case 't':
449       case 'f':
450         if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
451         else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
452         else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
453         else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
454         else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
455         state = saved_state;
456         break;
457       case 'u':
458         tok->ucs_char = 0;
459         tok->st_pos = 0;
460         state = json_tokener_state_escape_unicode;
461         break;
462       default:
463         tok->err = json_tokener_error_parse_string;
464         goto out;
465       }
466       break;
467 
468     case json_tokener_state_escape_unicode:
469         {
470           unsigned int got_hi_surrogate = 0;
471 
472           /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
473           while(1) {
474             if(strchr(json_hex_chars, c)) {
475               tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
476               if(tok->st_pos == 4) {
477                 unsigned char unescaped_utf[4];
478 
479                 if (got_hi_surrogate) {
480                   if (IS_LOW_SURROGATE(tok->ucs_char)) {
481                     /* Recalculate the ucs_char, then fall thru to process normally */
482                     tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
483                   } else {
484                     /* Hi surrogate was not followed by a low surrogate */
485                     /* Replace the hi and process the rest normally */
486                     printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
487                   }
488                   got_hi_surrogate = 0;
489                 }
490 
491                 if (tok->ucs_char < 0x80) {
492                   unescaped_utf[0] = tok->ucs_char;
493                   printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
494                 } else if (tok->ucs_char < 0x800) {
495                   unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
496                   unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
497                   printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
498                 } else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
499                   /* Got a high surrogate.  Remember it and look for the
500                    * the beginning of another sequence, which should be the
501                    * low surrogate.
502                    */
503                   got_hi_surrogate = tok->ucs_char;
504                   /* Not at end, and the next two chars should be "\u" */
505                   if ((tok->char_offset+1 != len) &&
506                       (tok->char_offset+2 != len) &&
507                       (str[1] == '\\') &&
508                       (str[2] == 'u'))
509                   {
510                 /* Advance through the 16 bit surrogate, and move on to the
511                  * next sequence. The next step is to process the following
512                  * characters.
513                  */
514                     if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
515                     printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
516                 }
517                     /* Advance to the first char of the next sequence and
518                      * continue processing with the next sequence.
519                      */
520                     if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
521                       printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
522                       goto out;
523                     }
524                     tok->ucs_char = 0;
525                     tok->st_pos = 0;
526                     continue; /* other json_tokener_state_escape_unicode */
527                   } else {
528                     /* Got a high surrogate without another sequence following
529                      * it.  Put a replacement char in for the hi surrogate
530                      * and pretend we finished.
531                      */
532                     printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
533                   }
534                 } else if (IS_LOW_SURROGATE(tok->ucs_char)) {
535                   /* Got a low surrogate not preceded by a high */
536                   printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
537                 } else if (tok->ucs_char < 0x10000) {
538                   unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
539                   unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
540                   unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
541                   printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
542                 } else if (tok->ucs_char < 0x110000) {
543                   unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
544                   unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
545                   unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
546                   unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
547                   printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
548                 } else {
549                   /* Don't know what we got--insert the replacement char */
550                   printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
551                 }
552                 state = saved_state;
553                 break;
554               }
555             } else {
556               tok->err = json_tokener_error_parse_string;
557               goto out;
558             }
559           if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
560             if (got_hi_surrogate) /* Clean up any pending chars */
561               printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
562             goto out;
563           }
564         }
565       }
566       break;
567 
568     case json_tokener_state_boolean:
569       printbuf_memappend_fast(tok->pb, &c, 1);
570       if(strncasecmp(json_true_str, tok->pb->buf,
571                      json_min(tok->st_pos+1, (int)strlen(json_true_str))) == 0) {
572         if(tok->st_pos == (int)strlen(json_true_str)) {
573           current = json_object_new_boolean(1);
574           saved_state = json_tokener_state_finish;
575           state = json_tokener_state_eatws;
576           goto redo_char;
577         }
578       } else if(strncasecmp(json_false_str, tok->pb->buf,
579                             json_min(tok->st_pos+1, (int)strlen(json_false_str))) == 0) {
580         if(tok->st_pos == (int)strlen(json_false_str)) {
581           current = json_object_new_boolean(0);
582           saved_state = json_tokener_state_finish;
583           state = json_tokener_state_eatws;
584           goto redo_char;
585         }
586       } else {
587         tok->err = json_tokener_error_parse_boolean;
588         goto out;
589       }
590       tok->st_pos++;
591       break;
592 
593     case json_tokener_state_number:
594       {
595         /* Advance until we change state */
596         const char *case_start = str;
597         int case_len=0;
598         while(c && strchr(json_number_chars, c)) {
599           ++case_len;
600           if(c == '.' || c == 'e' || c == 'E')
601             tok->is_double = 1;
602           if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
603             printbuf_memappend_fast(tok->pb, case_start, case_len);
604             goto out;
605           }
606         }
607         if (case_len>0)
608           printbuf_memappend_fast(tok->pb, case_start, case_len);
609       }
610       {
611         int64_t num64;
612         double  numd;
613         if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
614                 current = json_object_new_int64(num64);
615         } else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) {
616           current = json_object_new_double(numd);
617         } else {
618           tok->err = json_tokener_error_parse_number;
619           goto out;
620         }
621         saved_state = json_tokener_state_finish;
622         state = json_tokener_state_eatws;
623         goto redo_char;
624       }
625       break;
626 
627     case json_tokener_state_array_after_sep:
628     case json_tokener_state_array:
629       if(c == ']') {
630                 if (state == json_tokener_state_array_after_sep &&
631                         (tok->flags & JSON_TOKENER_STRICT))
632                 {
633                         tok->err = json_tokener_error_parse_unexpected;
634                         goto out;
635                 }
636         saved_state = json_tokener_state_finish;
637         state = json_tokener_state_eatws;
638       } else {
639         if(tok->depth >= tok->max_depth-1) {
640           tok->err = json_tokener_error_depth;
641           goto out;
642         }
643         state = json_tokener_state_array_add;
644         tok->depth++;
645         json_tokener_reset_level(tok, tok->depth);
646         goto redo_char;
647       }
648       break;
649 
650     case json_tokener_state_array_add:
651       json_object_array_add(current, obj);
652       saved_state = json_tokener_state_array_sep;
653       state = json_tokener_state_eatws;
654       goto redo_char;
655 
656     case json_tokener_state_array_sep:
657       if(c == ']') {
658         saved_state = json_tokener_state_finish;
659         state = json_tokener_state_eatws;
660       } else if(c == ',') {
661         saved_state = json_tokener_state_array_after_sep;
662         state = json_tokener_state_eatws;
663       } else {
664         tok->err = json_tokener_error_parse_array;
665         goto out;
666       }
667       break;
668 
669     case json_tokener_state_object_field_start:
670     case json_tokener_state_object_field_start_after_sep:
671       if(c == '}') {
672                 if (state == json_tokener_state_object_field_start_after_sep &&
673                     (tok->flags & JSON_TOKENER_STRICT))
674                 {
675                         tok->err = json_tokener_error_parse_unexpected;
676                         goto out;
677                 }
678         saved_state = json_tokener_state_finish;
679         state = json_tokener_state_eatws;
680       } else if (c == '"' || c == '\'') {
681         tok->quote_char = c;
682         printbuf_reset(tok->pb);
683         state = json_tokener_state_object_field;
684       } else {
685         tok->err = json_tokener_error_parse_object_key_name;
686         goto out;
687       }
688       break;
689 
690     case json_tokener_state_object_field:
691       {
692         /* Advance until we change state */
693         const char *case_start = str;
694         while(1) {
695           if(c == tok->quote_char) {
696             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
697             obj_field_name = strdup(tok->pb->buf);
698             saved_state = json_tokener_state_object_field_end;
699             state = json_tokener_state_eatws;
700             break;
701           } else if(c == '\\') {
702             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
703             saved_state = json_tokener_state_object_field;
704             state = json_tokener_state_string_escape;
705             break;
706           }
707           if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
708             printbuf_memappend_fast(tok->pb, case_start, str-case_start);
709             goto out;
710           }
711         }
712       }
713       break;
714 
715     case json_tokener_state_object_field_end:
716       if(c == ':') {
717         saved_state = json_tokener_state_object_value;
718         state = json_tokener_state_eatws;
719       } else {
720         tok->err = json_tokener_error_parse_object_key_sep;
721         goto out;
722       }
723       break;
724 
725     case json_tokener_state_object_value:
726       if(tok->depth >= tok->max_depth-1) {
727         tok->err = json_tokener_error_depth;
728         goto out;
729       }
730       state = json_tokener_state_object_value_add;
731       tok->depth++;
732       json_tokener_reset_level(tok, tok->depth);
733       goto redo_char;
734 
735     case json_tokener_state_object_value_add:
736       json_object_object_add(current, obj_field_name, obj);
737       free(obj_field_name);
738       obj_field_name = NULL;
739       saved_state = json_tokener_state_object_sep;
740       state = json_tokener_state_eatws;
741       goto redo_char;
742 
743     case json_tokener_state_object_sep:
744       if(c == '}') {
745         saved_state = json_tokener_state_finish;
746         state = json_tokener_state_eatws;
747       } else if(c == ',') {
748         saved_state = json_tokener_state_object_field_start_after_sep;
749         state = json_tokener_state_eatws;
750       } else {
751         tok->err = json_tokener_error_parse_object_value_sep;
752         goto out;
753       }
754       break;
755 
756     }
757     if (!ADVANCE_CHAR(str, tok))
758       goto out;
759   } /* while(POP_CHAR) */
760 
761  out:
762   if (!c) { /* We hit an eof char (0) */
763     if(state != json_tokener_state_finish &&
764        saved_state != json_tokener_state_finish)
765       tok->err = json_tokener_error_parse_eof;
766   }
767 
768 #ifdef HAVE_SETLOCALE
769   setlocale(LC_NUMERIC, oldlocale);
770   if (oldlocale) free(oldlocale);
771 #endif
772 
773   if (tok->err == json_tokener_success)
774   {
775     json_object *ret = json_object_get(current);
776         int ii;
777 
778         /* Partially reset, so we parse additional objects on subsequent calls. */
779     for(ii = tok->depth; ii >= 0; ii--)
780       json_tokener_reset_level(tok, ii);
781     return ret;
782   }
783 
784   MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
785            json_tokener_errors[tok->err], tok->char_offset);
786   return NULL;
787 }
788 
789 void json_tokener_set_flags(struct json_tokener *tok, int flags)
790 {
791         tok->flags = flags;
792 }
793 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt