Actual source code: loader.c

  1: #include "yaml_private.h"

  3: /*
  4:  * API functions.
  5:  */

  7: YAML_DECLARE(int)
  8: yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);

 10: /*
 11:  * Error handling.
 12:  */

 14: static int
 15: yaml_parser_set_composer_error(yaml_parser_t *parser,
 16:         const char *problem, yaml_mark_t problem_mark);

 18: static int
 19: yaml_parser_set_composer_error_context(yaml_parser_t *parser,
 20:         const char *context, yaml_mark_t context_mark,
 21:         const char *problem, yaml_mark_t problem_mark);


 24: /*
 25:  * Alias handling.
 26:  */

 28: static int
 29: yaml_parser_register_anchor(yaml_parser_t *parser,
 30:         int index, yaml_char_t *anchor);

 32: /*
 33:  * Clean up functions.
 34:  */

 36: static void
 37: yaml_parser_delete_aliases(yaml_parser_t *parser);

 39: /*
 40:  * Document loading context.
 41:  */
 42: struct loader_ctx {
 43:     int *start;
 44:     int *end;
 45:     int *top;
 46: };

 48: /*
 49:  * Composer functions.
 50:  */
 51: static int
 52: yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx);

 54: static int
 55: yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event);

 57: static int
 58: yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
 59:         struct loader_ctx *ctx);

 61: static int
 62: yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
 63:         struct loader_ctx *ctx);

 65: static int
 66: yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
 67:         struct loader_ctx *ctx);

 69: static int
 70: yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
 71:         struct loader_ctx *ctx);

 73: static int
 74: yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
 75:         struct loader_ctx *ctx);

 77: static int
 78: yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
 79:         struct loader_ctx *ctx);

 81: /*
 82:  * Load the next document of the stream.
 83:  */

 85: YAML_DECLARE(int)
 86: yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
 87: {
 88:     yaml_event_t event;

 90:     assert(parser);     /* Non-NULL parser object is expected. */
 91:     assert(document);   /* Non-NULL document object is expected. */

 93:     memset(document, 0, sizeof(yaml_document_t));
 94:     if (!STACK_INIT(parser, document->nodes, yaml_node_t*))
 95:         goto error;

 97:     if (!parser->stream_start_produced) {
 98:         if (!yaml_parser_parse(parser, &event)) goto error;
 99:         assert(event.type == YAML_STREAM_START_EVENT);
100:                         /* STREAM-START is expected. */
101:     }

103:     if (parser->stream_end_produced) return 1;

105:     if (!yaml_parser_parse(parser, &event)) goto error;
106:     if (event.type == YAML_STREAM_END_EVENT) return 1;

108:     if (!STACK_INIT(parser, parser->aliases, yaml_alias_data_t*))
109:         goto error;

111:     parser->document = document;

113:     if (!yaml_parser_load_document(parser, &event)) goto error;

115:     yaml_parser_delete_aliases(parser);
116:     parser->document = NULL;

118:     return 1;

120: error:

122:     yaml_parser_delete_aliases(parser);
123:     yaml_document_delete(document);
124:     parser->document = NULL;

126:     return 0;
127: }

129: /*
130:  * Set composer error.
131:  */

133: static int
134: yaml_parser_set_composer_error(yaml_parser_t *parser,
135:         const char *problem, yaml_mark_t problem_mark)
136: {
137:     parser->error = YAML_COMPOSER_ERROR;
138:     parser->problem = problem;
139:     parser->problem_mark = problem_mark;

141:     return 0;
142: }

144: /*
145:  * Set composer error with context.
146:  */

148: static int
149: yaml_parser_set_composer_error_context(yaml_parser_t *parser,
150:         const char *context, yaml_mark_t context_mark,
151:         const char *problem, yaml_mark_t problem_mark)
152: {
153:     parser->error = YAML_COMPOSER_ERROR;
154:     parser->context = context;
155:     parser->context_mark = context_mark;
156:     parser->problem = problem;
157:     parser->problem_mark = problem_mark;

159:     return 0;
160: }

162: /*
163:  * Delete the stack of aliases.
164:  */

166: static void
167: yaml_parser_delete_aliases(yaml_parser_t *parser)
168: {
169:     while (!STACK_EMPTY(parser, parser->aliases)) yaml_free(POP(parser, parser->aliases).anchor);
170:     STACK_DEL(parser, parser->aliases);
171: }

173: /*
174:  * Compose a document object.
175:  */

