]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libyaml/src/api.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libyaml / src / api.c
1
2 #include "yaml_private.h"
3
4 /*
5  * Get the library version.
6  */
7
8 YAML_DECLARE(const char *)
9 yaml_get_version_string(void)
10 {
11     return YAML_VERSION_STRING;
12 }
13
14 /*
15  * Get the library version numbers.
16  */
17
18 YAML_DECLARE(void)
19 yaml_get_version(int *major, int *minor, int *patch)
20 {
21     *major = YAML_VERSION_MAJOR;
22     *minor = YAML_VERSION_MINOR;
23     *patch = YAML_VERSION_PATCH;
24 }
25
26 /*
27  * Allocate a dynamic memory block.
28  */
29
30 YAML_DECLARE(void *)
31 yaml_malloc(size_t size)
32 {
33     return malloc(size ? size : 1);
34 }
35
36 /*
37  * Reallocate a dynamic memory block.
38  */
39
40 YAML_DECLARE(void *)
41 yaml_realloc(void *ptr, size_t size)
42 {
43     return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
44 }
45
46 /*
47  * Free a dynamic memory block.
48  */
49
50 YAML_DECLARE(void)
51 yaml_free(void *ptr)
52 {
53     if (ptr) free(ptr);
54 }
55
56 /*
57  * Duplicate a string.
58  */
59
60 YAML_DECLARE(yaml_char_t *)
61 yaml_strdup(const yaml_char_t *str)
62 {
63     if (!str)
64         return NULL;
65
66     return (yaml_char_t *)strdup((char *)str);
67 }
68
69 /*
70  * Extend a string.
71  */
72
73 YAML_DECLARE(int)
74 yaml_string_extend(yaml_char_t **start,
75         yaml_char_t **pointer, yaml_char_t **end)
76 {
77     yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2);
78
79     if (!new_start) return 0;
80
81     memset(new_start + (*end - *start), 0, *end - *start);
82
83     *pointer = new_start + (*pointer - *start);
84     *end = new_start + (*end - *start)*2;
85     *start = new_start;
86
87     return 1;
88 }
89
90 /*
91  * Append a string B to a string A.
92  */
93
94 YAML_DECLARE(int)
95 yaml_string_join(
96         yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
97         yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
98 {
99     if (*b_start == *b_pointer)
100         return 1;
101
102     while (*a_end - *a_pointer <= *b_pointer - *b_start) {
103         if (!yaml_string_extend(a_start, a_pointer, a_end))
104             return 0;
105     }
106
107     memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
108     *a_pointer += *b_pointer - *b_start;
109
110     return 1;
111 }
112
113 /*
114  * Extend a stack.
115  */
116
117 YAML_DECLARE(int)
118 yaml_stack_extend(void **start, void **top, void **end)
119 {
120     void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
121
122     if (!new_start) return 0;
123
124     *top = (char *)new_start + ((char *)*top - (char *)*start);
125     *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
126     *start = new_start;
127
128     return 1;
129 }
130
131 /*
132  * Extend or move a queue.
133  */
134
135 YAML_DECLARE(int)
136 yaml_queue_extend(void **start, void **head, void **tail, void **end)
137 {
138     /* Check if we need to resize the queue. */
139
140     if (*start == *head && *tail == *end) {
141         void *new_start = yaml_realloc(*start,
142                 ((char *)*end - (char *)*start)*2);
143
144         if (!new_start) return 0;
145
146         *head = (char *)new_start + ((char *)*head - (char *)*start);
147         *tail = (char *)new_start + ((char *)*tail - (char *)*start);
148         *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
149         *start = new_start;
150     }
151
152     /* Check if we need to move the queue at the beginning of the buffer. */
153
154     if (*tail == *end) {
155         if (*head != *tail) {
156             memmove(*start, *head, (char *)*tail - (char *)*head);
157         }
158         *tail = (char *)*tail - (char *)*head + (char *)*start;
159         *head = *start;
160     }
161
162     return 1;
163 }
164
165
166 /*
167  * Create a new parser object.
168  */
169
170 YAML_DECLARE(int)
171 yaml_parser_initialize(yaml_parser_t *parser)
172 {
173     assert(parser);     /* Non-NULL parser object expected. */
174
175     memset(parser, 0, sizeof(yaml_parser_t));
176     if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
177         goto error;
178     if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
179         goto error;
180     if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
181         goto error;
182     if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
183         goto error;
184     if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
185         goto error;
186     if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
187         goto error;
188     if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
189         goto error;
190     if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
191         goto error;
192
193     return 1;
194
195 error:
196
197     BUFFER_DEL(parser, parser->raw_buffer);
198     BUFFER_DEL(parser, parser->buffer);
199     QUEUE_DEL(parser, parser->tokens);
200     STACK_DEL(parser, parser->indents);
201     STACK_DEL(parser, parser->simple_keys);
202     STACK_DEL(parser, parser->states);
203     STACK_DEL(parser, parser->marks);
204     STACK_DEL(parser, parser->tag_directives);
205
206     return 0;
207 }
208
209 /*
210  * Destroy a parser object.
211  */
212
213 YAML_DECLARE(void)
214 yaml_parser_delete(yaml_parser_t *parser)
215 {
216     assert(parser); /* Non-NULL parser object expected. */
217
218     BUFFER_DEL(parser, parser->raw_buffer);
219     BUFFER_DEL(parser, parser->buffer);
220     while (!QUEUE_EMPTY(parser, parser->tokens)) {
221         yaml_token_delete(&DEQUEUE(parser, parser->tokens));
222     }
223     QUEUE_DEL(parser, parser->tokens);
224     STACK_DEL(parser, parser->indents);
225     STACK_DEL(parser, parser->simple_keys);
226     STACK_DEL(parser, parser->states);
227     STACK_DEL(parser, parser->marks);
228     while (!STACK_EMPTY(parser, parser->tag_directives)) {
229         yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
230         yaml_free(tag_directive.handle);
231         yaml_free(tag_directive.prefix);
232     }
233     STACK_DEL(parser, parser->tag_directives);
234
235     memset(parser, 0, sizeof(yaml_parser_t));
236 }
237
238 /*
239  * String read handler.
240  */
241
242 static int
243 yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
244         size_t *size_read)
245 {
246     yaml_parser_t *parser = data;
247
248     if (parser->input.string.current == parser->input.string.end) {
249         *size_read = 0;
250         return 1;
251     }
252
253     if (size > (size_t)(parser->input.string.end
254                 - parser->input.string.current)) {
255         size = parser->input.string.end - parser->input.string.current;
256     }
257
258     memcpy(buffer, parser->input.string.current, size);
259     parser->input.string.current += size;
260     *size_read = size;
261     return 1;
262 }
263
264 /*
265  * File read handler.
266  */
267
268 static int
269 yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
270         size_t *size_read)
271 {
272     yaml_parser_t *parser = data;
273
274     *size_read = fread(buffer, 1, size, parser->input.file);
275     return !ferror(parser->input.file);
276 }
277
278 /*
279  * Set a string input.
280  */
281
282 YAML_DECLARE(void)
283 yaml_parser_set_input_string(yaml_parser_t *parser,
284         const unsigned char *input, size_t size)
285 {
286     assert(parser); /* Non-NULL parser object expected. */
287     assert(!parser->read_handler);  /* You can set the source only once. */
288     assert(input);  /* Non-NULL input string expected. */
289
290     parser->read_handler = yaml_string_read_handler;
291     parser->read_handler_data = parser;
292
293     parser->input.string.start = input;
294     parser->input.string.current = input;
295     parser->input.string.end = input+size;
296 }
297
298 /*
299  * Set a file input.
300  */
301
302 YAML_DECLARE(void)
303 yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
304 {
305     assert(parser); /* Non-NULL parser object expected. */
306     assert(!parser->read_handler);  /* You can set the source only once. */
307     assert(file);   /* Non-NULL file object expected. */
308
309     parser->read_handler = yaml_file_read_handler;
310     parser->read_handler_data = parser;
311
312     parser->input.file = file;
313 }
314
315 /*
316  * Set a generic input.
317  */
318
319 YAML_DECLARE(void)
320 yaml_parser_set_input(yaml_parser_t *parser,
321         yaml_read_handler_t *handler, void *data)
322 {
323     assert(parser); /* Non-NULL parser object expected. */
324     assert(!parser->read_handler);  /* You can set the source only once. */
325     assert(handler);    /* Non-NULL read handler expected. */
326
327     parser->read_handler = handler;
328     parser->read_handler_data = data;
329 }
330
331 /*
332  * Set the source encoding.
333  */
334
335 YAML_DECLARE(void)
336 yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
337 {
338     assert(parser); /* Non-NULL parser object expected. */
339     assert(!parser->encoding); /* Encoding is already set or detected. */
340
341     parser->encoding = encoding;
342 }
343
344 /*
345  * Create a new emitter object.
346  */
347
348 YAML_DECLARE(int)
349 yaml_emitter_initialize(yaml_emitter_t *emitter)
350 {
351     assert(emitter);    /* Non-NULL emitter object expected. */
352
353     memset(emitter, 0, sizeof(yaml_emitter_t));
354     if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
355         goto error;
356     if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
357         goto error;
358     if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE))
359         goto error;
360     if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE))
361         goto error;
362     if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE))
363         goto error;
364     if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE))
365         goto error;
366
367     return 1;
368
369 error:
370
371     BUFFER_DEL(emitter, emitter->buffer);
372     BUFFER_DEL(emitter, emitter->raw_buffer);
373     STACK_DEL(emitter, emitter->states);
374     QUEUE_DEL(emitter, emitter->events);
375     STACK_DEL(emitter, emitter->indents);
376     STACK_DEL(emitter, emitter->tag_directives);
377
378     return 0;
379 }
380
381 /*
382  * Destroy an emitter object.
383  */
384
385 YAML_DECLARE(void)
386 yaml_emitter_delete(yaml_emitter_t *emitter)
387 {
388     assert(emitter);    /* Non-NULL emitter object expected. */
389
390     BUFFER_DEL(emitter, emitter->buffer);
391     BUFFER_DEL(emitter, emitter->raw_buffer);
392     STACK_DEL(emitter, emitter->states);
393     while (!QUEUE_EMPTY(emitter, emitter->events)) {
394         yaml_event_delete(&DEQUEUE(emitter, emitter->events));
395     }
396     QUEUE_DEL(emitter, emitter->events);
397     STACK_DEL(emitter, emitter->indents);
398     while (!STACK_EMPTY(empty, emitter->tag_directives)) {
399         yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
400         yaml_free(tag_directive.handle);
401         yaml_free(tag_directive.prefix);
402     }
403     STACK_DEL(emitter, emitter->tag_directives);
404     yaml_free(emitter->anchors);
405
406     memset(emitter, 0, sizeof(yaml_emitter_t));
407 }
408
409 /*
410  * String write handler.
411  */
412
413 static int
414 yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
415 {
416     yaml_emitter_t *emitter = data;
417
418     if (emitter->output.string.size + *emitter->output.string.size_written
419             < size) {
420         memcpy(emitter->output.string.buffer
421                 + *emitter->output.string.size_written,
422                 buffer,
423                 emitter->output.string.size
424                 - *emitter->output.string.size_written);
425         *emitter->output.string.size_written = emitter->output.string.size;
426         return 0;
427     }
428
429     memcpy(emitter->output.string.buffer
430             + *emitter->output.string.size_written, buffer, size);
431     *emitter->output.string.size_written += size;
432     return 1;
433 }
434
435 /*
436  * File write handler.
437  */
438
439 static int
440 yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
441 {
442     yaml_emitter_t *emitter = data;
443
444     return (fwrite(buffer, 1, size, emitter->output.file) == size);
445 }
446 /*
447  * Set a string output.
448  */
449
450 YAML_DECLARE(void)
451 yaml_emitter_set_output_string(yaml_emitter_t *emitter,
452         unsigned char *output, size_t size, size_t *size_written)
453 {
454     assert(emitter);    /* Non-NULL emitter object expected. */
455     assert(!emitter->write_handler);    /* You can set the output only once. */
456     assert(output);     /* Non-NULL output string expected. */
457
458     emitter->write_handler = yaml_string_write_handler;
459     emitter->write_handler_data = emitter;
460
461     emitter->output.string.buffer = output;
462     emitter->output.string.size = size;
463     emitter->output.string.size_written = size_written;
464     *size_written = 0;
465 }
466
467 /*
468  * Set a file output.
469  */
470
471 YAML_DECLARE(void)
472 yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
473 {
474     assert(emitter);    /* Non-NULL emitter object expected. */
475     assert(!emitter->write_handler);    /* You can set the output only once. */
476     assert(file);       /* Non-NULL file object expected. */
477
478     emitter->write_handler = yaml_file_write_handler;
479     emitter->write_handler_data = emitter;
480
481     emitter->output.file = file;
482 }
483
484 /*
485  * Set a generic output handler.
486  */
487
488 YAML_DECLARE(void)
489 yaml_emitter_set_output(yaml_emitter_t *emitter,
490         yaml_write_handler_t *handler, void *data)
491 {
492     assert(emitter);    /* Non-NULL emitter object expected. */
493     assert(!emitter->write_handler);    /* You can set the output only once. */
494     assert(handler);    /* Non-NULL handler object expected. */
495
496     emitter->write_handler = handler;
497     emitter->write_handler_data = data;
498 }
499
500 /*
501  * Set the output encoding.
502  */
503
504 YAML_DECLARE(void)
505 yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
506 {
507     assert(emitter);    /* Non-NULL emitter object expected. */
508     assert(!emitter->encoding);     /* You can set encoding only once. */
509
510     emitter->encoding = encoding;
511 }
512
513 /*
514  * Set the canonical output style.
515  */
516
517 YAML_DECLARE(void)
518 yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
519 {
520     assert(emitter);    /* Non-NULL emitter object expected. */
521
522     emitter->canonical = (canonical != 0);
523 }
524
525 /*
526  * Set the indentation increment.
527  */
528
529 YAML_DECLARE(void)
530 yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
531 {
532     assert(emitter);    /* Non-NULL emitter object expected. */
533
534     emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
535 }
536
537 /*
538  * Set the preferred line width.
539  */
540
541 YAML_DECLARE(void)
542 yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
543 {
544     assert(emitter);    /* Non-NULL emitter object expected. */
545
546     emitter->best_width = (width >= 0) ? width : -1;
547 }
548
549 /*
550  * Set if unescaped non-ASCII characters are allowed.
551  */
552
553 YAML_DECLARE(void)
554 yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
555 {
556     assert(emitter);    /* Non-NULL emitter object expected. */
557
558     emitter->unicode = (unicode != 0);
559 }
560
561 /*
562  * Set the preferred line break character.
563  */
564
565 YAML_DECLARE(void)
566 yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
567 {
568     assert(emitter);    /* Non-NULL emitter object expected. */
569
570     emitter->line_break = line_break;
571 }
572
573 /*
574  * Destroy a token object.
575  */
576
577 YAML_DECLARE(void)
578 yaml_token_delete(yaml_token_t *token)
579 {
580     assert(token);  /* Non-NULL token object expected. */
581
582     switch (token->type)
583     {
584         case YAML_TAG_DIRECTIVE_TOKEN:
585             yaml_free(token->data.tag_directive.handle);
586             yaml_free(token->data.tag_directive.prefix);
587             break;
588
589         case YAML_ALIAS_TOKEN:
590             yaml_free(token->data.alias.value);
591             break;
592
593         case YAML_ANCHOR_TOKEN:
594             yaml_free(token->data.anchor.value);
595             break;
596
597         case YAML_TAG_TOKEN:
598             yaml_free(token->data.tag.handle);
599             yaml_free(token->data.tag.suffix);
600             break;
601
602         case YAML_SCALAR_TOKEN:
603             yaml_free(token->data.scalar.value);
604             break;
605
606         default:
607             break;
608     }
609
610     memset(token, 0, sizeof(yaml_token_t));
611 }
612
613 /*
614  * Check if a string is a valid UTF-8 sequence.
615  *
616  * Check 'reader.c' for more details on UTF-8 encoding.
617  */
618
619 static int
620 yaml_check_utf8(yaml_char_t *start, size_t length)
621 {
622     yaml_char_t *end = start+length;
623     yaml_char_t *pointer = start;
624
625     while (pointer < end) {
626         unsigned char octet;
627         unsigned int width;
628         unsigned int value;
629         size_t k;
630
631         octet = pointer[0];
632         width = (octet & 0x80) == 0x00 ? 1 :
633                 (octet & 0xE0) == 0xC0 ? 2 :
634                 (octet & 0xF0) == 0xE0 ? 3 :
635                 (octet & 0xF8) == 0xF0 ? 4 : 0;
636         value = (octet & 0x80) == 0x00 ? octet & 0x7F :
637                 (octet & 0xE0) == 0xC0 ? octet & 0x1F :
638                 (octet & 0xF0) == 0xE0 ? octet & 0x0F :
639                 (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
640         if (!width) return 0;
641         if (pointer+width > end) return 0;
642         for (k = 1; k < width; k ++) {
643             octet = pointer[k];
644             if ((octet & 0xC0) != 0x80) return 0;
645             value = (value << 6) + (octet & 0x3F);
646         }
647         if (!((width == 1) ||
648             (width == 2 && value >= 0x80) ||
649             (width == 3 && value >= 0x800) ||
650             (width == 4 && value >= 0x10000))) return 0;
651
652         pointer += width;
653     }
654
655     return 1;
656 }
657
658 /*
659  * Create STREAM-START.
660  */
661
662 YAML_DECLARE(int)
663 yaml_stream_start_event_initialize(yaml_event_t *event,
664         yaml_encoding_t encoding)
665 {
666     yaml_mark_t mark = { 0, 0, 0 };
667
668     assert(event);  /* Non-NULL event object is expected. */
669
670     STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
671
672     return 1;
673 }
674
675 /*
676  * Create STREAM-END.
677  */
678
679 YAML_DECLARE(int)
680 yaml_stream_end_event_initialize(yaml_event_t *event)
681 {
682     yaml_mark_t mark = { 0, 0, 0 };
683
684     assert(event);  /* Non-NULL event object is expected. */
685
686     STREAM_END_EVENT_INIT(*event, mark, mark);
687
688     return 1;
689 }
690
691 /*
692  * Create DOCUMENT-START.
693  */
694
695 YAML_DECLARE(int)
696 yaml_document_start_event_initialize(yaml_event_t *event,
697         yaml_version_directive_t *version_directive,
698         yaml_tag_directive_t *tag_directives_start,
699         yaml_tag_directive_t *tag_directives_end,
700         int implicit)
701 {
702     struct {
703         yaml_error_type_t error;
704     } context;
705     yaml_mark_t mark = { 0, 0, 0 };
706     yaml_version_directive_t *version_directive_copy = NULL;
707     struct {
708         yaml_tag_directive_t *start;
709         yaml_tag_directive_t *end;
710         yaml_tag_directive_t *top;
711     } tag_directives_copy = { NULL, NULL, NULL };
712     yaml_tag_directive_t value = { NULL, NULL };
713
714     assert(event);          /* Non-NULL event object is expected. */
715     assert((tag_directives_start && tag_directives_end) ||
716             (tag_directives_start == tag_directives_end));
717                             /* Valid tag directives are expected. */
718
719     if (version_directive) {
720         version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
721         if (!version_directive_copy) goto error;
722         version_directive_copy->major = version_directive->major;
723         version_directive_copy->minor = version_directive->minor;
724     }
725
726     if (tag_directives_start != tag_directives_end) {
727         yaml_tag_directive_t *tag_directive;
728         if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
729             goto error;
730         for (tag_directive = tag_directives_start;
731                 tag_directive != tag_directives_end; tag_directive ++) {
732             assert(tag_directive->handle);
733             assert(tag_directive->prefix);
734             if (!yaml_check_utf8(tag_directive->handle,
735                         strlen((char *)tag_directive->handle)))
736                 goto error;
737             if (!yaml_check_utf8(tag_directive->prefix,
738                         strlen((char *)tag_directive->prefix)))
739                 goto error;
740             value.handle = yaml_strdup(tag_directive->handle);
741             value.prefix = yaml_strdup(tag_directive->prefix);
742             if (!value.handle || !value.prefix) goto error;
743             if (!PUSH(&context, tag_directives_copy, value))
744                 goto error;
745             value.handle = NULL;
746             value.prefix = NULL;
747         }
748     }
749
750     DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
751             tag_directives_copy.start, tag_directives_copy.top,
752             implicit, mark, mark);
753
754     return 1;
755
756 error:
757     yaml_free(version_directive_copy);
758     while (!STACK_EMPTY(context, tag_directives_copy)) {
759         yaml_tag_directive_t value = POP(context, tag_directives_copy);
760         yaml_free(value.handle);
761         yaml_free(value.prefix);
762     }
763     STACK_DEL(context, tag_directives_copy);
764     yaml_free(value.handle);
765     yaml_free(value.prefix);
766
767     return 0;
768 }
769
770 /*
771  * Create DOCUMENT-END.
772  */
773
774 YAML_DECLARE(int)
775 yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
776 {
777     yaml_mark_t mark = { 0, 0, 0 };
778
779     assert(event);      /* Non-NULL emitter object is expected. */
780
781     DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
782
783     return 1;
784 }
785
786 /*
787  * Create ALIAS.
788  */
789
790 YAML_DECLARE(int)
791 yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
792 {
793     yaml_mark_t mark = { 0, 0, 0 };
794     yaml_char_t *anchor_copy = NULL;
795
796     assert(event);      /* Non-NULL event object is expected. */
797     assert(anchor);     /* Non-NULL anchor is expected. */
798
799     if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
800
801     anchor_copy = yaml_strdup(anchor);
802     if (!anchor_copy)
803         return 0;
804
805     ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
806
807     return 1;
808 }
809
810 /*
811  * Create SCALAR.
812  */
813
814 YAML_DECLARE(int)
815 yaml_scalar_event_initialize(yaml_event_t *event,
816         yaml_char_t *anchor, yaml_char_t *tag,
817         yaml_char_t *value, int length,
818         int plain_implicit, int quoted_implicit,
819         yaml_scalar_style_t style)
820 {
821     yaml_mark_t mark = { 0, 0, 0 };
822     yaml_char_t *anchor_copy = NULL;
823     yaml_char_t *tag_copy = NULL;
824     yaml_char_t *value_copy = NULL;
825
826     assert(event);      /* Non-NULL event object is expected. */
827     assert(value);      /* Non-NULL anchor is expected. */
828
829     if (anchor) {
830         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
831         anchor_copy = yaml_strdup(anchor);
832         if (!anchor_copy) goto error;
833     }
834
835     if (tag) {
836         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
837         tag_copy = yaml_strdup(tag);
838         if (!tag_copy) goto error;
839     }
840
841     if (length < 0) {
842         length = strlen((char *)value);
843     }
844
845     if (!yaml_check_utf8(value, length)) goto error;
846     value_copy = yaml_malloc(length+1);
847     if (!value_copy) goto error;
848     memcpy(value_copy, value, length);
849     value_copy[length] = '\0';
850
851     SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
852             plain_implicit, quoted_implicit, style, mark, mark);
853
854     return 1;
855
856 error:
857     yaml_free(anchor_copy);
858     yaml_free(tag_copy);
859     yaml_free(value_copy);
860
861     return 0;
862 }
863
864 /*
865  * Create SEQUENCE-START.
866  */
867
868 YAML_DECLARE(int)
869 yaml_sequence_start_event_initialize(yaml_event_t *event,
870         yaml_char_t *anchor, yaml_char_t *tag, int implicit,
871         yaml_sequence_style_t style)
872 {
873     yaml_mark_t mark = { 0, 0, 0 };
874     yaml_char_t *anchor_copy = NULL;
875     yaml_char_t *tag_copy = NULL;
876
877     assert(event);      /* Non-NULL event object is expected. */
878
879     if (anchor) {
880         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
881         anchor_copy = yaml_strdup(anchor);
882         if (!anchor_copy) goto error;
883     }
884
885     if (tag) {
886         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
887         tag_copy = yaml_strdup(tag);
888         if (!tag_copy) goto error;
889     }
890
891     SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
892             implicit, style, mark, mark);
893
894     return 1;
895
896 error:
897     yaml_free(anchor_copy);
898     yaml_free(tag_copy);
899
900     return 0;
901 }
902
903 /*
904  * Create SEQUENCE-END.
905  */
906
907 YAML_DECLARE(int)
908 yaml_sequence_end_event_initialize(yaml_event_t *event)
909 {
910     yaml_mark_t mark = { 0, 0, 0 };
911
912     assert(event);      /* Non-NULL event object is expected. */
913
914     SEQUENCE_END_EVENT_INIT(*event, mark, mark);
915
916     return 1;
917 }
918
919 /*
920  * Create MAPPING-START.
921  */
922
923 YAML_DECLARE(int)
924 yaml_mapping_start_event_initialize(yaml_event_t *event,
925         yaml_char_t *anchor, yaml_char_t *tag, int implicit,
926         yaml_mapping_style_t style)
927 {
928     yaml_mark_t mark = { 0, 0, 0 };
929     yaml_char_t *anchor_copy = NULL;
930     yaml_char_t *tag_copy = NULL;
931
932     assert(event);      /* Non-NULL event object is expected. */
933
934     if (anchor) {
935         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
936         anchor_copy = yaml_strdup(anchor);
937         if (!anchor_copy) goto error;
938     }
939
940     if (tag) {
941         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
942         tag_copy = yaml_strdup(tag);
943         if (!tag_copy) goto error;
944     }
945
946     MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
947             implicit, style, mark, mark);
948
949     return 1;
950
951 error:
952     yaml_free(anchor_copy);
953     yaml_free(tag_copy);
954
955     return 0;
956 }
957
958 /*
959  * Create MAPPING-END.
960  */
961
962 YAML_DECLARE(int)
963 yaml_mapping_end_event_initialize(yaml_event_t *event)
964 {
965     yaml_mark_t mark = { 0, 0, 0 };
966
967     assert(event);      /* Non-NULL event object is expected. */
968
969     MAPPING_END_EVENT_INIT(*event, mark, mark);
970
971     return 1;
972 }
973
974 /*
975  * Destroy an event object.
976  */
977
978 YAML_DECLARE(void)
979 yaml_event_delete(yaml_event_t *event)
980 {
981     yaml_tag_directive_t *tag_directive;
982
983     assert(event);  /* Non-NULL event object expected. */
984
985     switch (event->type)
986     {
987         case YAML_DOCUMENT_START_EVENT:
988             yaml_free(event->data.document_start.version_directive);
989             for (tag_directive = event->data.document_start.tag_directives.start;
990                     tag_directive != event->data.document_start.tag_directives.end;
991                     tag_directive++) {
992                 yaml_free(tag_directive->handle);
993                 yaml_free(tag_directive->prefix);
994             }
995             yaml_free(event->data.document_start.tag_directives.start);
996             break;
997
998         case YAML_ALIAS_EVENT:
999             yaml_free(event->data.alias.anchor);
1000             break;
1001
1002         case YAML_SCALAR_EVENT:
1003             yaml_free(event->data.scalar.anchor);
1004             yaml_free(event->data.scalar.tag);
1005             yaml_free(event->data.scalar.value);
1006             break;
1007
1008         case YAML_SEQUENCE_START_EVENT:
1009             yaml_free(event->data.sequence_start.anchor);
1010             yaml_free(event->data.sequence_start.tag);
1011             break;
1012
1013         case YAML_MAPPING_START_EVENT:
1014             yaml_free(event->data.mapping_start.anchor);
1015             yaml_free(event->data.mapping_start.tag);
1016             break;
1017
1018         default:
1019             break;
1020     }
1021
1022     memset(event, 0, sizeof(yaml_event_t));
1023 }
1024
1025 /*
1026  * Create a document object.
1027  */
1028
1029 YAML_DECLARE(int)
1030 yaml_document_initialize(yaml_document_t *document,
1031         yaml_version_directive_t *version_directive,
1032         yaml_tag_directive_t *tag_directives_start,
1033         yaml_tag_directive_t *tag_directives_end,
1034         int start_implicit, int end_implicit)
1035 {
1036     struct {
1037         yaml_error_type_t error;
1038     } context;
1039     struct {
1040         yaml_node_t *start;
1041         yaml_node_t *end;
1042         yaml_node_t *top;
1043     } nodes = { NULL, NULL, NULL };
1044     yaml_version_directive_t *version_directive_copy = NULL;
1045     struct {
1046         yaml_tag_directive_t *start;
1047         yaml_tag_directive_t *end;
1048         yaml_tag_directive_t *top;
1049     } tag_directives_copy = { NULL, NULL, NULL };
1050     yaml_tag_directive_t value = { NULL, NULL };
1051     yaml_mark_t mark = { 0, 0, 0 };
1052
1053     assert(document);       /* Non-NULL document object is expected. */
1054     assert((tag_directives_start && tag_directives_end) ||
1055             (tag_directives_start == tag_directives_end));
1056                             /* Valid tag directives are expected. */
1057
1058     if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
1059
1060     if (version_directive) {
1061         version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1062         if (!version_directive_copy) goto error;
1063         version_directive_copy->major = version_directive->major;
1064         version_directive_copy->minor = version_directive->minor;
1065     }
1066
1067     if (tag_directives_start != tag_directives_end) {
1068         yaml_tag_directive_t *tag_directive;
1069         if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
1070             goto error;
1071         for (tag_directive = tag_directives_start;
1072                 tag_directive != tag_directives_end; tag_directive ++) {
1073             assert(tag_directive->handle);
1074             assert(tag_directive->prefix);
1075             if (!yaml_check_utf8(tag_directive->handle,
1076                         strlen((char *)tag_directive->handle)))
1077                 goto error;
1078             if (!yaml_check_utf8(tag_directive->prefix,
1079                         strlen((char *)tag_directive->prefix)))
1080                 goto error;
1081             value.handle = yaml_strdup(tag_directive->handle);
1082             value.prefix = yaml_strdup(tag_directive->prefix);
1083             if (!value.handle || !value.prefix) goto error;
1084             if (!PUSH(&context, tag_directives_copy, value))
1085                 goto error;
1086             value.handle = NULL;
1087             value.prefix = NULL;
1088         }
1089     }
1090
1091     DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1092             tag_directives_copy.start, tag_directives_copy.top,
1093             start_implicit, end_implicit, mark, mark);
1094
1095     return 1;
1096
1097 error:
1098     STACK_DEL(&context, nodes);
1099     yaml_free(version_directive_copy);
1100     while (!STACK_EMPTY(&context, tag_directives_copy)) {
1101         yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1102         yaml_free(value.handle);
1103         yaml_free(value.prefix);
1104     }
1105     STACK_DEL(&context, tag_directives_copy);
1106     yaml_free(value.handle);
1107     yaml_free(value.prefix);
1108
1109     return 0;
1110 }
1111
1112 /*
1113  * Destroy a document object.
1114  */
1115
1116 YAML_DECLARE(void)
1117 yaml_document_delete(yaml_document_t *document)
1118 {
1119     struct {
1120         yaml_error_type_t error;
1121     } context;
1122     yaml_tag_directive_t *tag_directive;
1123
1124     context.error = YAML_NO_ERROR;  /* Eliminate a compliler warning. */
1125
1126     assert(document);   /* Non-NULL document object is expected. */
1127
1128     while (!STACK_EMPTY(&context, document->nodes)) {
1129         yaml_node_t node = POP(&context, document->nodes);
1130         yaml_free(node.tag);
1131         switch (node.type) {
1132             case YAML_SCALAR_NODE:
1133                 yaml_free(node.data.scalar.value);
1134                 break;
1135             case YAML_SEQUENCE_NODE:
1136                 STACK_DEL(&context, node.data.sequence.items);
1137                 break;
1138             case YAML_MAPPING_NODE:
1139                 STACK_DEL(&context, node.data.mapping.pairs);
1140                 break;
1141             default:
1142                 assert(0);  /* Should not happen. */
1143         }
1144     }
1145     STACK_DEL(&context, document->nodes);
1146
1147     yaml_free(document->version_directive);
1148     for (tag_directive = document->tag_directives.start;
1149             tag_directive != document->tag_directives.end;
1150             tag_directive++) {
1151         yaml_free(tag_directive->handle);
1152         yaml_free(tag_directive->prefix);
1153     }
1154     yaml_free(document->tag_directives.start);
1155
1156     memset(document, 0, sizeof(yaml_document_t));
1157 }
1158
1159 /**
1160  * Get a document node.
1161  */
1162
1163 YAML_DECLARE(yaml_node_t *)
1164 yaml_document_get_node(yaml_document_t *document, int index)
1165 {
1166     assert(document);   /* Non-NULL document object is expected. */
1167
1168     if (index > 0 && document->nodes.start + index <= document->nodes.top) {
1169         return document->nodes.start + index - 1;
1170     }
1171     return NULL;
1172 }
1173
1174 /**
1175  * Get the root object.
1176  */
1177
1178 YAML_DECLARE(yaml_node_t *)
1179 yaml_document_get_root_node(yaml_document_t *document)
1180 {
1181     assert(document);   /* Non-NULL document object is expected. */
1182
1183     if (document->nodes.top != document->nodes.start) {
1184         return document->nodes.start;
1185     }
1186     return NULL;
1187 }
1188
1189 /*
1190  * Add a scalar node to a document.
1191  */
1192
1193 YAML_DECLARE(int)
1194 yaml_document_add_scalar(yaml_document_t *document,
1195         yaml_char_t *tag, yaml_char_t *value, int length,
1196         yaml_scalar_style_t style)
1197 {
1198     struct {
1199         yaml_error_type_t error;
1200     } context;
1201     yaml_mark_t mark = { 0, 0, 0 };
1202     yaml_char_t *tag_copy = NULL;
1203     yaml_char_t *value_copy = NULL;
1204     yaml_node_t node;
1205
1206     assert(document);   /* Non-NULL document object is expected. */
1207     assert(value);      /* Non-NULL value is expected. */
1208
1209     if (!tag) {
1210         tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
1211     }
1212
1213     if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1214     tag_copy = yaml_strdup(tag);
1215     if (!tag_copy) goto error;
1216
1217     if (length < 0) {
1218         length = strlen((char *)value);
1219     }
1220
1221     if (!yaml_check_utf8(value, length)) goto error;
1222     value_copy = yaml_malloc(length+1);
1223     if (!value_copy) goto error;
1224     memcpy(value_copy, value, length);
1225     value_copy[length] = '\0';
1226
1227     SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
1228     if (!PUSH(&context, document->nodes, node)) goto error;
1229
1230     return document->nodes.top - document->nodes.start;
1231
1232 error:
1233     yaml_free(tag_copy);
1234     yaml_free(value_copy);
1235
1236     return 0;
1237 }
1238
1239 /*
1240  * Add a sequence node to a document.
1241  */
1242
1243 YAML_DECLARE(int)
1244 yaml_document_add_sequence(yaml_document_t *document,
1245         yaml_char_t *tag, yaml_sequence_style_t style)
1246 {
1247     struct {
1248         yaml_error_type_t error;
1249     } context;
1250     yaml_mark_t mark = { 0, 0, 0 };
1251     yaml_char_t *tag_copy = NULL;
1252     struct {
1253         yaml_node_item_t *start;
1254         yaml_node_item_t *end;
1255         yaml_node_item_t *top;
1256     } items = { NULL, NULL, NULL };
1257     yaml_node_t node;
1258
1259     assert(document);   /* Non-NULL document object is expected. */
1260
1261     if (!tag) {
1262         tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
1263     }
1264
1265     if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1266     tag_copy = yaml_strdup(tag);
1267     if (!tag_copy) goto error;
1268
1269     if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
1270
1271     SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
1272             style, mark, mark);
1273     if (!PUSH(&context, document->nodes, node)) goto error;
1274
1275     return document->nodes.top - document->nodes.start;
1276
1277 error:
1278     STACK_DEL(&context, items);
1279     yaml_free(tag_copy);
1280
1281     return 0;
1282 }
1283
1284 /*
1285  * Add a mapping node to a document.
1286  */
1287
1288 YAML_DECLARE(int)
1289 yaml_document_add_mapping(yaml_document_t *document,
1290         yaml_char_t *tag, yaml_mapping_style_t style)
1291 {
1292     struct {
1293         yaml_error_type_t error;
1294     } context;
1295     yaml_mark_t mark = { 0, 0, 0 };
1296     yaml_char_t *tag_copy = NULL;
1297     struct {
1298         yaml_node_pair_t *start;
1299         yaml_node_pair_t *end;
1300         yaml_node_pair_t *top;
1301     } pairs = { NULL, NULL, NULL };
1302     yaml_node_t node;
1303
1304     assert(document);   /* Non-NULL document object is expected. */
1305
1306     if (!tag) {
1307         tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
1308     }
1309
1310     if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1311     tag_copy = yaml_strdup(tag);
1312     if (!tag_copy) goto error;
1313
1314     if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
1315
1316     MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
1317             style, mark, mark);
1318     if (!PUSH(&context, document->nodes, node)) goto error;
1319
1320     return document->nodes.top - document->nodes.start;
1321
1322 error:
1323     STACK_DEL(&context, pairs);
1324     yaml_free(tag_copy);
1325
1326     return 0;
1327 }
1328
1329 /*
1330  * Append an item to a sequence node.
1331  */
1332
1333 YAML_DECLARE(int)
1334 yaml_document_append_sequence_item(yaml_document_t *document,
1335         int sequence, int item)
1336 {
1337     struct {
1338         yaml_error_type_t error;
1339     } context;
1340
1341     assert(document);       /* Non-NULL document is required. */
1342     assert(sequence > 0
1343             && document->nodes.start + sequence <= document->nodes.top);
1344                             /* Valid sequence id is required. */
1345     assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
1346                             /* A sequence node is required. */
1347     assert(item > 0 && document->nodes.start + item <= document->nodes.top);
1348                             /* Valid item id is required. */
1349
1350     if (!PUSH(&context,
1351                 document->nodes.start[sequence-1].data.sequence.items, item))
1352         return 0;
1353
1354     return 1;
1355 }
1356
1357 /*
1358  * Append a pair of a key and a value to a mapping node.
1359  */
1360
1361 YAML_DECLARE(int)
1362 yaml_document_append_mapping_pair(yaml_document_t *document,
1363         int mapping, int key, int value)
1364 {
1365     struct {
1366         yaml_error_type_t error;
1367     } context;
1368
1369     yaml_node_pair_t pair;
1370
1371     assert(document);       /* Non-NULL document is required. */
1372     assert(mapping > 0
1373             && document->nodes.start + mapping <= document->nodes.top);
1374                             /* Valid mapping id is required. */
1375     assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
1376                             /* A mapping node is required. */
1377     assert(key > 0 && document->nodes.start + key <= document->nodes.top);
1378                             /* Valid key id is required. */
1379     assert(value > 0 && document->nodes.start + value <= document->nodes.top);
1380                             /* Valid value id is required. */
1381
1382     pair.key = key;
1383     pair.value = value;
1384
1385     if (!PUSH(&context,
1386                 document->nodes.start[mapping-1].data.mapping.pairs, pair))
1387         return 0;
1388
1389     return 1;
1390 }
1391
1392