Ruby  2.0.0p648(2015-12-16revision53162)
dumper.c
Go to the documentation of this file.
1 
2 #include "yaml_private.h"
3 
4 /*
5  * API functions.
6  */
7 
8 YAML_DECLARE(int)
10 
11 YAML_DECLARE(int)
13 
14 YAML_DECLARE(int)
16 
17 /*
18  * Clean up functions.
19  */
20 
21 static void
23 
24 /*
25  * Anchor functions.
26  */
27 
28 static void
29 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
30 
31 static yaml_char_t *
32 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
33 
34 
35 /*
36  * Serialize functions.
37  */
38 
39 static int
40 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
41 
42 static int
44 
45 static int
47  yaml_char_t *anchor);
48 
49 static int
51  yaml_char_t *anchor);
52 
53 static int
55  yaml_char_t *anchor);
56 
57 /*
58  * Issue a STREAM-START event.
59  */
60 
61 YAML_DECLARE(int)
63 {
64  yaml_event_t event;
65  yaml_mark_t mark = { 0, 0, 0 };
66 
67  assert(emitter); /* Non-NULL emitter object is required. */
68  assert(!emitter->opened); /* Emitter should not be opened yet. */
69 
70  STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
71 
72  if (!yaml_emitter_emit(emitter, &event)) {
73  return 0;
74  }
75 
76  emitter->opened = 1;
77 
78  return 1;
79 }
80 
81 /*
82  * Issue a STREAM-END event.
83  */
84 
85 YAML_DECLARE(int)
87 {
88  yaml_event_t event;
89  yaml_mark_t mark = { 0, 0, 0 };
90 
91  assert(emitter); /* Non-NULL emitter object is required. */
92  assert(emitter->opened); /* Emitter should be opened. */
93 
94  if (emitter->closed) return 1;
95 
96  STREAM_END_EVENT_INIT(event, mark, mark);
97 
98  if (!yaml_emitter_emit(emitter, &event)) {
99  return 0;
100  }
101 
102  emitter->closed = 1;
103 
104  return 1;
105 }
106 
107 /*
108  * Dump a YAML document.
109  */
110 
111 YAML_DECLARE(int)
113 {
114  yaml_event_t event;
115  yaml_mark_t mark = { 0, 0, 0 };
116 
117  assert(emitter); /* Non-NULL emitter object is required. */
118  assert(document); /* Non-NULL emitter object is expected. */
119 
120  emitter->document = document;
121 
122  if (!emitter->opened) {
123  if (!yaml_emitter_open(emitter)) goto error;
124  }
125 
126  if (STACK_EMPTY(emitter, document->nodes)) {
127  if (!yaml_emitter_close(emitter)) goto error;
129  return 1;
130  }
131 
132  assert(emitter->opened); /* Emitter should be opened. */
133 
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));
139 
141  document->tag_directives.start, document->tag_directives.end,
142  document->start_implicit, mark, mark);
143  if (!yaml_emitter_emit(emitter, &event)) goto error;
144 
145  yaml_emitter_anchor_node(emitter, 1);
146  if (!yaml_emitter_dump_node(emitter, 1)) goto error;
147 
148  DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
149  if (!yaml_emitter_emit(emitter, &event)) goto error;
150 
152 
153  return 1;
154 
155 error:
156 
158 
159  return 0;
160 }
161 
162 /*
163  * Clean up the emitter object after a document is dumped.
164  */
165 
166 static void
168 {
169  int index;
170 
171  if (!emitter->anchors) {
172  yaml_document_delete(emitter->document);
173  emitter->document = NULL;
174  return;
175  }
176 
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) {
181  yaml_free(node.tag);
182  if (node.type == YAML_SCALAR_NODE) {
183  yaml_free(node.data.scalar.value);
184  }
185  }
186  if (node.type == YAML_SEQUENCE_NODE) {
187  STACK_DEL(emitter, node.data.sequence.items);
188  }
189  if (node.type == YAML_MAPPING_NODE) {
190  STACK_DEL(emitter, node.data.mapping.pairs);
191  }
192  }
193 
194  STACK_DEL(emitter, emitter->document->nodes);
195  yaml_free(emitter->anchors);
196 
197  emitter->anchors = NULL;
198  emitter->last_anchor_id = 0;
199  emitter->document = NULL;
200 }
201 
202 /*
203  * Check the references of a node and assign the anchor id if needed.
204  */
205 
206 static void
208 {
209  yaml_node_t *node = emitter->document->nodes.start + index - 1;
210  yaml_node_item_t *item;
211  yaml_node_pair_t *pair;
212 
213  emitter->anchors[index-1].references ++;
214 
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);
221  }
222  break;
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);
228  }
229  break;
230  default:
231  break;
232  }
233  }
234 
235  else if (emitter->anchors[index-1].references == 2) {
236  emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
237  }
238 }
239 
240 /*
241  * Generate a textual representation for an anchor.
242  */
243 
244 #define ANCHOR_TEMPLATE "id%03d"
245 #define ANCHOR_TEMPLATE_LENGTH 16
246 
247 static yaml_char_t *
249 {
251 
252  if (!anchor) return NULL;
253 
254  sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
255 
256  return anchor;
257 }
258 
259 /*
260  * Serialize a node.
261  */
262 
263 static int
265 {
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;
269 
270  if (anchor_id) {
271  anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
272  if (!anchor) return 0;
273  }
274 
275  if (emitter->anchors[index-1].serialized) {
276  return yaml_emitter_dump_alias(emitter, anchor);
277  }
278 
279  emitter->anchors[index-1].serialized = 1;
280 
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);
288  default:
289  assert(0); /* Could not happen. */
290  break;
291  }
292 
293  return 0; /* Could not happen. */
294 }
295 
296 /*
297  * Serialize an alias.
298  */
299 
300 static int
302 {
303  yaml_event_t event;
304  yaml_mark_t mark = { 0, 0, 0 };
305 
306  ALIAS_EVENT_INIT(event, anchor, mark, mark);
307 
308  return yaml_emitter_emit(emitter, &event);
309 }
310 
311 /*
312  * Serialize a scalar.
313  */
314 
315 static int
317  yaml_char_t *anchor)
318 {
319  yaml_event_t event;
320  yaml_mark_t mark = { 0, 0, 0 };
321 
322  int plain_implicit = (strcmp((char *)node->tag,
324  int quoted_implicit = (strcmp((char *)node->tag,
326 
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);
330 
331  return yaml_emitter_emit(emitter, &event);
332 }
333 
334 /*
335  * Serialize a sequence.
336  */
337 
338 static int
340  yaml_char_t *anchor)
341 {
342  yaml_event_t event;
343  yaml_mark_t mark = { 0, 0, 0 };
344 
345  int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
346 
347  yaml_node_item_t *item;
348 
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;
352 
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;
356  }
357 
358  SEQUENCE_END_EVENT_INIT(event, mark, mark);
359  if (!yaml_emitter_emit(emitter, &event)) return 0;
360 
361  return 1;
362 }
363 
364 /*
365  * Serialize a mapping.
366  */
367 
368 static int
370  yaml_char_t *anchor)
371 {
372  yaml_event_t event;
373  yaml_mark_t mark = { 0, 0, 0 };
374 
375  int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
376 
377  yaml_node_pair_t *pair;
378 
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;
382 
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;
387  }
388 
389  MAPPING_END_EVENT_INIT(event, mark, mark);
390  if (!yaml_emitter_emit(emitter, &event)) return 0;
391 
392  return 1;
393 }
394 
union yaml_node_s::@29 data
The node data.
The pointer position.
Definition: yaml.h:145
#define STREAM_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:559
The event structure.
Definition: yaml.h:384
#define ANCHOR_TEMPLATE_LENGTH
Definition: dumper.c:245
#define SCALAR_EVENT_INIT(event, event_anchor, event_tag, event_value, event_length,event_plain_implicit, event_quoted_implicit, event_style, start_mark, end_mark)
Definition: yaml_private.h:578
static yaml_char_t * yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
Definition: dumper.c:248
static void yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
Definition: dumper.c:207
int last_anchor_id
The last assigned anchor id.
Definition: yaml.h:1753
static void yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
Definition: dumper.c:167
yaml_document_t * document
The currently emitted document.
Definition: yaml.h:1756
A scalar node.
Definition: yaml.h:695
#define STREAM_START_EVENT_INIT(event, event_encoding, start_mark, end_mark)
Definition: yaml_private.h:555
yaml_node_type_t type
The node type.
Definition: yaml.h:720
struct yaml_node_s::@29::@32 mapping
The mapping parameters (for YAML_MAPPING_NODE).
#define SEQUENCE_START_EVENT_INIT(event, event_anchor, event_tag,event_implicit, event_style, start_mark, end_mark)
Definition: yaml_private.h:589
unsigned char yaml_char_t
The character type (UTF-8 octet).
Definition: yaml.h:78
Let the parser choose the encoding.
Definition: yaml.h:99
int references
The number of references.
Definition: yaml.h:1745
#define MAPPING_START_EVENT_INIT(event, event_anchor, event_tag,event_implicit, event_style, start_mark, end_mark)
Definition: yaml_private.h:600
An element of a mapping node.
Definition: yaml.h:709
yaml_document_delete(yaml_document_t *document)
Delete a YAML document and all its nodes.
Definition: api.c:1121
int yaml_node_item_t
An element of a sequence node.
Definition: yaml.h:706
yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
Emit an event.
Definition: emitter.c:281
#define SEQUENCE_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:597
The node structure.
Definition: yaml.h:717
#define STACK_EMPTY(context, stack)
Definition: yaml_private.h:438
int key
The key of the element.
Definition: yaml.h:711
yaml_free(void *ptr)
Definition: api.c:51
#define YAML_DEFAULT_SEQUENCE_TAG
The default sequence tag is !!seq.
Definition: yaml.h:685
The emitter structure.
Definition: yaml.h:1525
A mapping node.
Definition: yaml.h:699
yaml_emitter_close(yaml_emitter_t *emitter)
Finish a YAML stream.
Definition: dumper.c:86
yaml_char_t * tag
The node tag.
Definition: yaml.h:723
static int yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
Definition: dumper.c:264
int serialized
If the node has been emitted?
Definition: yaml.h:1749
#define ALIAS_EVENT_INIT(event, event_anchor, start_mark, end_mark)
Definition: yaml_private.h:574
#define YAML_DECLARE(type)
The public API declaration.
Definition: yaml.h:38
static int yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, yaml_char_t *anchor)
Definition: dumper.c:316
#define STACK_DEL(context, stack)
Definition: yaml_private.h:434
yaml_node_t * top
The top of the stack.
Definition: yaml.h:787
struct yaml_node_s::@29::@30 scalar
The scalar parameters (for YAML_SCALAR_NODE).
#define DOCUMENT_END_EVENT_INIT(event, event_implicit, start_mark, end_mark)
Definition: yaml_private.h:570
static int yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
Definition: dumper.c:301
#define MAPPING_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:608
yaml_version_directive_t * version_directive
The version directive.
Definition: yaml.h:401
yaml_char_t * anchor
The anchor value.
Definition: yaml.h:1689
int value
The value of the element.
Definition: yaml.h:713
struct yaml_node_s::@29::@31 sequence
The sequence parameters (for YAML_SEQUENCE_NODE).
#define ANCHOR_TEMPLATE
Definition: dumper.c:244
static int yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, yaml_char_t *anchor)
Definition: dumper.c:369
A sequence node.
Definition: yaml.h:697
#define DOCUMENT_START_EVENT_INIT(event, event_version_directive,event_tag_directives_start, event_tag_directives_end, event_implicit, start_mark, end_mark)
Definition: yaml_private.h:562
#define YAML_DEFAULT_SCALAR_TAG
The default scalar tag is !!str.
Definition: yaml.h:683
struct yaml_document_s::@35 nodes
The document nodes.
yaml_node_t * start
The beginning of the stack.
Definition: yaml.h:783
static VALUE mark(VALUE self)
Definition: psych_parser.c:523
static int yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, yaml_char_t *anchor)
Definition: dumper.c:339
yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
Emit a YAML document.
Definition: dumper.c:112
#define assert(condition)
Definition: ossl.h:45
yaml_emitter_open(yaml_emitter_t *emitter)
Start a YAML stream.
Definition: dumper.c:62
yaml_malloc(size_t size)
Definition: api.c:31
#define YAML_DEFAULT_MAPPING_TAG
The default mapping tag is !!map.
Definition: yaml.h:687
#define NULL
Definition: _sdbm.c:102
The document structure.
Definition: yaml.h:778
struct yaml_emitter_s::@58 * anchors
The information associated with the document nodes.