177: static int
178: yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event)
179: {
180:     struct loader_ctx ctx = { NULL, NULL, NULL };

182:     assert(event->type == YAML_DOCUMENT_START_EVENT);
183:                         /* DOCUMENT-START is expected. */

185:     parser->document->version_directive
186:         = event->data.document_start.version_directive;
187:     parser->document->tag_directives.start
188:         = event->data.document_start.tag_directives.start;
189:     parser->document->tag_directives.end
190:         = event->data.document_start.tag_directives.end;
191:     parser->document->start_implicit
192:         = event->data.document_start.implicit;
193:     parser->document->start_mark = event->start_mark;

195:     if (!STACK_INIT(parser, ctx, int*)) return 0;
196:     if (!yaml_parser_load_nodes(parser, &ctx)) {
197:         STACK_DEL(parser, ctx);
198:         return 0;
199:     }
200:     STACK_DEL(parser, ctx);

202:     return 1;
203: }

205: /*
206:  * Compose a node tree.
207:  */

209: static int
210: yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx)
211: {
212:     yaml_event_t event;

214:     do {
215:         if (!yaml_parser_parse(parser, &event)) return 0;

217:         switch (event.type) {
218:             case YAML_ALIAS_EVENT:
219:                 if (!yaml_parser_load_alias(parser, &event, ctx)) return 0;
220:                 break;
221:             case YAML_SCALAR_EVENT:
222:                 if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0;
223:                 break;
224:             case YAML_SEQUENCE_START_EVENT:
225:                 if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0;
226:                 break;
227:             case YAML_SEQUENCE_END_EVENT:
228:                 if (!yaml_parser_load_sequence_end(parser, &event, ctx))
229:                     return 0;
230:                 break;
231:             case YAML_MAPPING_START_EVENT:
232:                 if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0;
233:                 break;
234:             case YAML_MAPPING_END_EVENT:
235:                 if (!yaml_parser_load_mapping_end(parser, &event, ctx))
236:                     return 0;
237:                 break;
238:             default:
239:                 assert(0);  /* Could not happen. */
240:                 return 0;
241:             case YAML_DOCUMENT_END_EVENT:
242:                 break;
243:         }
244:     } while (event.type != YAML_DOCUMENT_END_EVENT);

246:     parser->document->end_implicit = event.data.document_end.implicit;
247:     parser->document->end_mark = event.end_mark;

249:     return 1;
250: }

252: /*
253:  * Add an anchor.
254:  */

256: static int
257: yaml_parser_register_anchor(yaml_parser_t *parser,
258:         int index, yaml_char_t *anchor)
259: {
260:     yaml_alias_data_t data;
261:     yaml_alias_data_t *alias_data;

263:     if (!anchor) return 1;

265:     data.anchor = anchor;
266:     data.index = index;
267:     data.mark = parser->document->nodes.start[index-1].start_mark;

269:     for (alias_data = parser->aliases.start;
270:             alias_data != parser->aliases.top; alias_data ++) {
271:         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
272:             yaml_free(anchor);
273:             return yaml_parser_set_composer_error_context(parser,
274:                     "found duplicate anchor; first occurrence",
275:                     alias_data->mark, "second occurrence", data.mark);
276:         }
277:     }

279:     if (!PUSH(parser, parser->aliases, data)) {
280:         yaml_free(anchor);
281:         return 0;
282:     }

284:     return 1;
285: }

287: /*
288:  * Compose node into its parent in the stree.
289:  */

291: static int
292: yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx,
293:         int index)
294: {
295:     struct yaml_node_s *parent;
296:     int parent_index;

298:     if (STACK_EMPTY(parser, *ctx)) {
299:         /* This is the root node, there's no tree to add it to. */
300:         return 1;
301:     }

303:     parent_index = *((*ctx).top - 1);
304:     parent = &parser->document->nodes.start[parent_index-1];

306:     switch (parent->type) {
307:         case YAML_SEQUENCE_NODE:
308:             if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1))
309:                 return 0;
310:             if (!PUSH(parser, parent->data.sequence.items, index))
311:                 return 0;
312:             break;
313:         case YAML_MAPPING_NODE: {
314:             yaml_node_pair_t pair;
315:             if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) {
316:                 yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1;
317:                 if (p->key != 0 && p->value == 0) {
318:                     p->value = index;
319:                     break;
320:                 }
321:             }

323:             pair.key = index;
324:             pair.value = 0;
325:             if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1))
326:                 return 0;
327:             if (!PUSH(parser, parent->data.mapping.pairs, pair))
328:                 return 0;

330:             break;
331:         }
332:         default:
333:             assert(0); /* Could not happen. */
334:             return 0;
335:     }
336:     return 1;
337: }

339: /*
340:  * Compose a node corresponding to an alias.
341:  */

