Ruby  2.0.0p247(2013-06-27revision41674)
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     int index;
00287     yaml_char_t *tag = first_event->data.scalar.tag;
00288 
00289     if (!tag || strcmp((char *)tag, "!") == 0) {
00290         yaml_free(tag);
00291         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
00292         if (!tag) goto error;
00293     }
00294 
00295     SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
00296             first_event->data.scalar.length, first_event->data.scalar.style,
00297             first_event->start_mark, first_event->end_mark);
00298 
00299     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00300 
00301     index = parser->document->nodes.top - parser->document->nodes.start;
00302 
00303     if (!yaml_parser_register_anchor(parser, index,
00304                 first_event->data.scalar.anchor)) return 0;
00305 
00306     return index;
00307 
00308 error:
00309     yaml_free(tag);
00310     yaml_free(first_event->data.scalar.anchor);
00311     yaml_free(first_event->data.scalar.value);
00312     return 0;
00313 }
00314 
00315 /*
00316  * Compose a sequence node.
00317  */
00318 
00319 static int
00320 yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
00321 {
00322     yaml_event_t event;
00323     yaml_node_t node;
00324     struct {
00325         yaml_node_item_t *start;
00326         yaml_node_item_t *end;
00327         yaml_node_item_t *top;
00328     } items = { NULL, NULL, NULL };
00329     int index, item_index;
00330     yaml_char_t *tag = first_event->data.sequence_start.tag;
00331 
00332     if (!tag || strcmp((char *)tag, "!") == 0) {
00333         yaml_free(tag);
00334         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
00335         if (!tag) goto error;
00336     }
00337 
00338     if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
00339 
00340     SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
00341             first_event->data.sequence_start.style,
00342             first_event->start_mark, first_event->end_mark);
00343 
00344     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00345 
00346     index = parser->document->nodes.top - parser->document->nodes.start;
00347 
00348     if (!yaml_parser_register_anchor(parser, index,
00349                 first_event->data.sequence_start.anchor)) return 0;
00350 
00351     if (!yaml_parser_parse(parser, &event)) return 0;
00352 
00353     while (event.type != YAML_SEQUENCE_END_EVENT) {
00354         item_index = yaml_parser_load_node(parser, &event);
00355         if (!item_index) return 0;
00356         if (!PUSH(parser,
00357                     parser->document->nodes.start[index-1].data.sequence.items,
00358                     item_index)) return 0;
00359         if (!yaml_parser_parse(parser, &event)) return 0;
00360     }
00361 
00362     parser->document->nodes.start[index-1].end_mark = event.end_mark;
00363 
00364     return index;
00365 
00366 error:
00367     yaml_free(tag);
00368     yaml_free(first_event->data.sequence_start.anchor);
00369     return 0;
00370 }
00371 
00372 /*
00373  * Compose a mapping node.
00374  */
00375 
00376 static int
00377 yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
00378 {
00379     yaml_event_t event;
00380     yaml_node_t node;
00381     struct {
00382         yaml_node_pair_t *start;
00383         yaml_node_pair_t *end;
00384         yaml_node_pair_t *top;
00385     } pairs = { NULL, NULL, NULL };
00386     int index;
00387     yaml_node_pair_t pair;
00388     yaml_char_t *tag = first_event->data.mapping_start.tag;
00389 
00390     if (!tag || strcmp((char *)tag, "!") == 0) {
00391         yaml_free(tag);
00392         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
00393         if (!tag) goto error;
00394     }
00395 
00396     if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
00397 
00398     MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
00399             first_event->data.mapping_start.style,
00400             first_event->start_mark, first_event->end_mark);
00401 
00402     if (!PUSH(parser, parser->document->nodes, node)) goto error;
00403 
00404     index = parser->document->nodes.top - parser->document->nodes.start;
00405 
00406     if (!yaml_parser_register_anchor(parser, index,
00407                 first_event->data.mapping_start.anchor)) return 0;
00408 
00409     if (!yaml_parser_parse(parser, &event)) return 0;
00410 
00411     while (event.type != YAML_MAPPING_END_EVENT) {
00412         pair.key = yaml_parser_load_node(parser, &event);
00413         if (!pair.key) return 0;
00414         if (!yaml_parser_parse(parser, &event)) return 0;
00415         pair.value = yaml_parser_load_node(parser, &event);
00416         if (!pair.value) return 0;
00417         if (!PUSH(parser,
00418                     parser->document->nodes.start[index-1].data.mapping.pairs,
00419                     pair)) return 0;
00420         if (!yaml_parser_parse(parser, &event)) return 0;
00421     }
00422 
00423     parser->document->nodes.start[index-1].end_mark = event.end_mark;
00424 
00425     return index;
00426 
00427 error:
00428     yaml_free(tag);
00429     yaml_free(first_event->data.mapping_start.anchor);
00430     return 0;
00431 }
00432 
00433