Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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)
9 yaml_emitter_open(yaml_emitter_t *emitter);
10
11 YAML_DECLARE(int)
12 yaml_emitter_close(yaml_emitter_t *emitter);
13
14 YAML_DECLARE(int)
15 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
16
17 /*
18 * Clean up functions.
19 */
20
21 static void
22 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
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
43 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
44
45 static int
46 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
47 yaml_char_t *anchor);
48
49 static int
50 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
51 yaml_char_t *anchor);
52
53 static int
54 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
55 yaml_char_t *anchor);
56
57 /*
58 * Issue a STREAM-START event.
59 */
60
61 YAML_DECLARE(int)
62 yaml_emitter_open(yaml_emitter_t *emitter)
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)
86 yaml_emitter_close(yaml_emitter_t *emitter)
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)
112 yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
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;
128 yaml_emitter_delete_document_and_anchors(emitter);
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
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;
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
151 yaml_emitter_delete_document_and_anchors(emitter);
152
153 return 1;
154
155 error:
156
157 yaml_emitter_delete_document_and_anchors(emitter);
158
159 return 0;
160 }
161
162 /*
163 * Clean up the emitter object after a document is dumped.
164 */
165
166 static void
167 yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
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
207 yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
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 *
248 yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
249 {
250 yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
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
264 yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
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
301 yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
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
316 yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
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,
323 YAML_DEFAULT_SCALAR_TAG) == 0);
324 int quoted_implicit = (strcmp((char *)node->tag,
325 YAML_DEFAULT_SCALAR_TAG) == 0);
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
339 yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
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
369 yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
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
data
VALUE data
Definition: tcltklib.c:3368
yaml_node_s::data
union yaml_node_s::@29 data
The node data.
yaml_mark_s
The pointer position.
Definition: yaml.h:145
STREAM_END_EVENT_INIT
#define STREAM_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:538
yaml_event_s
The event structure.
Definition: yaml.h:384
ANCHOR_TEMPLATE_LENGTH
#define ANCHOR_TEMPLATE_LENGTH
Definition: dumper.c:245
SCALAR_EVENT_INIT
#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:557
yaml_emitter_generate_anchor
static yaml_char_t * yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
Definition: dumper.c:248
pair
volatile VALUE pair
Definition: tkutil.c:554
yaml_emitter_anchor_node
static void yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
Definition: dumper.c:207
yaml_emitter_s::last_anchor_id
int last_anchor_id
The last assigned anchor id.
Definition: yaml.h:1753
yaml_emitter_delete_document_and_anchors
static void yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
Definition: dumper.c:167
yaml_emitter_s::document
yaml_document_t * document
The currently emitted document.
Definition: yaml.h:1756
YAML_SCALAR_NODE
A scalar node.
Definition: yaml.h:695
STREAM_START_EVENT_INIT
#define STREAM_START_EVENT_INIT(event, event_encoding, start_mark, end_mark)
Definition: yaml_private.h:534
yaml_node_s::type
yaml_node_type_t type
The node type.
Definition: yaml.h:720
yaml_node_s::mapping
struct yaml_node_s::@29::@32 mapping
The mapping parameters (for YAML_MAPPING_NODE).
SEQUENCE_START_EVENT_INIT
#define SEQUENCE_START_EVENT_INIT(event, event_anchor, event_tag,event_implicit, event_style, start_mark, end_mark)
Definition: yaml_private.h:568
yaml_char_t
unsigned char yaml_char_t
The character type (UTF-8 octet).
Definition: yaml.h:78
YAML_ANY_ENCODING
Let the parser choose the encoding.
Definition: yaml.h:99
index
int index
Definition: tcltklib.c:4478
yaml_emitter_s::references
int references
The number of references.
Definition: yaml.h:1745
MAPPING_START_EVENT_INIT
#define MAPPING_START_EVENT_INIT(event, event_anchor, event_tag,event_implicit, event_style, start_mark, end_mark)
Definition: yaml_private.h:579
yaml_node_pair_s
An element of a mapping node.
Definition: yaml.h:709
yaml_document_delete
yaml_document_delete(yaml_document_t *document)
Delete a YAML document and all its nodes.
Definition: api.c:1117
yaml_node_item_t
int yaml_node_item_t
An element of a sequence node.
Definition: yaml.h:706
yaml_emitter_emit
yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
Emit an event.
Definition: emitter.c:281
SEQUENCE_END_EVENT_INIT
#define SEQUENCE_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:576
yaml_node_s
The node structure.
Definition: yaml.h:717
STACK_EMPTY
#define STACK_EMPTY(context, stack)
Definition: yaml_private.h:424
yaml_node_pair_s::key
int key
The key of the element.
Definition: yaml.h:711
yaml_free
yaml_free(void *ptr)
Definition: api.c:51
YAML_DEFAULT_SEQUENCE_TAG
#define YAML_DEFAULT_SEQUENCE_TAG
The default sequence tag is !!seq.
Definition: yaml.h:685
memset
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
yaml_emitter_s
The emitter structure.
Definition: yaml.h:1525
YAML_MAPPING_NODE
A mapping node.
Definition: yaml.h:699
yaml_emitter_close
yaml_emitter_close(yaml_emitter_t *emitter)
Finish a YAML stream.
Definition: dumper.c:86
yaml_node_s::tag
yaml_char_t * tag
The node tag.
Definition: yaml.h:723
yaml_emitter_dump_node
static int yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
Definition: dumper.c:264
yaml_emitter_s::serialized
int serialized
If the node has been emitted?
Definition: yaml.h:1749
ALIAS_EVENT_INIT
#define ALIAS_EVENT_INIT(event, event_anchor, start_mark, end_mark)
Definition: yaml_private.h:553
YAML_DECLARE
#define YAML_DECLARE(type)
The public API declaration.
Definition: yaml.h:38
yaml_emitter_dump_scalar
static int yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, yaml_char_t *anchor)
Definition: dumper.c:316
STACK_DEL
#define STACK_DEL(context, stack)
Definition: yaml_private.h:420
yaml_document_s::top
yaml_node_t * top
The top of the stack.
Definition: yaml.h:787
yaml_node_s::scalar
struct yaml_node_s::@29::@30 scalar
The scalar parameters (for YAML_SCALAR_NODE).
DOCUMENT_END_EVENT_INIT
#define DOCUMENT_END_EVENT_INIT(event, event_implicit, start_mark, end_mark)
Definition: yaml_private.h:549
yaml_emitter_dump_alias
static int yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
Definition: dumper.c:301
MAPPING_END_EVENT_INIT
#define MAPPING_END_EVENT_INIT(event, start_mark, end_mark)
Definition: yaml_private.h:587
yaml_event_s::version_directive
yaml_version_directive_t * version_directive
The version directive.
Definition: yaml.h:401
yaml_emitter_s::anchor
yaml_char_t * anchor
The anchor value.
Definition: yaml.h:1689
yaml_node_pair_s::value
int value
The value of the element.
Definition: yaml.h:713
yaml_node_s::sequence
struct yaml_node_s::@29::@31 sequence
The sequence parameters (for YAML_SEQUENCE_NODE).
ANCHOR_TEMPLATE
#define ANCHOR_TEMPLATE
Definition: dumper.c:244
yaml_emitter_dump_mapping
static int yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, yaml_char_t *anchor)
Definition: dumper.c:369
YAML_SEQUENCE_NODE
A sequence node.
Definition: yaml.h:697
DOCUMENT_START_EVENT_INIT
#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:541
YAML_DEFAULT_SCALAR_TAG
#define YAML_DEFAULT_SCALAR_TAG
The default scalar tag is !!str.
Definition: yaml.h:683
yaml_document_s::nodes
struct yaml_document_s::@35 nodes
The document nodes.
yaml_document_s::start
yaml_node_t * start
The beginning of the stack.
Definition: yaml.h:783
mark
static VALUE mark(VALUE self)
Definition: psych_parser.c:523
yaml_emitter_dump_sequence
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_dump(yaml_emitter_t *emitter, yaml_document_t *document)
Emit a YAML document.
Definition: dumper.c:112
assert
#define assert(condition)
Definition: ossl.h:45
yaml_emitter_open
yaml_emitter_open(yaml_emitter_t *emitter)
Start a YAML stream.
Definition: dumper.c:62
yaml_malloc
yaml_malloc(size_t size)
Definition: api.c:31
YAML_DEFAULT_MAPPING_TAG
#define YAML_DEFAULT_MAPPING_TAG
The default mapping tag is !!map.
Definition: yaml.h:687
yaml_private.h
NULL
#define NULL
Definition: _sdbm.c:103
yaml_document_s
The document structure.
Definition: yaml.h:778
yaml_emitter_s::anchors
struct yaml_emitter_s::@58 * anchors
The information associated with the document nodes.