Ruby  2.0.0p481(2014-05-08revision45883)
ext/psych/yaml/loader.c
Go to the documentation of this file.
00001 
00002 #include "yaml_private.h"
00003 
00004 /*
00005  * API functions.
00006  */
00007 
00008 YAML_DECLARE(int)
00009 yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
00010 
00011 /*
00012  * Error handling.
00013  */
00014 
00015 static int
00016 yaml_parser_set_composer_error(yaml_parser_t *parser,
00017         const char *problem, yaml_mark_t problem_mark);
00018 
00019 static int
00020 yaml_parser_set_composer_error_context(yaml_parser_t *parser,
00021         const char *context, yaml_mark_t context_mark,
00022         const char *problem, yaml_mark_t problem_mark);
00023 
00024 
00025 /*
00026  * Alias handling.
00027  */
00028 
00029 static int
00030 yaml_parser_register_anchor(yaml_parser_t *parser,
00031         int index, yaml_char_t *anchor);
00032 
00033 /*
00034  * Clean up functions.
00035  */
00036 
00037 static void
00038 yaml_parser_delete_aliases(yaml_parser_t *parser);
00039 
00040 /*
00041  * Composer functions.
00042  */
00043 
00044 static int
00045 yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
00046 
00047 static int
00048 yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
00049 
00050 static int
00051 yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
00052 
00053 static int
00054 yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
00055 
00056 static int
00057 yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
00058 
00059 static int
00060 yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
00061 
00062 /*
00063  * Load the next document of the stream.
00064  */
00065 
00066 YAML_DECLARE(int)
00067 yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
00068 {
00069     yaml_event_t event;
00070 
00071     assert(parser);     /* Non-NULL parser object is expected. */
00072     assert(document);   /* Non-NULL document object is expected. */
00073 
00074     memset(document, 0, sizeof(yaml_document_t));
00075     if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
00076         goto error;
00077 
00078     if (!parser->stream_start_produced) {
00079         if (!yaml_parser_parse(parser, &event)) goto error;
00080         assert(event.type == YAML_STREAM_START_EVENT);
00081                         /* STREAM-START is expected. */
00082     }
00083 
00084     if (parser->stream_end_produced) {
00085         return 1;
00086     }
00087 
00088     if (!yaml_parser_parse(parser, &event)) goto error;
00089     if (event.type == YAML_STREAM_END_EVENT) {
00090         return 1;
00091     }
00092 
00093     if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
00094         goto error;
00095 
00096     parser->document = document;
00097 
00098     if (!yaml_parser_load_document(parser, &event)) goto error;
00099 
00100     yaml_parser_delete_aliases(parser);
00101     parser->document = NULL;
00102 
00103     return 1;
00104 
00105 error:
00106 
00107     yaml_parser_delete_aliases(parser);
00108     yaml_document_delete(document);
00109     parser->document = NULL;
00110 
00111     return 0;
00112 }
00113 
00114 /*
00115  * Set composer error.
00116  */
00117 
00118 static int
00119 yaml_parser_set_composer_error(yaml_parser_t *parser,
00120         const char *problem, yaml_mark_t problem_mark)
00121 {
00122     parser->error = YAML_COMPOSER_ERROR;
00123     parser->problem = problem;
00124     parser->problem_mark = problem_mark;
00125 
00126     return 0;
00127 }
00128 
00129 /*
00130  * Set composer error with context.
00131  */
00132 
00133 static int
00134 yaml_parser_set_composer_error_context(yaml_parser_t *parser,
00135         const char *context, yaml_mark_t context_mark,
00136         const char *problem, yaml_mark_t problem_mark)
00137 {
00138     parser->error = YAML_COMPOSER_ERROR;
00139     parser->context = context;
00140     parser->context_mark = context_mark;
00141     parser->problem = problem;
00142     parser->problem_mark = problem_mark;
00143 
00144     return 0;
00145 }
00146 
00147 /*
00148  * Delete the stack of aliases.
00149  */
00150 
00151 static void
00152 yaml_parser_delete_aliases(yaml_parser_t *parser)
00153 {
00154     while (!STACK_EMPTY(parser, parser->aliases)) {
00155         yaml_free(POP(parser, parser->aliases).anchor);
00156     }
00157     STACK_DEL(parser, parser->aliases);
00158 }
00159 
00160 /*
00161  * Compose a document object.
00162  */
00163 
00164 static int
00165 yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
00166 {
00167     yaml_event_t event;
00168 
00169     assert(first_event->type == YAML_DOCUMENT_START_EVENT);
00170                         /* DOCUMENT-START is expected. */
00171 
00172     parser->document->version_directive
00173         = first_event->data.document_start.version_directive;
00174     parser->document->tag_directives.start
00175         = first_event->data.document_start.tag_directives.start;
00176     parser->document->tag_directives.end
00177         = first_event->data.document_start.tag_directives.end;
00178     parser->document->start_implicit
00179         = first_event->data.document_start.implicit;
00180     parser->document->start_mark = first_event->start_mark;
00181 
00182     if (!yaml_parser_parse(parser, &event)) return 0;
00183 
00184     if (!yaml_parser_load_node(parser, &event)) return 0;
00185 
00186     if (!yaml_parser_parse(parser, &event)) return 0;
00187     assert(event.type == YAML_DOCUMENT_END_EVENT);
00188                         /* DOCUMENT-END is expected. */
00189 
00190     parser->document->end_implicit = event.data.document_end.implicit;
00191     parser->document->end_mark = event.end_mark;
00192 
00193     return 1;
00194 }
00195 
00196 /*
00197  * Compose a node.
00198  */
00199 
00200 static int
00201 yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
00202 {
00203     switch (first_event->type) {
00204         case YAML_ALIAS_EVENT:
00205             return yaml_parser_load_alias(parser, first_event);
00206         case YAML_SCALAR_EVENT:
00207             return yaml_parser_load_scalar(parser, first_event);
00208         case YAML_SEQUENCE_START_EVENT:
00209             return yaml_parser_load_sequence(parser, first_event);
00210         case YAML_MAPPING_START_EVENT:
00211             return yaml_parser_load_mapping(parser, first_event);
00212         default:
00213             assert(0);  /* Could not happen. */
00214             return 0;
00215     }
00216 
00217     return 0;
00218 }
00219 
00220 /*
00221  * Add an anchor.
00222  */
00223 
00224 static int
00225 yaml_parser_register_anchor(yaml_parser_t *parser,
00226         int index, yaml_char_t *anchor)
00227 {
00228     yaml_alias_data_t data;
00229     yaml_alias_data_t *alias_data;
00230 
00231     if (!anchor) return 1;
00232 
00233     data.anchor = anchor;
00234     data.index = index;
00235     data.mark = parser->document->nodes.start[index-1].start_mark;
00236 
00237     for (alias_data = parser->aliases.start;
00238             alias_data != parser->aliases.top; alias_data ++) {
00239         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
00240             yaml_free(anchor);
00241             return yaml_parser_set_composer_error_context(parser,
00242                     "found duplicate anchor; first occurence",
00243                     alias_data->mark, "second occurence", data.mark);
00244         }
00245     }
00246 
00247     if (!PUSH(parser, parser->aliases, data)) {
00248         yaml_free(anchor);
00249         return 0;
00250     }
00251 
00252     return 1;
00253 }
00254 
00255 /*
00256  * Compose a node corresponding to an alias.
00257  */
00258 
00259 static int
00260 yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
00261 {
00262     yaml_char_t *anchor = first_event->data.alias.anchor;
00263     yaml_alias_data_t *alias_data;
00264 
00265     for (alias_data = parser->aliases.start;
00266             alias_data != parser->aliases.top; alias_data ++) {
00267         if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
00268             yaml_free(anchor);
00269             return alias_data->index;
00270         }
00271     }
00272 
00273     yaml_free(anchor);
00274     return yaml_parser_set_composer_error(parser, "found undefined alias",
00275             first_event->start_mark);
00276 }
00277 
00278 /*
00279  * Compose a scalar node.
00280  */
00281 
00282 static int
00283 yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
00284 {
00285     yaml_node_t node;
00286     ptrdiff_t node_index;
00287     int index;
00288     yaml_char_t *tag = first_event->data.scalar.tag;
00289 
00290     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
00291 
00292     if (!tag || strcmp((char *)tag, "!") == 0) {
00293         yaml_free(tag);
00294         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
00295         if (!tag) goto error;
00296     }
00297 
00298     SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
00299             first_event->data.scalar.length, first_event->data.scalar.style,
00300             first_event->start_mark, first_event->end_mark);
00301 
00302     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00303 
00304     node_index = parser->document->nodes.top - parser->document->nodes.start;
00305 #if PTRDIFF_MAX > INT_MAX
00306     if (node_index > INT_MAX) goto error;
00307 #endif
00308     index = (int)node_index;
00309 
00310     if (!yaml_parser_register_anchor(parser, index,
00311                 first_event->data.scalar.anchor)) return 0;
00312 
00313     return index;
00314 
00315 error:
00316     yaml_free(tag);
00317     yaml_free(first_event->data.scalar.anchor);
00318     yaml_free(first_event->data.scalar.value);
00319     return 0;
00320 }
00321 
00322 /*
00323  * Compose a sequence node.
00324  */
00325 
00326 static int
00327 yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
00328 {
00329     yaml_event_t event;
00330     yaml_node_t node;
00331     struct {
00332         yaml_node_item_t *start;
00333         yaml_node_item_t *end;
00334         yaml_node_item_t *top;
00335     } items = { NULL, NULL, NULL };
00336     int index, item_index;
00337     ptrdiff_t node_index;
00338     yaml_char_t *tag = first_event->data.sequence_start.tag;
00339 
00340     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
00341 
00342     if (!tag || strcmp((char *)tag, "!") == 0) {
00343         yaml_free(tag);
00344         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
00345         if (!tag) goto error;
00346     }
00347 
00348     if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
00349 
00350     SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
00351             first_event->data.sequence_start.style,
00352             first_event->start_mark, first_event->end_mark);
00353 
00354     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00355 
00356     node_index = parser->document->nodes.top - parser->document->nodes.start;
00357 #if PTRDIFF_MAX > INT_MAX
00358     if (node_index > INT_MAX) goto error;
00359 #endif
00360     index = (int)node_index;
00361 
00362     if (!yaml_parser_register_anchor(parser, index,
00363                 first_event->data.sequence_start.anchor)) return 0;
00364 
00365     if (!yaml_parser_parse(parser, &event)) return 0;
00366 
00367     while (event.type != YAML_SEQUENCE_END_EVENT) {
00368         if (!STACK_LIMIT(parser,
00369                     parser->document->nodes.start[index-1].data.sequence.items,
00370                     INT_MAX-1)) return 0;
00371         item_index = yaml_parser_load_node(parser, &event);
00372         if (!item_index) return 0;
00373         if (!PUSH(parser,
00374                     parser->document->nodes.start[index-1].data.sequence.items,
00375                     item_index)) return 0;
00376         if (!yaml_parser_parse(parser, &event)) return 0;
00377     }
00378 
00379     parser->document->nodes.start[index-1].end_mark = event.end_mark;
00380 
00381     return index;
00382 
00383 error:
00384     yaml_free(tag);
00385     yaml_free(first_event->data.sequence_start.anchor);
00386     return 0;
00387 }
00388 
00389 /*
00390  * Compose a mapping node.
00391  */
00392 
00393 static int
00394 yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
00395 {
00396     yaml_event_t event;
00397     yaml_node_t node;
00398     struct {
00399         yaml_node_pair_t *start;
00400         yaml_node_pair_t *end;
00401         yaml_node_pair_t *top;
00402     } pairs = { NULL, NULL, NULL };
00403     int index;
00404     ptrdiff_t node_index;
00405     yaml_node_pair_t pair;
00406     yaml_char_t *tag = first_event->data.mapping_start.tag;
00407 
00408     if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
00409 
00410     if (!tag || strcmp((char *)tag, "!") == 0) {
00411         yaml_free(tag);
00412         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
00413         if (!tag) goto error;
00414     }
00415 
00416     if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
00417 
00418     MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
00419             first_event->data.mapping_start.style,
00420             first_event->start_mark, first_event->end_mark);
00421 
00422     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00423 
00424     node_index = parser->document->nodes.top - parser->document->nodes.start;
00425 #if PTRDIFF_MAX > INT_MAX
00426     if (node_index > INT_MAX) goto error;
00427 #endif
00428     index = (int)node_index;
00429 
00430     if (!yaml_parser_register_anchor(parser, index,
00431                 first_event->data.mapping_start.anchor)) return 0;
00432 
00433     if (!yaml_parser_parse(parser, &event)) return 0;
00434 
00435     while (event.type != YAML_MAPPING_END_EVENT) {
00436         if (!STACK_LIMIT(parser,
00437                     parser->document->nodes.start[index-1].data.mapping.pairs,
00438                     INT_MAX-1)) return 0;
00439         pair.key = yaml_parser_load_node(parser, &event);
00440         if (!pair.key) return 0;
00441         if (!yaml_parser_parse(parser, &event)) return 0;
00442         pair.value = yaml_parser_load_node(parser, &event);
00443         if (!pair.value) return 0;
00444         if (!PUSH(parser,
00445                     parser->document->nodes.start[index-1].data.mapping.pairs,
00446                     pair)) return 0;
00447         if (!yaml_parser_parse(parser, &event)) return 0;
00448     }
00449 
00450     parser->document->nodes.start[index-1].end_mark = event.end_mark;
00451 
00452     return index;
00453 
00454 error:
00455     yaml_free(tag);
00456     yaml_free(first_event->data.mapping_start.anchor);
00457     return 0;
00458 }
00459 
00460