Contiki 3.x
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 char
47 pop(struct jsonparse_state *state)
48 {
49  if(state->depth == 0) {
50  return JSON_TYPE_ERROR;
51  }
52  state->depth--;
53  return state->stack[state->depth];
54 }
55 /*--------------------------------------------------------------------*/
56 /* will pass by the value and store the start and length of the value for
57  atomic types */
58 /*--------------------------------------------------------------------*/
59 static void
60 atomic(struct jsonparse_state *state, char type)
61 {
62  char c;
63 
64  state->vstart = state->pos;
65  state->vtype = type;
66  if(type == JSON_TYPE_STRING || type == JSON_TYPE_PAIR_NAME) {
67  while((c = state->json[state->pos++]) && c != '"') {
68  if(c == '\\') {
69  state->pos++; /* skip current char */
70  }
71  }
72  state->vlen = state->pos - state->vstart - 1;
73  } else if(type == JSON_TYPE_NUMBER) {
74  do {
75  c = state->json[state->pos];
76  if((c < '0' || c > '9') && c != '.') {
77  c = 0;
78  } else {
79  state->pos++;
80  }
81  } while(c);
82  /* need to back one step since first char is already gone */
83  state->vstart--;
84  state->vlen = state->pos - state->vstart;
85  }
86  /* no other types for now... */
87 }
88 /*--------------------------------------------------------------------*/
89 static void
90 skip_ws(struct jsonparse_state *state)
91 {
92  char c;
93 
94  while(state->pos < state->len &&
95  ((c = state->json[state->pos]) == ' ' || c == '\n')) {
96  state->pos++;
97  }
98 }
99 /*--------------------------------------------------------------------*/
100 void
101 jsonparse_setup(struct jsonparse_state *state, const char *json, int len)
102 {
103  state->json = json;
104  state->len = len;
105  state->pos = 0;
106  state->depth = 0;
107  state->error = 0;
108  state->stack[0] = 0;
109 }
110 /*--------------------------------------------------------------------*/
111 int
112 jsonparse_next(struct jsonparse_state *state)
113 {
114  char c;
115  char s;
116 
117  skip_ws(state);
118  c = state->json[state->pos];
119  s = jsonparse_get_type(state);
120  state->pos++;
121 
122  switch(c) {
123  case '{':
124  push(state, c);
125  return c;
126  case '}':
127  if(s == ':' && state->vtype != 0) {
128 /* printf("Popping vtype: '%c'\n", state->vtype); */
129  pop(state);
130  s = jsonparse_get_type(state);
131  }
132  if(s == '{') {
133  pop(state);
134  } else {
135  state->error = JSON_ERROR_SYNTAX;
136  return JSON_TYPE_ERROR;
137  }
138  return c;
139  case ']':
140  if(s == '[') {
141  pop(state);
142  } else {
143  state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
144  return JSON_TYPE_ERROR;
145  }
146  return c;
147  case ':':
148  push(state, c);
149  return c;
150  case ',':
151  /* if x:y ... , */
152  if(s == ':' && state->vtype != 0) {
153  pop(state);
154  } else if(s == '[') {
155  /* ok! */
156  } else {
157  state->error = JSON_ERROR_SYNTAX;
158  return JSON_TYPE_ERROR;
159  }
160  return c;
161  case '"':
162  if(s == '{' || s == '[' || s == ':') {
163  atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
164  } else {
165  state->error = JSON_ERROR_UNEXPECTED_STRING;
166  return JSON_TYPE_ERROR;
167  }
168  return c;
169  case '[':
170  if(s == '{' || s == '[' || s == ':') {
171  push(state, c);
172  } else {
173  state->error = JSON_ERROR_UNEXPECTED_ARRAY;
174  return JSON_TYPE_ERROR;
175  }
176  return c;
177  default:
178  if(s == ':' || s == '[') {
179  if(c <= '9' && c >= '0') {
180  atomic(state, JSON_TYPE_NUMBER);
181  return JSON_TYPE_NUMBER;
182  }
183  }
184  }
185  return 0;
186 }
187 /*--------------------------------------------------------------------*/
188 /* get the json value of the current position
189  * works only on "atomic" values such as string, number, null, false, true
190  */
191 /*--------------------------------------------------------------------*/
192 int
193 jsonparse_copy_value(struct jsonparse_state *state, char *str, int size)
194 {
195  int i;
196 
197  if(state->vtype == 0) {
198  return 0;
199  }
200  size = size <= state->vlen ? (size - 1) : state->vlen;
201  for(i = 0; i < size; i++) {
202  str[i] = state->json[state->vstart + i];
203  }
204  str[i] = 0;
205  return state->vtype;
206 }
207 /*--------------------------------------------------------------------*/
208 int
209 jsonparse_get_value_as_int(struct jsonparse_state *state)
210 {
211  if(state->vtype != JSON_TYPE_NUMBER) {
212  return 0;
213  }
214  return atoi(&state->json[state->vstart]);
215 }
216 /*--------------------------------------------------------------------*/
217 long
218 jsonparse_get_value_as_long(struct jsonparse_state *state)
219 {
220  if(state->vtype != JSON_TYPE_NUMBER) {
221  return 0;
222  }
223  return atol(&state->json[state->vstart]);
224 }
225 /*--------------------------------------------------------------------*/
226 /* strcmp - assume no strange chars that needs to be stuffed in string... */
227 /*--------------------------------------------------------------------*/
228 int
229 jsonparse_strcmp_value(struct jsonparse_state *state, const char *str)
230 {
231  if(state->vtype == 0) {
232  return -1;
233  }
234  return strncmp(str, &state->json[state->vstart], state->vlen);
235 }
236 /*--------------------------------------------------------------------*/
237 int
238 jsonparse_get_len(struct jsonparse_state *state)
239 {
240  return state->vlen;
241 }
242 /*--------------------------------------------------------------------*/
243 int
244 jsonparse_get_type(struct jsonparse_state *state)
245 {
246  if(state->depth == 0) {
247  return 0;
248  }
249  return state->stack[state->depth - 1];
250 }
251 /*--------------------------------------------------------------------*/
252 int
253 jsonparse_has_next(struct jsonparse_state *state)
254 {
255  return state->pos < state->len;
256 }
257 /*--------------------------------------------------------------------*/