CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
jsmn.cpp
Go to the documentation of this file.
1
4#include "jsmn.h"
5
6using namespace cmlabs;
7
12 jsmntok_t *tokens, size_t num_tokens) {
13 jsmntok_t *tok;
14 if (parser->toknext >= num_tokens) {
15 return NULL;
16 }
17 tok = &tokens[parser->toknext++];
18 tok->start = tok->end = -1;
19 tok->size = 0;
20#ifdef JSMN_PARENT_LINKS
21 tok->parent = -1;
22#endif
23 return tok;
24}
25
29static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
30 int start, int end) {
31 token->type = type;
32 token->start = start;
33 token->end = end;
34 token->size = 0;
35}
36
40static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
41 size_t len, jsmntok_t *tokens, size_t num_tokens) {
42 jsmntok_t *token;
43 int start;
44
45 start = parser->pos;
46
47 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
48 switch (js[parser->pos]) {
49#ifndef JSMN_STRICT
50 /* In strict mode primitive must be followed by "," or "}" or "]" */
51 case ':':
52#endif
53 case '\t' : case '\r' : case '\n' : case ' ' :
54 case ',' : case ']' : case '}' :
55 goto found;
56 }
57 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
58 parser->pos = start;
59 return JSMN_ERROR_INVAL;
60 }
61 }
62#ifdef JSMN_STRICT
63 /* In strict mode primitive must be followed by a comma/object/array */
64 parser->pos = start;
65 return JSMN_ERROR_PART;
66#endif
67
68found:
69 if (tokens == NULL) {
70 parser->pos--;
71 return 0;
72 }
73 token = jsmn_alloc_token(parser, tokens, num_tokens);
74 if (token == NULL) {
75 parser->pos = start;
76 return JSMN_ERROR_NOMEM;
77 }
78 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
79#ifdef JSMN_PARENT_LINKS
80 token->parent = parser->toksuper;
81#endif
82 parser->pos--;
83 return 0;
84}
85
89static int jsmn_parse_string(jsmn_parser *parser, const char *js,
90 size_t len, jsmntok_t *tokens, size_t num_tokens) {
91 jsmntok_t *token;
92
93 int start = parser->pos;
94
95 parser->pos++;
96
97 /* Skip starting quote */
98 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
99 char c = js[parser->pos];
100
101 /* Quote: end of string */
102 if (c == '\"') {
103 if (tokens == NULL) {
104 return 0;
105 }
106 token = jsmn_alloc_token(parser, tokens, num_tokens);
107 if (token == NULL) {
108 parser->pos = start;
109 return JSMN_ERROR_NOMEM;
110 }
111 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
112#ifdef JSMN_PARENT_LINKS
113 token->parent = parser->toksuper;
114#endif
115 return 0;
116 }
117
118 /* Backslash: Quoted symbol expected */
119 if (c == '\\' && parser->pos + 1 < len) {
120 int i;
121 parser->pos++;
122 switch (js[parser->pos]) {
123 /* Allowed escaped symbols */
124 case '\"': case '/' : case '\\' : case 'b' :
125 case 'f' : case 'r' : case 'n' : case 't' :
126 break;
127 /* Allows escaped symbol \uXXXX */
128 case 'u':
129 parser->pos++;
130 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
131 /* If it isn't a hex character we have an error */
132 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
133 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
134 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
135 parser->pos = start;
136 return JSMN_ERROR_INVAL;
137 }
138 parser->pos++;
139 }
140 parser->pos--;
141 break;
142 /* Unexpected symbol */
143 default:
144 parser->pos = start;
145 return JSMN_ERROR_INVAL;
146 }
147 }
148 }
149 parser->pos = start;
150 return JSMN_ERROR_PART;
151}
152
156int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
157 jsmntok_t *tokens, unsigned int num_tokens) {
158 int r;
159 int i;
160 jsmntok_t *token;
161 int count = parser->toknext;
162
163 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
164 char c;
165 jsmntype_t type;
166
167 c = js[parser->pos];
168 switch (c) {
169 case '{': case '[':
170 count++;
171 if (tokens == NULL) {
172 break;
173 }
174 token = jsmn_alloc_token(parser, tokens, num_tokens);
175 if (token == NULL)
176 return JSMN_ERROR_NOMEM;
177 if (parser->toksuper != -1) {
178 tokens[parser->toksuper].size++;
179#ifdef JSMN_PARENT_LINKS
180 token->parent = parser->toksuper;
181#endif
182 }
183 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
184 token->start = parser->pos;
185 parser->toksuper = parser->toknext - 1;
186 break;
187 case '}': case ']':
188 if (tokens == NULL)
189 break;
190 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
191#ifdef JSMN_PARENT_LINKS
192 if (parser->toknext < 1) {
193 return JSMN_ERROR_INVAL;
194 }
195 token = &tokens[parser->toknext - 1];
196 for (;;) {
197 if (token->start != -1 && token->end == -1) {
198 if (token->type != type) {
199 return JSMN_ERROR_INVAL;
200 }
201 token->end = parser->pos + 1;
202 parser->toksuper = token->parent;
203 break;
204 }
205 if (token->parent == -1) {
206 break;
207 }
208 token = &tokens[token->parent];
209 }
210#else
211 for (i = parser->toknext - 1; i >= 0; i--) {
212 token = &tokens[i];
213 if (token->start != -1 && token->end == -1) {
214 if (token->type != type) {
215 return JSMN_ERROR_INVAL;
216 }
217 parser->toksuper = -1;
218 token->end = parser->pos + 1;
219 break;
220 }
221 }
222 /* Error if unmatched closing bracket */
223 if (i == -1) return JSMN_ERROR_INVAL;
224 for (; i >= 0; i--) {
225 token = &tokens[i];
226 if (token->start != -1 && token->end == -1) {
227 parser->toksuper = i;
228 break;
229 }
230 }
231#endif
232 break;
233 case '\"':
234 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
235 if (r < 0) return r;
236 count++;
237 if (parser->toksuper != -1 && tokens != NULL)
238 tokens[parser->toksuper].size++;
239 break;
240 case '\t' : case '\r' : case '\n' : case ' ':
241 break;
242 case ':':
243 parser->toksuper = parser->toknext - 1;
244 break;
245 case ',':
246 if (tokens != NULL && parser->toksuper != -1 &&
247 tokens[parser->toksuper].type != JSMN_ARRAY &&
248 tokens[parser->toksuper].type != JSMN_OBJECT) {
249#ifdef JSMN_PARENT_LINKS
250 parser->toksuper = tokens[parser->toksuper].parent;
251#else
252 for (i = parser->toknext - 1; i >= 0; i--) {
253 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
254 if (tokens[i].start != -1 && tokens[i].end == -1) {
255 parser->toksuper = i;
256 break;
257 }
258 }
259 }
260#endif
261 }
262 break;
263#ifdef JSMN_STRICT
264 /* In strict mode primitives are: numbers and booleans */
265 case '-': case '0': case '1' : case '2': case '3' : case '4':
266 case '5': case '6': case '7' : case '8': case '9':
267 case 't': case 'f': case 'n' :
268 /* And they must not be keys of the object */
269 if (tokens != NULL && parser->toksuper != -1) {
270 jsmntok_t *t = &tokens[parser->toksuper];
271 if (t->type == JSMN_OBJECT ||
272 (t->type == JSMN_STRING && t->size != 0)) {
273 return JSMN_ERROR_INVAL;
274 }
275 }
276#else
277 /* In non-strict mode every unquoted value is a primitive */
278 default:
279#endif
280 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
281 if (r < 0) return r;
282 count++;
283 if (parser->toksuper != -1 && tokens != NULL)
284 tokens[parser->toksuper].size++;
285 break;
286
287#ifdef JSMN_STRICT
288 /* Unexpected char in strict mode */
289 default:
290 return JSMN_ERROR_INVAL;
291#endif
292 }
293 }
294
295 if (tokens != NULL) {
296 for (i = parser->toknext - 1; i >= 0; i--) {
297 /* Unmatched opened object or array */
298 if (tokens[i].start != -1 && tokens[i].end == -1) {
299 return JSMN_ERROR_PART;
300 }
301 }
302 }
303
304 return count;
305}
306
311void jsmn_init(jsmn_parser *parser) {
312 parser->pos = 0;
313 parser->toknext = 0;
314 parser->toksuper = -1;
315}
316
317int GetJSONTokenLevel(jsmntok_t *tokens, int startToken) {
318 if (!tokens || startToken < 0) return 0;
319 int level = 1;
320 int n = startToken;
321 while (tokens[n].parent >= 0) {
322 n = tokens[n].parent;
323 level++;
324 }
325 return level;
326}
327
328int GetJSONToken(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
329 if (!tokens || !tokenCount || !key) return -1;
330
331 int inst = 0;
332 int keyLen = (int)strlen(key);
333 if (!keyLen) return -1;
334
335 for (int n = 0; n<tokenCount - 1; n++) {
336 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
337 if (parent != tokens[n].parent)
338 continue;
339 if (keyLen == tokens[n].end - tokens[n].start && strncmp(json + tokens[n].start, key, keyLen) == 0) {
340 return n+1;
341 }
342 }
343 }
344 return -1;
345}
346
347const char* GetJSONValue(jsmntok_t* tokens, int tokenCount, const char* json, int token, int &valLength) {
348 valLength = 0;
349 if (!tokens || !tokenCount || (token < 0) || (token >= tokenCount)) return NULL;
350 valLength = tokens[token].end - tokens[token].start;
351 return json + tokens[token].start;
352}
353
354std::string GetJSONValueString(jsmntok_t* tokens, int tokenCount, const char* json, int token) {
355 int len = 0;
356 const char* str = GetJSONValue(tokens, tokenCount, json, token, len);
357 if (!str || !len)
358 return "";
359 return std::string(str, len);
360}
361
362int64 GetJSONValueInt64(jsmntok_t* tokens, int tokenCount, const char* json, int token) {
363 return utils::Ascii2Int64(GetJSONValueString(tokens, tokenCount, json, token).c_str());
364}
365
366uint64 GetJSONValueUint64(jsmntok_t* tokens, int tokenCount, const char* json, int token) {
367 return utils::Ascii2Uint64(GetJSONValueString(tokens, tokenCount, json, token).c_str());
368}
369
370float64 GetJSONValueFloat64(jsmntok_t* tokens, int tokenCount, const char* json, int token) {
371 return utils::Ascii2Float64(GetJSONValueString(tokens, tokenCount, json, token).c_str());
372}
373
374
375const char* GetJSONValue(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int &valLength, int level, int instance) {
376 valLength = 0;
377 if (!tokens || !tokenCount || !key) return NULL;
378
379 int inst = 0;
380 int keyLen = (int) strlen(key);
381 if (!keyLen) return NULL;
382
383 for (int n=0; n<tokenCount-1; n++) {
384 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
385 if (keyLen == tokens[n].end - tokens[n].start && strncmp(json + tokens[n].start, key, keyLen) == 0) {
386 if (level && GetJSONTokenLevel(tokens, n) != level)
387 continue;
388 if (instance && (++inst) != instance)
389 continue;
390 valLength = tokens[n+1].end - tokens[n+1].start;
391 return json + tokens[n+1].start;
392 }
393 }
394 }
395 return NULL;
396}
397
398const char* GetJSONChildValue(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type, int &valLength) {
399 valLength = 0;
400 if (!tokens || !tokenCount || !key) return NULL;
401
402 int inst = 0;
403 int keyLen = (int)strlen(key);
404 if (!keyLen) return NULL;
405
406 for (int n = 0; n<tokenCount - 1; n++) {
407 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
408 if (parent != tokens[n].parent)
409 continue;
410 if (keyLen == tokens[n].end - tokens[n].start && strncmp(json + tokens[n].start, key, keyLen) == 0) {
411 valLength = tokens[n + 1].end - tokens[n + 1].start;
412 return json + tokens[n + 1].start;
413 }
414 }
415 }
416 return NULL;
417}
418
419
420std::string GetJSONValueString(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int level, int instance) {
421 int len = 0;
422 const char* str = GetJSONValue(tokens, tokenCount, json, key, type, len, level, instance);
423 if (!str || !len)
424 return "";
425 return std::string(str, len);
426}
427
428int64 GetJSONValueInt64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int level, int instance) {
429 return utils::Ascii2Int64(GetJSONValueString(tokens, tokenCount, json, key, type, level, instance).c_str());
430}
431
432uint64 GetJSONValueUint64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int level, int instance) {
433 return utils::Ascii2Uint64(GetJSONValueString(tokens, tokenCount, json, key, type, level, instance).c_str());
434}
435
436float64 GetJSONValueFloat64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int level, int instance) {
437 return utils::Ascii2Float64(GetJSONValueString(tokens, tokenCount, json, key, type, level, instance).c_str());
438}
439
440
441std::string GetJSONChildValueString(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
442 int len = 0;
443 const char* str = GetJSONChildValue(tokens, tokenCount, json, key, parent, type, len);
444 if (!str || !len)
445 return "";
446 return std::string(str, len);
447}
448
449int64 GetJSONChildValueInt64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
450 return utils::Ascii2Int64(GetJSONChildValueString(tokens, tokenCount, json, key, parent, type).c_str());
451}
452
453uint64 GetJSONChildValueUint64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
454 return utils::Ascii2Uint64(GetJSONChildValueString(tokens, tokenCount, json, key, parent, type).c_str());
455}
456
457float64 GetJSONChildValueFloat64(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
458 return utils::Ascii2Float64(GetJSONChildValueString(tokens, tokenCount, json, key, parent, type).c_str());
459}
460
461
462
463
464std::vector<int> GetJSONArrayIndexes(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, jsmntype_t type, int level, int instance) {
465 std::vector<int> indexes;
466
467 if (!tokens || !tokenCount || !key) return indexes;
468
469 int inst = 0;
470 int keyLen = (int) strlen(key);
471 if (!keyLen) return indexes;
472
473 for (int n=0; n<tokenCount-1; n++) {
474 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
475 if (keyLen == tokens[n].end - tokens[n].start && strncmp(json + tokens[n].start, key, keyLen) == 0) {
476 if (level && GetJSONTokenLevel(tokens, n) != level)
477 continue;
478 if (instance && (++inst) != instance)
479 continue;
480 // We now need to find all nodes who's parent is n+1
481 for (int m=n+2; m<tokenCount-1; m++) {
482 if (tokens[m].parent == n+1)
483 indexes.push_back(m);
484 }
485 return indexes;
486 }
487 }
488 }
489 return indexes;
490}
491
492std::vector<int> GetJSONChildArrayIndexes(jsmntok_t* tokens, int tokenCount, const char* json, const char* key, int parent, jsmntype_t type) {
493 std::vector<int> indexes;
494
495 if (!tokens || !tokenCount || !key) return indexes;
496
497 int inst = 0;
498 int keyLen = (int)strlen(key);
499 if (!keyLen) return indexes;
500
501 for (int n = 0; n<tokenCount - 1; n++) {
502 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
503 if (parent != tokens[n].parent)
504 continue;
505 if (keyLen == tokens[n].end - tokens[n].start && strncmp(json + tokens[n].start, key, keyLen) == 0) {
506 // We now need to find all nodes who's parent is n+1
507 for (int m = n + 2; m<tokenCount - 1; m++) {
508 if (tokens[m].parent == n + 1)
509 indexes.push_back(m);
510 }
511 return indexes;
512 }
513 }
514 }
515 return indexes;
516}
517
518
519std::vector<int> GetJSONChildArrayIndexes(jsmntok_t* tokens, int tokenCount, const char* json, int parent, jsmntype_t type) {
520 std::vector<int> indexes;
521
522 if (!tokens || !tokenCount) return indexes;
523
524 if ((parent < 0) || (parent >= tokenCount)) return indexes;
525
526 int inst = 0;
527
528 for (int n = 0; n<tokenCount - 1; n++) {
529 if (type == JSMN_UNDEFINED || tokens[n].type == type) {
530 if (parent == tokens[n].parent+1) {
531 indexes.push_back(n);
532 }
533 }
534 }
535 return indexes;
536}
537
538
539std::string AddToJSONRoot(const char* json, const char* subJSON) {
540 if (!json || !strlen(json))
541 return utils::StringFormat("{%s}", subJSON);
542
543 // just add at the end
544 const char* lastBracket = utils::laststrstr(json, "}");
545 if (!lastBracket)
546 return "";
547
548 std::string fullJSON = json;
549 return utils::StringFormat("%s,%s}", fullJSON.substr(0, lastBracket - json).c_str(), subJSON);
550}
const char * laststrstr(const char *str1, const char *str2)
Find the last occurrence of str2 in str1.
Definition Utils.cpp:7183
std::string StringFormat(const char *format,...)
printf into a std::string.
Definition Utils.cpp:6626
uint64 Ascii2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit decimal integer from a substring.
Definition Utils.cpp:7480
int64 Ascii2Int64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 64-bit decimal integer from a substring.
Definition Utils.cpp:7462
float64 Ascii2Float64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a 64-bit float from a substring (decimal point, not locale dependent).
Definition Utils.cpp:7546
const char * GetJSONValue(jsmntok_t *tokens, int tokenCount, const char *json, int token, int &valLength)
Definition jsmn.cpp:347
std::vector< int > GetJSONChildArrayIndexes(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:492
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, int start, int end)
Fills token type and boundaries.
Definition jsmn.cpp:29
const char * GetJSONChildValue(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type, int &valLength)
Definition jsmn.cpp:398
int GetJSONToken(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:328
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens)
Fills next available token with JSON primitive.
Definition jsmn.cpp:40
static jsmntok_t * jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, size_t num_tokens)
Allocates a fresh unused token from the token pull.
Definition jsmn.cpp:11
std::vector< int > GetJSONArrayIndexes(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, jsmntype_t type, int level, int instance)
Definition jsmn.cpp:464
static int jsmn_parse_string(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens)
Filsl next token with JSON string.
Definition jsmn.cpp:89
std::string GetJSONValueString(jsmntok_t *tokens, int tokenCount, const char *json, int token)
Definition jsmn.cpp:354
std::string GetJSONChildValueString(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:441
int GetJSONTokenLevel(jsmntok_t *tokens, int startToken)
Definition jsmn.cpp:317
uint64 GetJSONValueUint64(jsmntok_t *tokens, int tokenCount, const char *json, int token)
Definition jsmn.cpp:366
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, unsigned int num_tokens)
Parse JSON string and fill tokens.
Definition jsmn.cpp:156
void jsmn_init(jsmn_parser *parser)
Creates a new parser based over a given buffer with an array of tokens available.
Definition jsmn.cpp:311
float64 GetJSONChildValueFloat64(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:457
int64 GetJSONChildValueInt64(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:449
std::string AddToJSONRoot(const char *json, const char *subJSON)
Definition jsmn.cpp:539
uint64 GetJSONChildValueUint64(jsmntok_t *tokens, int tokenCount, const char *json, const char *key, int parent, jsmntype_t type)
Definition jsmn.cpp:453
int64 GetJSONValueInt64(jsmntok_t *tokens, int tokenCount, const char *json, int token)
Definition jsmn.cpp:362
float64 GetJSONValueFloat64(jsmntok_t *tokens, int tokenCount, const char *json, int token)
Definition jsmn.cpp:370
Third-party (vendored): jsmn minimalistic JSON tokenizer by Serge Zaitsev (MIT licence),...
jsmntype_t
JSON type identifier.
Definition jsmn.h:28
@ JSMN_PRIMITIVE
Definition jsmn.h:33
@ JSMN_OBJECT
Definition jsmn.h:30
@ JSMN_UNDEFINED
Definition jsmn.h:29
@ JSMN_ARRAY
Definition jsmn.h:31
@ JSMN_STRING
Definition jsmn.h:32
@ JSMN_ERROR_INVAL
Definition jsmn.h:40
@ JSMN_ERROR_PART
Definition jsmn.h:42
@ JSMN_ERROR_NOMEM
Definition jsmn.h:38
JSON parser.
Definition jsmn.h:65
unsigned int pos
Definition jsmn.h:66
int toksuper
Definition jsmn.h:68
unsigned int toknext
Definition jsmn.h:67
JSON token description.
Definition jsmn.h:51
int start
Definition jsmn.h:53
int parent
Definition jsmn.h:57
int size
Definition jsmn.h:55
int end
Definition jsmn.h:54
jsmntype_t type
Definition jsmn.h:52