* Parse JSON string and fill tokens. */
| 267 | * Parse JSON string and fill tokens. |
| 268 | */ |
| 269 | JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, |
| 270 | jsmntok_t *tokens, const unsigned int num_tokens) { |
| 271 | int r; |
| 272 | int i; |
| 273 | jsmntok_t *token; |
| 274 | int count = parser->toknext; |
| 275 | |
| 276 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
| 277 | char c; |
| 278 | jsmntype_t type; |
| 279 | |
| 280 | c = js[parser->pos]; |
| 281 | switch (c) { |
| 282 | case '{': |
| 283 | case '[': |
| 284 | count++; |
| 285 | if (tokens == NULL) { |
| 286 | break; |
| 287 | } |
| 288 | token = jsmn_alloc_token(parser, tokens, num_tokens); |
| 289 | if (token == NULL) { |
| 290 | return JSMN_ERROR_NOMEM; |
| 291 | } |
| 292 | if (parser->toksuper != -1) { |
| 293 | jsmntok_t *t = &tokens[parser->toksuper]; |
| 294 | #ifdef JSMN_STRICT |
| 295 | /* In strict mode an object or array can't become a key */ |
| 296 | if (t->type == JSMN_OBJECT) { |
| 297 | return JSMN_ERROR_INVAL; |
| 298 | } |
| 299 | #endif |
| 300 | t->size++; |
| 301 | #ifdef JSMN_PARENT_LINKS |
| 302 | token->parent = parser->toksuper; |
| 303 | #endif |
| 304 | } |
| 305 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); |
| 306 | token->start = parser->pos; |
| 307 | parser->toksuper = parser->toknext - 1; |
| 308 | break; |
| 309 | case '}': |
| 310 | case ']': |
| 311 | if (tokens == NULL) { |
| 312 | break; |
| 313 | } |
| 314 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); |
| 315 | #ifdef JSMN_PARENT_LINKS |
| 316 | if (parser->toknext < 1) { |
| 317 | return JSMN_ERROR_INVAL; |
| 318 | } |
| 319 | token = &tokens[parser->toknext - 1]; |
| 320 | for (;;) { |
| 321 | if (token->start != -1 && token->end == -1) { |
| 322 | if (token->type != type) { |
| 323 | return JSMN_ERROR_INVAL; |
| 324 | } |
| 325 | token->end = parser->pos + 1; |
| 326 | parser->toksuper = token->parent; |
no test coverage detected