TI J721E Imaging User Guide
jsmn.h
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2010 Serge Zaitsev
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
34 #ifndef JSMN_H
35 #define JSMN_H
36 
37 #include <stddef.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 #ifdef JSMN_STATIC
44 #define JSMN_API static
45 #else
46 #define JSMN_API extern
47 #endif
48 
49 //#define JSMN_PARENT_LINKS
57 typedef enum {
59  JSMN_OBJECT = 1 << 0,
60  JSMN_ARRAY = 1 << 1,
61  JSMN_STRING = 1 << 2,
62  JSMN_PRIMITIVE = 1 << 3
63 } jsmntype_t;
64 
65 enum jsmnerr {
66  /* Not enough tokens were provided */
68  /* Invalid character inside JSON string */
70  /* The string is not a full JSON packet, more bytes expected */
72 };
73 
80 typedef struct jsmntok {
82  int start;
83  int end;
84  int size;
85 #ifdef JSMN_PARENT_LINKS
86  int parent;
87 #endif
88 } jsmntok_t;
89 
94 typedef struct jsmn_parser {
95  unsigned int pos; /* offset in the JSON string */
96  unsigned int toknext; /* next token to allocate */
97  int toksuper; /* superior token node, e.g. parent object or array */
98 } jsmn_parser;
99 
103 JSMN_API void jsmn_init(jsmn_parser *parser);
104 
110 JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
111  jsmntok_t *tokens, const unsigned int num_tokens);
112 
113 #ifndef JSMN_HEADER
114 
118  const size_t num_tokens) {
119  jsmntok_t *tok;
120  if (parser->toknext >= num_tokens) {
121  return NULL;
122  }
123  tok = &tokens[parser->toknext++];
124  tok->start = tok->end = -1;
125  tok->size = 0;
126 #ifdef JSMN_PARENT_LINKS
127  tok->parent = -1;
128 #endif
129  return tok;
130 }
131 
135 static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
136  const int start, const int end) {
137  token->type = type;
138  token->start = start;
139  token->end = end;
140  token->size = 0;
141 }
142 
146 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
147  const size_t len, jsmntok_t *tokens,
148  const size_t num_tokens) {
149  jsmntok_t *token;
150  int start;
151 
152  start = parser->pos;
153 
154  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
155  switch (js[parser->pos]) {
156 #ifndef JSMN_STRICT
157  /* In strict mode primitive must be followed by "," or "}" or "]" */
158  case ':':
159 #endif
160  case '\t':
161  case '\r':
162  case '\n':
163  case ' ':
164  case ',':
165  case ']':
166  case '}':
167  goto found;
168  default:
169  /* to quiet a warning from gcc*/
170  break;
171  }
172  if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
173  parser->pos = start;
174  return JSMN_ERROR_INVAL;
175  }
176  }
177 #ifdef JSMN_STRICT
178  /* In strict mode primitive must be followed by a comma/object/array */
179  parser->pos = start;
180  return JSMN_ERROR_PART;
181 #endif
182 
183 found:
184  if (tokens == NULL) {
185  parser->pos--;
186  return 0;
187  }
188  token = jsmn_alloc_token(parser, tokens, num_tokens);
189  if (token == NULL) {
190  parser->pos = start;
191  return JSMN_ERROR_NOMEM;
192  }
193  jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
194 #ifdef JSMN_PARENT_LINKS
195  token->parent = parser->toksuper;
196 #endif
197  parser->pos--;
198  return 0;
199 }
200 
204 static int jsmn_parse_string(jsmn_parser *parser, const char *js,
205  const size_t len, jsmntok_t *tokens,
206  const size_t num_tokens) {
207  jsmntok_t *token;
208 
209  int start = parser->pos;
210 
211  /* Skip starting quote */
212  parser->pos++;
213 
214  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
215  char c = js[parser->pos];
216 
217  /* Quote: end of string */
218  if (c == '\"') {
219  if (tokens == NULL) {
220  return 0;
221  }
222  token = jsmn_alloc_token(parser, tokens, num_tokens);
223  if (token == NULL) {
224  parser->pos = start;
225  return JSMN_ERROR_NOMEM;
226  }
227  jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
228 #ifdef JSMN_PARENT_LINKS
229  token->parent = parser->toksuper;
230 #endif
231  return 0;
232  }
233 
234  /* Backslash: Quoted symbol expected */
235  if (c == '\\' && parser->pos + 1 < len) {
236  int i;
237  parser->pos++;
238  switch (js[parser->pos]) {
239  /* Allowed escaped symbols */
240  case '\"':
241  case '/':
242  case '\\':
243  case 'b':
244  case 'f':
245  case 'r':
246  case 'n':
247  case 't':
248  break;
249  /* Allows escaped symbol \uXXXX */
250  case 'u':
251  parser->pos++;
252  for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
253  i++) {
254  /* If it isn't a hex character we have an error */
255  if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
256  (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
257  (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
258  parser->pos = start;
259  return JSMN_ERROR_INVAL;
260  }
261  parser->pos++;
262  }
263  parser->pos--;
264  break;
265  /* Unexpected symbol */
266  default:
267  parser->pos = start;
268  return JSMN_ERROR_INVAL;
269  }
270  }
271  }
272  parser->pos = start;
273  return JSMN_ERROR_PART;
274 }
275 
279 JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
280  jsmntok_t *tokens, const unsigned int num_tokens) {
281  int r;
282  int i;
283  jsmntok_t *token;
284  int count = parser->toknext;
285 
286  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
287  char c;
288  jsmntype_t type;
289 
290  c = js[parser->pos];
291  switch (c) {
292  case '{':
293  case '[':
294  count++;
295  if (tokens == NULL) {
296  break;
297  }
298  token = jsmn_alloc_token(parser, tokens, num_tokens);
299  if (token == NULL) {
300  return JSMN_ERROR_NOMEM;
301  }
302  if (parser->toksuper != -1) {
303  jsmntok_t *t = &tokens[parser->toksuper];
304 #ifdef JSMN_STRICT
305  /* In strict mode an object or array can't become a key */
306  if (t->type == JSMN_OBJECT) {
307  return JSMN_ERROR_INVAL;
308  }
309 #endif
310  t->size++;
311 #ifdef JSMN_PARENT_LINKS
312  token->parent = parser->toksuper;
313 #endif
314  }
315  token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
316  token->start = parser->pos;
317  parser->toksuper = parser->toknext - 1;
318  break;
319  case '}':
320  case ']':
321  if (tokens == NULL) {
322  break;
323  }
324  type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
325 #ifdef JSMN_PARENT_LINKS
326  if (parser->toknext < 1) {
327  return JSMN_ERROR_INVAL;
328  }
329  token = &tokens[parser->toknext - 1];
330  for (;;) {
331  if (token->start != -1 && token->end == -1) {
332  if (token->type != type) {
333  return JSMN_ERROR_INVAL;
334  }
335  token->end = parser->pos + 1;
336  parser->toksuper = token->parent;
337  break;
338  }
339  if (token->parent == -1) {
340  if (token->type != type || parser->toksuper == -1) {
341  return JSMN_ERROR_INVAL;
342  }
343  break;
344  }
345  token = &tokens[token->parent];
346  }
347 #else
348  for (i = parser->toknext - 1; i >= 0; i--) {
349  token = &tokens[i];
350  if (token->start != -1 && token->end == -1) {
351  if (token->type != type) {
352  return JSMN_ERROR_INVAL;
353  }
354  parser->toksuper = -1;
355  token->end = parser->pos + 1;
356  break;
357  }
358  }
359  /* Error if unmatched closing bracket */
360  if (i == -1) {
361  return JSMN_ERROR_INVAL;
362  }
363  for (; i >= 0; i--) {
364  token = &tokens[i];
365  if (token->start != -1 && token->end == -1) {
366  parser->toksuper = i;
367  break;
368  }
369  }
370 #endif
371  break;
372  case '\"':
373  r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
374  if (r < 0) {
375  return r;
376  }
377  count++;
378  if (parser->toksuper != -1 && tokens != NULL) {
379  tokens[parser->toksuper].size++;
380  }
381  break;
382  case '\t':
383  case '\r':
384  case '\n':
385  case ' ':
386  break;
387  case ':':
388  parser->toksuper = parser->toknext - 1;
389  break;
390  case ',':
391  if (tokens != NULL && parser->toksuper != -1 &&
392  tokens[parser->toksuper].type != JSMN_ARRAY &&
393  tokens[parser->toksuper].type != JSMN_OBJECT) {
394 #ifdef JSMN_PARENT_LINKS
395  parser->toksuper = tokens[parser->toksuper].parent;
396 #else
397  for (i = parser->toknext - 1; i >= 0; i--) {
398  if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
399  if (tokens[i].start != -1 && tokens[i].end == -1) {
400  parser->toksuper = i;
401  break;
402  }
403  }
404  }
405 #endif
406  }
407  break;
408 #ifdef JSMN_STRICT
409  /* In strict mode primitives are: numbers and booleans */
410  case '-':
411  case '0':
412  case '1':
413  case '2':
414  case '3':
415  case '4':
416  case '5':
417  case '6':
418  case '7':
419  case '8':
420  case '9':
421  case 't':
422  case 'f':
423  case 'n':
424  /* And they must not be keys of the object */
425  if (tokens != NULL && parser->toksuper != -1) {
426  const jsmntok_t *t = &tokens[parser->toksuper];
427  if (t->type == JSMN_OBJECT ||
428  (t->type == JSMN_STRING && t->size != 0)) {
429  return JSMN_ERROR_INVAL;
430  }
431  }
432 #else
433  /* In non-strict mode every unquoted value is a primitive */
434  default:
435 #endif
436  r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
437  if (r < 0) {
438  return r;
439  }
440  count++;
441  if (parser->toksuper != -1 && tokens != NULL) {
442  tokens[parser->toksuper].size++;
443  }
444  break;
445 
446 #ifdef JSMN_STRICT
447  /* Unexpected char in strict mode */
448  default:
449  return JSMN_ERROR_INVAL;
450 #endif
451  }
452  }
453 
454  if (tokens != NULL) {
455  for (i = parser->toknext - 1; i >= 0; i--) {
456  /* Unmatched opened object or array */
457  if (tokens[i].start != -1 && tokens[i].end == -1) {
458  return JSMN_ERROR_PART;
459  }
460  }
461  }
462 
463  return count;
464 }
465 
471  parser->pos = 0;
472  parser->toknext = 0;
473  parser->toksuper = -1;
474 }
475 
476 #endif /* JSMN_HEADER */
477 
478 #ifdef __cplusplus
479 }
480 #endif
481 
482 #endif /* JSMN_H */
Definition: jsmn.h:80
jsmntype_t
Definition: jsmn.h:57
Definition: jsmn.h:58
unsigned int toknext
Definition: jsmn.h:96
Definition: jsmn.h:61
JSMN_API void jsmn_init(jsmn_parser *parser)
Definition: jsmn.h:470
Definition: jsmn.h:67
static int jsmn_parse_string(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const size_t num_tokens)
Definition: jsmn.h:204
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const size_t num_tokens)
Definition: jsmn.h:146
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const unsigned int num_tokens)
Definition: jsmn.h:279
Definition: jsmn.h:59
jsmntype_t type
Definition: jsmn.h:81
Definition: jsmn.h:94
Definition: jsmn.h:62
int toksuper
Definition: jsmn.h:97
int start
Definition: jsmn.h:82
Definition: jsmn.h:69
Definition: jsmn.h:71
Definition: jsmn.h:60
int end
Definition: jsmn.h:83
static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, const int start, const int end)
Definition: jsmn.h:135
#define JSMN_API
Definition: jsmn.h:46
static jsmntok_t * jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, const size_t num_tokens)
Definition: jsmn.h:117
int size
Definition: jsmn.h:84
unsigned int pos
Definition: jsmn.h:95
jsmnerr
Definition: jsmn.h:65