blob: 3f196db37b08aa5a07c292e2098de033cc941f90 [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;
86 for(i = tok->depth; i >= 0; i--)
87 json_tokener_reset_level(tok, i);
88 tok->depth = 0;
89 tok->err = json_tokener_success;
90}
91
92struct json_object* json_tokener_parse(char *str)
93{
94 struct json_tokener* tok;
Michael Clarkf0d08882007-03-13 08:26:18 +000095 struct json_object* obj;
96
Michael Clarka850f8e2007-03-13 08:26:26 +000097 tok = json_tokener_new();
98 obj = json_tokener_parse_ex(tok, str, -1);
99 if(tok->err != json_tokener_success)
100 obj = error_ptr(-tok->err);
101 json_tokener_free(tok);
Michael Clarkf0d08882007-03-13 08:26:18 +0000102 return obj;
103}
104
Michael Clarka850f8e2007-03-13 08:26:26 +0000105
Michael Clark4504df72007-03-13 08:26:20 +0000106#if !HAVE_STRNDUP
107/* CAW: compliant version of strndup() */
108char* strndup(const char* str, size_t n)
109{
Michael Clarka850f8e2007-03-13 08:26:26 +0000110 if(str) {
111 size_t len = strlen(str);
112 size_t nn = min(len,n);
113 char* s = (char*)malloc(sizeof(char) * (nn + 1));
Michael Clark4504df72007-03-13 08:26:20 +0000114
Michael Clarka850f8e2007-03-13 08:26:26 +0000115 if(s) {
116 memcpy(s, str, nn);
117 s[nn] = '\0';
118 }
Michael Clark4504df72007-03-13 08:26:20 +0000119
Michael Clarka850f8e2007-03-13 08:26:26 +0000120 return s;
121 }
Michael Clark4504df72007-03-13 08:26:20 +0000122
Michael Clarka850f8e2007-03-13 08:26:26 +0000123 return NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000124}
125#endif
126
Michael Clarka850f8e2007-03-13 08:26:26 +0000127
128#define state tok->stack[tok->depth].state
129#define saved_state tok->stack[tok->depth].saved_state
130#define current tok->stack[tok->depth].current
131#define obj_field_name tok->stack[tok->depth].obj_field_name
132
133struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
134 char *str, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +0000135{
Michael Clarka850f8e2007-03-13 08:26:26 +0000136 struct json_object *obj = NULL;
Michael Clark4504df72007-03-13 08:26:20 +0000137 char c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000138
Michael Clarka850f8e2007-03-13 08:26:26 +0000139 tok->char_offset = 0;
140 tok->err = json_tokener_success;
Michael Clarkf0d08882007-03-13 08:26:18 +0000141
Michael Clarkf0d08882007-03-13 08:26:18 +0000142 do {
Michael Clarka850f8e2007-03-13 08:26:26 +0000143 if(tok->char_offset == len) {
144 if(tok->depth == 0 && state == json_tokener_state_eatws &&
145 saved_state == json_tokener_state_finish)
146 tok->err = json_tokener_success;
147 else
148 tok->err = json_tokener_continue;
149 goto out;
150 }
151
152 c = *str;
153 redo_char:
Michael Clarkf0d08882007-03-13 08:26:18 +0000154 switch(state) {
155
156 case json_tokener_state_eatws:
157 if(isspace(c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000158 /* okay */
Michael Clarkf0d08882007-03-13 08:26:18 +0000159 } else if(c == '/') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000160 printbuf_reset(tok->pb);
161 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000162 state = json_tokener_state_comment_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000163 } else {
164 state = saved_state;
Michael Clarka850f8e2007-03-13 08:26:26 +0000165 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000166 }
167 break;
168
169 case json_tokener_state_start:
170 switch(c) {
171 case '{':
172 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000173 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000174 current = json_object_new_object();
Michael Clarkf0d08882007-03-13 08:26:18 +0000175 break;
176 case '[':
177 state = json_tokener_state_eatws;
178 saved_state = json_tokener_state_array;
179 current = json_object_new_array();
Michael Clarkf0d08882007-03-13 08:26:18 +0000180 break;
181 case 'N':
182 case 'n':
183 state = json_tokener_state_null;
Michael Clarka850f8e2007-03-13 08:26:26 +0000184 printbuf_reset(tok->pb);
185 tok->st_pos = 0;
186 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000187 case '"':
188 case '\'':
Michael Clarkf0d08882007-03-13 08:26:18 +0000189 state = json_tokener_state_string;
Michael Clarka850f8e2007-03-13 08:26:26 +0000190 printbuf_reset(tok->pb);
191 tok->quote_char = c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000192 break;
193 case 'T':
194 case 't':
195 case 'F':
196 case 'f':
197 state = json_tokener_state_boolean;
Michael Clarka850f8e2007-03-13 08:26:26 +0000198 printbuf_reset(tok->pb);
199 tok->st_pos = 0;
200 goto redo_char;
Michael Clark4504df72007-03-13 08:26:20 +0000201#if defined(__GNUC__)
202 case '0' ... '9':
203#else
204 case '0':
205 case '1':
206 case '2':
207 case '3':
208 case '4':
209 case '5':
210 case '6':
211 case '7':
212 case '8':
213 case '9':
214#endif
Michael Clarkf0d08882007-03-13 08:26:18 +0000215 case '-':
Michael Clarkf0d08882007-03-13 08:26:18 +0000216 state = json_tokener_state_number;
Michael Clarka850f8e2007-03-13 08:26:26 +0000217 printbuf_reset(tok->pb);
218 tok->is_double = 0;
219 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000220 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000221 tok->err = json_tokener_error_parse_unexpected;
Michael Clarkf0d08882007-03-13 08:26:18 +0000222 goto out;
223 }
224 break;
225
226 case json_tokener_state_finish:
Michael Clarka850f8e2007-03-13 08:26:26 +0000227 if(tok->depth == 0) goto out;
228 obj = json_object_get(current);
229 json_tokener_reset_level(tok, tok->depth);
230 tok->depth--;
231 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000232
233 case json_tokener_state_null:
Michael Clarka850f8e2007-03-13 08:26:26 +0000234 printbuf_memappend(tok->pb, &c, 1);
235 if(strncasecmp(json_null_str, tok->pb->buf,
236 min(tok->st_pos+1, strlen(json_null_str))) == 0) {
237 if(tok->st_pos == strlen(json_null_str)) {
238 current = NULL;
239 saved_state = json_tokener_state_finish;
240 state = json_tokener_state_eatws;
241 goto redo_char;
242 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000243 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000244 tok->err = json_tokener_error_parse_null;
245 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000246 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000247 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000248 break;
249
250 case json_tokener_state_comment_start:
251 if(c == '*') {
252 state = json_tokener_state_comment;
253 } else if(c == '/') {
254 state = json_tokener_state_comment_eol;
255 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000256 tok->err = json_tokener_error_parse_comment;
Michael Clarkf0d08882007-03-13 08:26:18 +0000257 goto out;
258 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000259 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000260 break;
261
262 case json_tokener_state_comment:
263 if(c == '*') state = json_tokener_state_comment_end;
Michael Clarka850f8e2007-03-13 08:26:26 +0000264 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000265 break;
266
267 case json_tokener_state_comment_eol:
268 if(c == '\n') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000269 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000270 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000271 } else {
272 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000273 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000274 break;
275
276 case json_tokener_state_comment_end:
Michael Clarka850f8e2007-03-13 08:26:26 +0000277 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000278 if(c == '/') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000279 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000280 state = json_tokener_state_eatws;
281 } else {
282 state = json_tokener_state_comment;
283 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000284 break;
285
286 case json_tokener_state_string:
Michael Clarka850f8e2007-03-13 08:26:26 +0000287 if(c == tok->quote_char) {
288 current = json_object_new_string(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000289 saved_state = json_tokener_state_finish;
290 state = json_tokener_state_eatws;
291 } else if(c == '\\') {
292 saved_state = json_tokener_state_string;
293 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000294 } else {
295 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000296 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000297 break;
298
299 case json_tokener_state_string_escape:
300 switch(c) {
301 case '"':
302 case '\\':
Michael Clarka850f8e2007-03-13 08:26:26 +0000303 case '/':
304 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000305 state = saved_state;
306 break;
307 case 'b':
308 case 'n':
309 case 'r':
310 case 't':
Michael Clarka850f8e2007-03-13 08:26:26 +0000311 if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
312 else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
313 else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
314 else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000315 state = saved_state;
316 break;
317 case 'u':
Michael Clarka850f8e2007-03-13 08:26:26 +0000318 tok->ucs_char = 0;
319 tok->st_pos = 0;
Michael Clarkf0d08882007-03-13 08:26:18 +0000320 state = json_tokener_state_escape_unicode;
321 break;
322 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000323 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000324 goto out;
325 }
326 break;
327
328 case json_tokener_state_escape_unicode:
329 if(strchr(json_hex_chars, c)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000330 tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
331 if(tok->st_pos == 4) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000332 unsigned char utf_out[3];
Michael Clarka850f8e2007-03-13 08:26:26 +0000333 if (tok->ucs_char < 0x80) {
334 utf_out[0] = tok->ucs_char;
335 printbuf_memappend(tok->pb, (char*)utf_out, 1);
336 } else if (tok->ucs_char < 0x800) {
337 utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
338 utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
339 printbuf_memappend(tok->pb, (char*)utf_out, 2);
Michael Clarkf0d08882007-03-13 08:26:18 +0000340 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000341 utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
342 utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
343 utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
344 printbuf_memappend(tok->pb, (char*)utf_out, 3);
Michael Clarkf0d08882007-03-13 08:26:18 +0000345 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000346 state = saved_state;
347 }
348 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000349 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000350 goto out;
351 }
352 break;
353
354 case json_tokener_state_boolean:
Michael Clarka850f8e2007-03-13 08:26:26 +0000355 printbuf_memappend(tok->pb, &c, 1);
356 if(strncasecmp(json_true_str, tok->pb->buf,
357 min(tok->st_pos+1, strlen(json_true_str))) == 0) {
358 if(tok->st_pos == strlen(json_true_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000359 current = json_object_new_boolean(1);
360 saved_state = json_tokener_state_finish;
361 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000362 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000363 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000364 } else if(strncasecmp(json_false_str, tok->pb->buf,
365 min(tok->st_pos+1, strlen(json_false_str))) == 0) {
366 if(tok->st_pos == strlen(json_false_str)) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000367 current = json_object_new_boolean(0);
368 saved_state = json_tokener_state_finish;
369 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000370 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000371 }
372 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000373 tok->err = json_tokener_error_parse_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000374 goto out;
375 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000376 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000377 break;
378
379 case json_tokener_state_number:
Michael Clarka850f8e2007-03-13 08:26:26 +0000380 if(c && strchr(json_number_chars, c)) {
381 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkc8f4a6e2007-12-07 02:44:24 +0000382 if(c == '.' || c == 'e' || c == 'E') tok->is_double = 1;
Michael Clarka850f8e2007-03-13 08:26:26 +0000383 } else {
Michael Clarkf0d08882007-03-13 08:26:18 +0000384 int numi;
385 double numd;
Michael Clarka850f8e2007-03-13 08:26:26 +0000386 if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000387 current = json_object_new_int(numi);
Michael Clarka850f8e2007-03-13 08:26:26 +0000388 } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000389 current = json_object_new_double(numd);
390 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000391 tok->err = json_tokener_error_parse_number;
Michael Clarkf0d08882007-03-13 08:26:18 +0000392 goto out;
393 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000394 saved_state = json_tokener_state_finish;
395 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000396 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000397 }
398 break;
399
400 case json_tokener_state_array:
401 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000402 saved_state = json_tokener_state_finish;
403 state = json_tokener_state_eatws;
404 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000405 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
406 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000407 goto out;
408 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000409 state = json_tokener_state_array_add;
410 tok->depth++;
411 json_tokener_reset_level(tok, tok->depth);
412 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000413 }
414 break;
415
Michael Clarka850f8e2007-03-13 08:26:26 +0000416 case json_tokener_state_array_add:
417 json_object_array_add(current, obj);
418 saved_state = json_tokener_state_array_sep;
419 state = json_tokener_state_eatws;
420 goto redo_char;
421
Michael Clarkf0d08882007-03-13 08:26:18 +0000422 case json_tokener_state_array_sep:
423 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000424 saved_state = json_tokener_state_finish;
425 state = json_tokener_state_eatws;
426 } else if(c == ',') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000427 saved_state = json_tokener_state_array;
428 state = json_tokener_state_eatws;
429 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000430 tok->err = json_tokener_error_parse_array;
431 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000432 }
433 break;
434
Michael Clarkf0d08882007-03-13 08:26:18 +0000435 case json_tokener_state_object_field_start:
436 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000437 saved_state = json_tokener_state_finish;
438 state = json_tokener_state_eatws;
439 } else if (c == '"' || c == '\'') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000440 tok->quote_char = c;
441 printbuf_reset(tok->pb);
Michael Clarkf0d08882007-03-13 08:26:18 +0000442 state = json_tokener_state_object_field;
Michael Clark0370baa2007-03-13 08:26:22 +0000443 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000444 tok->err = json_tokener_error_parse_object_key_name;
Michael Clark0370baa2007-03-13 08:26:22 +0000445 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000446 }
447 break;
448
449 case json_tokener_state_object_field:
Michael Clarka850f8e2007-03-13 08:26:26 +0000450 if(c == tok->quote_char) {
451 obj_field_name = strdup(tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000452 saved_state = json_tokener_state_object_field_end;
453 state = json_tokener_state_eatws;
454 } else if(c == '\\') {
455 saved_state = json_tokener_state_object_field;
456 state = json_tokener_state_string_escape;
Michael Clarka850f8e2007-03-13 08:26:26 +0000457 } else {
458 printbuf_memappend(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000459 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000460 break;
461
462 case json_tokener_state_object_field_end:
463 if(c == ':') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000464 saved_state = json_tokener_state_object_value;
465 state = json_tokener_state_eatws;
466 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000467 tok->err = json_tokener_error_parse_object_key_sep;
468 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000469 }
470 break;
471
472 case json_tokener_state_object_value:
Michael Clarka850f8e2007-03-13 08:26:26 +0000473 if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
474 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000475 goto out;
476 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000477 state = json_tokener_state_object_value_add;
478 tok->depth++;
479 json_tokener_reset_level(tok, tok->depth);
480 goto redo_char;
481
482 case json_tokener_state_object_value_add:
Michael Clarkf0d08882007-03-13 08:26:18 +0000483 json_object_object_add(current, obj_field_name, obj);
484 free(obj_field_name);
485 obj_field_name = NULL;
486 saved_state = json_tokener_state_object_sep;
487 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000488 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000489
490 case json_tokener_state_object_sep:
491 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000492 saved_state = json_tokener_state_finish;
493 state = json_tokener_state_eatws;
494 } else if(c == ',') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000495 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000496 state = json_tokener_state_eatws;
497 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000498 tok->err = json_tokener_error_parse_object_value_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000499 goto out;
500 }
501 break;
502
503 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000504 str++;
505 tok->char_offset++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000506 } while(c);
507
508 if(state != json_tokener_state_finish &&
509 saved_state != json_tokener_state_finish)
Michael Clarka850f8e2007-03-13 08:26:26 +0000510 tok->err = json_tokener_error_parse_eof;
Michael Clarkf0d08882007-03-13 08:26:18 +0000511
512 out:
Michael Clarka850f8e2007-03-13 08:26:26 +0000513 if(tok->err == json_tokener_success) return json_object_get(current);
Michael Clarkdfaf6702007-10-25 02:26:00 +0000514 MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
Michael Clarka850f8e2007-03-13 08:26:26 +0000515 json_tokener_errors[tok->err], tok->char_offset);
516 return NULL;
Michael Clarkf0d08882007-03-13 08:26:18 +0000517}