Contiki-NG
jsonparse.c
1 /*
2  * Copyright (c) 2011-2012, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 #include "jsonparse.h"
33 #include <stdlib.h>
34 #include <string.h>
35 
36 /*--------------------------------------------------------------------*/
37 static int
38 push(struct jsonparse_state *state, char c)
39 {
40  state->stack[state->depth] = c;
41  state->depth++;
42  state->vtype = 0;
43  return state->depth < JSONPARSE_MAX_DEPTH;
44 }
45 /*--------------------------------------------------------------------*/
46 static void
47 modify(struct jsonparse_state *state, char c)
48 {
49  if(state->depth > 0) {
50  state->stack[state->depth - 1] = c;
51  }
52 }
53 /*--------------------------------------------------------------------*/
54 static char
55 pop(struct jsonparse_state *state)
56 {
57  if(state->depth == 0) {
58  return JSON_TYPE_ERROR;
59  }
60  state->depth--;
61  state->vtype = state->stack[state->depth];
62  return state->stack[state->depth];
63 }
64 /*--------------------------------------------------------------------*/
65 /* will pass by the value and store the start and length of the value for
66  atomic types */
67 /*--------------------------------------------------------------------*/
68 static char
69 atomic(struct jsonparse_state *state, char type)
70 {
71  char c;
72  const char *str;
73  int len;
74 
75  state->vstart = state->pos;
76  if(type == JSON_TYPE_STRING || type == JSON_TYPE_PAIR_NAME) {
77  while((c = state->json[state->pos++]) && c != '"') {
78  if(c == '\\') {
79  state->pos++; /* skip current char */
80  }
81  }
82  if (c != '"') {
83  state->error = JSON_ERROR_SYNTAX;
84  return JSON_TYPE_ERROR;
85  }
86  state->vlen = state->pos - state->vstart - 1;
87  } else if(type == JSON_TYPE_NUMBER) {
88  do {
89  c = state->json[state->pos];
90  if((c < '0' || c > '9') && c != '.') {
91  c = 0;
92  } else {
93  state->pos++;
94  }
95  } while(c);
96  /* need to back one step since first char is already gone */
97  state->vstart--;
98  state->vlen = state->pos - state->vstart;
99  } else if(type == JSON_TYPE_NULL || type == JSON_TYPE_TRUE || type == JSON_TYPE_FALSE) {
100  state->vstart--;
101  switch (type) {
102  case JSON_TYPE_NULL: str = "null"; break;
103  case JSON_TYPE_TRUE: str = "true"; break;
104  case JSON_TYPE_FALSE: str = "false"; break;
105  default: str = ""; break;
106  }
107 
108  while ((c = state->json[state->pos]) && c != ' ' && c != ',' && c != ']' && c != '}') {
109  state->pos++;
110  }
111 
112  state->vlen = state->pos - state->vstart;
113  len = strlen(str);
114  len = state->vlen > len ? state->vlen : len;
115 
116  if (strncmp(str, &state->json[state->vstart], len) != 0) {
117  state->error = JSON_ERROR_SYNTAX;
118  return JSON_TYPE_ERROR;
119  }
120  }
121 
122  state->vtype = type;
123  return state->vtype;
124 }
125 /*--------------------------------------------------------------------*/
126 static void
127 skip_ws(struct jsonparse_state *state)
128 {
129  char c;
130 
131  while(state->pos < state->len &&
132  ((c = state->json[state->pos]) == ' ' || c == '\n')) {
133  state->pos++;
134  }
135 }
136 /*--------------------------------------------------------------------*/
137 static int
138 is_atomic(struct jsonparse_state *state)
139 {
140  char v = state->vtype;
141  if(v == 'N' || v == '"' || v == '0' || v == 'n' || v == 't' || v == 'f') {
142  return 1;
143  } else {
144  return 0;
145  }
146 }
147 /*--------------------------------------------------------------------*/
148 void
149 jsonparse_setup(struct jsonparse_state *state, const char *json, int len)
150 {
151  state->json = json;
152  state->len = len;
153  state->pos = 0;
154  state->depth = 0;
155  state->error = 0;
156  state->vtype = 0;
157  state->stack[0] = 0;
158 }
159 /*--------------------------------------------------------------------*/
160 int
161 jsonparse_next(struct jsonparse_state *state)
162 {
163  char c;
164  char s;
165  char v;
166 
167  skip_ws(state);
168  c = state->json[state->pos];
169  s = jsonparse_get_type(state);
170  v = state->vtype;
171  state->pos++;
172 
173  switch(c) {
174  case '{':
175  if((s == 0 && v == 0) || s == '[' || s == ':') {
176  push(state, c);
177  } else {
178  state->error = JSON_ERROR_UNEXPECTED_OBJECT;
179  return JSON_TYPE_ERROR;
180  }
181  return c;
182  case '}':
183  if((s == ':' && v != ',' && v != 0 ) || (s == '{' && v == 0)) {
184  pop(state);
185  } else {
186  state->error = JSON_ERROR_UNEXPECTED_END_OF_OBJECT;
187  return JSON_TYPE_ERROR;
188  }
189  return c;
190  case ']':
191  if(s == '[' && v != ',') {
192  pop(state);
193  } else {
194  state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
195  return JSON_TYPE_ERROR;
196  }
197  return c;
198  case ':':
199  if(s == '{' && v == 'N') {
200  modify(state, ':');
201  state->vtype = 0;
202  } else {
203  state->error = JSON_ERROR_SYNTAX;
204  return JSON_TYPE_ERROR;
205  }
206  return jsonparse_next(state);
207  case ',':
208  if(s == ':' && v != 0) {
209  modify(state, '{');
210  state->vtype = c;
211  } else if(s == '[') {
212  state->vtype = c;
213  } else {
214  state->error = JSON_ERROR_SYNTAX;
215  return JSON_TYPE_ERROR;
216  }
217  return c;
218  case '"':
219  if((s == 0 && v == 0) || s == '{' || s == '[' || s == ':') {
220  return atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
221  } else {
222  state->error = JSON_ERROR_UNEXPECTED_STRING;
223  return JSON_TYPE_ERROR;
224  }
225  return c;
226  case '[':
227  if((s == 0 && v == 0) || s == '[' || s == ':') {
228  push(state, c);
229  } else {
230  state->error = JSON_ERROR_UNEXPECTED_ARRAY;
231  return JSON_TYPE_ERROR;
232  }
233  return c;
234  case 0:
235  if(v == 0 || state->depth > 0) {
236  state->error = JSON_ERROR_SYNTAX;
237  }
238  return JSON_TYPE_ERROR;
239  default:
240  if(s == 0 || s == ':' || s == '[') {
241  if (v != 0 && v != ',') {
242  state->error = JSON_ERROR_SYNTAX;
243  return JSON_TYPE_ERROR;
244  }
245  if(c == '-' || (c <= '9' && c >= '0')) {
246  return atomic(state, JSON_TYPE_NUMBER);
247  } else if(c == 'n') {
248  return atomic(state, JSON_TYPE_NULL);
249  } else if(c == 't') {
250  return atomic(state, JSON_TYPE_TRUE);
251  } else if(c == 'f') {
252  return atomic(state, JSON_TYPE_FALSE);
253  } else {
254  state->error = JSON_ERROR_SYNTAX;
255  return JSON_TYPE_ERROR;
256  }
257  } else if(s == '{') {
258  state->error = JSON_ERROR_SYNTAX;
259  return JSON_TYPE_ERROR;
260  }
261  }
262  return 0;
263 }
264 /*--------------------------------------------------------------------*/
265 /* get the json value of the current position
266  * works only on "atomic" values such as string, number, null, false, true
267  */
268 /*--------------------------------------------------------------------*/
269 int
270 jsonparse_copy_value(struct jsonparse_state *state, char *str, int size)
271 {
272  int i, o;
273  char c;
274 
275  if(!is_atomic(state)) {
276  return 0;
277  }
278  for(i = 0, o = 0; i < state->vlen && o < size - 1; i++) {
279  c = state->json[state->vstart + i];
280  if(c == '\\') {
281  i++;
282  switch(state->json[state->vstart + i]) {
283  case '"': str[o++] = '"'; break;
284  case '\\': str[o++] = '\\'; break;
285  case '/': str[o++] = '/'; break;
286  case 'b': str[o++] = '\b'; break;
287  case 'f': str[o++] = '\f'; break;
288  case 'n': str[o++] = '\n'; break;
289  case 'r': str[o++] = '\r'; break;
290  case 't': str[o++] = '\t'; break;
291  }
292  continue;
293  }
294  str[o++] = c;
295  }
296  str[o] = 0;
297  return state->vtype;
298 }
299 /*--------------------------------------------------------------------*/
300 int
301 jsonparse_get_value_as_int(struct jsonparse_state *state)
302 {
303  if(state->vtype != JSON_TYPE_NUMBER) {
304  return 0;
305  }
306  return atoi(&state->json[state->vstart]);
307 }
308 /*--------------------------------------------------------------------*/
309 long
310 jsonparse_get_value_as_long(struct jsonparse_state *state)
311 {
312  if(state->vtype != JSON_TYPE_NUMBER) {
313  return 0;
314  }
315  return atol(&state->json[state->vstart]);
316 }
317 /*--------------------------------------------------------------------*/
318 /* strcmp - assume no strange chars that needs to be stuffed in string... */
319 /*--------------------------------------------------------------------*/
320 int
321 jsonparse_strcmp_value(struct jsonparse_state *state, const char *str)
322 {
323  if(!is_atomic(state)) {
324  return -1;
325  }
326  return strncmp(str, &state->json[state->vstart], state->vlen);
327 }
328 /*--------------------------------------------------------------------*/
329 int
330 jsonparse_get_len(struct jsonparse_state *state)
331 {
332  return state->vlen;
333 }
334 /*--------------------------------------------------------------------*/
335 int
336 jsonparse_get_type(struct jsonparse_state *state)
337 {
338  if(state->depth == 0) {
339  return 0;
340  }
341  return state->stack[state->depth - 1];
342 }
343 /*--------------------------------------------------------------------*/
344 int
345 jsonparse_has_next(struct jsonparse_state *state)
346 {
347  return state->pos < state->len;
348 }
349 /*--------------------------------------------------------------------*/