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