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 
12 #include "config.h"
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <strings.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 
27 
28 #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 
36 static const char* json_null_str = "null";
37 static const char* json_true_str = "true";
38 static const char* json_false_str = "false";
39 
40 const 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 
59 {
60  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 
67 {
68  json_tokener_reset(tok);
69  if(tok) printbuf_free(tok->pb);
70  free(tok);
71 }
72 
73 static void json_tokener_reset_level(struct json_tokener *tok, int depth)
74 {
75  tok->stack[depth].state = json_tokener_state_eatws;
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 
84 {
85  int i;
86  for(i = tok->depth; i >= 0; i--)
88  tok->depth = 0;
90 }
91 
92 struct json_object* json_tokener_parse(const char *str)
93 {
94  struct json_tokener* tok;
95  struct json_object* obj;
96 
97  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);
102  return obj;
103 }
104 
105 
106 /*#if !HAVE_STRNDUP*/
107 /* CAW: compliant version of strndup() */
108 char* json_c_strndup(const char* str, size_t n)
109 {
110  if(str) {
111  size_t len = strlen(str);
112  size_t nn = min(len,n);
113  char* s = (char*)malloc(sizeof(char) * (nn + 1));
114 
115  if(s) {
116  memcpy(s, str, nn);
117  s[nn] = '\0';
118  }
119 
120  return s;
121  }
122 
123  return NULL;
124 }
125 /*#endif*/
126 
127 
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 
134  const char *str, int len)
135 {
136  struct json_object *obj = NULL;
137  char c;
138 
139  tok->char_offset = 0;
140  tok->err = json_tokener_success;
141 
142  do {
143  if(tok->char_offset == len) {
144  if(tok->depth == 0 && state == json_tokener_state_eatws &&
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:
154  switch(state) {
155 
157  if(isspace(c)) {
158  /* okay */
159  } else if(c == '/') {
160  printbuf_reset(tok->pb);
161  printbuf_memappend(tok->pb, &c, 1);
163  } else {
164  state = saved_state;
165  goto redo_char;
166  }
167  break;
168 
170  switch(c) {
171  case '{':
175  break;
176  case '[':
180  break;
181  case 'N':
182  case 'n':
184  printbuf_reset(tok->pb);
185  tok->st_pos = 0;
186  goto redo_char;
187  case '"':
188  case '\'':
190  printbuf_reset(tok->pb);
191  tok->quote_char = c;
192  break;
193  case 'T':
194  case 't':
195  case 'F':
196  case 'f':
198  printbuf_reset(tok->pb);
199  tok->st_pos = 0;
200  goto redo_char;
201 #if 0 /*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
215  case '-':
217  printbuf_reset(tok->pb);
218  tok->is_double = 0;
219  goto redo_char;
220  default:
222  goto out;
223  }
224  break;
225 
227  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;
232 
234  printbuf_memappend(tok->pb, &c, 1);
235  if(strncasecmp(json_null_str, tok->pb->buf,
236  min( (size_t) (tok->st_pos+1), strlen(json_null_str))) == 0) {
237  if( ((size_t) tok->st_pos) == strlen(json_null_str)) {
238  current = NULL;
241  goto redo_char;
242  }
243  } else {
245  goto out;
246  }
247  tok->st_pos++;
248  break;
249 
251  if(c == '*') {
253  } else if(c == '/') {
255  } else {
257  goto out;
258  }
259  printbuf_memappend(tok->pb, &c, 1);
260  break;
261 
263  if(c == '*') state = json_tokener_state_comment_end;
264  printbuf_memappend(tok->pb, &c, 1);
265  break;
266 
268  if(c == '\n') {
269  mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
271  } else {
272  printbuf_memappend(tok->pb, &c, 1);
273  }
274  break;
275 
277  printbuf_memappend(tok->pb, &c, 1);
278  if(c == '/') {
279  mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
281  } else {
283  }
284  break;
285 
287  if(c == tok->quote_char) {
291  } else if(c == '\\') {
294  } else {
295  printbuf_memappend(tok->pb, &c, 1);
296  }
297  break;
298 
300  switch(c) {
301  case '"':
302  case '\\':
303  case '/':
304  printbuf_memappend(tok->pb, &c, 1);
305  state = saved_state;
306  break;
307  case 'b':
308  case 'n':
309  case 'r':
310  case 't':
311  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);
315  state = saved_state;
316  break;
317  case 'u':
318  tok->ucs_char = 0;
319  tok->st_pos = 0;
321  break;
322  default:
324  goto out;
325  }
326  break;
327 
329  if(strchr(json_hex_chars, c)) {
330  tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
331  if(tok->st_pos == 4) {
332  unsigned char utf_out[3];
333  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);
340  } else {
341  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);
345  }
346  state = saved_state;
347  }
348  } else {
350  goto out;
351  }
352  break;
353 
355  printbuf_memappend(tok->pb, &c, 1);
356  if(strncasecmp(json_true_str, tok->pb->buf,
357  min( (size_t)(tok->st_pos+1), strlen(json_true_str))) == 0) {
358  if(((size_t) tok->st_pos) == strlen(json_true_str)) {
362  goto redo_char;
363  }
364  } else if(strncasecmp(json_false_str, tok->pb->buf,
365  min((size_t)(tok->st_pos+1), strlen(json_false_str))) == 0) {
366  if(( (size_t) tok->st_pos) == strlen(json_false_str)) {
370  goto redo_char;
371  }
372  } else {
374  goto out;
375  }
376  tok->st_pos++;
377  break;
378 
380  if(c && strchr(json_number_chars, c)) {
381  printbuf_memappend(tok->pb, &c, 1);
382  if(c == '.' || c == 'e') tok->is_double = 1;
383  } else {
384  int numi;
385  double numd;
386  if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
388  } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
390  } else {
392  goto out;
393  }
396  goto redo_char;
397  }
398  break;
399 
401  if(c == ']') {
404  } else {
405  if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
407  goto out;
408  }
410  tok->depth++;
411  json_tokener_reset_level(tok, tok->depth);
412  goto redo_char;
413  }
414  break;
415 
420  goto redo_char;
421 
423  if(c == ']') {
426  } else if(c == ',') {
429  } else {
431  goto out;
432  }
433  break;
434 
436  if(c == '}') {
439  } else if (c == '"' || c == '\'') {
440  tok->quote_char = c;
441  printbuf_reset(tok->pb);
443  } else {
445  goto out;
446  }
447  break;
448 
450  if(c == tok->quote_char) {
451  obj_field_name = strdup(tok->pb->buf);
454  } else if(c == '\\') {
457  } else {
458  printbuf_memappend(tok->pb, &c, 1);
459  }
460  break;
461 
463  if(c == ':') {
466  } else {
468  goto out;
469  }
470  break;
471 
473  if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
475  goto out;
476  }
478  tok->depth++;
479  json_tokener_reset_level(tok, tok->depth);
480  goto redo_char;
481 
484  free(obj_field_name);
485  obj_field_name = NULL;
488  goto redo_char;
489 
491  if(c == '}') {
494  } else if(c == ',') {
497  } else {
499  goto out;
500  }
501  break;
502 
503  }
504  str++;
505  tok->char_offset++;
506  } while(c);
507 
511 
512  out:
513  if(tok->err == json_tokener_success) return json_object_get(current);
514  mc_debug("json_tokener_parse_ex: error %s at offset %d\n",
515  json_tokener_errors[tok->err], tok->char_offset);
516  return NULL;
517 }
#define current
Definition: json_tokener.c:130
void json_object_put(struct json_object *this)
Definition: json_object.c:144
struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH]
Definition: json_tokener.h:77
static const char * json_null_str
Definition: json_tokener.c:36
enum json_tokener_error err
Definition: json_tokener.h:74
char * buf
Definition: printbuf.h:18
struct json_object * json_object_new_boolean(boolean b)
Definition: json_object.c:297
struct json_object * json_object_new_double(double d)
Definition: json_object.c:386
void mc_debug(const char *msg,...)
Definition: debug.c:58
char * json_c_strndup(const char *str, size_t n)
Definition: json_tokener.c:108
struct printbuf * printbuf_new()
Definition: printbuf.c:28
struct json_object * json_object_new_string(const char *s)
Definition: json_object.c:432
void json_tokener_free(struct json_tokener *tok)
Definition: json_tokener.c:66
#define JSON_TOKENER_MAX_DEPTH
Definition: json_tokener.h:67
#define error_ptr(error)
Definition: bits.h:24
void json_tokener_reset(struct json_tokener *tok)
Definition: json_tokener.c:83
int json_object_array_add(struct json_object *this, struct json_object *val)
Definition: json_object.c:522
#define saved_state
Definition: json_tokener.c:129
struct json_object * current
Definition: json_tokener.h:63
#define min(a, b)
Definition: bits.h:16
struct json_object * json_object_new_array()
Definition: json_object.c:495
#define state
Definition: json_tokener.c:128
struct json_object * json_object_get(struct json_object *this)
Definition: json_object.c:136
struct json_object * json_object_new_object()
Definition: json_object.c:248
const char * json_tokener_errors[]
Definition: json_tokener.c:40
struct json_object * json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
Definition: json_tokener.c:133
struct json_object * json_object_new_int(int i)
Definition: json_object.c:332
unsigned int ucs_char
Definition: json_tokener.h:75
struct printbuf * pb
Definition: json_tokener.h:72
void json_object_object_add(struct json_object *this, const char *key, struct json_object *val)
Definition: json_object.c:270
void printbuf_free(struct printbuf *p)
Definition: printbuf.c:138
const char * json_hex_chars
Definition: json_object.c:41
#define obj_field_name
Definition: json_tokener.c:131
static const char * json_true_str
Definition: json_tokener.c:37
const char * json_number_chars
Definition: json_object.c:40
enum json_tokener_state state saved_state
Definition: json_tokener.h:61
static const char * json_false_str
Definition: json_tokener.c:38
struct json_tokener * json_tokener_new()
Definition: json_tokener.c:58
int printbuf_memappend(struct printbuf *p, const char *buf, int size)
Definition: printbuf.c:43
void printbuf_reset(struct printbuf *p)
Definition: printbuf.c:132
struct json_object * json_tokener_parse(const char *str)
Definition: json_tokener.c:92
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
Definition: json_tokener.c:73
#define hexdigit(x)
Definition: bits.h:23


csm
Author(s): Andrea Censi
autogenerated on Tue May 11 2021 02:18:23