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 #include <stdbool.h>
36 
37 /*--------------------------------------------------------------------*/
38 static bool
39 push(struct jsonparse_state *state, char c)
40 {
41  if(state->depth < JSONPARSE_MAX_DEPTH) {
42  state->stack[state->depth] = c;
43  state->depth++;
44  state->vtype = 0;
45  return true;
46  } else {
47  return false;
48  }
49 }
50 /*--------------------------------------------------------------------*/
51 static bool
52 modify(struct jsonparse_state *state, char c)
53 {
54  if(state->depth > 0) {
55  state->stack[state->depth - 1] = c;
56  return true;
57  } else {
58  return false;
59  }
60 }
61 /*--------------------------------------------------------------------*/
62 static bool
63 pop(struct jsonparse_state *state)
64 {
65  if(state->depth == 0) {
66  return false;
67  }
68  state->depth--;
69  state->vtype = state->stack[state->depth];
70  return true;
71 }
72 /*--------------------------------------------------------------------*/
73 /* will pass by the value and store the start and length of the value for
74  atomic types */
75 /*--------------------------------------------------------------------*/
76 static char
77 atomic(struct jsonparse_state *state, char type)
78 {
79  char c;
80  const char *str;
81  int len;
82 
83  state->vstart = state->pos;
84  if(type == JSON_TYPE_STRING || type == JSON_TYPE_PAIR_NAME) {
85  while((c = state->json[state->pos++]) && c != '"') {
86  if(c == '\\') {
87  state->pos++; /* skip current char */
88  }
89  }
90  if (c != '"') {
91  state->error = JSON_ERROR_SYNTAX;
92  return JSON_TYPE_ERROR;
93  }
94  state->vlen = state->pos - state->vstart - 1;
95  } else if(type == JSON_TYPE_NUMBER) {
96  do {
97  c = state->json[state->pos];
98  if((c < '0' || c > '9') && c != '.') {
99  c = 0;
100  } else {
101  state->pos++;
102  }
103  } while(c);
104  /* need to back one step since first char is already gone */
105  state->vstart--;
106  state->vlen = state->pos - state->vstart;
107  } else if(type == JSON_TYPE_NULL || type == JSON_TYPE_TRUE || type == JSON_TYPE_FALSE) {
108  state->vstart--;
109  switch (type) {
110  case JSON_TYPE_NULL: str = "null"; break;
111  case JSON_TYPE_TRUE: str = "true"; break;
112  case JSON_TYPE_FALSE: str = "false"; break;
113  default: str = ""; break;
114  }
115 
116  while ((c = state->json[state->pos]) && c != ' ' && c != ',' && c != ']' && c != '}') {
117  state->pos++;
118  }
119 
120  state->vlen = state->pos - state->vstart;
121  len = strlen(str);
122  len = state->vlen > len ? state->vlen : len;
123 
124  if (strncmp(str, &state->json[state->vstart], len) != 0) {
125  state->error = JSON_ERROR_SYNTAX;
126  return JSON_TYPE_ERROR;
127  }
128  }
129 
130  state->vtype = type;
131  return state->vtype;
132 }
133 /*--------------------------------------------------------------------*/
134 static void
135 skip_ws(struct jsonparse_state *state)
136 {
137  char c;
138 
139  while(state->pos < state->len &&
140  ((c = state->json[state->pos]) == ' ' || c == '\n')) {
141  state->pos++;
142  }
143 }
144 /*--------------------------------------------------------------------*/
145 static bool
146 is_atomic(struct jsonparse_state *state)
147 {
148  char v = state->vtype;
149  return v == 'N' || v == '"' || v == '0' || v == 'n' || v == 't' || v == 'f';
150 }
151 /*--------------------------------------------------------------------*/
152 void
153 jsonparse_setup(struct jsonparse_state *state, const char *json, int len)
154 {
155  state->json = json;
156  state->len = len;
157  state->pos = 0;
158  state->depth = 0;
159  state->error = 0;
160  state->vtype = 0;
161  state->stack[0] = 0;
162 }
163 /*--------------------------------------------------------------------*/
164 int
165 jsonparse_next(struct jsonparse_state *state)
166 {
167  char c;
168  char s;
169  char v;
170  bool ret;
171 
172  skip_ws(state);
173  c = state->json[state->pos];
174  s = jsonparse_get_type(state);
175  v = state->vtype;
176  state->pos++;
177 
178  switch(c) {
179  case '{':
180  if((s == 0 && v == 0) || s == '[' || s == ':') {
181  if(push(state, c)) {
182  return c;
183  }
184  }
185  state->error = JSON_ERROR_UNEXPECTED_OBJECT;
186  return JSON_TYPE_ERROR;
187  case '}':
188  if((s == ':' && v != ',' && v != 0 ) || (s == '{' && v == 0)) {
189  if(pop(state)) {
190  return c;
191  }
192  }
193  state->error = JSON_ERROR_UNEXPECTED_END_OF_OBJECT;
194  return JSON_TYPE_ERROR;
195  case ']':
196  if(s == '[' && v != ',') {
197  if(pop(state)) {
198  return c;
199  }
200  }
201  state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
202  return JSON_TYPE_ERROR;
203  case ':':
204  if(s == '{' && v == 'N') {
205  ret = modify(state, ':');
206  state->vtype = 0;
207  if(ret) {
208  return jsonparse_next(state);
209  }
210  }
211  state->error = JSON_ERROR_SYNTAX;
212  return JSON_TYPE_ERROR;
213  case ',':
214  if(s == ':' && v != 0) {
215  ret = modify(state, '{');
216  state->vtype = c;
217  if(ret) {
218  return c;
219  }
220  } else if(s == '[') {
221  state->vtype = c;
222  return c;
223  }
224  state->error = JSON_ERROR_SYNTAX;
225  return JSON_TYPE_ERROR;
226  case '"':
227  if((s == 0 && v == 0) || s == '{' || s == '[' || s == ':') {
228  return atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
229  } else {
230  state->error = JSON_ERROR_UNEXPECTED_STRING;
231  return JSON_TYPE_ERROR;
232  }
233  return c;
234  case '[':
235  if((s == 0 && v == 0) || s == '[' || s == ':') {
236  if(push(state, c)) {
237  return c;
238  }
239  }
240  state->error = JSON_ERROR_UNEXPECTED_ARRAY;
241  return JSON_TYPE_ERROR;
242  case 0:
243  if(v == 0 || state->depth > 0) {
244  state->error = JSON_ERROR_SYNTAX;
245  }
246  return JSON_TYPE_ERROR;
247  default:
248  if(s == 0 || s == ':' || s == '[') {
249  if (v != 0 && v != ',') {
250  state->error = JSON_ERROR_SYNTAX;
251  return JSON_TYPE_ERROR;
252  }
253  if(c == '-' || (c <= '9' && c >= '0')) {
254  return atomic(state, JSON_TYPE_NUMBER);
255  } else if(c == 'n') {
256  return atomic(state, JSON_TYPE_NULL);
257  } else if(c == 't') {
258  return atomic(state, JSON_TYPE_TRUE);
259  } else if(c == 'f') {
260  return atomic(state, JSON_TYPE_FALSE);
261  } else {
262  state->error = JSON_ERROR_SYNTAX;
263  return JSON_TYPE_ERROR;
264  }
265  } else if(s == '{') {
266  state->error = JSON_ERROR_SYNTAX;
267  return JSON_TYPE_ERROR;
268  }
269  }
270  return 0;
271 }
272 /*--------------------------------------------------------------------*/
273 /* get the json value of the current position
274  * works only on "atomic" values such as string, number, null, false, true
275  */
276 /*--------------------------------------------------------------------*/
277 int
278 jsonparse_copy_value(struct jsonparse_state *state, char *str, int size)
279 {
280  int i, o;
281  char c;
282 
283  if(!is_atomic(state)) {
284  return 0;
285  }
286  for(i = 0, o = 0; i < state->vlen && o < size - 1; i++) {
287  c = state->json[state->vstart + i];
288  if(c == '\\') {
289  i++;
290  switch(state->json[state->vstart + i]) {
291  case '"': str[o++] = '"'; break;
292  case '\\': str[o++] = '\\'; break;
293  case '/': str[o++] = '/'; break;
294  case 'b': str[o++] = '\b'; break;
295  case 'f': str[o++] = '\f'; break;
296  case 'n': str[o++] = '\n'; break;
297  case 'r': str[o++] = '\r'; break;
298  case 't': str[o++] = '\t'; break;
299  }
300  continue;
301  }
302  str[o++] = c;
303  }
304  str[o] = 0;
305  return state->vtype;
306 }
307 /*--------------------------------------------------------------------*/
308 int
309 jsonparse_get_value_as_int(struct jsonparse_state *state)
310 {
311  if(state->vtype != JSON_TYPE_NUMBER) {
312  return 0;
313  }
314  return atoi(&state->json[state->vstart]);
315 }
316 /*--------------------------------------------------------------------*/
317 long
318 jsonparse_get_value_as_long(struct jsonparse_state *state)
319 {
320  if(state->vtype != JSON_TYPE_NUMBER) {
321  return 0;
322  }
323  return atol(&state->json[state->vstart]);
324 }
325 /*--------------------------------------------------------------------*/
326 /* strcmp - assume no strange chars that needs to be stuffed in string... */
327 /*--------------------------------------------------------------------*/
328 int
329 jsonparse_strcmp_value(struct jsonparse_state *state, const char *str)
330 {
331  if(!is_atomic(state)) {
332  return -1;
333  }
334  return strncmp(str, &state->json[state->vstart], state->vlen);
335 }
336 /*--------------------------------------------------------------------*/
337 int
338 jsonparse_get_len(struct jsonparse_state *state)
339 {
340  return state->vlen;
341 }
342 /*--------------------------------------------------------------------*/
343 int
344 jsonparse_get_type(struct jsonparse_state *state)
345 {
346  if(state->depth == 0) {
347  return 0;
348  }
349  return state->stack[state->depth - 1];
350 }
351 /*--------------------------------------------------------------------*/
352 int
353 jsonparse_has_next(struct jsonparse_state *state)
354 {
355  return state->pos < state->len;
356 }
357 /*--------------------------------------------------------------------*/