blob: 60e81f279d3e666c1b6b9a804442af90eed27a35 [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 *
Michael Clark95f55a72009-04-27 08:16:58 +000010 *
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)
Michael Clarkf0d08882007-03-13 08:26:18 +000014 */
15
Michael Clark4504df72007-03-13 08:26:20 +000016#include "config.h"
17
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -040018#include <math.h>
Michael Clarkf0d08882007-03-13 08:26:18 +000019#include <stdio.h>
20#include <stdlib.h>
Michael Clarkc8f4a6e2007-12-07 02:44:24 +000021#include <stddef.h>
Michael Clarkf0d08882007-03-13 08:26:18 +000022#include <ctype.h>
23#include <string.h>
Michael Clarkc4dceae2010-10-06 16:39:20 +000024#include <limits.h>
Michael Clarkf0d08882007-03-13 08:26:18 +000025
Michael Clarkf0d08882007-03-13 08:26:18 +000026#include "debug.h"
27#include "printbuf.h"
28#include "arraylist.h"
Michael Clarkc4dceae2010-10-06 16:39:20 +000029#include "json_inttypes.h"
Michael Clarkf0d08882007-03-13 08:26:18 +000030#include "json_object.h"
31#include "json_tokener.h"
Michael Clarkc4dceae2010-10-06 16:39:20 +000032#include "json_util.h"
Michael Clarka850f8e2007-03-13 08:26:26 +000033
Remi Colleta01b6592012-12-13 09:47:33 +010034#ifdef HAVE_LOCALE_H
35#include <locale.h>
36#endif /* HAVE_LOCALE_H */
37
Eric Haszlakiewiczd4e81f92014-05-03 22:29:10 -040038#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
39
Mateusz Loskota6f39a32012-05-21 23:22:36 +010040#if !HAVE_STRDUP && defined(_MSC_VER)
41 /* MSC has the version as _strdup */
42# define strdup _strdup
43#elif !HAVE_STRDUP
44# error You do not have strdup on your system.
45#endif /* HAVE_STRDUP */
46
Michael Clark837240f2007-03-13 08:26:25 +000047#if !HAVE_STRNCASECMP && defined(_MSC_VER)
48 /* MSC has the version as _strnicmp */
49# define strncasecmp _strnicmp
50#elif !HAVE_STRNCASECMP
51# error You do not have strncasecmp on your system.
52#endif /* HAVE_STRNCASECMP */
53
Markus Stenberga1c89912014-03-18 16:29:49 +020054/* Use C99 NAN by default; if not available, nan("") should work too. */
55#ifndef NAN
56#define NAN nan("")
57#endif /* !NAN */
58
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -040059static const char json_null_str[] = "null";
60static const int json_null_str_len = sizeof(json_null_str) - 1;
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -040061static const char json_inf_str[] = "Infinity";
62static const int json_inf_str_len = sizeof(json_inf_str) - 1;
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -040063static const char json_nan_str[] = "NaN";
64static const int json_nan_str_len = sizeof(json_nan_str) - 1;
65static const char json_true_str[] = "true";
66static const int json_true_str_len = sizeof(json_true_str) - 1;
67static const char json_false_str[] = "false";
68static const int json_false_str_len = sizeof(json_false_str) - 1;
Michael Clarkf0d08882007-03-13 08:26:18 +000069
Eric Haszlakiewiczf9136f62014-03-22 21:41:24 -040070static const char* json_tokener_errors[] = {
Michael Clarka850f8e2007-03-13 08:26:26 +000071 "success",
72 "continue",
Eric Haszlakiewicz3620cba2012-03-31 12:52:59 -050073 "nesting too deep",
Michael Clarka850f8e2007-03-13 08:26:26 +000074 "unexpected end of data",
75 "unexpected character",
76 "null expected",
77 "boolean expected",
78 "number expected",
79 "array value separator ',' expected",
80 "quoted object property name expected",
81 "object property name separator ':' expected",
82 "object value separator ',' expected",
83 "invalid string sequence",
84 "expected comment",
Michael Clark64e36902014-04-09 13:48:21 +080085 "buffer size overflow"
Michael Clarka850f8e2007-03-13 08:26:26 +000086};
87
Eric Haszlakiewicz2f9091f2012-02-22 08:24:40 -060088const char *json_tokener_error_desc(enum json_tokener_error jerr)
89{
Eric Haszlakiewiczca8b27d2013-02-09 16:35:24 -060090 int jerr_int = (int)jerr;
Eric Haszlakiewicz56df93d2014-02-11 23:16:53 -050091 if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
Eric Haszlakiewicz2f9091f2012-02-22 08:24:40 -060092 return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
93 return json_tokener_errors[jerr];
94}
95
96enum json_tokener_error json_tokener_get_error(json_tokener *tok)
97{
98 return tok->err;
99}
100
Brent Miller126ad952009-08-20 06:50:22 +0000101/* Stuff for decoding unicode sequences */
102#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
103#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
104#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
105static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
106
Remi Collet197cb1d2012-11-27 09:01:45 +0100107struct json_tokener* json_tokener_new_ex(int depth)
Michael Clarkf0d08882007-03-13 08:26:18 +0000108{
Michael Clarkaaec1ef2009-02-25 02:31:32 +0000109 struct json_tokener *tok;
110
111 tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
Christopher Watford543bb142009-07-08 03:46:10 +0000112 if (!tok) return NULL;
Eric Haszlakiewiczca8b27d2013-02-09 16:35:24 -0600113 tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
Remi Collet197cb1d2012-11-27 09:01:45 +0100114 if (!tok->stack) {
115 free(tok);
116 return NULL;
117 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000118 tok->pb = printbuf_new();
Remi Collet197cb1d2012-11-27 09:01:45 +0100119 tok->max_depth = depth;
Michael Clarka850f8e2007-03-13 08:26:26 +0000120 json_tokener_reset(tok);
121 return tok;
122}
123
Remi Collet197cb1d2012-11-27 09:01:45 +0100124struct json_tokener* json_tokener_new(void)
125{
126 return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
127}
128
Michael Clarka850f8e2007-03-13 08:26:26 +0000129void json_tokener_free(struct json_tokener *tok)
130{
131 json_tokener_reset(tok);
Remi Collet197cb1d2012-11-27 09:01:45 +0100132 if (tok->pb) printbuf_free(tok->pb);
133 if (tok->stack) free(tok->stack);
Michael Clarka850f8e2007-03-13 08:26:26 +0000134 free(tok);
135}
136
137static void json_tokener_reset_level(struct json_tokener *tok, int depth)
138{
139 tok->stack[depth].state = json_tokener_state_eatws;
140 tok->stack[depth].saved_state = json_tokener_state_start;
141 json_object_put(tok->stack[depth].current);
142 tok->stack[depth].current = NULL;
143 free(tok->stack[depth].obj_field_name);
144 tok->stack[depth].obj_field_name = NULL;
145}
146
147void json_tokener_reset(struct json_tokener *tok)
148{
149 int i;
Michael Clark22dee7c2009-02-25 01:51:40 +0000150 if (!tok)
151 return;
152
Michael Clarka850f8e2007-03-13 08:26:26 +0000153 for(i = tok->depth; i >= 0; i--)
154 json_tokener_reset_level(tok, i);
155 tok->depth = 0;
156 tok->err = json_tokener_success;
157}
158
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000159struct json_object* json_tokener_parse(const char *str)
Michael Clarka850f8e2007-03-13 08:26:26 +0000160{
Eric Haszlakiewicz3620cba2012-03-31 12:52:59 -0500161 enum json_tokener_error jerr_ignored;
162 struct json_object* obj;
163 obj = json_tokener_parse_verbose(str, &jerr_ignored);
164 return obj;
Michael Clarkf0d08882007-03-13 08:26:18 +0000165}
166
Jehiah Czebotara503ee82010-12-08 03:52:07 +0000167struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
168{
169 struct json_tokener* tok;
170 struct json_object* obj;
171
172 tok = json_tokener_new();
Eric Haszlakiewicz3620cba2012-03-31 12:52:59 -0500173 if (!tok)
174 return NULL;
Jehiah Czebotara503ee82010-12-08 03:52:07 +0000175 obj = json_tokener_parse_ex(tok, str, -1);
176 *error = tok->err;
177 if(tok->err != json_tokener_success) {
Eric Haszlakiewicz3620cba2012-03-31 12:52:59 -0500178 if (obj != NULL)
179 json_object_put(obj);
Jehiah Czebotara503ee82010-12-08 03:52:07 +0000180 obj = NULL;
181 }
182
183 json_tokener_free(tok);
184 return obj;
185}
186
Michael Clarka850f8e2007-03-13 08:26:26 +0000187#define state tok->stack[tok->depth].state
188#define saved_state tok->stack[tok->depth].saved_state
189#define current tok->stack[tok->depth].current
190#define obj_field_name tok->stack[tok->depth].obj_field_name
191
Michael Clark95f55a72009-04-27 08:16:58 +0000192/* Optimization:
193 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
194 * iterating character-by character. A large performance boost is
195 * achieved by using tighter loops to locally handle units such as
William Dignaziobb492d42013-03-06 12:29:33 -0500196 * comments and strings. Loops that handle an entire token within
197 * their scope also gather entire strings and pass them to
Michael Clark95f55a72009-04-27 08:16:58 +0000198 * printbuf_memappend() in a single call, rather than calling
199 * printbuf_memappend() one char at a time.
200 *
William Dignaziobb492d42013-03-06 12:29:33 -0500201 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
Michael Clark95f55a72009-04-27 08:16:58 +0000202 * common to both the main loop and the tighter loops.
203 */
204
William Dignaziobb492d42013-03-06 12:29:33 -0500205/* PEEK_CHAR(dest, tok) macro:
206 * Peeks at the current char and stores it in dest.
Michael Clark95f55a72009-04-27 08:16:58 +0000207 * Returns 1 on success, sets tok->err and returns 0 if no more chars.
208 * Implicit inputs: str, len vars
209 */
William Dignaziobb492d42013-03-06 12:29:33 -0500210#define PEEK_CHAR(dest, tok) \
Michael Clark95f55a72009-04-27 08:16:58 +0000211 (((tok)->char_offset == len) ? \
212 (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
213 (((tok)->err = json_tokener_success), 0) \
214 : \
215 (((tok)->err = json_tokener_continue), 0) \
216 ) : \
217 (((dest) = *str), 1) \
218 )
William Dignaziobb492d42013-03-06 12:29:33 -0500219
Michael Clark95f55a72009-04-27 08:16:58 +0000220/* ADVANCE_CHAR() macro:
221 * Incrementes str & tok->char_offset.
222 * For convenience of existing conditionals, returns the old value of c (0 on eof)
223 * Implicit inputs: c var
224 */
225#define ADVANCE_CHAR(str, tok) \
226 ( ++(str), ((tok)->char_offset)++, c)
227
Brent Miller126ad952009-08-20 06:50:22 +0000228
Michael Clark95f55a72009-04-27 08:16:58 +0000229/* End optimization macro defs */
230
231
Michael Clarka850f8e2007-03-13 08:26:26 +0000232struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000233 const char *str, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +0000234{
Michael Clarka850f8e2007-03-13 08:26:26 +0000235 struct json_object *obj = NULL;
Michael Clark95f55a72009-04-27 08:16:58 +0000236 char c = '\1';
Remi Colleta01b6592012-12-13 09:47:33 +0100237#ifdef HAVE_SETLOCALE
238 char *oldlocale=NULL, *tmplocale;
239
240 tmplocale = setlocale(LC_NUMERIC, NULL);
241 if (tmplocale) oldlocale = strdup(tmplocale);
242 setlocale(LC_NUMERIC, "C");
243#endif
Michael Clarkf0d08882007-03-13 08:26:18 +0000244
Michael Clarka850f8e2007-03-13 08:26:26 +0000245 tok->char_offset = 0;
246 tok->err = json_tokener_success;
Michael Clarkf0d08882007-03-13 08:26:18 +0000247
Michael Clark64e36902014-04-09 13:48:21 +0800248 /* this interface is presently not 64-bit clean due to the int len argument
249 and the internal printbuf interface that takes 32-bit int len arguments
250 so the function limits the maximum string size to INT32_MAX (2GB).
251 If the function is called with len == -1 then strlen is called to check
252 the string length is less than INT32_MAX (2GB) */
253 if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
254 tok->err = json_tokener_error_size;
255 return NULL;
256 }
257
William Dignaziobb492d42013-03-06 12:29:33 -0500258 while (PEEK_CHAR(c, tok)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000259
Michael Clarka850f8e2007-03-13 08:26:26 +0000260 redo_char:
Michael Clarkf0d08882007-03-13 08:26:18 +0000261 switch(state) {
262
263 case json_tokener_state_eatws:
Michael Clark95f55a72009-04-27 08:16:58 +0000264 /* Advance until we change state */
ehaszla252669c2010-12-07 18:15:35 +0000265 while (isspace((int)c)) {
William Dignaziobb492d42013-03-06 12:29:33 -0500266 if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
Michael Clark95f55a72009-04-27 08:16:58 +0000267 goto out;
268 }
Remi Collet87fa32d2013-08-21 15:41:40 +0200269 if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000270 printbuf_reset(tok->pb);
Michael Clark95f55a72009-04-27 08:16:58 +0000271 printbuf_memappend_fast(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000272 state = json_tokener_state_comment_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000273 } else {
274 state = saved_state;
Michael Clarka850f8e2007-03-13 08:26:26 +0000275 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000276 }
277 break;
278
279 case json_tokener_state_start:
280 switch(c) {
281 case '{':
282 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000283 saved_state = json_tokener_state_object_field_start;
Michael Clarkf0d08882007-03-13 08:26:18 +0000284 current = json_object_new_object();
Michael Clarkf0d08882007-03-13 08:26:18 +0000285 break;
286 case '[':
287 state = json_tokener_state_eatws;
288 saved_state = json_tokener_state_array;
289 current = json_object_new_array();
Michael Clarkf0d08882007-03-13 08:26:18 +0000290 break;
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -0400291 case 'I':
292 case 'i':
293 state = json_tokener_state_inf;
294 printbuf_reset(tok->pb);
295 tok->st_pos = 0;
296 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000297 case 'N':
298 case 'n':
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400299 state = json_tokener_state_null; // or NaN
Michael Clarka850f8e2007-03-13 08:26:26 +0000300 printbuf_reset(tok->pb);
301 tok->st_pos = 0;
302 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000303 case '\'':
Remi Colleta07ef3d2013-08-06 10:41:14 +0200304 if (tok->flags & JSON_TOKENER_STRICT) {
305 /* in STRICT mode only double-quote are allowed */
306 tok->err = json_tokener_error_parse_unexpected;
307 goto out;
308 }
309 case '"':
Michael Clarkf0d08882007-03-13 08:26:18 +0000310 state = json_tokener_state_string;
Michael Clarka850f8e2007-03-13 08:26:26 +0000311 printbuf_reset(tok->pb);
312 tok->quote_char = c;
Michael Clarkf0d08882007-03-13 08:26:18 +0000313 break;
314 case 'T':
315 case 't':
316 case 'F':
317 case 'f':
318 state = json_tokener_state_boolean;
Michael Clarka850f8e2007-03-13 08:26:26 +0000319 printbuf_reset(tok->pb);
320 tok->st_pos = 0;
321 goto redo_char;
Michael Clark4504df72007-03-13 08:26:20 +0000322#if defined(__GNUC__)
323 case '0' ... '9':
324#else
325 case '0':
326 case '1':
327 case '2':
328 case '3':
329 case '4':
330 case '5':
331 case '6':
332 case '7':
333 case '8':
334 case '9':
335#endif
Michael Clarkf0d08882007-03-13 08:26:18 +0000336 case '-':
Michael Clarkf0d08882007-03-13 08:26:18 +0000337 state = json_tokener_state_number;
Michael Clarka850f8e2007-03-13 08:26:26 +0000338 printbuf_reset(tok->pb);
339 tok->is_double = 0;
340 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000341 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000342 tok->err = json_tokener_error_parse_unexpected;
Michael Clarkf0d08882007-03-13 08:26:18 +0000343 goto out;
344 }
345 break;
346
347 case json_tokener_state_finish:
Michael Clarka850f8e2007-03-13 08:26:26 +0000348 if(tok->depth == 0) goto out;
349 obj = json_object_get(current);
350 json_tokener_reset_level(tok, tok->depth);
351 tok->depth--;
352 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000353
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -0400354 case json_tokener_state_inf: /* aka starts with 'i' */
355 {
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -0400356 int size_inf;
357 int is_negative = 0;
358
359 printbuf_memappend_fast(tok->pb, &c, 1);
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -0400360 size_inf = json_min(tok->st_pos+1, json_inf_str_len);
361 char *infbuf = tok->pb->buf;
362 if (*infbuf == '-')
363 {
364 infbuf++;
365 is_negative = 1;
366 }
367 if ((!(tok->flags & JSON_TOKENER_STRICT) &&
368 strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
369 (strncmp(json_inf_str, infbuf, size_inf) == 0)
370 )
371 {
372 if (tok->st_pos == json_inf_str_len)
373 {
374 current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
375 saved_state = json_tokener_state_finish;
376 state = json_tokener_state_eatws;
377 goto redo_char;
378 }
379 } else {
380 tok->err = json_tokener_error_parse_unexpected;
381 goto out;
382 }
383 tok->st_pos++;
384 }
385 break;
386 case json_tokener_state_null: /* aka starts with 'n' */
Andrea Fauldsbda05402013-11-14 21:13:32 +0000387 {
388 int size;
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400389 int size_nan;
Andrea Fauldsbda05402013-11-14 21:13:32 +0000390 printbuf_memappend_fast(tok->pb, &c, 1);
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400391 size = json_min(tok->st_pos+1, json_null_str_len);
392 size_nan = json_min(tok->st_pos+1, json_nan_str_len);
Andrea Fauldsbda05402013-11-14 21:13:32 +0000393 if((!(tok->flags & JSON_TOKENER_STRICT) &&
394 strncasecmp(json_null_str, tok->pb->buf, size) == 0)
395 || (strncmp(json_null_str, tok->pb->buf, size) == 0)
396 ) {
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400397 if (tok->st_pos == json_null_str_len) {
Andrea Fauldsbda05402013-11-14 21:13:32 +0000398 current = NULL;
399 saved_state = json_tokener_state_finish;
400 state = json_tokener_state_eatws;
401 goto redo_char;
402 }
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400403 }
404 else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
405 strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
406 (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
407 )
408 {
409 if (tok->st_pos == json_nan_str_len)
410 {
Markus Stenberga1c89912014-03-18 16:29:49 +0200411 current = json_object_new_double(NAN);
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400412 saved_state = json_tokener_state_finish;
413 state = json_tokener_state_eatws;
414 goto redo_char;
415 }
Andrea Fauldsbda05402013-11-14 21:13:32 +0000416 } else {
417 tok->err = json_tokener_error_parse_null;
418 goto out;
Michael Clarka850f8e2007-03-13 08:26:26 +0000419 }
Andrea Fauldsbda05402013-11-14 21:13:32 +0000420 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000421 }
422 break;
423
424 case json_tokener_state_comment_start:
425 if(c == '*') {
426 state = json_tokener_state_comment;
427 } else if(c == '/') {
428 state = json_tokener_state_comment_eol;
429 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000430 tok->err = json_tokener_error_parse_comment;
Michael Clarkf0d08882007-03-13 08:26:18 +0000431 goto out;
432 }
Michael Clark95f55a72009-04-27 08:16:58 +0000433 printbuf_memappend_fast(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000434 break;
435
436 case json_tokener_state_comment:
Michael Clark95f55a72009-04-27 08:16:58 +0000437 {
438 /* Advance until we change state */
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000439 const char *case_start = str;
Michael Clark95f55a72009-04-27 08:16:58 +0000440 while(c != '*') {
William Dignaziobb492d42013-03-06 12:29:33 -0500441 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Michael Clark95f55a72009-04-27 08:16:58 +0000442 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
443 goto out;
William Dignaziobb492d42013-03-06 12:29:33 -0500444 }
Michael Clark95f55a72009-04-27 08:16:58 +0000445 }
446 printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
447 state = json_tokener_state_comment_end;
448 }
449 break;
Michael Clarkf0d08882007-03-13 08:26:18 +0000450
451 case json_tokener_state_comment_eol:
Michael Clark95f55a72009-04-27 08:16:58 +0000452 {
453 /* Advance until we change state */
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000454 const char *case_start = str;
Michael Clark95f55a72009-04-27 08:16:58 +0000455 while(c != '\n') {
William Dignaziobb492d42013-03-06 12:29:33 -0500456 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Michael Clark95f55a72009-04-27 08:16:58 +0000457 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
458 goto out;
459 }
460 }
461 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Michael Clarkdfaf6702007-10-25 02:26:00 +0000462 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000463 state = json_tokener_state_eatws;
464 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000465 break;
466
467 case json_tokener_state_comment_end:
Michael Clark95f55a72009-04-27 08:16:58 +0000468 printbuf_memappend_fast(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000469 if(c == '/') {
Michael Clarkdfaf6702007-10-25 02:26:00 +0000470 MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Michael Clarkf0d08882007-03-13 08:26:18 +0000471 state = json_tokener_state_eatws;
472 } else {
473 state = json_tokener_state_comment;
474 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000475 break;
476
477 case json_tokener_state_string:
Michael Clark95f55a72009-04-27 08:16:58 +0000478 {
479 /* Advance until we change state */
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000480 const char *case_start = str;
Michael Clark95f55a72009-04-27 08:16:58 +0000481 while(1) {
482 if(c == tok->quote_char) {
483 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Eric Haszlakiewicz4e4af932012-12-09 16:32:11 -0600484 current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
Michael Clark95f55a72009-04-27 08:16:58 +0000485 saved_state = json_tokener_state_finish;
486 state = json_tokener_state_eatws;
487 break;
488 } else if(c == '\\') {
489 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
490 saved_state = json_tokener_state_string;
491 state = json_tokener_state_string_escape;
492 break;
493 }
William Dignaziobb492d42013-03-06 12:29:33 -0500494 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Michael Clark95f55a72009-04-27 08:16:58 +0000495 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
496 goto out;
497 }
498 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000499 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000500 break;
501
502 case json_tokener_state_string_escape:
503 switch(c) {
504 case '"':
505 case '\\':
Michael Clarka850f8e2007-03-13 08:26:26 +0000506 case '/':
Michael Clark95f55a72009-04-27 08:16:58 +0000507 printbuf_memappend_fast(tok->pb, &c, 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000508 state = saved_state;
509 break;
510 case 'b':
511 case 'n':
512 case 'r':
513 case 't':
Eric Haszlakiewicz92f31bd2012-07-29 12:31:07 -0500514 case 'f':
Michael Clark95f55a72009-04-27 08:16:58 +0000515 if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
516 else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
517 else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
518 else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
Eric Haszlakiewicz92f31bd2012-07-29 12:31:07 -0500519 else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
Michael Clarkf0d08882007-03-13 08:26:18 +0000520 state = saved_state;
521 break;
522 case 'u':
Michael Clarka850f8e2007-03-13 08:26:26 +0000523 tok->ucs_char = 0;
524 tok->st_pos = 0;
Michael Clarkf0d08882007-03-13 08:26:18 +0000525 state = json_tokener_state_escape_unicode;
526 break;
527 default:
Michael Clarka850f8e2007-03-13 08:26:26 +0000528 tok->err = json_tokener_error_parse_string;
Michael Clarkf0d08882007-03-13 08:26:18 +0000529 goto out;
530 }
531 break;
532
533 case json_tokener_state_escape_unicode:
Michael Clark95f55a72009-04-27 08:16:58 +0000534 {
Brent Miller126ad952009-08-20 06:50:22 +0000535 unsigned int got_hi_surrogate = 0;
536
537 /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
Michael Clark95f55a72009-04-27 08:16:58 +0000538 while(1) {
539 if(strchr(json_hex_chars, c)) {
Eric Haszlakiewiczd4e81f92014-05-03 22:29:10 -0400540 tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
Michael Clark95f55a72009-04-27 08:16:58 +0000541 if(tok->st_pos == 4) {
Brent Miller126ad952009-08-20 06:50:22 +0000542 unsigned char unescaped_utf[4];
543
544 if (got_hi_surrogate) {
545 if (IS_LOW_SURROGATE(tok->ucs_char)) {
546 /* Recalculate the ucs_char, then fall thru to process normally */
547 tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
548 } else {
549 /* Hi surrogate was not followed by a low surrogate */
550 /* Replace the hi and process the rest normally */
551 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
552 }
553 got_hi_surrogate = 0;
554 }
555
Michael Clark95f55a72009-04-27 08:16:58 +0000556 if (tok->ucs_char < 0x80) {
Brent Miller126ad952009-08-20 06:50:22 +0000557 unescaped_utf[0] = tok->ucs_char;
558 printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
Michael Clark95f55a72009-04-27 08:16:58 +0000559 } else if (tok->ucs_char < 0x800) {
Brent Miller126ad952009-08-20 06:50:22 +0000560 unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
561 unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
562 printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
563 } else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
564 /* Got a high surrogate. Remember it and look for the
565 * the beginning of another sequence, which should be the
566 * low surrogate.
567 */
568 got_hi_surrogate = tok->ucs_char;
569 /* Not at end, and the next two chars should be "\u" */
570 if ((tok->char_offset+1 != len) &&
571 (tok->char_offset+2 != len) &&
572 (str[1] == '\\') &&
573 (str[2] == 'u'))
574 {
William Dignazio32eddd62013-03-06 20:18:14 -0500575 /* Advance through the 16 bit surrogate, and move on to the
576 * next sequence. The next step is to process the following
577 * characters.
578 */
579 if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
580 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
581 }
Brent Miller126ad952009-08-20 06:50:22 +0000582 /* Advance to the first char of the next sequence and
583 * continue processing with the next sequence.
584 */
William Dignaziobb492d42013-03-06 12:29:33 -0500585 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Brent Miller126ad952009-08-20 06:50:22 +0000586 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
587 goto out;
588 }
589 tok->ucs_char = 0;
590 tok->st_pos = 0;
591 continue; /* other json_tokener_state_escape_unicode */
592 } else {
593 /* Got a high surrogate without another sequence following
594 * it. Put a replacement char in for the hi surrogate
595 * and pretend we finished.
596 */
597 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
598 }
599 } else if (IS_LOW_SURROGATE(tok->ucs_char)) {
600 /* Got a low surrogate not preceded by a high */
601 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
602 } else if (tok->ucs_char < 0x10000) {
603 unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
604 unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
605 unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
606 printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
607 } else if (tok->ucs_char < 0x110000) {
608 unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
609 unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
610 unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
611 unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
612 printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
Michael Clark95f55a72009-04-27 08:16:58 +0000613 } else {
Brent Miller126ad952009-08-20 06:50:22 +0000614 /* Don't know what we got--insert the replacement char */
615 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
616 }
Michael Clark95f55a72009-04-27 08:16:58 +0000617 state = saved_state;
618 break;
619 }
620 } else {
621 tok->err = json_tokener_error_parse_string;
622 goto out;
Brent Miller126ad952009-08-20 06:50:22 +0000623 }
William Dignaziobb492d42013-03-06 12:29:33 -0500624 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Brent Miller126ad952009-08-20 06:50:22 +0000625 if (got_hi_surrogate) /* Clean up any pending chars */
626 printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
Michael Clark95f55a72009-04-27 08:16:58 +0000627 goto out;
Brent Miller126ad952009-08-20 06:50:22 +0000628 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000629 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000630 }
631 break;
632
633 case json_tokener_state_boolean:
Andrea Fauldsbda05402013-11-14 21:13:32 +0000634 {
635 int size1, size2;
636 printbuf_memappend_fast(tok->pb, &c, 1);
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400637 size1 = json_min(tok->st_pos+1, json_true_str_len);
638 size2 = json_min(tok->st_pos+1, json_false_str_len);
Andrea Fauldsbda05402013-11-14 21:13:32 +0000639 if((!(tok->flags & JSON_TOKENER_STRICT) &&
640 strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
641 || (strncmp(json_true_str, tok->pb->buf, size1) == 0)
642 ) {
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400643 if(tok->st_pos == json_true_str_len) {
Andrea Fauldsbda05402013-11-14 21:13:32 +0000644 current = json_object_new_boolean(1);
645 saved_state = json_tokener_state_finish;
646 state = json_tokener_state_eatws;
647 goto redo_char;
648 }
649 } else if((!(tok->flags & JSON_TOKENER_STRICT) &&
650 strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
651 || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
Eric Haszlakiewicz0eedf382014-03-09 16:41:33 -0400652 if(tok->st_pos == json_false_str_len) {
Andrea Fauldsbda05402013-11-14 21:13:32 +0000653 current = json_object_new_boolean(0);
654 saved_state = json_tokener_state_finish;
655 state = json_tokener_state_eatws;
656 goto redo_char;
657 }
658 } else {
659 tok->err = json_tokener_error_parse_boolean;
660 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000661 }
Andrea Fauldsbda05402013-11-14 21:13:32 +0000662 tok->st_pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000663 }
664 break;
665
666 case json_tokener_state_number:
Michael Clark95f55a72009-04-27 08:16:58 +0000667 {
668 /* Advance until we change state */
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000669 const char *case_start = str;
Michael Clark95f55a72009-04-27 08:16:58 +0000670 int case_len=0;
671 while(c && strchr(json_number_chars, c)) {
672 ++case_len;
Eric Haszlakiewiczf931f612012-04-24 22:17:13 -0500673 if(c == '.' || c == 'e' || c == 'E')
674 tok->is_double = 1;
William Dignaziobb492d42013-03-06 12:29:33 -0500675 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Michael Clark95f55a72009-04-27 08:16:58 +0000676 printbuf_memappend_fast(tok->pb, case_start, case_len);
677 goto out;
678 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000679 }
Michael Clark95f55a72009-04-27 08:16:58 +0000680 if (case_len>0)
681 printbuf_memappend_fast(tok->pb, case_start, case_len);
Eric Haszlakiewicz05da3162014-03-22 17:28:40 -0400682
683 // Check for -Infinity
684 if (tok->pb->buf[0] == '-' && case_len == 1 &&
685 (c == 'i' || c == 'I'))
686 {
687 state = json_tokener_state_inf;
688 goto redo_char;
689 }
Michael Clark95f55a72009-04-27 08:16:58 +0000690 }
691 {
Michael Clarkc4dceae2010-10-06 16:39:20 +0000692 int64_t num64;
693 double numd;
694 if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
Remi Collete9ee4ae2013-06-13 13:40:01 +0200695 if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) {
Eric Haszlakiewiczd032aad2013-06-19 09:14:19 -0500696 /* in strict mode, number must not start with 0 */
Remi Collete9ee4ae2013-06-13 13:40:01 +0200697 tok->err = json_tokener_error_parse_number;
698 goto out;
699 }
ehaszla252669c2010-12-07 18:15:35 +0000700 current = json_object_new_int64(num64);
Eric Haszlakiewicz51993c22013-09-11 20:27:39 -0500701 }
702 else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
703 {
704 current = json_object_new_double_s(numd, tok->pb->buf);
Michael Clark95f55a72009-04-27 08:16:58 +0000705 } else {
706 tok->err = json_tokener_error_parse_number;
707 goto out;
708 }
709 saved_state = json_tokener_state_finish;
710 state = json_tokener_state_eatws;
711 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000712 }
713 break;
714
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500715 case json_tokener_state_array_after_sep:
Michael Clarkf0d08882007-03-13 08:26:18 +0000716 case json_tokener_state_array:
717 if(c == ']') {
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500718 if (state == json_tokener_state_array_after_sep &&
719 (tok->flags & JSON_TOKENER_STRICT))
720 {
721 tok->err = json_tokener_error_parse_unexpected;
722 goto out;
723 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000724 saved_state = json_tokener_state_finish;
725 state = json_tokener_state_eatws;
726 } else {
Remi Collet197cb1d2012-11-27 09:01:45 +0100727 if(tok->depth >= tok->max_depth-1) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000728 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000729 goto out;
730 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000731 state = json_tokener_state_array_add;
732 tok->depth++;
733 json_tokener_reset_level(tok, tok->depth);
734 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000735 }
736 break;
737
Michael Clarka850f8e2007-03-13 08:26:26 +0000738 case json_tokener_state_array_add:
739 json_object_array_add(current, obj);
740 saved_state = json_tokener_state_array_sep;
741 state = json_tokener_state_eatws;
742 goto redo_char;
743
Michael Clarkf0d08882007-03-13 08:26:18 +0000744 case json_tokener_state_array_sep:
745 if(c == ']') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000746 saved_state = json_tokener_state_finish;
747 state = json_tokener_state_eatws;
748 } else if(c == ',') {
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500749 saved_state = json_tokener_state_array_after_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000750 state = json_tokener_state_eatws;
751 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000752 tok->err = json_tokener_error_parse_array;
753 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000754 }
755 break;
756
Michael Clarkf0d08882007-03-13 08:26:18 +0000757 case json_tokener_state_object_field_start:
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500758 case json_tokener_state_object_field_start_after_sep:
Michael Clarkf0d08882007-03-13 08:26:18 +0000759 if(c == '}') {
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500760 if (state == json_tokener_state_object_field_start_after_sep &&
761 (tok->flags & JSON_TOKENER_STRICT))
762 {
763 tok->err = json_tokener_error_parse_unexpected;
764 goto out;
765 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000766 saved_state = json_tokener_state_finish;
767 state = json_tokener_state_eatws;
768 } else if (c == '"' || c == '\'') {
Michael Clarka850f8e2007-03-13 08:26:26 +0000769 tok->quote_char = c;
770 printbuf_reset(tok->pb);
Michael Clarkf0d08882007-03-13 08:26:18 +0000771 state = json_tokener_state_object_field;
Michael Clark0370baa2007-03-13 08:26:22 +0000772 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000773 tok->err = json_tokener_error_parse_object_key_name;
Michael Clark0370baa2007-03-13 08:26:22 +0000774 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000775 }
776 break;
777
778 case json_tokener_state_object_field:
Michael Clark95f55a72009-04-27 08:16:58 +0000779 {
780 /* Advance until we change state */
Christopher Watfordb1a22ac2009-07-08 04:02:05 +0000781 const char *case_start = str;
Michael Clark95f55a72009-04-27 08:16:58 +0000782 while(1) {
783 if(c == tok->quote_char) {
784 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
785 obj_field_name = strdup(tok->pb->buf);
786 saved_state = json_tokener_state_object_field_end;
787 state = json_tokener_state_eatws;
788 break;
789 } else if(c == '\\') {
790 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
791 saved_state = json_tokener_state_object_field;
792 state = json_tokener_state_string_escape;
793 break;
794 }
William Dignaziobb492d42013-03-06 12:29:33 -0500795 if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Michael Clark95f55a72009-04-27 08:16:58 +0000796 printbuf_memappend_fast(tok->pb, case_start, str-case_start);
797 goto out;
798 }
799 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000800 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000801 break;
802
803 case json_tokener_state_object_field_end:
804 if(c == ':') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000805 saved_state = json_tokener_state_object_value;
806 state = json_tokener_state_eatws;
807 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000808 tok->err = json_tokener_error_parse_object_key_sep;
809 goto out;
Michael Clarkf0d08882007-03-13 08:26:18 +0000810 }
811 break;
812
813 case json_tokener_state_object_value:
Remi Collet197cb1d2012-11-27 09:01:45 +0100814 if(tok->depth >= tok->max_depth-1) {
Michael Clarka850f8e2007-03-13 08:26:26 +0000815 tok->err = json_tokener_error_depth;
Michael Clarkf0d08882007-03-13 08:26:18 +0000816 goto out;
817 }
Michael Clarka850f8e2007-03-13 08:26:26 +0000818 state = json_tokener_state_object_value_add;
819 tok->depth++;
820 json_tokener_reset_level(tok, tok->depth);
821 goto redo_char;
822
823 case json_tokener_state_object_value_add:
Michael Clarkf0d08882007-03-13 08:26:18 +0000824 json_object_object_add(current, obj_field_name, obj);
825 free(obj_field_name);
826 obj_field_name = NULL;
827 saved_state = json_tokener_state_object_sep;
828 state = json_tokener_state_eatws;
Michael Clarka850f8e2007-03-13 08:26:26 +0000829 goto redo_char;
Michael Clarkf0d08882007-03-13 08:26:18 +0000830
831 case json_tokener_state_object_sep:
832 if(c == '}') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000833 saved_state = json_tokener_state_finish;
834 state = json_tokener_state_eatws;
835 } else if(c == ',') {
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500836 saved_state = json_tokener_state_object_field_start_after_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000837 state = json_tokener_state_eatws;
838 } else {
Michael Clarka850f8e2007-03-13 08:26:26 +0000839 tok->err = json_tokener_error_parse_object_value_sep;
Michael Clarkf0d08882007-03-13 08:26:18 +0000840 goto out;
841 }
842 break;
843
844 }
Michael Clark95f55a72009-04-27 08:16:58 +0000845 if (!ADVANCE_CHAR(str, tok))
846 goto out;
847 } /* while(POP_CHAR) */
Michael Clarkf0d08882007-03-13 08:26:18 +0000848
849 out:
Remi Collet4039f912013-08-23 13:40:01 +0200850 if (c &&
851 (state == json_tokener_state_finish) &&
852 (tok->depth == 0) &&
853 (tok->flags & JSON_TOKENER_STRICT)) {
854 /* unexpected char after JSON data */
855 tok->err = json_tokener_error_parse_unexpected;
856 }
Michael Clark95f55a72009-04-27 08:16:58 +0000857 if (!c) { /* We hit an eof char (0) */
858 if(state != json_tokener_state_finish &&
859 saved_state != json_tokener_state_finish)
860 tok->err = json_tokener_error_parse_eof;
861 }
862
Remi Colleta01b6592012-12-13 09:47:33 +0100863#ifdef HAVE_SETLOCALE
864 setlocale(LC_NUMERIC, oldlocale);
865 if (oldlocale) free(oldlocale);
866#endif
867
William Dignaziobb492d42013-03-06 12:29:33 -0500868 if (tok->err == json_tokener_success)
Eric Haszlakiewiczd809fa62012-03-31 22:53:43 -0500869 {
870 json_object *ret = json_object_get(current);
871 int ii;
872
873 /* Partially reset, so we parse additional objects on subsequent calls. */
874 for(ii = tok->depth; ii >= 0; ii--)
875 json_tokener_reset_level(tok, ii);
876 return ret;
877 }
878
Michael Clarkdfaf6702007-10-25 02:26:00 +0000879 MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
Michael Clarka850f8e2007-03-13 08:26:26 +0000880 json_tokener_errors[tok->err], tok->char_offset);
881 return NULL;
Michael Clarkf0d08882007-03-13 08:26:18 +0000882}
Eric Haszlakiewicze8161a12013-03-31 20:05:36 -0500883
884void json_tokener_set_flags(struct json_tokener *tok, int flags)
885{
886 tok->flags = flags;
887}