File Coverage

dumper.c
Criterion Covered Total %
statement 0 140 0.0
branch 0 82 0.0
condition n/a
subroutine n/a
pod n/a
total 0 222 0.0


line stmt bran cond sub pod time code
1              
2             #include "yaml_private.h"
3              
4             /*
5             * API functions: see yaml.h
6             */
7              
8             /*
9             * Clean up functions.
10             */
11              
12             static void
13             yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
14              
15             /*
16             * Anchor functions.
17             */
18              
19             static void
20             yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
21              
22             static yaml_char_t *
23             yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
24              
25              
26             /*
27             * Serialize functions.
28             */
29              
30             static int
31             yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
32              
33             static int
34             yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
35              
36             static int
37             yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
38             yaml_char_t *anchor);
39              
40             static int
41             yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
42             yaml_char_t *anchor);
43              
44             static int
45             yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
46             yaml_char_t *anchor);
47              
48             /*
49             * Issue a STREAM-START event.
50             */
51              
52             YAML_DECLARE(int)
53 0           yaml_emitter_open(yaml_emitter_t *emitter)
54             {
55             yaml_event_t event;
56 0           yaml_mark_t mark = { 0, 0, 0 };
57              
58 0 0         assert(emitter); /* Non-NULL emitter object is required. */
59 0 0         assert(!emitter->opened); /* Emitter should not be opened yet. */
60              
61 0           STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
62              
63 0 0         if (!yaml_emitter_emit(emitter, &event)) {
64 0           return 0;
65             }
66              
67 0           emitter->opened = 1;
68              
69 0           return 1;
70             }
71              
72             /*
73             * Issue a STREAM-END event.
74             */
75              
76             YAML_DECLARE(int)
77 0           yaml_emitter_close(yaml_emitter_t *emitter)
78             {
79             yaml_event_t event;
80 0           yaml_mark_t mark = { 0, 0, 0 };
81              
82 0 0         assert(emitter); /* Non-NULL emitter object is required. */
83 0 0         assert(emitter->opened); /* Emitter should be opened. */
84              
85 0 0         if (emitter->closed) return 1;
86              
87 0           STREAM_END_EVENT_INIT(event, mark, mark);
88              
89 0 0         if (!yaml_emitter_emit(emitter, &event)) {
90 0           return 0;
91             }
92              
93 0           emitter->closed = 1;
94              
95 0           return 1;
96             }
97              
98             /*
99             * Dump a YAML document.
100             */
101              
102             YAML_DECLARE(int)
103 0           yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
104             {
105             yaml_event_t event;
106 0           yaml_mark_t mark = { 0, 0, 0 };
107              
108 0 0         assert(emitter); /* Non-NULL emitter object is required. */
109 0 0         assert(document); /* Non-NULL emitter object is expected. */
110              
111 0           emitter->document = document;
112              
113 0 0         if (!emitter->opened) {
114 0 0         if (!yaml_emitter_open(emitter)) goto error;
115             }
116              
117 0 0         if (STACK_EMPTY(emitter, document->nodes)) {
118 0 0         if (!yaml_emitter_close(emitter)) goto error;
119 0           yaml_emitter_delete_document_and_anchors(emitter);
120 0           return 1;
121             }
122              
123 0 0         assert(emitter->opened); /* Emitter should be opened. */
124              
125 0           emitter->anchors = (yaml_anchors_t*)yaml_malloc(sizeof(*(emitter->anchors))
126 0           * (document->nodes.top - document->nodes.start));
127 0 0         if (!emitter->anchors) goto error;
128 0           memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
129 0           * (document->nodes.top - document->nodes.start));
130              
131 0           DOCUMENT_START_EVENT_INIT(event, document->version_directive,
132             document->tag_directives.start, document->tag_directives.end,
133             document->start_implicit, mark, mark);
134 0 0         if (!yaml_emitter_emit(emitter, &event)) goto error;
135              
136 0           yaml_emitter_anchor_node(emitter, 1);
137 0 0         if (!yaml_emitter_dump_node(emitter, 1)) goto error;
138              
139 0           DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
140 0 0         if (!yaml_emitter_emit(emitter, &event)) goto error;
141              
142 0           yaml_emitter_delete_document_and_anchors(emitter);
143              
144 0           return 1;
145              
146             error:
147              
148 0           yaml_emitter_delete_document_and_anchors(emitter);
149              
150 0           return 0;
151             }
152              
153             /*
154             * Clean up the emitter object after a document is dumped.
155             */
156              
157             static void
158 0           yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
159             {
160             int index;
161              
162 0 0         if (!emitter->anchors) {
163 0           yaml_document_delete(emitter->document);
164 0           emitter->document = NULL;
165 0           return;
166             }
167              
168 0 0         for (index = 0; emitter->document->nodes.start + index
169 0           < emitter->document->nodes.top; index ++) {
170 0           yaml_node_t node = emitter->document->nodes.start[index];
171 0 0         if (!emitter->anchors[index].serialized) {
172 0           yaml_free(node.tag);
173 0 0         if (node.type == YAML_SCALAR_NODE) {
174 0           yaml_free(node.data.scalar.value);
175             }
176             }
177 0 0         if (node.type == YAML_SEQUENCE_NODE) {
178 0           STACK_DEL(emitter, node.data.sequence.items);
179             }
180 0 0         if (node.type == YAML_MAPPING_NODE) {
181 0           STACK_DEL(emitter, node.data.mapping.pairs);
182             }
183             }
184              
185 0           STACK_DEL(emitter, emitter->document->nodes);
186 0           yaml_free(emitter->anchors);
187              
188 0           emitter->anchors = NULL;
189 0           emitter->last_anchor_id = 0;
190 0           emitter->document = NULL;
191             }
192              
193             /*
194             * Check the references of a node and assign the anchor id if needed.
195             */
196              
197             static void
198 0           yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
199             {
200 0           yaml_node_t *node = emitter->document->nodes.start + index - 1;
201             yaml_node_item_t *item;
202             yaml_node_pair_t *pair;
203              
204 0           emitter->anchors[index-1].references ++;
205              
206 0 0         if (emitter->anchors[index-1].references == 1) {
207 0           switch (node->type) {
208             case YAML_SEQUENCE_NODE:
209 0 0         for (item = node->data.sequence.items.start;
210 0           item < node->data.sequence.items.top; item ++) {
211 0           yaml_emitter_anchor_node(emitter, *item);
212             }
213 0           break;
214             case YAML_MAPPING_NODE:
215 0 0         for (pair = node->data.mapping.pairs.start;
216 0           pair < node->data.mapping.pairs.top; pair ++) {
217 0           yaml_emitter_anchor_node(emitter, pair->key);
218 0           yaml_emitter_anchor_node(emitter, pair->value);
219             }
220 0           break;
221             default:
222 0           break;
223             }
224             }
225              
226 0 0         else if (emitter->anchors[index-1].references == 2) {
227 0           emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
228             }
229 0           }
230              
231             /*
232             * Generate a textual representation for an anchor.
233             */
234              
235             #define ANCHOR_TEMPLATE "id%03d"
236             #define ANCHOR_TEMPLATE_LENGTH 16
237              
238             static yaml_char_t *
239 0           yaml_emitter_generate_anchor(SHIM(yaml_emitter_t *emitter), int anchor_id)
240             {
241 0           yaml_char_t *anchor = YAML_MALLOC(ANCHOR_TEMPLATE_LENGTH);
242              
243 0 0         if (!anchor) return NULL;
244              
245 0           sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
246              
247 0           return anchor;
248             }
249              
250             /*
251             * Serialize a node.
252             */
253              
254             static int
255 0           yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
256             {
257 0           yaml_node_t *node = emitter->document->nodes.start + index - 1;
258 0           int anchor_id = emitter->anchors[index-1].anchor;
259 0           yaml_char_t *anchor = NULL;
260              
261 0 0         if (anchor_id) {
262 0           anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
263 0 0         if (!anchor) return 0;
264             }
265              
266 0 0         if (emitter->anchors[index-1].serialized) {
267 0           return yaml_emitter_dump_alias(emitter, anchor);
268             }
269              
270 0           emitter->anchors[index-1].serialized = 1;
271              
272 0           switch (node->type) {
273             case YAML_SCALAR_NODE:
274 0           return yaml_emitter_dump_scalar(emitter, node, anchor);
275             case YAML_SEQUENCE_NODE:
276 0           return yaml_emitter_dump_sequence(emitter, node, anchor);
277             case YAML_MAPPING_NODE:
278 0           return yaml_emitter_dump_mapping(emitter, node, anchor);
279             default:
280 0           assert(0); /* Could not happen. */
281             break;
282             }
283              
284             return 0; /* Could not happen. */
285             }
286              
287             /*
288             * Serialize an alias.
289             */
290              
291             static int
292 0           yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
293             {
294             yaml_event_t event;
295 0           yaml_mark_t mark = { 0, 0, 0 };
296              
297 0           ALIAS_EVENT_INIT(event, anchor, mark, mark);
298              
299 0           return yaml_emitter_emit(emitter, &event);
300             }
301              
302             /*
303             * Serialize a scalar.
304             */
305              
306             static int
307 0           yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
308             yaml_char_t *anchor)
309             {
310             yaml_event_t event;
311 0           yaml_mark_t mark = { 0, 0, 0 };
312              
313 0           int plain_implicit = (strcmp((char *)node->tag,
314 0           YAML_DEFAULT_SCALAR_TAG) == 0);
315 0           int quoted_implicit = (strcmp((char *)node->tag,
316 0           YAML_DEFAULT_SCALAR_TAG) == 0);
317              
318 0           SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
319             node->data.scalar.length, plain_implicit, quoted_implicit,
320             node->data.scalar.style, mark, mark);
321              
322 0           return yaml_emitter_emit(emitter, &event);
323             }
324              
325             /*
326             * Serialize a sequence.
327             */
328              
329             static int
330 0           yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
331             yaml_char_t *anchor)
332             {
333             yaml_event_t event;
334 0           yaml_mark_t mark = { 0, 0, 0 };
335              
336 0           int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
337              
338             yaml_node_item_t *item;
339              
340 0           SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
341             node->data.sequence.style, mark, mark);
342 0 0         if (!yaml_emitter_emit(emitter, &event)) return 0;
343              
344 0 0         for (item = node->data.sequence.items.start;
345 0           item < node->data.sequence.items.top; item ++) {
346 0 0         if (!yaml_emitter_dump_node(emitter, *item)) return 0;
347             }
348              
349 0           SEQUENCE_END_EVENT_INIT(event, mark, mark);
350 0 0         if (!yaml_emitter_emit(emitter, &event)) return 0;
351              
352 0           return 1;
353             }
354              
355             /*
356             * Serialize a mapping.
357             */
358              
359             static int
360 0           yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
361             yaml_char_t *anchor)
362             {
363             yaml_event_t event;
364 0           yaml_mark_t mark = { 0, 0, 0 };
365              
366 0           int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
367              
368             yaml_node_pair_t *pair;
369              
370 0           MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
371             node->data.mapping.style, mark, mark);
372 0 0         if (!yaml_emitter_emit(emitter, &event)) return 0;
373              
374 0 0         for (pair = node->data.mapping.pairs.start;
375 0           pair < node->data.mapping.pairs.top; pair ++) {
376 0 0         if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
377 0 0         if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
378             }
379              
380 0           MAPPING_END_EVENT_INIT(event, mark, mark);
381 0 0         if (!yaml_emitter_emit(emitter, &event)) return 0;
382              
383 0           return 1;
384             }
385