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