00001
00002 #include "yaml_private.h"
00003
00004
00005
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
00019
00020
00021 static void
00022 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
00023
00024
00025
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
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
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);
00068 assert(!emitter->opened);
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
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);
00092 assert(emitter->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
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);
00118 assert(document);
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);
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
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
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
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
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);
00290 break;
00291 }
00292
00293 return 0;
00294 }
00295
00296
00297
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
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
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
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