2 #include "yaml_private.h"
9 yaml_emitter_open(yaml_emitter_t *emitter);
12 yaml_emitter_close(yaml_emitter_t *emitter);
15 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
22 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
29 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
32 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
36 * Serialize functions.
40 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
43 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
46 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
50 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
54 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
58 * Issue a STREAM-START event.
62 yaml_emitter_open(yaml_emitter_t *emitter)
65 yaml_mark_t mark = { 0, 0, 0 };
67 assert(emitter); /* Non-NULL emitter object is required. */
68 assert(!emitter->opened); /* Emitter should not be opened yet. */
70 STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
72 if (!yaml_emitter_emit(emitter, &event)) {
82 * Issue a STREAM-END event.
86 yaml_emitter_close(yaml_emitter_t *emitter)
89 yaml_mark_t mark = { 0, 0, 0 };
91 assert(emitter); /* Non-NULL emitter object is required. */
92 assert(emitter->opened); /* Emitter should be opened. */
94 if (emitter->closed) return 1;
96 STREAM_END_EVENT_INIT(event, mark, mark);
98 if (!yaml_emitter_emit(emitter, &event)) {
108 * Dump a YAML document.
112 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
115 yaml_mark_t mark = { 0, 0, 0 };
117 assert(emitter); /* Non-NULL emitter object is required. */
118 assert(document); /* Non-NULL emitter object is expected. */
120 emitter->document = document;
122 if (!emitter->opened) {
123 if (!yaml_emitter_open(emitter)) goto error;
126 if (STACK_EMPTY(emitter, document->nodes)) {
127 if (!yaml_emitter_close(emitter)) goto error;
128 yaml_emitter_delete_document_and_anchors(emitter);
132 assert(emitter->opened); /* Emitter should be opened. */
134 emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
135 * (document->nodes.top - document->nodes.start));
136 if (!emitter->anchors) goto error;
137 memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
138 * (document->nodes.top - document->nodes.start));
140 DOCUMENT_START_EVENT_INIT(event, document->version_directive,
141 document->tag_directives.start, document->tag_directives.end,
142 document->start_implicit, mark, mark);
143 if (!yaml_emitter_emit(emitter, &event)) goto error;
145 yaml_emitter_anchor_node(emitter, 1);
146 if (!yaml_emitter_dump_node(emitter, 1)) goto error;
148 DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
149 if (!yaml_emitter_emit(emitter, &event)) goto error;
151 yaml_emitter_delete_document_and_anchors(emitter);
157 yaml_emitter_delete_document_and_anchors(emitter);
163 * Clean up the emitter object after a document is dumped.
167 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
171 if (!emitter->anchors) {
172 yaml_document_delete(emitter->document);
173 emitter->document = NULL;
177 for (index = 0; emitter->document->nodes.start + index
178 < emitter->document->nodes.top; index ++) {
179 yaml_node_t node = emitter->document->nodes.start[index];
180 if (!emitter->anchors[index].serialized) {
182 if (node.type == YAML_SCALAR_NODE) {
183 yaml_free(node.data.scalar.value);
186 if (node.type == YAML_SEQUENCE_NODE) {
187 STACK_DEL(emitter, node.data.sequence.items);
189 if (node.type == YAML_MAPPING_NODE) {
190 STACK_DEL(emitter, node.data.mapping.pairs);
194 STACK_DEL(emitter, emitter->document->nodes);
195 yaml_free(emitter->anchors);
197 emitter->anchors = NULL;
198 emitter->last_anchor_id = 0;
199 emitter->document = NULL;
203 * Check the references of a node and assign the anchor id if needed.
207 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
209 yaml_node_t *node = emitter->document->nodes.start + index - 1;
210 yaml_node_item_t *item;
211 yaml_node_pair_t *pair;
213 emitter->anchors[index-1].references ++;
215 if (emitter->anchors[index-1].references == 1) {
216 switch (node->type) {
217 case YAML_SEQUENCE_NODE:
218 for (item = node->data.sequence.items.start;
219 item < node->data.sequence.items.top; item ++) {
220 yaml_emitter_anchor_node(emitter, *item);
223 case YAML_MAPPING_NODE:
224 for (pair = node->data.mapping.pairs.start;
225 pair < node->data.mapping.pairs.top; pair ++) {
226 yaml_emitter_anchor_node(emitter, pair->key);
227 yaml_emitter_anchor_node(emitter, pair->value);
235 else if (emitter->anchors[index-1].references == 2) {
236 emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
241 * Generate a textual representation for an anchor.
244 #define ANCHOR_TEMPLATE "id%03d"
245 #define ANCHOR_TEMPLATE_LENGTH 16
248 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
250 yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
252 if (!anchor) return NULL;
254 sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
264 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
266 yaml_node_t *node = emitter->document->nodes.start + index - 1;
267 int anchor_id = emitter->anchors[index-1].anchor;
268 yaml_char_t *anchor = NULL;
271 anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
272 if (!anchor) return 0;
275 if (emitter->anchors[index-1].serialized) {
276 return yaml_emitter_dump_alias(emitter, anchor);
279 emitter->anchors[index-1].serialized = 1;
281 switch (node->type) {
282 case YAML_SCALAR_NODE:
283 return yaml_emitter_dump_scalar(emitter, node, anchor);
284 case YAML_SEQUENCE_NODE:
285 return yaml_emitter_dump_sequence(emitter, node, anchor);
286 case YAML_MAPPING_NODE:
287 return yaml_emitter_dump_mapping(emitter, node, anchor);
289 assert(0); /* Could not happen. */
293 return 0; /* Could not happen. */
297 * Serialize an alias.
301 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
304 yaml_mark_t mark = { 0, 0, 0 };
306 ALIAS_EVENT_INIT(event, anchor, mark, mark);
308 return yaml_emitter_emit(emitter, &event);
312 * Serialize a scalar.
316 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
320 yaml_mark_t mark = { 0, 0, 0 };
322 int plain_implicit = (strcmp((char *)node->tag,
323 YAML_DEFAULT_SCALAR_TAG) == 0);
324 int quoted_implicit = (strcmp((char *)node->tag,
325 YAML_DEFAULT_SCALAR_TAG) == 0);
327 SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
328 node->data.scalar.length, plain_implicit, quoted_implicit,
329 node->data.scalar.style, mark, mark);
331 return yaml_emitter_emit(emitter, &event);
335 * Serialize a sequence.
339 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
343 yaml_mark_t mark = { 0, 0, 0 };
345 int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
347 yaml_node_item_t *item;
349 SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
350 node->data.sequence.style, mark, mark);
351 if (!yaml_emitter_emit(emitter, &event)) return 0;
353 for (item = node->data.sequence.items.start;
354 item < node->data.sequence.items.top; item ++) {
355 if (!yaml_emitter_dump_node(emitter, *item)) return 0;
358 SEQUENCE_END_EVENT_INIT(event, mark, mark);
359 if (!yaml_emitter_emit(emitter, &event)) return 0;
365 * Serialize a mapping.
369 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
373 yaml_mark_t mark = { 0, 0, 0 };
375 int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
377 yaml_node_pair_t *pair;
379 MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
380 node->data.mapping.style, mark, mark);
381 if (!yaml_emitter_emit(emitter, &event)) return 0;
383 for (pair = node->data.mapping.pairs.start;
384 pair < node->data.mapping.pairs.top; pair ++) {
385 if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
386 if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
389 MAPPING_END_EVENT_INIT(event, mark, mark);
390 if (!yaml_emitter_emit(emitter, &event)) return 0;