Parse inline properties: {key: "value", ...} */
| 474 | |
| 475 | /* Parse inline properties: {key: "value", ...} */ |
| 476 | static int parse_props(parser_t *p, cbm_prop_filter_t **out, int *count) { |
| 477 | *out = NULL; |
| 478 | *count = 0; |
| 479 | if (!match(p, TOK_LBRACE)) { |
| 480 | return 0; |
| 481 | } |
| 482 | |
| 483 | int cap = CYP_INIT_CAP4; |
| 484 | int n = 0; |
| 485 | cbm_prop_filter_t *arr = malloc(cap * sizeof(cbm_prop_filter_t)); |
| 486 | if (!arr) { |
| 487 | return CBM_NOT_FOUND; |
| 488 | } |
| 489 | |
| 490 | while (!check(p, TOK_RBRACE) && !check(p, TOK_EOF)) { |
| 491 | const cbm_token_t *key = expect(p, TOK_IDENT); |
| 492 | if (!key) { |
| 493 | free(arr); |
| 494 | return CBM_NOT_FOUND; |
| 495 | } |
| 496 | if (!expect(p, TOK_COLON)) { |
| 497 | free(arr); |
| 498 | return CBM_NOT_FOUND; |
| 499 | } |
| 500 | const cbm_token_t *val = expect(p, TOK_STRING); |
| 501 | if (!val) { |
| 502 | free(arr); |
| 503 | return CBM_NOT_FOUND; |
| 504 | } |
| 505 | |
| 506 | if (n >= cap) { |
| 507 | int new_cap = cap * PAIR_LEN; |
| 508 | void *tmp = realloc(arr, new_cap * sizeof(cbm_prop_filter_t)); |
| 509 | if (!tmp) { |
| 510 | for (int i = 0; i < n; i++) { |
| 511 | safe_str_free(&arr[i].key); |
| 512 | safe_str_free(&arr[i].value); |
| 513 | } |
| 514 | free(arr); |
| 515 | return CBM_NOT_FOUND; |
| 516 | } |
| 517 | arr = tmp; |
| 518 | cap = new_cap; |
| 519 | } |
| 520 | const char *new_key = heap_strdup(key->text); |
| 521 | const char *new_val = heap_strdup(val->text); |
| 522 | if (!new_key || !new_val) { |
| 523 | safe_str_free(&new_key); |
| 524 | safe_str_free(&new_val); |
| 525 | for (int i = 0; i < n; i++) { |
| 526 | safe_str_free(&arr[i].key); |
| 527 | safe_str_free(&arr[i].value); |
| 528 | } |
| 529 | free(arr); |
| 530 | return CBM_NOT_FOUND; |
| 531 | } |
| 532 | arr[n].key = new_key; |
| 533 | arr[n].value = new_val; |
no test coverage detected