blob: 9c057284887e78ee267ea9a3859469facaed0cbb [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>
Michael Clarkc8f4a6e2007-12-07 02:44:24 +000016#include <stddef.h>
Michael Clarkf0d08882007-03-13 08:26:18 +000017#include <ctype.h>
18#include <string.h>
19
20#include "bits.h"
21#include "debug.h"
22#include "printbuf.h"
23#include "arraylist.h"
24#include "json_object.h"
25#include "json_tokener.h"
26
Michael Clarka850f8e2007-03-13 08:26:26 +000027
Michael Clark837240f2007-03-13 08:26:25 +000028#if !HAVE_STRNCASECMP && defined(_MSC_VER)
29 /* MSC has the version as _strnicmp */
30# define strncasecmp _strnicmp
31#elif !HAVE_STRNCASECMP
32# error You do not have strncasecmp on your system.
33#endif /* HAVE_STRNCASECMP */
34
35
Michael Clarka850f8e2007-03-13 08:26:26 +000036static const char* json_null_str = "null";
37static const char* json_true_str = "true";
38static const char* json_false_str = "false";
Michael Clarkf0d08882007-03-13 08:26:18 +000039
Michael Clarka850f8e2007-03-13 08:26:26 +000040const char* json_tokener_errors[] = {
41 "success",
42 "continue",
43 "nesting to deep",
44 "unexpected end of data",
45 "unexpected character",
46 "null expected",
47 "boolean expected",
48 "number expected",
49 "array value separator ',' expected",
50 "quoted object property name expected",
51 "object property name separator ':' expected",
52 "object value separator ',' expected",
53 "invalid string sequence",
54 "expected comment",
55};
56
57
Michael Clarke8de0782009-02-25 01:45:00 +000058struct json_tokener* json_tokener_new(void)
Michael Clarkf0d08882007-03-13 08:26:18 +000059{
Michael Clarka850f8e2007-03-13 08:26:26 +000060 struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
61 tok->pb = printbuf_new();
62 json_tokener_reset(tok);
63 return tok;
64}
65
66void json_tokener_free(struct json_tokener *tok)
67{
68 json_tokener_reset(tok);
69 if(tok) printbuf_free(tok->pb);
70 free(tok);
71}
72
73static void json_tokener_reset_level(struct json_tokener *tok, int depth)
74{
75 tok->stack[depth].state = json_tokener_state_eatws;
76 tok->stack[depth].saved_state = json_tokener_state_start;
77 json_object_put(tok->stack[depth].current);
78 tok->stack[depth].current = NULL;
79 free(tok->stack[depth].obj_field_name);
80 tok->stack[depth].obj_field_name = NULL;
81}
82
83void json_tokener_reset(struct json_tokener *tok)
84{
85 int i;
Michael Clark22dee7c2009-02-25 01:51:40 +000086 if (!tok)
87 return;
88
Michael Clarka850f8e2007-03-13 08:26:26 +000089 for(i = tok->depth; i >= 0; i--)
90 json_tokener_reset_level(tok, i);
91 tok->depth = 0;
92 tok->err = json_tokener_success;
93}
94
95struct json_object* json_tokener_parse(char *str)
96{
97 struct json_tokener* tok;
Michael Clarkf0d08882007-03-13 08:26:18 +000098 struct json_object* obj;
99
Michael Clarka850f8e2007-03-13 08:26:26 +0000100 tok = json_tokener_new();
101 obj = json_tokener_parse_ex(tok, str, -1);
102 if(tok->err != json_tokener_success)
103 obj = error_ptr(-tok->err);
104 json_tokener_free(tok);
Michael Clarkf0d08882007-03-13 08:26:18 +0000105 return obj;
106}
107
Michael Clarka850f8e2007-03-13 08:26:26 +0000108
Michael Clark4504df72007-03-13 08:26:20 +0000109#if !HAVE_STRNDUP
110/* CAW: compliant version of strndup() */
111char* strndup(const char* str, size_t n)
112{
Michael Clarka850f8e2007-03-13 08:26:26 +0000113 if(str) {
114 size_t len = strlen(str);
115 size_t nn = min(len,n);
116 char* s = (char*)malloc(sizeof(char) * (nn + 1));
Michael Clark4504df72007-03-13 08:26:20 +0000117
Michael Clarka850f8e2007-03-13 08:26:26 +0000118 if(s) {
119 memcpy(s, str, nn);
120 s[nn] = '\0';
121 }
Michael Clark4504df72007-03-13 08:26:20 +0000122
Michael Clarka850f8e2007-03-13 08:26:26 +0000123 return s;
124 }
Michael Clark4504df72007-03-13 08:26:20 +0000125
Michael Clarka850f8e2007-03-13 08:26:26 +0000126 return NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000127}
128#endif
129
Michael Clarka850f8e2007-03-13 08:26:26 +0000130
131#define state tok->stack[tok->depth].state
132#define saved_state tok->stack[tok->depth].saved_state
133#define current tok->stack[tok->depth].current
134#define obj_field_name tok->stack[tok->depth].obj_field_name
135
136struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
137 char *str, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +0000138{
Michael Clarka850f8e2007-03-13 08:26:26 +0000139 struct json_object *obj = NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000140 char c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000141
Michael Clarka850f8e2007-03-13 08:26:26 +0000142 tok->char_offset = 0;
143 tok->err = json_tokener_success;
Michael Clarkf0d08882007-03-13 08:26:18 +0000144
Michael Clarkf0d08882007-03-13 08:26:18 +0000145 do {
Michael Clarka850f8e2007-03-13 08:26:26 +0000146 if(tok->char_offset == len) {
147 if(tok->depth == 0 && state == json_tokener_state_eatws &&
148 saved_state == json_tokener_state_finish)
149 tok->err = json_tokener_success;
150 else
151 tok->err = json_tokener_continue;
152 goto out;
153 }
154
155 c = *str;
156 redo_char:
Michael Clarkf0d08882007-03-13 08:26:18 +0000157 switch(state) {
158
159 case json_tokener_state_eatws:
160 if(isspace(c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000161 /* okay */
Michael Clarkf0d08882007-03-13 08:26:18 +0000162 } else if(c == '/') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000163 printbuf_reset(tok->pb);
164 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000165 state = json_tokener_state_comment_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000166 } else {
167 state = saved_state;
Michael Clarka850f8e2007-03-13 08:26:26 +0000168 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000169 }
170 break;
171
172 case json_tokener_state_start:
173 switch(c) {
174 case '{':
175 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000176 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000177 current = json_object_new_object();
Michael Clarkf0d08882007-03-13 08:26:18 +0000178 break;
179 case '[':
180 state = json_tokener_state_eatws;
181 saved_state = json_tokener_state_array;
182 current = json_object_new_array();
Michael Clarkf0d08882007-03-13 08:26:18 +0000183 break;
184 case 'N':
185 case 'n':
186 state = json_tokener_state_null;
Michael Clarka850f8e2007-03-13 08:26:26 +0000187 printbuf_reset(tok->pb);
188 tok->st_pos = 0;
189 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000190 case '"':
191 case '\'':
Michael Clarkf0d08882007-03-13 08:26:18 +0000192 state = json_tokener_state_string;
Michael Clarka850f8e2007-03-13 08:26:26 +0000193 printbuf_reset(tok->pb);
194 tok->quote_char = c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000195 break;
196 case 'T':
197 case 't':
198 case 'F':
199 case 'f':
200 state = json_tokener_state_boolean;
Michael Clarka850f8e2007-03-13 08:26:26 +0000201 printbuf_reset(tok->pb);
202 tok->st_pos = 0;
203 goto redo_char;
Michael Clark4504df72007-03-13 08:26:20 +0000204#if defined(__GNUC__)
205 case '0' ... '9':
206#else
207 case '0':
208 case '1':
209 case '2':
210 case '3':
211 case '4':
212 case '5':
213 case '6':
214 case '7':
215 case '8':
216 case '9':
217#endif
Michael Clarkf0d08882007-03-13 08:26:18 +0000218 case '-':
Michael Clarkf0d08882007-03-13 08:26:18 +0000219 state = json_tokener_state_number;
Michael Clarka850f8e2007-03-13 08:26:26 +0000220 printbuf_reset(tok->pb);
221 tok->is_double = 0;
222 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000223 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000224 tok->err = json_tokener_error_parse_unexpected;
Michael Clarkf0d08882007-03-13 08:26:18 +0000225 goto out;
226 }
227 break;
228
229 case json_tokener_state_finish:
Michael Clarka850f8e2007-03-13 08:26:26 +0000230 if(tok->depth == 0) goto out;
231 obj = json_object_get(current);
232 json_tokener_reset_level(tok, tok->depth);
233 tok->depth--;
234 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000235
236 case json_tokener_state_null:
Michael Clarka850f8e2007-03-13 08:26:26 +0000237 printbuf_memappend(tok->pb, &c, 1);
238 if(strncasecmp(json_null_str, tok->pb->buf,
239 min(tok->st_pos+1, strlen(json_null_str))) == 0) {
240 if(tok->st_pos == strlen(json_null_str)) {
241 current = NULL;
242 saved_state = json_tokener_state_finish;
243 state = json_tokener_state_eatws;
244 goto redo_char;
245 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000246 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000247 tok->err = json_tokener_error_parse_null;
248 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000249 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000250 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000251 break;
252
253 case json_tokener_state_comment_start:
254 if(c == '*') {
255 state = json_tokener_state_comment;
256 } else if(c == '/') {
257 state = json_tokener_state_comment_eol;
258 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000259 tok->err = json_tokener_error_parse_comment;
Michael Clarkf0d08882007-03-13 08:26:18 +0000260 goto out;
261 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000262 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000263 break;
264
265 case json_tokener_state_comment:
266 if(c == '*') state = json_tokener_state_comment_end;
Michael Clarka850f8e2007-03-13 08:26:26 +0000267 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000268 break;
269
270 case json_tokener_state_comment_eol:
271 if(c == '\n') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000272 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000273 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000274 } else {
275 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000276 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000277 break;
278
279 case json_tokener_state_comment_end:
Michael Clarka850f8e2007-03-13 08:26:26 +0000280 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000281 if(c == '/') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000282 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000283 state = json_tokener_state_eatws;
284 } else {
285 state = json_tokener_state_comment;
286 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000287 break;
288
289 case json_tokener_state_string:
Michael Clarka850f8e2007-03-13 08:26:26 +0000290 if(c == tok->quote_char) {
291 current = json_object_new_string(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000292 saved_state = json_tokener_state_finish;
293 state = json_tokener_state_eatws;
294 } else if(c == '\\') {
295 saved_state = json_tokener_state_string;
296 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000297 } else {
298 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000299 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000300 break;
301
302 case json_tokener_state_string_escape:
303 switch(c) {
304 case '"':
305 case '\\':
Michael Clarka850f8e2007-03-13 08:26:26 +0000306 case '/':
307 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000308 state = saved_state;
309 break;
310 case 'b':
311 case 'n':
312 case 'r':
313 case 't':
Michael Clarka850f8e2007-03-13 08:26:26 +0000314 if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
315 else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
316 else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
317 else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000318 state = saved_state;
319 break;
320 case 'u':
Michael Clarka850f8e2007-03-13 08:26:26 +0000321 tok->ucs_char = 0;
322 tok->st_pos = 0;
Michael Clarkf0d08882007-03-13 08:26:18 +0000323 state = json_tokener_state_escape_unicode;
324 break;
325 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000326 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000327 goto out;
328 }
329 break;
330
331 case json_tokener_state_escape_unicode:
332 if(strchr(json_hex_chars, c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000333 tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
334 if(tok->st_pos == 4) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000335 unsigned char utf_out[3];
Michael Clarka850f8e2007-03-13 08:26:26 +0000336 if (tok->ucs_char < 0x80) {
337 utf_out[0] = tok->ucs_char;
338 printbuf_memappend(tok->pb, (char*)utf_out, 1);
339 } else if (tok->ucs_char < 0x800) {
340 utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
341 utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
342 printbuf_memappend(tok->pb, (char*)utf_out, 2);
Michael Clarkf0d08882007-03-13 08:26:18 +0000343 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000344 utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
345 utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
346 utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
347 printbuf_memappend(tok->pb, (char*)utf_out, 3);
Michael Clarkf0d08882007-03-13 08:26:18 +0000348 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000349 state = saved_state;
350 }
351 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000352 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000353 goto out;
354 }
355 break;
356
357 case json_tokener_state_boolean:
Michael Clarka850f8e2007-03-13 08:26:26 +0000358 printbuf_memappend(tok->pb, &c, 1);
359 if(strncasecmp(json_true_str, tok->pb->buf,
360 min(tok->st_pos+1, strlen(json_true_str))) == 0) {
361 if(tok->st_pos == strlen(json_true_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000362 current = json_object_new_boolean(1);
363 saved_state = json_tokener_state_finish;
364 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000365 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000366 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000367 } else if(strncasecmp(json_false_str, tok->pb->buf,
368 min(tok->st_pos+1, strlen(json_false_str))) == 0) {
369 if(tok->st_pos == strlen(json_false_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000370 current = json_object_new_boolean(0);
371 saved_state = json_tokener_state_finish;
372 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000373 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000374 }
375 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000376 tok->err = json_tokener_error_parse_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000377 goto out;
378 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000379 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000380 break;
381
382 case json_tokener_state_number:
Michael Clarka850f8e2007-03-13 08:26:26 +0000383 if(c && strchr(json_number_chars, c)) {
384 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkc8f4a6e2007-12-07 02:44:24 +0000385 if(c == '.' || c == 'e' || c == 'E') tok->is_double = 1;
Michael Clarka850f8e2007-03-13 08:26:26 +0000386 } else {
Michael Clarkf0d08882007-03-13 08:26:18 +0000387 int numi;
388 double numd;
Michael Clarka850f8e2007-03-13 08:26:26 +0000389 if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000390 current = json_object_new_int(numi);
Michael Clarka850f8e2007-03-13 08:26:26 +0000391 } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000392 current = json_object_new_double(numd);
393 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000394 tok->err = json_tokener_error_parse_number;
Michael Clarkf0d08882007-03-13 08:26:18 +0000395 goto out;
396 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000397 saved_state = json_tokener_state_finish;
398 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000399 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000400 }
401 break;
402
403 case json_tokener_state_array:
404 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000405 saved_state = json_tokener_state_finish;
406 state = json_tokener_state_eatws;
407 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000408 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
409 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000410 goto out;
411 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000412 state = json_tokener_state_array_add;
413 tok->depth++;
414 json_tokener_reset_level(tok, tok->depth);
415 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000416 }
417 break;
418
Michael Clarka850f8e2007-03-13 08:26:26 +0000419 case json_tokener_state_array_add:
420 json_object_array_add(current, obj);
421 saved_state = json_tokener_state_array_sep;
422 state = json_tokener_state_eatws;
423 goto redo_char;
424
Michael Clarkf0d08882007-03-13 08:26:18 +0000425 case json_tokener_state_array_sep:
426 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000427 saved_state = json_tokener_state_finish;
428 state = json_tokener_state_eatws;
429 } else if(c == ',') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000430 saved_state = json_tokener_state_array;
431 state = json_tokener_state_eatws;
432 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000433 tok->err = json_tokener_error_parse_array;
434 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000435 }
436 break;
437
Michael Clarkf0d08882007-03-13 08:26:18 +0000438 case json_tokener_state_object_field_start:
439 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000440 saved_state = json_tokener_state_finish;
441 state = json_tokener_state_eatws;
442 } else if (c == '"' || c == '\'') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000443 tok->quote_char = c;
444 printbuf_reset(tok->pb);
Michael Clarkf0d08882007-03-13 08:26:18 +0000445 state = json_tokener_state_object_field;
Michael Clark0370baa2007-03-13 08:26:22 +0000446 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000447 tok->err = json_tokener_error_parse_object_key_name;
Michael Clark0370baa2007-03-13 08:26:22 +0000448 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000449 }
450 break;
451
452 case json_tokener_state_object_field:
Michael Clarka850f8e2007-03-13 08:26:26 +0000453 if(c == tok->quote_char) {
454 obj_field_name = strdup(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000455 saved_state = json_tokener_state_object_field_end;
456 state = json_tokener_state_eatws;
457 } else if(c == '\\') {
458 saved_state = json_tokener_state_object_field;
459 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000460 } else {
461 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000462 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000463 break;
464
465 case json_tokener_state_object_field_end:
466 if(c == ':') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000467 saved_state = json_tokener_state_object_value;
468 state = json_tokener_state_eatws;
469 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000470 tok->err = json_tokener_error_parse_object_key_sep;
471 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000472 }
473 break;
474
475 case json_tokener_state_object_value:
Michael Clarka850f8e2007-03-13 08:26:26 +0000476 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
477 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000478 goto out;
479 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000480 state = json_tokener_state_object_value_add;
481 tok->depth++;
482 json_tokener_reset_level(tok, tok->depth);
483 goto redo_char;
484
485 case json_tokener_state_object_value_add:
Michael Clarkf0d08882007-03-13 08:26:18 +0000486 json_object_object_add(current, obj_field_name, obj);
487 free(obj_field_name);
488 obj_field_name = NULL;
489 saved_state = json_tokener_state_object_sep;
490 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000491 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000492
493 case json_tokener_state_object_sep:
494 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000495 saved_state = json_tokener_state_finish;
496 state = json_tokener_state_eatws;
497 } else if(c == ',') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000498 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000499 state = json_tokener_state_eatws;
500 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000501 tok->err = json_tokener_error_parse_object_value_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000502 goto out;
503 }
504 break;
505
506 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000507 str++;
508 tok->char_offset++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000509 } while(c);
510
511 if(state != json_tokener_state_finish &&
512 saved_state != json_tokener_state_finish)
Michael Clarka850f8e2007-03-13 08:26:26 +0000513 tok->err = json_tokener_error_parse_eof;
Michael Clarkf0d08882007-03-13 08:26:18 +0000514
515 out:
Michael Clarka850f8e2007-03-13 08:26:26 +0000516 if(tok->err == json_tokener_success) return json_object_get(current);
Michael Clarkdfaf6702007-10-25 02:26:00 +0000517 MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
Michael Clarka850f8e2007-03-13 08:26:26 +0000518 json_tokener_errors[tok->err], tok->char_offset);
519 return NULL;
Michael Clarkf0d08882007-03-13 08:26:18 +0000520}