Helper for jsonml_parse. */
| 630 | |
| 631 | /* Helper for jsonml_parse. */ |
| 632 | static Node jsonml_element(jsmntok_t **tok, Graph g) |
| 633 | { |
| 634 | static unsigned node_id = 0; |
| 635 | jsmntok_t *token = *tok; |
| 636 | /* Every element corresponds to a (fresh) tree node. */ |
| 637 | Node node = node_create(); |
| 638 | /* Misuse visited as node id: */ |
| 639 | node->visited = node_id++; |
| 640 | node_add(g, node); |
| 641 | /* Input must be a non-empty array or scalar: */ |
| 642 | if (token->type == JSMN_ARRAY) { |
| 643 | int elems = token->size; |
| 644 | token++; /* skip the [ */ |
| 645 | /* elem 0: string, XML element tag: */ |
| 646 | expect(token, JSMN_STRING); |
| 647 | node->label = token; |
| 648 | token++; elems--; |
| 649 | /* Mind: can have singleton arrays (caused by self-closed XML element) */ |
| 650 | |
| 651 | /* elem 1: optional object, XML element attributes */ |
| 652 | if (elems && token->type == JSMN_OBJECT) { |
| 653 | token = jsonml_attributes(token, node); |
| 654 | elems--; |
| 655 | } |
| 656 | /* Optional array (nested elements) or scalar (text nodes) */ |
| 657 | while (elems--) { |
| 658 | /* All children of this node. */ |
| 659 | Edge edge = edge_create(); |
| 660 | adj_edge_add(node, edge, jsonml_element(&token, g)); |
| 661 | edge_add(g, edge); // graph edges not really used. |
| 662 | } |
| 663 | } |
| 664 | else { |
| 665 | expect_scalar(token); |
| 666 | node->label = token; |
| 667 | /* Misuse line to indicate this is a token (and not just any leaf). */ |
| 668 | node->line = 1; |
| 669 | token++; |
| 670 | } |
| 671 | *tok = token; |
| 672 | return node; |
| 673 | } |
| 674 | |
| 675 | /* Parse an explicit JSON tree structure consisting of nested arrays and |
| 676 | scalars elements and optional objects for attributes, the result of |
no test coverage detected