MACSio  0.9
Multi-purpose, Application-Centric, Scalable I/O Proxy App
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
json_tokener.c
Go to the documentation of this file.
1 /*
2  * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
3  *
4  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
5  * Michael Clark <michael@metaparadigm.com>
6  *
7  * This library is free software; you can redistribute it and/or modify
8  * it under the terms of the MIT license. See COPYING for details.
9  *
10  *
11  * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
12  * The copyrights to the contents of this file are licensed under the MIT License
13  * (http://www.opensource.org/licenses/mit-license.php)
14  */
15 
16 #include "config.h"
17 
18 #include <math.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stddef.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <limits.h>
25 
26 #include "bits.h"
27 #include "debug.h"
28 #include "printbuf.h"
29 #include "arraylist.h"
30 #include "json_inttypes.h"
31 #include "json_object.h"
32 #include "json_tokener.h"
33 #include "json_util.h"
34 
35 #ifdef HAVE_LOCALE_H
36 #include <locale.h>
37 #endif /* HAVE_LOCALE_H */
38 
39 #if !HAVE_STRDUP && defined(_MSC_VER)
40  /* MSC has the version as _strdup */
41 # define strdup _strdup
42 #elif !HAVE_STRDUP
43 # error You do not have strdup on your system.
44 #endif /* HAVE_STRDUP */
45 
46 #if !HAVE_STRNCASECMP && defined(_MSC_VER)
47  /* MSC has the version as _strnicmp */
48 # define strncasecmp _strnicmp
49 #elif !HAVE_STRNCASECMP
50 # error You do not have strncasecmp on your system.
51 #endif /* HAVE_STRNCASECMP */
52 
53 /* Use C99 NAN by default; if not available, nan("") should work too. */
54 #ifndef NAN
55 #define NAN nan("")
56 #endif /* !NAN */
57 
58 static const char json_null_str[] = "null";
59 static const int json_null_str_len = sizeof(json_null_str) - 1;
60 static const char json_inf_str[] = "Infinity";
61 static const int json_inf_str_len = sizeof(json_inf_str) - 1;
62 static const char json_nan_str[] = "NaN";
63 static const int json_nan_str_len = sizeof(json_nan_str) - 1;
64 static const char json_true_str[] = "true";
65 static const int json_true_str_len = sizeof(json_true_str) - 1;
66 static const char json_false_str[] = "false";
67 static const int json_false_str_len = sizeof(json_false_str) - 1;
68 
69 static const char* json_tokener_errors[] = {
70  "success",
71  "continue",
72  "nesting too deep",
73  "unexpected end of data",
74  "unexpected character",
75  "null expected",
76  "boolean expected",
77  "number expected",
78  "array value separator ',' expected",
79  "quoted object property name expected",
80  "object property name separator ':' expected",
81  "object value separator ',' expected",
82  "invalid string sequence",
83  "expected comment",
84  "buffer size overflow"
85 };
86 
88 {
89  int jerr_int = (int)jerr;
90  if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
91  return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
92  return json_tokener_errors[jerr];
93 }
94 
96 {
97  return tok->err;
98 }
99 
100 /* Stuff for decoding unicode sequences */
101 #define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
102 #define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
103 #define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
104 static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
105 
107 {
108  struct json_tokener *tok;
109 
110  tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
111  if (!tok) return NULL;
112  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
113  if (!tok->stack) {
114  free(tok);
115  return NULL;
116  }
117  tok->pb = printbuf_new();
118  tok->max_depth = depth;
119  json_tokener_reset(tok);
120  return tok;
121 }
122 
124 {
126 }
127 
129 {
130  json_tokener_reset(tok);
131  if (tok->pb) printbuf_free(tok->pb);
132  if (tok->stack) free(tok->stack);
133  free(tok);
134 }
135 
136 static void json_tokener_reset_level(struct json_tokener *tok, int depth)
137 {
138  tok->stack[depth].state = json_tokener_state_eatws;
140  json_object_put(tok->stack[depth].current);
141  tok->stack[depth].current = NULL;
142  free(tok->stack[depth].obj_field_name);
143  tok->stack[depth].obj_field_name = NULL;
144 }
145 
147 {
148  int i;
149  if (!tok)
150  return;
151 
152  for(i = tok->depth; i >= 0; i--)
153  json_tokener_reset_level(tok, i);
154  tok->depth = 0;
155  tok->err = json_tokener_success;
156 }
157 
158 struct json_object* json_tokener_parse(const char *str)
159 {
160  enum json_tokener_error jerr_ignored;
161  struct json_object* obj;
162  obj = json_tokener_parse_verbose(str, &jerr_ignored);
163  return obj;
164 }
165 
166 struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
167 {
168  struct json_tokener* tok;
169  struct json_object* obj;
170 
171  tok = json_tokener_new();
172  if (!tok)
173  return NULL;
174  obj = json_tokener_parse_ex(tok, str, -1);
175  *error = tok->err;
176  if(tok->err != json_tokener_success) {
177  if (obj != NULL)
178  json_object_put(obj);
179  obj = NULL;
180  }
181 
182  json_tokener_free(tok);
183  return obj;
184 }
185 
186 #define state tok->stack[tok->depth].state
187 #define saved_state tok->stack[tok->depth].saved_state
188 #define current tok->stack[tok->depth].current
189 #define obj_field_name tok->stack[tok->depth].obj_field_name
190 
191 /* Optimization:
192  * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
193  * iterating character-by character. A large performance boost is
194  * achieved by using tighter loops to locally handle units such as
195  * comments and strings. Loops that handle an entire token within
196  * their scope also gather entire strings and pass them to
197  * printbuf_memappend() in a single call, rather than calling
198  * printbuf_memappend() one char at a time.
199  *
200  * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
201  * common to both the main loop and the tighter loops.
202  */
203 
204 /* PEEK_CHAR(dest, tok) macro:
205  * Peeks at the current char and stores it in dest.
206  * Returns 1 on success, sets tok->err and returns 0 if no more chars.
207  * Implicit inputs: str, len vars
208  */
209 #define PEEK_CHAR(dest, tok) \
210  (((tok)->char_offset == len) ? \
211  (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
212  (((tok)->err = json_tokener_success), 0) \
213  : \
214  (((tok)->err = json_tokener_continue), 0) \
215  ) : \
216  (((dest) = *str), 1) \
217  )
218 
219 /* ADVANCE_CHAR() macro:
220  * Incrementes str & tok->char_offset.
221  * For convenience of existing conditionals, returns the old value of c (0 on eof)
222  * Implicit inputs: c var
223  */
224 #define ADVANCE_CHAR(str, tok) \
225  ( ++(str), ((tok)->char_offset)++, c)
226 
227 
228 /* End optimization macro defs */
229 
230 static void put_extarr_val(struct json_object* cur, struct json_object* o, int extarr_idx)
231 {
232  switch (json_object_extarr_type(cur))
233  {
236  {
237  break;
238  }
240  {
241  unsigned char val = (unsigned char) json_object_get_int(o);
242  *((unsigned char*)json_object_extarr_data(cur)+extarr_idx) = val;
243  break;
244  }
246  {
247  int val = json_object_get_int(o);
248  *((int*)json_object_extarr_data(cur)+extarr_idx) = val;
249  break;
250  }
252  {
253  int64_t val = json_object_get_int64(o);
254  *((int64_t*)json_object_extarr_data(cur)+extarr_idx) = val;
255  break;
256  }
258  {
259  float val = (float) json_object_get_double(o);
260  *((float*)json_object_extarr_data(cur)+extarr_idx) = val;
261  break;
262  }
264  {
265  double val = json_object_get_double(o);
266  *((double*)json_object_extarr_data(cur)+extarr_idx) = val;
267  break;
268  }
269  }
270  json_object_put(o);
271 }
272 
274  const char *str, int len)
275 {
276  struct json_object *obj = NULL;
277  int extarr_idx = 0;
278  char c = '\1';
279 #ifdef HAVE_SETLOCALE
280  char *oldlocale=NULL, *tmplocale;
281 
282  tmplocale = setlocale(LC_NUMERIC, NULL);
283  if (tmplocale) oldlocale = strdup(tmplocale);
284  setlocale(LC_NUMERIC, "C");
285 #endif
286 
287  tok->char_offset = 0;
288  tok->err = json_tokener_success;
289 
290  /* this interface is presently not 64-bit clean due to the int len argument
291  and the internal printbuf interface that takes 32-bit int len arguments
292  so the function limits the maximum string size to INT32_MAX (2GB).
293  If the function is called with len == -1 then strlen is called to check
294  the string length is less than INT32_MAX (2GB) */
295 #ifdef INT32_MAX
296  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
297 #else
298  if ((len < -1) || (len == -1 && strlen(str) > INT_MAX)) {
299 #endif
301  return NULL;
302  }
303 
304  while (PEEK_CHAR(c, tok)) {
305 
306  redo_char:
307  switch(state) {
308 
310  /* Advance until we change state */
311  while (isspace((int)c)) {
312  if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
313  goto out;
314  }
315  if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
316  printbuf_reset(tok->pb);
317  printbuf_memappend_fast(tok->pb, &c, 1);
319  } else {
320  state = saved_state;
321  goto redo_char;
322  }
323  break;
324 
326  switch(c) {
327  case '{':
331  break;
332  case '[':
336  break;
337  case '(':
338  if (tok->flags & JSON_TOKENER_STRICT) {
339  /* in STRICT extarr objects not supported */
341  goto out;
342  }
346  break;
347  case '<':
348  if (tok->flags & JSON_TOKENER_STRICT) {
349  /* in STRICT enum objects not supported */
351  goto out;
352  }
356  break;
357  case 'I':
358  case 'i':
360  printbuf_reset(tok->pb);
361  tok->st_pos = 0;
362  goto redo_char;
363  case 'N':
364  case 'n':
365  state = json_tokener_state_null; // or NaN
366  printbuf_reset(tok->pb);
367  tok->st_pos = 0;
368  goto redo_char;
369  case '\'':
370  if (tok->flags & JSON_TOKENER_STRICT) {
371  /* in STRICT mode only double-quote are allowed */
373  goto out;
374  }
375  case '"':
377  printbuf_reset(tok->pb);
378  tok->quote_char = c;
379  break;
380  case 'T':
381  case 't':
382  case 'F':
383  case 'f':
385  printbuf_reset(tok->pb);
386  tok->st_pos = 0;
387  goto redo_char;
388 #if defined(__GNUC__)
389  case '0' ... '9':
390 #else
391  case '0':
392  case '1':
393  case '2':
394  case '3':
395  case '4':
396  case '5':
397  case '6':
398  case '7':
399  case '8':
400  case '9':
401 #endif
402  case '-':
404  printbuf_reset(tok->pb);
405  tok->is_double = 0;
406  goto redo_char;
407  default:
409  goto out;
410  }
411  break;
412 
414  if(tok->depth == 0) goto out;
415  obj = json_object_get(current);
416  json_tokener_reset_level(tok, tok->depth);
417  tok->depth--;
418  goto redo_char;
419 
420  case json_tokener_state_inf: /* aka starts with 'i' */
421  {
422  int size;
423  int size_inf;
424  int is_negative = 0;
425 
426  printbuf_memappend_fast(tok->pb, &c, 1);
427  size = json_min(tok->st_pos+1, json_null_str_len);
428  size_inf = json_min(tok->st_pos+1, json_inf_str_len);
429  char *infbuf = tok->pb->buf;
430  if (*infbuf == '-')
431  {
432  infbuf++;
433  is_negative = 1;
434  }
435  if ((!(tok->flags & JSON_TOKENER_STRICT) &&
436  strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
437  (strncmp(json_inf_str, infbuf, size_inf) == 0)
438  )
439  {
440  if (tok->st_pos == json_inf_str_len)
441  {
442  current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
445  goto redo_char;
446  }
447  } else {
449  goto out;
450  }
451  tok->st_pos++;
452  }
453  break;
454  case json_tokener_state_null: /* aka starts with 'n' */
455  {
456  int size;
457  int size_nan;
458  printbuf_memappend_fast(tok->pb, &c, 1);
459  size = json_min(tok->st_pos+1, json_null_str_len);
460  size_nan = json_min(tok->st_pos+1, json_nan_str_len);
461  if((!(tok->flags & JSON_TOKENER_STRICT) &&
462  strncasecmp(json_null_str, tok->pb->buf, size) == 0)
463  || (strncmp(json_null_str, tok->pb->buf, size) == 0)
464  ) {
465  if (tok->st_pos == json_null_str_len) {
466  current = NULL;
469  goto redo_char;
470  }
471  }
472  else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
473  strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
474  (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
475  )
476  {
477  if (tok->st_pos == json_nan_str_len)
478  {
482  goto redo_char;
483  }
484  } else {
486  goto out;
487  }
488  tok->st_pos++;
489  }
490  break;
491 
493  if(c == '*') {
495  } else if(c == '/') {
497  } else {
499  goto out;
500  }
501  printbuf_memappend_fast(tok->pb, &c, 1);
502  break;
503 
505  {
506  /* Advance until we change state */
507  const char *case_start = str;
508  while(c != '*') {
509  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
510  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
511  goto out;
512  }
513  }
514  printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
516  }
517  break;
518 
520  {
521  /* Advance until we change state */
522  const char *case_start = str;
523  while(c != '\n') {
524  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
525  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
526  goto out;
527  }
528  }
529  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
530  MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
532  }
533  break;
534 
536  printbuf_memappend_fast(tok->pb, &c, 1);
537  if(c == '/') {
538  MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
540  } else {
542  }
543  break;
544 
546  {
547  /* Advance until we change state */
548  const char *case_start = str;
549  while(1) {
550  if(c == tok->quote_char) {
551  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
555  break;
556  } else if(c == '\\') {
557  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
560  break;
561  }
562  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
563  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
564  goto out;
565  }
566  }
567  }
568  break;
569 
571  switch(c) {
572  case '"':
573  case '\\':
574  case '/':
575  printbuf_memappend_fast(tok->pb, &c, 1);
576  state = saved_state;
577  break;
578  case 'b':
579  case 'n':
580  case 'r':
581  case 't':
582  case 'f':
583  if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
584  else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
585  else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
586  else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
587  else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
588  state = saved_state;
589  break;
590  case 'u':
591  tok->ucs_char = 0;
592  tok->st_pos = 0;
594  break;
595  default:
597  goto out;
598  }
599  break;
600 
602  {
603  unsigned int got_hi_surrogate = 0;
604 
605  /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
606  while(1) {
607  if(strchr(json_hex_chars, c)) {
608  tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
609  if(tok->st_pos == 4) {
610  unsigned char unescaped_utf[4];
611 
612  if (got_hi_surrogate) {
613  if (IS_LOW_SURROGATE(tok->ucs_char)) {
614  /* Recalculate the ucs_char, then fall thru to process normally */
615  tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
616  } else {
617  /* Hi surrogate was not followed by a low surrogate */
618  /* Replace the hi and process the rest normally */
620  }
621  got_hi_surrogate = 0;
622  }
623 
624  if (tok->ucs_char < 0x80) {
625  unescaped_utf[0] = tok->ucs_char;
626  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
627  } else if (tok->ucs_char < 0x800) {
628  unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
629  unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
630  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
631  } else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
632  /* Got a high surrogate. Remember it and look for the
633  * the beginning of another sequence, which should be the
634  * low surrogate.
635  */
636  got_hi_surrogate = tok->ucs_char;
637  /* Not at end, and the next two chars should be "\u" */
638  if ((tok->char_offset+1 != len) &&
639  (tok->char_offset+2 != len) &&
640  (str[1] == '\\') &&
641  (str[2] == 'u'))
642  {
643  /* Advance through the 16 bit surrogate, and move on to the
644  * next sequence. The next step is to process the following
645  * characters.
646  */
647  if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
649  }
650  /* Advance to the first char of the next sequence and
651  * continue processing with the next sequence.
652  */
653  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
655  goto out;
656  }
657  tok->ucs_char = 0;
658  tok->st_pos = 0;
659  continue; /* other json_tokener_state_escape_unicode */
660  } else {
661  /* Got a high surrogate without another sequence following
662  * it. Put a replacement char in for the hi surrogate
663  * and pretend we finished.
664  */
666  }
667  } else if (IS_LOW_SURROGATE(tok->ucs_char)) {
668  /* Got a low surrogate not preceded by a high */
670  } else if (tok->ucs_char < 0x10000) {
671  unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
672  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
673  unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
674  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
675  } else if (tok->ucs_char < 0x110000) {
676  unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
677  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
678  unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
679  unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
680  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
681  } else {
682  /* Don't know what we got--insert the replacement char */
684  }
685  state = saved_state;
686  break;
687  }
688  } else {
690  goto out;
691  }
692  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
693  if (got_hi_surrogate) /* Clean up any pending chars */
695  goto out;
696  }
697  }
698  }
699  break;
700 
702  {
703  int size1, size2;
704  printbuf_memappend_fast(tok->pb, &c, 1);
705  size1 = json_min(tok->st_pos+1, json_true_str_len);
706  size2 = json_min(tok->st_pos+1, json_false_str_len);
707  if((!(tok->flags & JSON_TOKENER_STRICT) &&
708  strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
709  || (strncmp(json_true_str, tok->pb->buf, size1) == 0)
710  ) {
711  if(tok->st_pos == json_true_str_len) {
715  goto redo_char;
716  }
717  } else if((!(tok->flags & JSON_TOKENER_STRICT) &&
718  strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
719  || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
720  if(tok->st_pos == json_false_str_len) {
724  goto redo_char;
725  }
726  } else {
728  goto out;
729  }
730  tok->st_pos++;
731  }
732  break;
733 
735  {
736  /* Advance until we change state */
737  const char *case_start = str;
738  int case_len=0;
739  while(c && strchr(json_number_chars, c)) {
740  ++case_len;
741  if(c == '.' || c == 'e' || c == 'E')
742  tok->is_double = 1;
743  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
744  printbuf_memappend_fast(tok->pb, case_start, case_len);
745  goto out;
746  }
747  }
748  if (case_len>0)
749  printbuf_memappend_fast(tok->pb, case_start, case_len);
750 
751  // Check for -Infinity
752  if (tok->pb->buf[0] == '-' && case_len == 1 &&
753  (c == 'i' || c == 'I'))
754  {
756  goto redo_char;
757  }
758  }
759  {
760  int64_t num64;
761  double numd;
762  if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
763  if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) {
764  /* in strict mode, number must not start with 0 */
766  goto out;
767  }
769  }
770  else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
771  {
772  current = json_object_new_double_s(numd, tok->pb->buf);
773  } else {
775  goto out;
776  }
779  goto redo_char;
780  }
781  break;
782 
785  if(c == ']') {
787  (tok->flags & JSON_TOKENER_STRICT))
788  {
790  goto out;
791  }
794  } else {
795  if(tok->depth >= tok->max_depth-1) {
797  goto out;
798  }
800  tok->depth++;
801  json_tokener_reset_level(tok, tok->depth);
802  goto redo_char;
803  }
804  break;
805 
810  goto redo_char;
811 
813  if(c == ']') {
816  } else if(c == ',') {
819  } else {
821  goto out;
822  }
823  break;
824 
827  if(c == ')') {
829  (tok->flags & JSON_TOKENER_STRICT))
830  {
832  goto out;
833  }
836  } else {
837  if(tok->depth >= tok->max_depth-1) {
839  goto out;
840  }
842  tok->depth++;
843  json_tokener_reset_level(tok, tok->depth);
844  goto redo_char;
845  }
846  break;
847 
849  if (json_object_array_length(current) == 0) /* extarr_type member */
850  {
854  goto redo_char;
855  }
856  else if (json_object_array_length(current) == 1) /* ndims member */
857  {
861  goto redo_char;
862  }
863  else /* dimension size members */
864  {
865  struct json_object* etypeobj = json_object_array_get_idx(current, 0);
866  struct json_object* ndimsobj = json_object_array_get_idx(current, 1);
867  int ndims = json_object_get_int(ndimsobj);
868  enum json_extarr_type etype = (json_extarr_type) json_object_get_int(etypeobj);
869  if (json_object_array_length(current) < ndims + 2)
870  {
871  json_object_array_add(current, obj); /* dimenion size member */
874  goto redo_char;
875  }
876  else if (json_object_array_length(current) == ndims + 2)
877  {
878  int i, *dims;
879  dims = (int*) malloc(ndims * sizeof(int));
880  for (i = 0; i < ndims; i++)
881  {
882  struct json_object* dimobj = json_object_array_get_idx(current, 2+i);
883  dims[i] = json_object_get_int(dimobj);
884  }
886  current = json_object_new_extarr_alloc(etype, ndims, dims);
887  extarr_idx = 0;
888  put_extarr_val(current, obj, extarr_idx);
889  extarr_idx++;
892  goto redo_char;
893  }
894  }
895  break;
896 
898  if(c == ')') {
901  } else if(c == ',') {
904  } else {
906  goto out;
907  }
908  break;
909 
912  if(c == ')') {
914  (tok->flags & JSON_TOKENER_STRICT))
915  {
917  goto out;
918  }
921  } else {
922  if(tok->depth >= tok->max_depth-1) {
924  goto out;
925  }
927  tok->depth++;
928  json_tokener_reset_level(tok, tok->depth);
929  goto redo_char;
930  }
931  break;
932 
934  {
935  put_extarr_val(current, obj, extarr_idx);
936  extarr_idx++;
937  if (extarr_idx > json_object_extarr_nvals(current))
938  {
940  goto out;
941  }
944  goto redo_char;
945  }
946 
948  if(c == ')') {
951  } else if(c == ',') {
954  } else {
956  goto out;
957  }
958  break;
959 
962  if(c == '}' || c == '>') {
964  (tok->flags & JSON_TOKENER_STRICT))
965  {
967  goto out;
968  }
971  } else if (c == '"' || c == '\'') {
972  tok->quote_char = c;
973  printbuf_reset(tok->pb);
975  } else {
977  goto out;
978  }
979  break;
980 
982  {
983  /* Advance until we change state */
984  const char *case_start = str;
985  while(1) {
986  if(c == tok->quote_char) {
987  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
988  obj_field_name = strdup(tok->pb->buf);
991  break;
992  } else if(c == '\\') {
993  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
996  break;
997  }
998  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
999  printbuf_memappend_fast(tok->pb, case_start, str-case_start);
1000  goto out;
1001  }
1002  }
1003  }
1004  break;
1005 
1007  if(c == ':') {
1010  } else {
1012  goto out;
1013  }
1014  break;
1015 
1017  if(tok->depth >= tok->max_depth-1) {
1019  goto out;
1020  }
1022  tok->depth++;
1023  json_tokener_reset_level(tok, tok->depth);
1024  goto redo_char;
1025 
1028  {
1029  json_bool selected = JSON_C_FALSE;
1030  if (json_object_enum_length(current) == 0)
1031  selected = JSON_C_TRUE;
1033  }
1034  else
1035  {
1037  }
1038  free(obj_field_name);
1039  obj_field_name = NULL;
1042  goto redo_char;
1043 
1045  if(c == '}' || c == '>') {
1048  } else if(c == ',') {
1051  } else {
1053  goto out;
1054  }
1055  break;
1056 
1057  }
1058  if (!ADVANCE_CHAR(str, tok))
1059  goto out;
1060  } /* while(POP_CHAR) */
1061 
1062  out:
1063  if (c &&
1065  (tok->depth == 0) &&
1066  (tok->flags & JSON_TOKENER_STRICT)) {
1067  /* unexpected char after JSON data */
1069  }
1070  if (!c) { /* We hit an eof char (0) */
1074  }
1075 
1076 #ifdef HAVE_SETLOCALE
1077  setlocale(LC_NUMERIC, oldlocale);
1078  if (oldlocale) free(oldlocale);
1079 #endif
1080 
1081  if (tok->err == json_tokener_success)
1082  {
1084  int ii;
1085 
1086  /* Partially reset, so we parse additional objects on subsequent calls. */
1087  for(ii = tok->depth; ii >= 0; ii--)
1088  json_tokener_reset_level(tok, ii);
1089  return ret;
1090  }
1091 
1092  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
1093  json_tokener_errors[tok->err], tok->char_offset);
1094  return NULL;
1095 }
1096 
1097 void json_tokener_set_flags(struct json_tokener *tok, int flags)
1098 {
1099  tok->flags = flags;
1100 }
#define current
Definition: json_tokener.c:188
struct json_object * json_object_new_extarr_alloc(enum json_extarr_type etype, int ndims, int const *dims)
Definition: json_object.c:1115
void json_object_enum_add(struct json_object *jso, char const *name, int64_t val, json_bool selected)
Add a name/value pair to an enumeration.
Definition: json_object.c:1327
static const int json_inf_str_len
Definition: json_tokener.c:61
static unsigned char utf8_replacement_char[3]
Definition: json_tokener.c:104
#define DECODE_SURROGATE_PAIR(hi, lo)
Definition: json_tokener.c:103
int bpos
Definition: printbuf.h:25
int json_parse_double(const char *buf, double *retval)
Definition: json_util.c:149
struct json_tokener_srec * stack
Definition: json_tokener.h:96
#define json_min(a, b)
Definition: bits.h:16
#define hexdigit(x)
Definition: bits.h:23
struct json_object * json_object_new_object(void)
Definition: json_object.c:369
static const char json_false_str[]
Definition: json_tokener.c:66
void const * json_object_extarr_data(struct json_object *jso)
Definition: json_object.c:1206
#define IS_LOW_SURROGATE(uc)
Definition: json_tokener.c:102
void json_tokener_free(struct json_tokener *tok)
Definition: json_tokener.c:128
union json_object::data o
static const char json_true_str[]
Definition: json_tokener.c:64
int json_object_is_type(struct json_object *obj, enum json_type type)
Definition: json_object.c:204
static const int json_null_str_len
Definition: json_tokener.c:59
struct json_object * json_object_new_string_len(const char *s, int len)
Definition: json_object.c:738
void json_tokener_reset(struct json_tokener *tok)
Definition: json_tokener.c:146
static const int json_nan_str_len
Definition: json_tokener.c:63
struct json_object * json_object_new_double_s(double d, const char *ds)
Definition: json_object.c:632
#define saved_state
Definition: json_tokener.c:187
#define JSON_TOKENER_STRICT
Definition: json_tokener.h:110
const char * json_hex_chars
Definition: json_object.c:53
static const int json_false_str_len
Definition: json_tokener.c:67
int json_bool
Definition: json_object.h:80
void json_tokener_set_flags(struct json_tokener *tok, int flags)
static const int json_true_str_len
Definition: json_tokener.c:65
struct printbuf * printbuf_new(void)
Definition: printbuf.c:34
enum json_tokener_state state saved_state
Definition: json_tokener.h:80
void printbuf_reset(struct printbuf *p)
Definition: printbuf.c:180
int json_object_array_add(struct json_object *obj, struct json_object *val)
Definition: json_object.c:859
struct printbuf * pb
Definition: json_tokener.h:91
json_extarr_type
Definition: json_object.h:120
#define NAN
Definition: json_tokener.c:55
static const char json_nan_str[]
Definition: json_tokener.c:62
int json_object_array_length(struct json_object *obj)
Definition: json_object.c:854
static const char json_null_str[]
Definition: json_tokener.c:58
struct json_object * json_object_new_int64(int64_t i)
Definition: json_object.c:550
#define state
Definition: json_tokener.c:186
struct json_object * json_object_new_array(void)
Definition: json_object.c:828
int json_object_extarr_nvals(struct json_object *jso)
Definition: json_object.c:1149
struct json_object * json_object_new_boolean(json_bool b)
Definition: json_object.c:458
void printbuf_free(struct printbuf *p)
Definition: printbuf.c:186
#define JSON_C_TRUE
Definition: json_object.h:65
struct json_object * json_object_new_double(double d)
Definition: json_object.c:622
enum json_tokener_error json_tokener_get_error(json_tokener *tok)
Definition: json_tokener.c:95
double json_object_get_double(struct json_object *obj)
Definition: json_object.c:656
const char * json_tokener_error_desc(enum json_tokener_error jerr)
Definition: json_tokener.c:87
#define JSON_TOKENER_DEFAULT_DEPTH
Definition: json_tokener.h:86
struct json_object * json_object_new_enum(void)
Create a new, empty enumeration object.
Definition: json_object.c:1305
static const char * json_tokener_errors[]
Definition: json_tokener.c:69
#define IS_HIGH_SURROGATE(uc)
Definition: json_tokener.c:101
struct json_object * json_object_array_get_idx(struct json_object *obj, int idx)
Definition: json_object.c:870
struct json_object * json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
Definition: json_tokener.c:273
unsigned int ucs_char
Definition: json_tokener.h:94
struct json_object * current
Definition: json_tokener.h:82
struct json_object * json_object_get(struct json_object *obj)
Definition: json_object.c:147
#define obj_field_name
Definition: json_tokener.c:189
char * buf
Definition: printbuf.h:24
int json_object_put(struct json_object *obj)
Definition: json_object.c:155
int64_t json_object_get_int64(struct json_object *obj)
Definition: json_object.c:559
#define ADVANCE_CHAR(str, tok)
Definition: json_tokener.c:224
#define MC_DEBUG(x,...)
Definition: debug.h:63
int32_t json_object_get_int(struct json_object *obj)
Definition: json_object.c:504
int json_parse_int64(const char *buf, int64_t *retval)
Definition: json_util.c:188
enum json_extarr_type json_object_extarr_type(struct json_object *jso)
Definition: json_object.c:1143
struct json_tokener * json_tokener_new(void)
Definition: json_tokener.c:123
#define JSON_C_FALSE
Definition: json_object.h:64
enum json_tokener_error err
Definition: json_tokener.h:93
int json_object_enum_length(struct json_object *jso)
Get the length (or size) of an enumeration.
Definition: json_object.c:1362
struct json_object * json_tokener_parse(const char *str)
Definition: json_tokener.c:158
#define printbuf_memappend_fast(p, bufptr, bufsize)
Definition: printbuf.h:42
const char * json_number_chars
Definition: json_object.c:52
static const char json_inf_str[]
Definition: json_tokener.c:60
struct json_tokener * json_tokener_new_ex(int depth)
Definition: json_tokener.c:106
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
Definition: json_tokener.c:136
static void put_extarr_val(struct json_object *cur, struct json_object *o, int extarr_idx)
Definition: json_tokener.c:230
void json_object_object_add(struct json_object *obj, const char *key, struct json_object *val)
Definition: json_object.c:391
#define PEEK_CHAR(dest, tok)
Definition: json_tokener.c:209
json_tokener_error
Definition: json_tokener.h:22
struct json_object * json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
Definition: json_tokener.c:166