Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 00002 #include "yaml_private.h" 00003 00004 /* 00005 * API functions. 00006 */ 00007 00008 YAML_DECLARE(int) 00009 yaml_emitter_open(yaml_emitter_t *emitter); 00010 00011 YAML_DECLARE(int) 00012 yaml_emitter_close(yaml_emitter_t *emitter); 00013 00014 YAML_DECLARE(int) 00015 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document); 00016 00017 /* 00018 * Clean up functions. 00019 */ 00020 00021 static void 00022 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter); 00023 00024 /* 00025 * Anchor functions. 00026 */ 00027 00028 static void 00029 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index); 00030 00031 static yaml_char_t * 00032 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id); 00033 00034 00035 /* 00036 * Serialize functions. 00037 */ 00038 00039 static int 00040 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index); 00041 00042 static int 00043 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor); 00044 00045 static int 00046 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, 00047 yaml_char_t *anchor); 00048 00049 static int 00050 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, 00051 yaml_char_t *anchor); 00052 00053 static int 00054 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, 00055 yaml_char_t *anchor); 00056 00057 /* 00058 * Issue a STREAM-START event. 00059 */ 00060 00061 YAML_DECLARE(int) 00062 yaml_emitter_open(yaml_emitter_t *emitter) 00063 { 00064 yaml_event_t event; 00065 yaml_mark_t mark = { 0, 0, 0 }; 00066 00067 assert(emitter); /* Non-NULL emitter object is required. */ 00068 assert(!emitter->opened); /* Emitter should not be opened yet. */ 00069 00070 STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark); 00071 00072 if (!yaml_emitter_emit(emitter, &event)) { 00073 return 0; 00074 } 00075 00076 emitter->opened = 1; 00077 00078 return 1; 00079 } 00080 00081 /* 00082 * Issue a STREAM-END event. 00083 */ 00084 00085 YAML_DECLARE(int) 00086 yaml_emitter_close(yaml_emitter_t *emitter) 00087 { 00088 yaml_event_t event; 00089 yaml_mark_t mark = { 0, 0, 0 }; 00090 00091 assert(emitter); /* Non-NULL emitter object is required. */ 00092 assert(emitter->opened); /* Emitter should be opened. */ 00093 00094 if (emitter->closed) return 1; 00095 00096 STREAM_END_EVENT_INIT(event, mark, mark); 00097 00098 if (!yaml_emitter_emit(emitter, &event)) { 00099 return 0; 00100 } 00101 00102 emitter->closed = 1; 00103 00104 return 1; 00105 } 00106 00107 /* 00108 * Dump a YAML document. 00109 */ 00110 00111 YAML_DECLARE(int) 00112 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document) 00113 { 00114 yaml_event_t event; 00115 yaml_mark_t mark = { 0, 0, 0 }; 00116 00117 assert(emitter); /* Non-NULL emitter object is required. */ 00118 assert(document); /* Non-NULL emitter object is expected. */ 00119 00120 emitter->document = document; 00121 00122 if (!emitter->opened) { 00123 if (!yaml_emitter_open(emitter)) goto error; 00124 } 00125 00126 if (STACK_EMPTY(emitter, document->nodes)) { 00127 if (!yaml_emitter_close(emitter)) goto error; 00128 yaml_emitter_delete_document_and_anchors(emitter); 00129 return 1; 00130 } 00131 00132 assert(emitter->opened); /* Emitter should be opened. */ 00133 00134 emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors)) 00135 * (document->nodes.top - document->nodes.start)); 00136 if (!emitter->anchors) goto error; 00137 memset(emitter->anchors, 0, sizeof(*(emitter->anchors)) 00138 * (document->nodes.top - document->nodes.start)); 00139 00140 DOCUMENT_START_EVENT_INIT(event, document->version_directive, 00141 document->tag_directives.start, document->tag_directives.end, 00142 document->start_implicit, mark, mark); 00143 if (!yaml_emitter_emit(emitter, &event)) goto error; 00144 00145 yaml_emitter_anchor_node(emitter, 1); 00146 if (!yaml_emitter_dump_node(emitter, 1)) goto error; 00147 00148 DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark); 00149 if (!yaml_emitter_emit(emitter, &event)) goto error; 00150 00151 yaml_emitter_delete_document_and_anchors(emitter); 00152 00153 return 1; 00154 00155 error: 00156 00157 yaml_emitter_delete_document_and_anchors(emitter); 00158 00159 return 0; 00160 } 00161 00162 /* 00163 * Clean up the emitter object after a document is dumped. 00164 */ 00165 00166 static void 00167 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter) 00168 { 00169 int index; 00170 00171 if (!emitter->anchors) { 00172 yaml_document_delete(emitter->document); 00173 emitter->document = NULL; 00174 return; 00175 } 00176 00177 for (index = 0; emitter->document->nodes.start + index 00178 < emitter->document->nodes.top; index ++) { 00179 yaml_node_t node = emitter->document->nodes.start[index]; 00180 if (!emitter->anchors[index].serialized) { 00181 yaml_free(node.tag); 00182 if (node.type == YAML_SCALAR_NODE) { 00183 yaml_free(node.data.scalar.value); 00184 } 00185 } 00186 if (node.type == YAML_SEQUENCE_NODE) { 00187 STACK_DEL(emitter, node.data.sequence.items); 00188 } 00189 if (node.type == YAML_MAPPING_NODE) { 00190 STACK_DEL(emitter, node.data.mapping.pairs); 00191 } 00192 } 00193 00194 STACK_DEL(emitter, emitter->document->nodes); 00195 yaml_free(emitter->anchors); 00196 00197 emitter->anchors = NULL; 00198 emitter->last_anchor_id = 0; 00199 emitter->document = NULL; 00200 } 00201 00202 /* 00203 * Check the references of a node and assign the anchor id if needed. 00204 */ 00205 00206 static void 00207 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index) 00208 { 00209 yaml_node_t *node = emitter->document->nodes.start + index - 1; 00210 yaml_node_item_t *item; 00211 yaml_node_pair_t *pair; 00212 00213 emitter->anchors[index-1].references ++; 00214 00215 if (emitter->anchors[index-1].references == 1) { 00216 switch (node->type) { 00217 case YAML_SEQUENCE_NODE: 00218 for (item = node->data.sequence.items.start; 00219 item < node->data.sequence.items.top; item ++) { 00220 yaml_emitter_anchor_node(emitter, *item); 00221 } 00222 break; 00223 case YAML_MAPPING_NODE: 00224 for (pair = node->data.mapping.pairs.start; 00225 pair < node->data.mapping.pairs.top; pair ++) { 00226 yaml_emitter_anchor_node(emitter, pair->key); 00227 yaml_emitter_anchor_node(emitter, pair->value); 00228 } 00229 break; 00230 default: 00231 break; 00232 } 00233 } 00234 00235 else if (emitter->anchors[index-1].references == 2) { 00236 emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id); 00237 } 00238 } 00239 00240 /* 00241 * Generate a textual representation for an anchor. 00242 */ 00243 00244 #define ANCHOR_TEMPLATE "id%03d" 00245 #define ANCHOR_TEMPLATE_LENGTH 16 00246 00247 static yaml_char_t * 00248 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id) 00249 { 00250 yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH); 00251 00252 if (!anchor) return NULL; 00253 00254 sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id); 00255 00256 return anchor; 00257 } 00258 00259 /* 00260 * Serialize a node. 00261 */ 00262 00263 static int 00264 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index) 00265 { 00266 yaml_node_t *node = emitter->document->nodes.start + index - 1; 00267 int anchor_id = emitter->anchors[index-1].anchor; 00268 yaml_char_t *anchor = NULL; 00269 00270 if (anchor_id) { 00271 anchor = yaml_emitter_generate_anchor(emitter, anchor_id); 00272 if (!anchor) return 0; 00273 } 00274 00275 if (emitter->anchors[index-1].serialized) { 00276 return yaml_emitter_dump_alias(emitter, anchor); 00277 } 00278 00279 emitter->anchors[index-1].serialized = 1; 00280 00281 switch (node->type) { 00282 case YAML_SCALAR_NODE: 00283 return yaml_emitter_dump_scalar(emitter, node, anchor); 00284 case YAML_SEQUENCE_NODE: 00285 return yaml_emitter_dump_sequence(emitter, node, anchor); 00286 case YAML_MAPPING_NODE: 00287 return yaml_emitter_dump_mapping(emitter, node, anchor); 00288 default: 00289 assert(0); /* Could not happen. */ 00290 break; 00291 } 00292 00293 return 0; /* Could not happen. */ 00294 } 00295 00296 /* 00297 * Serialize an alias. 00298 */ 00299 00300 static int 00301 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor) 00302 { 00303 yaml_event_t event; 00304 yaml_mark_t mark = { 0, 0, 0 }; 00305 00306 ALIAS_EVENT_INIT(event, anchor, mark, mark); 00307 00308 return yaml_emitter_emit(emitter, &event); 00309 } 00310 00311 /* 00312 * Serialize a scalar. 00313 */ 00314 00315 static int 00316 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, 00317 yaml_char_t *anchor) 00318 { 00319 yaml_event_t event; 00320 yaml_mark_t mark = { 0, 0, 0 }; 00321 00322 int plain_implicit = (strcmp((char *)node->tag, 00323 YAML_DEFAULT_SCALAR_TAG) == 0); 00324 int quoted_implicit = (strcmp((char *)node->tag, 00325 YAML_DEFAULT_SCALAR_TAG) == 0); 00326 00327 SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value, 00328 node->data.scalar.length, plain_implicit, quoted_implicit, 00329 node->data.scalar.style, mark, mark); 00330 00331 return yaml_emitter_emit(emitter, &event); 00332 } 00333 00334 /* 00335 * Serialize a sequence. 00336 */ 00337 00338 static int 00339 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, 00340 yaml_char_t *anchor) 00341 { 00342 yaml_event_t event; 00343 yaml_mark_t mark = { 0, 0, 0 }; 00344 00345 int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0); 00346 00347 yaml_node_item_t *item; 00348 00349 SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit, 00350 node->data.sequence.style, mark, mark); 00351 if (!yaml_emitter_emit(emitter, &event)) return 0; 00352 00353 for (item = node->data.sequence.items.start; 00354 item < node->data.sequence.items.top; item ++) { 00355 if (!yaml_emitter_dump_node(emitter, *item)) return 0; 00356 } 00357 00358 SEQUENCE_END_EVENT_INIT(event, mark, mark); 00359 if (!yaml_emitter_emit(emitter, &event)) return 0; 00360 00361 return 1; 00362 } 00363 00364 /* 00365 * Serialize a mapping. 00366 */ 00367 00368 static int 00369 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, 00370 yaml_char_t *anchor) 00371 { 00372 yaml_event_t event; 00373 yaml_mark_t mark = { 0, 0, 0 }; 00374 00375 int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0); 00376 00377 yaml_node_pair_t *pair; 00378 00379 MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit, 00380 node->data.mapping.style, mark, mark); 00381 if (!yaml_emitter_emit(emitter, &event)) return 0; 00382 00383 for (pair = node->data.mapping.pairs.start; 00384 pair < node->data.mapping.pairs.top; pair ++) { 00385 if (!yaml_emitter_dump_node(emitter, pair->key)) return 0; 00386 if (!yaml_emitter_dump_node(emitter, pair->value)) return 0; 00387 } 00388 00389 MAPPING_END_EVENT_INIT(event, mark, mark); 00390 if (!yaml_emitter_emit(emitter, &event)) return 0; 00391 00392 return 1; 00393 } 00394 00395