blob: ba329fe8953ca3830772ff27f8bba9e898780e0f [file] [log] [blame]
Michael Clarkf0d08882007-03-13 08:26:18 +00001/*
Michael Clarka850f8e2007-03-13 08:26:26 +00002 * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
Michael Clarkf0d08882007-03-13 08:26:18 +00003 *
Michael Clarkf6a6e482007-03-13 08:26:23 +00004 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
Michael Clarkf0d08882007-03-13 08:26:18 +00005 * Michael Clark <michael@metaparadigm.com>
6 *
Michael Clarkf6a6e482007-03-13 08:26:23 +00007 * 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.
Michael Clarkf0d08882007-03-13 08:26:18 +00009 *
10 */
11
Michael Clark4504df72007-03-13 08:26:20 +000012#include "config.h"
13
Michael Clarkf0d08882007-03-13 08:26:18 +000014#include <stdio.h>
15#include <stdlib.h>
16#include <ctype.h>
17#include <string.h>
18
19#include "bits.h"
20#include "debug.h"
21#include "printbuf.h"
22#include "arraylist.h"
23#include "json_object.h"
24#include "json_tokener.h"
25
Michael Clarka850f8e2007-03-13 08:26:26 +000026
Michael Clark837240f2007-03-13 08:26:25 +000027#if !HAVE_STRNCASECMP && defined(_MSC_VER)
28 /* MSC has the version as _strnicmp */
29# define strncasecmp _strnicmp
30#elif !HAVE_STRNCASECMP
31# error You do not have strncasecmp on your system.
32#endif /* HAVE_STRNCASECMP */
33
34
Michael Clarka850f8e2007-03-13 08:26:26 +000035static const char* json_null_str = "null";
36static const char* json_true_str = "true";
37static const char* json_false_str = "false";
Michael Clarkf0d08882007-03-13 08:26:18 +000038
Michael Clarka850f8e2007-03-13 08:26:26 +000039const char* json_tokener_errors[] = {
40 "success",
41 "continue",
42 "nesting to deep",
43 "unexpected end of data",
44 "unexpected character",
45 "null expected",
46 "boolean expected",
47 "number expected",
48 "array value separator ',' expected",
49 "quoted object property name expected",
50 "object property name separator ':' expected",
51 "object value separator ',' expected",
52 "invalid string sequence",
53 "expected comment",
54};
55
56
57struct json_tokener* json_tokener_new()
Michael Clarkf0d08882007-03-13 08:26:18 +000058{
Michael Clarka850f8e2007-03-13 08:26:26 +000059 struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
60 tok->pb = printbuf_new();
61 json_tokener_reset(tok);
62 return tok;
63}
64
65void json_tokener_free(struct json_tokener *tok)
66{
67 json_tokener_reset(tok);
68 if(tok) printbuf_free(tok->pb);
69 free(tok);
70}
71
72static void json_tokener_reset_level(struct json_tokener *tok, int depth)
73{
74 tok->stack[depth].state = json_tokener_state_eatws;
75 tok->stack[depth].saved_state = json_tokener_state_start;
76 json_object_put(tok->stack[depth].current);
77 tok->stack[depth].current = NULL;
78 free(tok->stack[depth].obj_field_name);
79 tok->stack[depth].obj_field_name = NULL;
80}
81
82void json_tokener_reset(struct json_tokener *tok)
83{
84 int i;
85 for(i = tok->depth; i >= 0; i--)
86 json_tokener_reset_level(tok, i);
87 tok->depth = 0;
88 tok->err = json_tokener_success;
89}
90
91struct json_object* json_tokener_parse(char *str)
92{
93 struct json_tokener* tok;
Michael Clarkf0d08882007-03-13 08:26:18 +000094 struct json_object* obj;
95
Michael Clarka850f8e2007-03-13 08:26:26 +000096 tok = json_tokener_new();
97 obj = json_tokener_parse_ex(tok, str, -1);
98 if(tok->err != json_tokener_success)
99 obj = error_ptr(-tok->err);
100 json_tokener_free(tok);
Michael Clarkf0d08882007-03-13 08:26:18 +0000101 return obj;
102}
103
Michael Clarka850f8e2007-03-13 08:26:26 +0000104
Michael Clark4504df72007-03-13 08:26:20 +0000105#if !HAVE_STRNDUP
106/* CAW: compliant version of strndup() */
107char* strndup(const char* str, size_t n)
108{
Michael Clarka850f8e2007-03-13 08:26:26 +0000109 if(str) {
110 size_t len = strlen(str);
111 size_t nn = min(len,n);
112 char* s = (char*)malloc(sizeof(char) * (nn + 1));
Michael Clark4504df72007-03-13 08:26:20 +0000113
Michael Clarka850f8e2007-03-13 08:26:26 +0000114 if(s) {
115 memcpy(s, str, nn);
116 s[nn] = '\0';
117 }
Michael Clark4504df72007-03-13 08:26:20 +0000118
Michael Clarka850f8e2007-03-13 08:26:26 +0000119 return s;
120 }
Michael Clark4504df72007-03-13 08:26:20 +0000121
Michael Clarka850f8e2007-03-13 08:26:26 +0000122 return NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000123}
124#endif
125
Michael Clarka850f8e2007-03-13 08:26:26 +0000126
127#define state tok->stack[tok->depth].state
128#define saved_state tok->stack[tok->depth].saved_state
129#define current tok->stack[tok->depth].current
130#define obj_field_name tok->stack[tok->depth].obj_field_name
131
132struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
133 char *str, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +0000134{
Michael Clarka850f8e2007-03-13 08:26:26 +0000135 struct json_object *obj = NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000136 char c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000137
Michael Clarka850f8e2007-03-13 08:26:26 +0000138 tok->char_offset = 0;
139 tok->err = json_tokener_success;
Michael Clarkf0d08882007-03-13 08:26:18 +0000140
Michael Clarkf0d08882007-03-13 08:26:18 +0000141 do {
Michael Clarka850f8e2007-03-13 08:26:26 +0000142 if(tok->char_offset == len) {
143 if(tok->depth == 0 && state == json_tokener_state_eatws &&
144 saved_state == json_tokener_state_finish)
145 tok->err = json_tokener_success;
146 else
147 tok->err = json_tokener_continue;
148 goto out;
149 }
150
151 c = *str;
152 redo_char:
Michael Clarkf0d08882007-03-13 08:26:18 +0000153 switch(state) {
154
155 case json_tokener_state_eatws:
156 if(isspace(c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000157 /* okay */
Michael Clarkf0d08882007-03-13 08:26:18 +0000158 } else if(c == '/') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000159 printbuf_reset(tok->pb);
160 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000161 state = json_tokener_state_comment_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000162 } else {
163 state = saved_state;
Michael Clarka850f8e2007-03-13 08:26:26 +0000164 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000165 }
166 break;
167
168 case json_tokener_state_start:
169 switch(c) {
170 case '{':
171 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000172 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000173 current = json_object_new_object();
Michael Clarkf0d08882007-03-13 08:26:18 +0000174 break;
175 case '[':
176 state = json_tokener_state_eatws;
177 saved_state = json_tokener_state_array;
178 current = json_object_new_array();
Michael Clarkf0d08882007-03-13 08:26:18 +0000179 break;
180 case 'N':
181 case 'n':
182 state = json_tokener_state_null;
Michael Clarka850f8e2007-03-13 08:26:26 +0000183 printbuf_reset(tok->pb);
184 tok->st_pos = 0;
185 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000186 case '"':
187 case '\'':
Michael Clarkf0d08882007-03-13 08:26:18 +0000188 state = json_tokener_state_string;
Michael Clarka850f8e2007-03-13 08:26:26 +0000189 printbuf_reset(tok->pb);
190 tok->quote_char = c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000191 break;
192 case 'T':
193 case 't':
194 case 'F':
195 case 'f':
196 state = json_tokener_state_boolean;
Michael Clarka850f8e2007-03-13 08:26:26 +0000197 printbuf_reset(tok->pb);
198 tok->st_pos = 0;
199 goto redo_char;
Michael Clark4504df72007-03-13 08:26:20 +0000200#if defined(__GNUC__)
201 case '0' ... '9':
202#else
203 case '0':
204 case '1':
205 case '2':
206 case '3':
207 case '4':
208 case '5':
209 case '6':
210 case '7':
211 case '8':
212 case '9':
213#endif
Michael Clarkf0d08882007-03-13 08:26:18 +0000214 case '-':
Michael Clarkf0d08882007-03-13 08:26:18 +0000215 state = json_tokener_state_number;
Michael Clarka850f8e2007-03-13 08:26:26 +0000216 printbuf_reset(tok->pb);
217 tok->is_double = 0;
218 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000219 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000220 tok->err = json_tokener_error_parse_unexpected;
Michael Clarkf0d08882007-03-13 08:26:18 +0000221 goto out;
222 }
223 break;
224
225 case json_tokener_state_finish:
Michael Clarka850f8e2007-03-13 08:26:26 +0000226 if(tok->depth == 0) goto out;
227 obj = json_object_get(current);
228 json_tokener_reset_level(tok, tok->depth);
229 tok->depth--;
230 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000231
232 case json_tokener_state_null:
Michael Clarka850f8e2007-03-13 08:26:26 +0000233 printbuf_memappend(tok->pb, &c, 1);
234 if(strncasecmp(json_null_str, tok->pb->buf,
235 min(tok->st_pos+1, strlen(json_null_str))) == 0) {
236 if(tok->st_pos == strlen(json_null_str)) {
237 current = NULL;
238 saved_state = json_tokener_state_finish;
239 state = json_tokener_state_eatws;
240 goto redo_char;
241 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000242 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000243 tok->err = json_tokener_error_parse_null;
244 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000245 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000246 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000247 break;
248
249 case json_tokener_state_comment_start:
250 if(c == '*') {
251 state = json_tokener_state_comment;
252 } else if(c == '/') {
253 state = json_tokener_state_comment_eol;
254 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000255 tok->err = json_tokener_error_parse_comment;
Michael Clarkf0d08882007-03-13 08:26:18 +0000256 goto out;
257 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000258 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000259 break;
260
261 case json_tokener_state_comment:
262 if(c == '*') state = json_tokener_state_comment_end;
Michael Clarka850f8e2007-03-13 08:26:26 +0000263 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000264 break;
265
266 case json_tokener_state_comment_eol:
267 if(c == '\n') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000268 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000269 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000270 } else {
271 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000272 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000273 break;
274
275 case json_tokener_state_comment_end:
Michael Clarka850f8e2007-03-13 08:26:26 +0000276 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000277 if(c == '/') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000278 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000279 state = json_tokener_state_eatws;
280 } else {
281 state = json_tokener_state_comment;
282 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000283 break;
284
285 case json_tokener_state_string:
Michael Clarka850f8e2007-03-13 08:26:26 +0000286 if(c == tok->quote_char) {
287 current = json_object_new_string(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000288 saved_state = json_tokener_state_finish;
289 state = json_tokener_state_eatws;
290 } else if(c == '\\') {
291 saved_state = json_tokener_state_string;
292 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000293 } else {
294 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000295 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000296 break;
297
298 case json_tokener_state_string_escape:
299 switch(c) {
300 case '"':
301 case '\\':
Michael Clarka850f8e2007-03-13 08:26:26 +0000302 case '/':
303 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000304 state = saved_state;
305 break;
306 case 'b':
307 case 'n':
308 case 'r':
309 case 't':
Michael Clarka850f8e2007-03-13 08:26:26 +0000310 if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
311 else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
312 else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
313 else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000314 state = saved_state;
315 break;
316 case 'u':
Michael Clarka850f8e2007-03-13 08:26:26 +0000317 tok->ucs_char = 0;
318 tok->st_pos = 0;
Michael Clarkf0d08882007-03-13 08:26:18 +0000319 state = json_tokener_state_escape_unicode;
320 break;
321 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000322 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000323 goto out;
324 }
325 break;
326
327 case json_tokener_state_escape_unicode:
328 if(strchr(json_hex_chars, c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000329 tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
330 if(tok->st_pos == 4) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000331 unsigned char utf_out[3];
Michael Clarka850f8e2007-03-13 08:26:26 +0000332 if (tok->ucs_char < 0x80) {
333 utf_out[0] = tok->ucs_char;
334 printbuf_memappend(tok->pb, (char*)utf_out, 1);
335 } else if (tok->ucs_char < 0x800) {
336 utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
337 utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
338 printbuf_memappend(tok->pb, (char*)utf_out, 2);
Michael Clarkf0d08882007-03-13 08:26:18 +0000339 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000340 utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
341 utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
342 utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
343 printbuf_memappend(tok->pb, (char*)utf_out, 3);
Michael Clarkf0d08882007-03-13 08:26:18 +0000344 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000345 state = saved_state;
346 }
347 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000348 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000349 goto out;
350 }
351 break;
352
353 case json_tokener_state_boolean:
Michael Clarka850f8e2007-03-13 08:26:26 +0000354 printbuf_memappend(tok->pb, &c, 1);
355 if(strncasecmp(json_true_str, tok->pb->buf,
356 min(tok->st_pos+1, strlen(json_true_str))) == 0) {
357 if(tok->st_pos == strlen(json_true_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000358 current = json_object_new_boolean(1);
359 saved_state = json_tokener_state_finish;
360 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000361 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000362 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000363 } else if(strncasecmp(json_false_str, tok->pb->buf,
364 min(tok->st_pos+1, strlen(json_false_str))) == 0) {
365 if(tok->st_pos == strlen(json_false_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000366 current = json_object_new_boolean(0);
367 saved_state = json_tokener_state_finish;
368 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000369 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000370 }
371 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000372 tok->err = json_tokener_error_parse_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000373 goto out;
374 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000375 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000376 break;
377
378 case json_tokener_state_number:
Michael Clarka850f8e2007-03-13 08:26:26 +0000379 if(c && strchr(json_number_chars, c)) {
380 printbuf_memappend(tok->pb, &c, 1);
381 if(c == '.' || c == 'e') tok->is_double = 1;
382 } else {
Michael Clarkf0d08882007-03-13 08:26:18 +0000383 int numi;
384 double numd;
Michael Clarka850f8e2007-03-13 08:26:26 +0000385 if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000386 current = json_object_new_int(numi);
Michael Clarka850f8e2007-03-13 08:26:26 +0000387 } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000388 current = json_object_new_double(numd);
389 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000390 tok->err = json_tokener_error_parse_number;
Michael Clarkf0d08882007-03-13 08:26:18 +0000391 goto out;
392 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000393 saved_state = json_tokener_state_finish;
394 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000395 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000396 }
397 break;
398
399 case json_tokener_state_array:
400 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000401 saved_state = json_tokener_state_finish;
402 state = json_tokener_state_eatws;
403 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000404 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
405 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000406 goto out;
407 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000408 state = json_tokener_state_array_add;
409 tok->depth++;
410 json_tokener_reset_level(tok, tok->depth);
411 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000412 }
413 break;
414
Michael Clarka850f8e2007-03-13 08:26:26 +0000415 case json_tokener_state_array_add:
416 json_object_array_add(current, obj);
417 saved_state = json_tokener_state_array_sep;
418 state = json_tokener_state_eatws;
419 goto redo_char;
420
Michael Clarkf0d08882007-03-13 08:26:18 +0000421 case json_tokener_state_array_sep:
422 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000423 saved_state = json_tokener_state_finish;
424 state = json_tokener_state_eatws;
425 } else if(c == ',') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000426 saved_state = json_tokener_state_array;
427 state = json_tokener_state_eatws;
428 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000429 tok->err = json_tokener_error_parse_array;
430 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000431 }
432 break;
433
Michael Clarkf0d08882007-03-13 08:26:18 +0000434 case json_tokener_state_object_field_start:
435 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000436 saved_state = json_tokener_state_finish;
437 state = json_tokener_state_eatws;
438 } else if (c == '"' || c == '\'') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000439 tok->quote_char = c;
440 printbuf_reset(tok->pb);
Michael Clarkf0d08882007-03-13 08:26:18 +0000441 state = json_tokener_state_object_field;
Michael Clark0370baa2007-03-13 08:26:22 +0000442 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000443 tok->err = json_tokener_error_parse_object_key_name;
Michael Clark0370baa2007-03-13 08:26:22 +0000444 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000445 }
446 break;
447
448 case json_tokener_state_object_field:
Michael Clarka850f8e2007-03-13 08:26:26 +0000449 if(c == tok->quote_char) {
450 obj_field_name = strdup(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000451 saved_state = json_tokener_state_object_field_end;
452 state = json_tokener_state_eatws;
453 } else if(c == '\\') {
454 saved_state = json_tokener_state_object_field;
455 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000456 } else {
457 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000458 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000459 break;
460
461 case json_tokener_state_object_field_end:
462 if(c == ':') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000463 saved_state = json_tokener_state_object_value;
464 state = json_tokener_state_eatws;
465 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000466 tok->err = json_tokener_error_parse_object_key_sep;
467 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000468 }
469 break;
470
471 case json_tokener_state_object_value:
Michael Clarka850f8e2007-03-13 08:26:26 +0000472 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
473 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000474 goto out;
475 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000476 state = json_tokener_state_object_value_add;
477 tok->depth++;
478 json_tokener_reset_level(tok, tok->depth);
479 goto redo_char;
480
481 case json_tokener_state_object_value_add:
Michael Clarkf0d08882007-03-13 08:26:18 +0000482 json_object_object_add(current, obj_field_name, obj);
483 free(obj_field_name);
484 obj_field_name = NULL;
485 saved_state = json_tokener_state_object_sep;
486 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000487 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000488
489 case json_tokener_state_object_sep:
490 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000491 saved_state = json_tokener_state_finish;
492 state = json_tokener_state_eatws;
493 } else if(c == ',') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000494 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000495 state = json_tokener_state_eatws;
496 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000497 tok->err = json_tokener_error_parse_object_value_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000498 goto out;
499 }
500 break;
501
502 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000503 str++;
504 tok->char_offset++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000505 } while(c);
506
507 if(state != json_tokener_state_finish &&
508 saved_state != json_tokener_state_finish)
Michael Clarka850f8e2007-03-13 08:26:26 +0000509 tok->err = json_tokener_error_parse_eof;
Michael Clarkf0d08882007-03-13 08:26:18 +0000510
511 out:
Michael Clarka850f8e2007-03-13 08:26:26 +0000512 if(tok->err == json_tokener_success) return json_object_get(current);
Michael Clarkdfaf6702007-10-25 02:26:00 +0000513 MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
Michael Clarka850f8e2007-03-13 08:26:26 +0000514 json_tokener_errors[tok->err], tok->char_offset);
515 return NULL;
Michael Clarkf0d08882007-03-13 08:26:18 +0000516}