343: static int
344: yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
345:         struct loader_ctx *ctx)
346: {
347:     yaml_char_t *anchor = event->data.alias.anchor;
348:     yaml_alias_data_t *alias_data;

350:     for (alias_data = parser->aliases.start;
351:             alias_data != parser->aliases.top; alias_data ++) {
352:         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
353:             yaml_free(anchor);
354:             return yaml_parser_load_node_add(parser, ctx, alias_data->index);
355:         }
356:     }

358:     yaml_free(anchor);
359:     return yaml_parser_set_composer_error(parser, "found undefined alias",
360:             event->start_mark);
361: }

363: /*
364:  * Compose a scalar node.
365:  */

367: static int
368: yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
369:         struct loader_ctx *ctx)
370: {
371:     yaml_node_t node;
372:     int index;
373:     yaml_char_t *tag = event->data.scalar.tag;

375:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

377:     if (!tag || strcmp((char *)tag, "!") == 0) {
378:         yaml_free(tag);
379:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
380:         if (!tag) goto error;
381:     }

383:     SCALAR_NODE_INIT(node, tag, event->data.scalar.value,
384:             event->data.scalar.length, event->data.scalar.style,
385:             event->start_mark, event->end_mark);

387:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

389:     index = parser->document->nodes.top - parser->document->nodes.start;

391:     if (!yaml_parser_register_anchor(parser, index,
392:                 event->data.scalar.anchor)) return 0;

394:     return yaml_parser_load_node_add(parser, ctx, index);

396: error:
397:     yaml_free(tag);
398:     yaml_free(event->data.scalar.anchor);
399:     yaml_free(event->data.scalar.value);
400:     return 0;
401: }

403: /*
404:  * Compose a sequence node.
405:  */

407: static int
408: yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
409:         struct loader_ctx *ctx)
410: {
411:     yaml_node_t node;
412:     struct {
413:         yaml_node_item_t *start;
414:         yaml_node_item_t *end;
415:         yaml_node_item_t *top;
416:     } items = { NULL, NULL, NULL };
417:     int index;
418:     yaml_char_t *tag = event->data.sequence_start.tag;

420:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

422:     if (!tag || strcmp((char *)tag, "!") == 0) {
423:         yaml_free(tag);
424:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
425:         if (!tag) goto error;
426:     }

428:     if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error;

430:     SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
431:             event->data.sequence_start.style,
432:             event->start_mark, event->end_mark);

434:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

436:     index = parser->document->nodes.top - parser->document->nodes.start;

438:     if (!yaml_parser_register_anchor(parser, index,
439:                 event->data.sequence_start.anchor)) return 0;

441:     if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;

443:     if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
444:     if (!PUSH(parser, *ctx, index)) return 0;

446:     return 1;

448: error:
449:     yaml_free(tag);
450:     yaml_free(event->data.sequence_start.anchor);
451:     return 0;
452: }

454: static int
455: yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
456:         struct loader_ctx *ctx)
457: {
458:     int index;

460:     assert(((*ctx).top - (*ctx).start) > 0);

462:     index = *((*ctx).top - 1);
463:     assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE);
464:     parser->document->nodes.start[index-1].end_mark = event->end_mark;

466:     (void)POP(parser, *ctx);

468:     return 1;
469: }

471: /*
472:  * Compose a mapping node.
473:  */

475: static int
476: yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
477:         struct loader_ctx *ctx)
478: {
479:     yaml_node_t node;
480:     struct {
481:         yaml_node_pair_t *start;
482:         yaml_node_pair_t *end;
483:         yaml_node_pair_t *top;
484:     } pairs = { NULL, NULL, NULL };
485:     int index;
486:     yaml_char_t *tag = event->data.mapping_start.tag;

488:     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

490:     if (!tag || strcmp((char *)tag, "!") == 0) {
491:         yaml_free(tag);
492:         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
493:         if (!tag) goto error;
494:     }

496:     if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error;

498:     MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
499:             event->data.mapping_start.style,
500:             event->start_mark, event->end_mark);

502:     if (!PUSH(parser, parser->document->nodes, node)) goto error;

504:     index = parser->document->nodes.top - parser->document->nodes.start;

506:     if (!yaml_parser_register_anchor(parser, index,
507:                 event->data.mapping_start.anchor)) return 0;

509:     if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;

511:     if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
512:     if (!PUSH(parser, *ctx, index)) return 0;

514:     return 1;

516: error:
517:     yaml_free(tag);
518:     yaml_free(event->data.mapping_start.anchor);
519:     return 0;
520: }

522: static int
523: yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
524:         struct loader_ctx *ctx)
525: {
526:     int index;

528:     assert(((*ctx).top - (*ctx).start) > 0);

530:     index = *((*ctx).top - 1);
531:     assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE);
532:     parser->document->nodes.start[index-1].end_mark = event->end_mark;

534:     (void)POP(parser, *ctx);

536:     return 1;
537: }