diff --git a/src/loader.c b/src/loader.c index 248af9405bb3eb259e1c2fcca7f8bc3d34f8a89d_c3JjL2xvYWRlci5j..191d64170c09bdf62aca6e65db3916ea01da644e_c3JjL2xvYWRlci5j 100644 --- a/src/loader.c +++ b/src/loader.c @@ -38,5 +38,14 @@ yaml_parser_delete_aliases(yaml_parser_t *parser); /* + * Document loading context. + */ +struct loader_ctx { + int *start; + int *end; + int *top; +}; + +/* * Composer functions. */ @@ -41,4 +50,6 @@ * Composer functions. */ +static int +yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx); static int @@ -43,8 +54,5 @@ static int -yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event); - -static int -yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event); static int @@ -49,5 +57,10 @@ static int -yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); + +static int +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int @@ -52,5 +65,6 @@ static int -yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int @@ -55,5 +69,6 @@ static int -yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int @@ -58,6 +73,11 @@ static int -yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); + +static int +yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); /* * Load the next document of the stream. @@ -162,5 +182,5 @@ */ static int -yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event) { @@ -166,3 +186,3 @@ { - yaml_event_t event; + struct loader_ctx ctx = { NULL, NULL, NULL }; @@ -168,5 +188,5 @@ - assert(first_event->type == YAML_DOCUMENT_START_EVENT); + assert(event->type == YAML_DOCUMENT_START_EVENT); /* DOCUMENT-START is expected. */ parser->document->version_directive @@ -170,5 +190,5 @@ /* DOCUMENT-START is expected. */ parser->document->version_directive - = first_event->data.document_start.version_directive; + = event->data.document_start.version_directive; parser->document->tag_directives.start @@ -174,3 +194,3 @@ parser->document->tag_directives.start - = first_event->data.document_start.tag_directives.start; + = event->data.document_start.tag_directives.start; parser->document->tag_directives.end @@ -176,3 +196,3 @@ parser->document->tag_directives.end - = first_event->data.document_start.tag_directives.end; + = event->data.document_start.tag_directives.end; parser->document->start_implicit @@ -178,4 +198,11 @@ parser->document->start_implicit - = first_event->data.document_start.implicit; - parser->document->start_mark = first_event->start_mark; + = event->data.document_start.implicit; + parser->document->start_mark = event->start_mark; + + if (!STACK_INIT(parser, ctx, int*)) return 0; + if (!yaml_parser_load_nodes(parser, &ctx)) { + STACK_DEL(parser, ctx); + return 0; + } + STACK_DEL(parser, ctx); @@ -181,3 +208,16 @@ - if (!yaml_parser_parse(parser, &event)) return 0; + return 1; +} + +/* + * Compose a node tree. + */ + +static int +yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx) +{ + yaml_event_t event; + + do { + if (!yaml_parser_parse(parser, &event)) return 0; @@ -183,9 +223,32 @@ - if (!yaml_parser_load_node(parser, &event)) return 0; - - if (!yaml_parser_parse(parser, &event)) return 0; - assert(event.type == YAML_DOCUMENT_END_EVENT); - /* DOCUMENT-END is expected. */ + switch (event.type) { + case YAML_ALIAS_EVENT: + if (!yaml_parser_load_alias(parser, &event, ctx)) return 0; + break; + case YAML_SCALAR_EVENT: + if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0; + break; + case YAML_SEQUENCE_START_EVENT: + if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0; + break; + case YAML_SEQUENCE_END_EVENT: + if (!yaml_parser_load_sequence_end(parser, &event, ctx)) + return 0; + break; + case YAML_MAPPING_START_EVENT: + if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0; + break; + case YAML_MAPPING_END_EVENT: + if (!yaml_parser_load_mapping_end(parser, &event, ctx)) + return 0; + break; + default: + assert(0); /* Could not happen. */ + return 0; + case YAML_DOCUMENT_END_EVENT: + break; + } + } while (event.type != YAML_DOCUMENT_END_EVENT); parser->document->end_implicit = event.data.document_end.implicit; parser->document->end_mark = event.end_mark; @@ -194,30 +257,6 @@ } /* - * Compose a node. - */ - -static int -yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event) -{ - switch (first_event->type) { - case YAML_ALIAS_EVENT: - return yaml_parser_load_alias(parser, first_event); - case YAML_SCALAR_EVENT: - return yaml_parser_load_scalar(parser, first_event); - case YAML_SEQUENCE_START_EVENT: - return yaml_parser_load_sequence(parser, first_event); - case YAML_MAPPING_START_EVENT: - return yaml_parser_load_mapping(parser, first_event); - default: - assert(0); /* Could not happen. */ - return 0; - } - - return 0; -} - -/* * Add an anchor. */ @@ -253,7 +292,59 @@ } /* + * Compose node into its parent in the stree. + */ + +static int +yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx, + int index) +{ + struct yaml_node_s *parent; + int parent_index; + + if (STACK_EMPTY(parser, *ctx)) { + /* This is the root node, there's no tree to add it to. */ + return 1; + } + + parent_index = *((*ctx).top - 1); + parent = &parser->document->nodes.start[parent_index-1]; + + switch (parent->type) { + case YAML_SEQUENCE_NODE: + if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1)) + return 0; + if (!PUSH(parser, parent->data.sequence.items, index)) + return 0; + break; + case YAML_MAPPING_NODE: { + yaml_node_pair_t pair; + if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) { + yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1; + if (p->key != 0 && p->value == 0) { + p->value = index; + break; + } + } + + pair.key = index; + pair.value = 0; + if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1)) + return 0; + if (!PUSH(parser, parent->data.mapping.pairs, pair)) + return 0; + + break; + } + default: + assert(0); /* Could not happen. */ + return 0; + } + return 1; +} + +/* * Compose a node corresponding to an alias. */ static int @@ -256,6 +347,7 @@ * Compose a node corresponding to an alias. */ static int -yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { @@ -261,8 +353,8 @@ { - yaml_char_t *anchor = first_event->data.alias.anchor; + yaml_char_t *anchor = event->data.alias.anchor; yaml_alias_data_t *alias_data; for (alias_data = parser->aliases.start; alias_data != parser->aliases.top; alias_data ++) { if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { yaml_free(anchor); @@ -263,12 +355,12 @@ yaml_alias_data_t *alias_data; for (alias_data = parser->aliases.start; alias_data != parser->aliases.top; alias_data ++) { if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { yaml_free(anchor); - return alias_data->index; + return yaml_parser_load_node_add(parser, ctx, alias_data->index); } } yaml_free(anchor); return yaml_parser_set_composer_error(parser, "found undefined alias", @@ -270,9 +362,9 @@ } } yaml_free(anchor); return yaml_parser_set_composer_error(parser, "found undefined alias", - first_event->start_mark); + event->start_mark); } /* @@ -280,7 +372,8 @@ */ static int -yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { yaml_node_t node; int index; @@ -284,7 +377,7 @@ { yaml_node_t node; int index; - yaml_char_t *tag = first_event->data.scalar.tag; + yaml_char_t *tag = event->data.scalar.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -294,12 +387,12 @@ if (!tag) goto error; } - SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value, - first_event->data.scalar.length, first_event->data.scalar.style, - first_event->start_mark, first_event->end_mark); + SCALAR_NODE_INIT(node, tag, event->data.scalar.value, + event->data.scalar.length, event->data.scalar.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, @@ -300,8 +393,8 @@ if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, - first_event->data.scalar.anchor)) return 0; + event->data.scalar.anchor)) return 0; @@ -307,5 +400,5 @@ - return index; + return yaml_parser_load_node_add(parser, ctx, index); error: yaml_free(tag); @@ -309,8 +402,8 @@ error: yaml_free(tag); - yaml_free(first_event->data.scalar.anchor); - yaml_free(first_event->data.scalar.value); + yaml_free(event->data.scalar.anchor); + yaml_free(event->data.scalar.value); return 0; } @@ -319,5 +412,6 @@ */ static int -yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { @@ -323,8 +417,7 @@ { - yaml_event_t event; yaml_node_t node; struct { yaml_node_item_t *start; yaml_node_item_t *end; yaml_node_item_t *top; } items = { NULL, NULL, NULL }; @@ -325,11 +418,11 @@ yaml_node_t node; struct { yaml_node_item_t *start; yaml_node_item_t *end; yaml_node_item_t *top; } items = { NULL, NULL, NULL }; - int index, item_index; - yaml_char_t *tag = first_event->data.sequence_start.tag; + int index; + yaml_char_t *tag = event->data.sequence_start.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -342,11 +435,11 @@ if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error; SEQUENCE_NODE_INIT(node, tag, items.start, items.end, - first_event->data.sequence_start.style, - first_event->start_mark, first_event->end_mark); + event->data.sequence_start.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, @@ -347,8 +440,8 @@ if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, - first_event->data.sequence_start.anchor)) return 0; + event->data.sequence_start.anchor)) return 0; @@ -354,3 +447,3 @@ - if (!yaml_parser_parse(parser, &event)) return 0; + if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; @@ -356,13 +449,4 @@ - while (event.type != YAML_SEQUENCE_END_EVENT) { - if (!STACK_LIMIT(parser, - parser->document->nodes.start[index-1].data.sequence.items, - INT_MAX-1)) return 0; - item_index = yaml_parser_load_node(parser, &event); - if (!item_index) return 0; - if (!PUSH(parser, - parser->document->nodes.start[index-1].data.sequence.items, - item_index)) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - } + if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; + if (!PUSH(parser, *ctx, index)) return 0; @@ -368,7 +452,5 @@ - parser->document->nodes.start[index-1].end_mark = event.end_mark; - - return index; + return 1; error: yaml_free(tag); @@ -372,7 +454,7 @@ error: yaml_free(tag); - yaml_free(first_event->data.sequence_start.anchor); + yaml_free(event->data.sequence_start.anchor); return 0; } @@ -376,8 +458,25 @@ return 0; } +static int +yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) +{ + int index; + + assert(((*ctx).top - (*ctx).start) > 0); + + index = *((*ctx).top - 1); + assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE); + parser->document->nodes.start[index-1].end_mark = event->end_mark; + + (void)POP(parser, *ctx); + + return 1; +} + /* * Compose a mapping node. */ static int @@ -379,7 +478,8 @@ /* * Compose a mapping node. */ static int -yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { @@ -385,5 +485,4 @@ { - yaml_event_t event; yaml_node_t node; struct { yaml_node_pair_t *start; @@ -391,8 +490,7 @@ yaml_node_pair_t *top; } pairs = { NULL, NULL, NULL }; int index; - yaml_node_pair_t pair; - yaml_char_t *tag = first_event->data.mapping_start.tag; + yaml_char_t *tag = event->data.mapping_start.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -405,11 +503,11 @@ if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error; MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, - first_event->data.mapping_start.style, - first_event->start_mark, first_event->end_mark); + event->data.mapping_start.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, @@ -410,8 +508,8 @@ if (!PUSH(parser, parser->document->nodes, node)) goto error; index = parser->document->nodes.top - parser->document->nodes.start; if (!yaml_parser_register_anchor(parser, index, - first_event->data.mapping_start.anchor)) return 0; + event->data.mapping_start.anchor)) return 0; @@ -417,3 +515,3 @@ - if (!yaml_parser_parse(parser, &event)) return 0; + if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; @@ -419,16 +517,4 @@ - while (event.type != YAML_MAPPING_END_EVENT) { - if (!STACK_LIMIT(parser, - parser->document->nodes.start[index-1].data.mapping.pairs, - INT_MAX-1)) return 0; - pair.key = yaml_parser_load_node(parser, &event); - if (!pair.key) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - pair.value = yaml_parser_load_node(parser, &event); - if (!pair.value) return 0; - if (!PUSH(parser, - parser->document->nodes.start[index-1].data.mapping.pairs, - pair)) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - } + if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; + if (!PUSH(parser, *ctx, index)) return 0; @@ -434,7 +520,5 @@ - parser->document->nodes.start[index-1].end_mark = event.end_mark; - - return index; + return 1; error: yaml_free(tag); @@ -438,7 +522,7 @@ error: yaml_free(tag); - yaml_free(first_event->data.mapping_start.anchor); + yaml_free(event->data.mapping_start.anchor); return 0; } @@ -442,3 +526,19 @@ return 0; } +static int +yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) +{ + int index; + + assert(((*ctx).top - (*ctx).start) > 0); + + index = *((*ctx).top - 1); + assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE); + parser->document->nodes.start[index-1].end_mark = event->end_mark; + + (void)POP(parser, *ctx); + + return 1; +} \ No newline at end of file