source: libyaml/trunk/src/api.c @ 263

Revision 263, 43.0 KB checked in by xi, 7 years ago (diff)

Completed the first phase of API refactoring.

Line 
1
2#include "yaml_private.h"
3
4/*
5 * Get the library version.
6 */
7
8YAML_DECLARE(const char *)
9yaml_get_version_string(void)
10{
11    return YAML_VERSION_STRING;
12}
13
14/*
15 * Get the library version numbers.
16 */
17
18YAML_DECLARE(void)
19yaml_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
30YAML_DECLARE(void *)
31yaml_malloc(size_t size)
32{
33    return malloc(size ? size : 1);
34}
35
36/*
37 * Reallocate a dynamic memory block.
38 */
39
40YAML_DECLARE(void *)
41yaml_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
50YAML_DECLARE(void)
51yaml_free(void *ptr)
52{
53    if (ptr) free(ptr);
54}
55
56/*
57 * Duplicate a string.
58 */
59
60YAML_DECLARE(yaml_char_t *)
61yaml_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
73YAML_DECLARE(int)
74yaml_string_extend(yaml_char_t **buffer, size_t *capacity)
75{
76    yaml_char_t *new_buffer = yaml_realloc(*buffer, (*capacity)*2);
77
78    if (!new_buffer) return 0;
79
80    memset(new_buffer + *capacity, 0, *capacity);
81
82    *buffer = new_buffer;
83    *capacity *= 2;
84
85    return 1;
86}
87
88/*
89 * Append an adjunct string to a base string.
90 */
91
92YAML_DECLARE(int)
93yaml_string_join(
94        yaml_char_t **base_buffer, size_t *base_pointer, size_t *base_capacity,
95        yaml_char_t *adj_buffer, size_t adj_pointer, size_t adj_capacity)
96{
97    if (!adj_pointer)
98        return 1;
99
100    while (*base_capacity - *base_pointer <= adj_pointer) {
101        if (!yaml_string_extend(base_buffer, base_capacity))
102            return 0;
103    }
104
105    memcpy(*base_buffer+*base_pointer, adj_buffer, adj_pointer);
106    *base_pointer += adj_pointer;
107
108    return 1;
109}
110
111/*
112 * Extend a stack.
113 */
114
115YAML_DECLARE(int)
116yaml_stack_extend(void **list, size_t size, size_t *length, size_t *capacity)
117{
118    void *new_list = yaml_realloc(*list, (*capacity)*size*2);
119
120    if (!new_list) return 0;
121
122    *list = new_list;
123    *capacity *= 2;
124
125    return 1;
126}
127
128/*
129 * Extend or move a queue.
130 */
131
132YAML_DECLARE(int)
133yaml_queue_extend(void **list, size_t size,
134        size_t *head, size_t *tail, size_t *capacity)
135{
136    /* Check if we need to resize the queue. */
137
138    if (*head == 0 && *tail == *capacity) {
139        void *new_list = yaml_realloc(*list, (*capacity)*size*2);
140
141        if (!new_list) return 0;
142
143        *list = new_list;
144        *capacity *= 2;
145    }
146
147    /* Check if we need to move the queue at the beginning of the buffer. */
148
149    if (*tail == *capacity) {
150        if (*head != *tail) {
151            memmove((char *)*list, (char *)*list + (*head)*size,
152                    (*tail-*head)*size);
153        }
154        *tail -= *head;
155        *head = 0;
156    }
157
158    return 1;
159}
160
161
162/*
163 * Create a new parser object.
164 */
165
166YAML_DECLARE(yaml_parser_t *)
167yaml_parser_new(void)
168{
169    yaml_parser_t *parser = yaml_malloc(sizeof(yaml_parser_t));
170
171    if (!parser)
172        return NULL;
173
174    memset(parser, 0, sizeof(yaml_parser_t));
175    if (!STRING_INIT(parser, parser->raw_input, RAW_INPUT_BUFFER_CAPACITY))
176        goto error;
177    if (!STRING_INIT(parser, parser->input, INPUT_BUFFER_CAPACITY))
178        goto error;
179    if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_CAPACITY))
180        goto error;
181    if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_CAPACITY))
182        goto error;
183    if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_CAPACITY))
184        goto error;
185    if (!STACK_INIT(parser, parser->states, INITIAL_STACK_CAPACITY))
186        goto error;
187    if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_CAPACITY))
188        goto error;
189    if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_CAPACITY))
190        goto error;
191
192    return parser;
193
194error:
195    yaml_parser_delete(parser);
196
197    return NULL;
198}
199
200/*
201 * Destroy a parser object.
202 */
203
204YAML_DECLARE(void)
205yaml_parser_delete(yaml_parser_t *parser)
206{
207    assert(parser); /* Non-NULL parser object expected. */
208
209    STRING_DEL(parser, parser->raw_input);
210    STRING_DEL(parser, parser->input);
211    while (!QUEUE_EMPTY(parser, parser->tokens)) {
212        yaml_token_destroy(&DEQUEUE(parser, parser->tokens));
213    }
214    QUEUE_DEL(parser, parser->tokens);
215    STACK_DEL(parser, parser->indents);
216    STACK_DEL(parser, parser->simple_keys);
217    STACK_DEL(parser, parser->states);
218    STACK_DEL(parser, parser->marks);
219    while (!STACK_EMPTY(parser, parser->tag_directives)) {
220        yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
221        yaml_free(tag_directive.handle);
222        yaml_free(tag_directive.prefix);
223    }
224    STACK_DEL(parser, parser->tag_directives);
225
226    memset(parser, 0, sizeof(yaml_parser_t));
227    yaml_free(parser);
228}
229
230/*
231 * Get the current parser error.
232 */
233
234YAML_DECLARE(void)
235yaml_parser_get_error(yaml_parser_t *parser, yaml_error_t *error)
236{
237    assert(parser); /* Non-NULL parser object expected. */
238
239    *error = parser->error;
240}
241
242/*
243 * Standard string read handler.
244 */
245
246static int
247yaml_string_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
248        size_t *length)
249{
250    yaml_standard_reader_data_t *data = untyped_data;
251
252    if (data->string.pointer == data->string.capacity) {
253        *length = 0;
254        return 1;
255    }
256
257    if (capacity > (size_t)(data->string.capacity - data->string.pointer)) {
258        capacity = data->string.capacity - data->string.pointer;
259    }
260
261    memcpy(buffer, data->string.buffer + data->string.pointer, capacity);
262    data->string.pointer += capacity;
263    *length = capacity;
264    return 1;
265}
266
267/*
268 * Standard file read handler.
269 */
270
271static int
272yaml_file_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
273        size_t *length)
274{
275    yaml_standard_reader_data_t *data = untyped_data;
276
277    *length = fread(buffer, 1, capacity, data->file);
278    return !ferror(data->file);
279}
280
281/*
282 * Set a string input.
283 */
284
285YAML_DECLARE(void)
286yaml_parser_set_string_reader(yaml_parser_t *parser,
287        const unsigned char *buffer, size_t length)
288{
289    assert(parser); /* Non-NULL parser object expected. */
290    assert(!parser->reader);    /* You can set the input handler only once. */
291    assert(buffer); /* Non-NULL input string expected. */
292
293    parser->reader = yaml_string_reader;
294    parser->reader_data = &(parser->standard_reader_data);
295
296    parser->standard_reader_data.string.buffer = (unsigned char *)buffer;
297    parser->standard_reader_data.string.pointer = 0;
298    parser->standard_reader_data.string.capacity = length;
299}
300
301/*
302 * Set a file input.
303 */
304
305YAML_DECLARE(void)
306yaml_parser_set_file_reader(yaml_parser_t *parser, FILE *file)
307{
308    assert(parser); /* Non-NULL parser object expected. */
309    assert(!parser->reader);    /* You can set the input handler only once. */
310    assert(file);   /* Non-NULL file object expected. */
311
312    parser->reader = yaml_file_reader;
313    parser->reader_data = &(parser->standard_reader_data);
314
315    parser->standard_reader_data.file = file;
316}
317
318/*
319 * Set a generic input.
320 */
321
322YAML_DECLARE(void)
323yaml_parser_set_reader(yaml_parser_t *parser,
324        yaml_reader_t *reader, void *data)
325{
326    assert(parser); /* Non-NULL parser object expected. */
327    assert(!parser->reader);    /* You can set the input handler only once. */
328    assert(reader); /* Non-NULL read handler expected. */
329
330    parser->reader = reader;
331    parser->reader_data = data;
332}
333
334/*
335 * Set the source encoding.
336 */
337
338YAML_DECLARE(void)
339yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
340{
341    assert(parser); /* Non-NULL parser object expected. */
342    assert(!parser->encoding);  /* Encoding is already set or detected. */
343
344    parser->encoding = encoding;
345}
346
347/*
348 * Create a new emitter object.
349 */
350
351YAML_DECLARE(yaml_emitter_t *)
352yaml_emitter_new(void)
353{
354    yaml_emitter_t *emitter = yaml_malloc(sizeof(yaml_emitter_t));
355
356    if (!emitter)
357        return NULL;
358
359    memset(emitter, 0, sizeof(yaml_emitter_t));
360    if (!STRING_INIT(emitter, emitter->output, OUTPUT_BUFFER_CAPACITY))
361        goto error;
362    if (!STRING_INIT(emitter, emitter->raw_output, RAW_OUTPUT_BUFFER_CAPACITY))
363        goto error;
364    if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_CAPACITY))
365        goto error;
366    if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_CAPACITY))
367        goto error;
368    if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_CAPACITY))
369        goto error;
370    if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_CAPACITY))
371        goto error;
372
373    return emitter;
374
375error:
376    yaml_emitter_delete(emitter);
377
378    return NULL;
379}
380
381/*
382 * Destroy an emitter object.
383 */
384
385YAML_DECLARE(void)
386yaml_emitter_delete(yaml_emitter_t *emitter)
387{
388    assert(emitter);    /* Non-NULL emitter object expected. */
389
390    STRING_DEL(emitter, emitter->output);
391    STRING_DEL(emitter, emitter->raw_output);
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    yaml_free(emitter);
408}
409
410/*
411 * Get the current emitter error.
412 */
413
414YAML_DECLARE(void)
415yaml_emitter_get_error(yaml_emitter_t *emitter, yaml_error_t *error)
416{
417    assert(emitter);    /* Non-NULL emitter object expected. */
418
419    *error = emitter->error;
420}
421
422/*
423 * String write handler.
424 */
425
426static int
427yaml_string_writer(void *untyped_data, unsigned char *buffer, size_t length)
428{
429    yaml_standard_writer_data_t *data = untyped_data;
430    int result = 1;
431
432    if (data->string.capacity - data->string.pointer < length) {
433        length = data->string.capacity - data->string.pointer;
434        result = 0;
435    }
436
437    memcpy(data->string.buffer + data->string.pointer, buffer, length);
438    data->string.pointer += length;
439    *data->length += length;
440
441    return result;
442}
443
444/*
445 * File write handler.
446 */
447
448static int
449yaml_file_writer(void *untyped_data, unsigned char *buffer, size_t length)
450{
451    yaml_standard_writer_data_t *data = untyped_data;
452
453    return (fwrite(buffer, 1, length, data->file) == length);
454}
455/*
456 * Set a string output.
457 */
458
459YAML_DECLARE(void)
460yaml_emitter_set_string_writer(yaml_emitter_t *emitter,
461        unsigned char *buffer, size_t *length, size_t capacity)
462{
463    assert(emitter);    /* Non-NULL emitter object expected. */
464    assert(!emitter->writer);   /* You can set the output only once. */
465    assert(buffer);     /* Non-NULL output string expected. */
466
467    emitter->writer = yaml_string_writer;
468    emitter->writer_data = &(emitter->standard_writer_data);
469
470    emitter->standard_writer_data.string.buffer = buffer;
471    emitter->standard_writer_data.string.pointer = 0;
472    emitter->standard_writer_data.string.capacity = capacity;
473    emitter->standard_writer_data.length = length;
474
475    *length = 0;
476}
477
478/*
479 * Set a file output.
480 */
481
482YAML_DECLARE(void)
483yaml_emitter_set_file_writer(yaml_emitter_t *emitter, FILE *file)
484{
485    assert(emitter);    /* Non-NULL emitter object expected. */
486    assert(!emitter->writer);   /* You can set the output only once. */
487    assert(file);       /* Non-NULL file object expected. */
488
489    emitter->writer = yaml_string_writer;
490    emitter->writer_data = &(emitter->standard_writer_data);
491
492    emitter->standard_writer_data.file = file;
493}
494
495/*
496 * Set a generic output handler.
497 */
498
499YAML_DECLARE(void)
500yaml_emitter_set_writer(yaml_emitter_t *emitter,
501        yaml_writer_t *writer, void *data)
502{
503    assert(emitter);    /* Non-NULL emitter object expected. */
504    assert(!emitter->writer);   /* You can set the output only once. */
505    assert(writer); /* Non-NULL handler object expected. */
506
507    emitter->writer = writer;
508    emitter->writer_data = data;
509}
510
511/*
512 * Set the output encoding.
513 */
514
515YAML_DECLARE(void)
516yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
517{
518    assert(emitter);    /* Non-NULL emitter object expected. */
519    assert(!emitter->encoding);     /* You can set encoding only once. */
520
521    emitter->encoding = encoding;
522}
523
524/*
525 * Set the canonical output style.
526 */
527
528YAML_DECLARE(void)
529yaml_emitter_set_canonical(yaml_emitter_t *emitter, int is_canonical)
530{
531    assert(emitter);    /* Non-NULL emitter object expected. */
532
533    emitter->is_canonical = (is_canonical != 0);
534}
535
536/*
537 * Set the indentation increment.
538 */
539
540YAML_DECLARE(void)
541yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
542{
543    assert(emitter);    /* Non-NULL emitter object expected. */
544
545    emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
546}
547
548/*
549 * Set the preferred line width.
550 */
551
552YAML_DECLARE(void)
553yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
554{
555    assert(emitter);    /* Non-NULL emitter object expected. */
556
557    emitter->best_width = (width >= 0) ? width : -1;
558}
559
560/*
561 * Set if unescaped non-ASCII characters are allowed.
562 */
563
564YAML_DECLARE(void)
565yaml_emitter_set_unicode(yaml_emitter_t *emitter, int is_unicode)
566{
567    assert(emitter);    /* Non-NULL emitter object expected. */
568
569    emitter->is_unicode = (is_unicode != 0);
570}
571
572/*
573 * Set the preferred line break character.
574 */
575
576YAML_DECLARE(void)
577yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
578{
579    assert(emitter);    /* Non-NULL emitter object expected. */
580
581    emitter->line_break = line_break;
582}
583
584/*
585 * Allocate a token object.
586 */
587
588YAML_DECLARE(yaml_token_t *)
589yaml_token_new(void)
590{
591    yaml_token_t *token = yaml_malloc(sizeof(yaml_token_t));
592
593    if (!token)
594        return NULL;
595
596    memset(token, 0, sizeof(yaml_token_t));
597
598    return token;
599}
600
601/*
602 * Deallocate a token object.
603 */
604
605YAML_DECLARE(void)
606yaml_token_delete(yaml_token_t *token)
607{
608    assert(token);  /* Non-NULL token object expected. */
609
610    yaml_token_destroy(token);
611    yaml_free(token);
612}
613
614/*
615 * Duplicate a token object.
616 */
617
618YAML_DECLARE(int)
619yaml_token_duplicate(yaml_token_t *token, yaml_token_t *model)
620{
621    assert(token);  /* Non-NULL token object is expected. */
622    assert(model);  /* Non-NULL model token object is expected. */
623
624    memset(token, 0, sizeof(yaml_token_t));
625
626    token->type = model->type;
627    token->start_mark = model->start_mark;
628    token->end_mark = model->end_mark;
629
630    switch (token->type)
631    {
632        case YAML_STREAM_START_TOKEN:
633            token->data.stream_start.encoding =
634                model->data.stream_start.encoding;
635            break;
636
637        case YAML_VERSION_DIRECTIVE_TOKEN:
638            token->data.version_directive.major =
639                model->data.version_directive.major;
640            token->data.version_directive.minor =
641                model->data.version_directive.minor;
642            break;
643
644        case YAML_TAG_DIRECTIVE_TOKEN:
645            if (!(token->data.tag_directive.handle =
646                        yaml_strdup(model->data.tag_directive.handle)))
647                goto error;
648            if (!(token->data.tag_directive.prefix =
649                        yaml_strdup(model->data.tag_directive.prefix)))
650                goto error;
651            break;
652
653        case YAML_ALIAS_TOKEN:
654            if (!(token->data.alias.value =
655                        yaml_strdup(model->data.alias.value)))
656                goto error;
657            break;
658
659        case YAML_ANCHOR_TOKEN:
660            if (!(token->data.anchor.value =
661                        yaml_strdup(model->data.anchor.value)))
662                goto error;
663            break;
664
665        case YAML_TAG_TOKEN:
666            if (!(token->data.tag.handle = yaml_strdup(model->data.tag.handle)))
667                goto error;
668            if (!(token->data.tag.suffix = yaml_strdup(model->data.tag.suffix)))
669                goto error;
670            break;
671
672        case YAML_SCALAR_TOKEN:
673            if (!(token->data.scalar.value =
674                        yaml_malloc(model->data.scalar.length+1)))
675                goto error;
676            memcpy(token->data.scalar.value, model->data.scalar.value,
677                    model->data.scalar.length+1);
678            token->data.scalar.length = model->data.scalar.length;
679            break;
680
681        default:
682            break;
683    }
684
685    return 1;
686
687error:
688    yaml_token_destroy(token);
689
690    return 0;
691}
692
693/*
694 * Destroy a token object.
695 */
696
697YAML_DECLARE(void)
698yaml_token_destroy(yaml_token_t *token)
699{
700    assert(token);  /* Non-NULL token object expected. */
701
702    switch (token->type)
703    {
704        case YAML_TAG_DIRECTIVE_TOKEN:
705            yaml_free(token->data.tag_directive.handle);
706            yaml_free(token->data.tag_directive.prefix);
707            break;
708
709        case YAML_ALIAS_TOKEN:
710            yaml_free(token->data.alias.value);
711            break;
712
713        case YAML_ANCHOR_TOKEN:
714            yaml_free(token->data.anchor.value);
715            break;
716
717        case YAML_TAG_TOKEN:
718            yaml_free(token->data.tag.handle);
719            yaml_free(token->data.tag.suffix);
720            break;
721
722        case YAML_SCALAR_TOKEN:
723            yaml_free(token->data.scalar.value);
724            break;
725
726        default:
727            break;
728    }
729
730    memset(token, 0, sizeof(yaml_token_t));
731}
732
733/*
734 * Check if a string is a valid UTF-8 sequence.
735 *
736 * Check 'reader.c' for more details on UTF-8 encoding.
737 */
738
739static int
740yaml_valid_utf8(const yaml_char_t *buffer, size_t length)
741{
742    size_t pointer = 0;
743
744    while (pointer < length) {
745        unsigned char octet;
746        unsigned int width;
747        unsigned int value;
748        size_t k;
749
750        octet = buffer[pointer];
751        width = (octet & 0x80) == 0x00 ? 1 :
752                (octet & 0xE0) == 0xC0 ? 2 :
753                (octet & 0xF0) == 0xE0 ? 3 :
754                (octet & 0xF8) == 0xF0 ? 4 : 0;
755        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
756                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
757                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
758                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
759        if (!width) return 0;
760        if (pointer+width > length) return 0;
761        for (k = 1; k < width; k ++) {
762            octet = buffer[pointer+k];
763            if ((octet & 0xC0) != 0x80) return 0;
764            value = (value << 6) + (octet & 0x3F);
765        }
766        if (!((width == 1) ||
767            (width == 2 && value >= 0x80) ||
768            (width == 3 && value >= 0x800) ||
769            (width == 4 && value >= 0x10000))) return 0;
770
771        pointer += width;
772    }
773
774    return 1;
775}
776
777/*
778 * Allocate an event object.
779 */
780
781YAML_DECLARE(yaml_event_t *)
782yaml_event_new(void)
783{
784    yaml_event_t *event = yaml_malloc(sizeof(yaml_event_t));
785
786    if (!event)
787        return NULL;
788
789    memset(event, 0, sizeof(yaml_event_t));
790
791    return event;
792}
793
794/*
795 * Deallocate an event object.
796 */
797
798YAML_DECLARE(void)
799yaml_event_delete(yaml_event_t *event)
800{
801    assert(event);  /* Non-NULL event object expected. */
802
803    yaml_event_destroy(event);
804    yaml_free(event);
805}
806
807/*
808 * Duplicate an event object.
809 */
810
811YAML_DECLARE(int)
812yaml_event_duplicate(yaml_event_t *event, yaml_event_t *model)
813{
814    struct {
815        yaml_error_t error;
816    } self;
817
818    assert(event);  /* Non-NULL event object is expected. */
819    assert(model);  /* Non-NULL model event object is expected. */
820
821    memset(event, 0, sizeof(yaml_event_t));
822
823    event->type = model->type;
824    event->start_mark = model->start_mark;
825    event->end_mark = model->end_mark;
826
827    switch (event->type)
828    {
829        case YAML_STREAM_START_EVENT:
830            event->data.stream_start.encoding =
831                model->data.stream_start.encoding;
832            break;
833
834        case YAML_DOCUMENT_START_EVENT:
835            if (model->data.document_start.version_directive) {
836                if (!(event->data.document_start.version_directive =
837                            yaml_malloc(sizeof(yaml_version_directive_t))))
838                    goto error;
839                *event->data.document_start.version_directive =
840                    *model->data.document_start.version_directive;
841            }
842            if (model->data.document_start.tag_directives.length) {
843                yaml_tag_directive_t *tag_directives =
844                    model->data.document_start.tag_directives.list;
845                if (!STACK_INIT(&self, event->data.document_start.tag_directives,
846                            model->data.document_start.tag_directives.capacity))
847                    goto error;
848                while (event->data.document_start.tag_directives.length !=
849                        model->data.document_start.tag_directives.length) {
850                    yaml_tag_directive_t value;
851                    value.handle = yaml_strdup(tag_directives->handle);
852                    value.prefix = yaml_strdup(tag_directives->prefix);
853                    PUSH(&self, event->data.document_start.tag_directives, value);
854                    if (!value.handle || !value.prefix)
855                        goto error;
856                    tag_directives ++;
857                }
858            }
859            event->data.document_start.is_implicit =
860                model->data.document_start.is_implicit;
861            break;
862
863        case YAML_DOCUMENT_END_EVENT:
864            event->data.document_end.is_implicit =
865                model->data.document_end.is_implicit;
866
867        case YAML_ALIAS_EVENT:
868            if (!(event->data.alias.anchor =
869                        yaml_strdup(model->data.alias.anchor)))
870                goto error;
871            break;
872
873        case YAML_SCALAR_EVENT:
874            if (model->data.scalar.anchor &&
875                    !(event->data.scalar.anchor =
876                        yaml_strdup(model->data.scalar.anchor)))
877                goto error;
878            if (event->data.scalar.tag &&
879                    !(event->data.scalar.tag =
880                        yaml_strdup(model->data.scalar.tag)))
881                goto error;
882            if (!(event->data.scalar.value =
883                        yaml_malloc(model->data.scalar.length+1)))
884                goto error;
885            memcpy(event->data.scalar.value, model->data.scalar.value,
886                    model->data.scalar.length+1);
887            event->data.scalar.length = model->data.scalar.length;
888            event->data.scalar.is_plain_implicit =
889                model->data.scalar.is_plain_implicit;
890            event->data.scalar.is_quoted_implicit =
891                model->data.scalar.is_quoted_implicit;
892            event->data.scalar.style = model->data.scalar.style;
893            break;
894
895        case YAML_SEQUENCE_START_EVENT:
896            if (model->data.sequence_start.anchor &&
897                    !(event->data.sequence_start.anchor =
898                        yaml_strdup(model->data.sequence_start.anchor)))
899                goto error;
900            if (event->data.sequence_start.tag &&
901                    !(event->data.sequence_start.tag =
902                        yaml_strdup(model->data.sequence_start.tag)))
903                goto error;
904            event->data.sequence_start.is_implicit =
905                model->data.sequence_start.is_implicit;
906            event->data.sequence_start.style =
907                model->data.sequence_start.style;
908            break;
909
910        case YAML_MAPPING_START_EVENT:
911            if (model->data.mapping_start.anchor &&
912                    !(event->data.mapping_start.anchor =
913                        yaml_strdup(model->data.mapping_start.anchor)))
914                goto error;
915            if (event->data.mapping_start.tag &&
916                    !(event->data.mapping_start.tag =
917                        yaml_strdup(model->data.mapping_start.tag)))
918                goto error;
919            event->data.mapping_start.is_implicit =
920                model->data.mapping_start.is_implicit;
921            event->data.mapping_start.style =
922                model->data.mapping_start.style;
923            break;
924
925        default:
926            break;
927    }
928
929    return 1;
930
931error:
932    yaml_event_destroy(event);
933
934    return 0;
935}
936
937/*
938 * Create STREAM-START.
939 */
940
941YAML_DECLARE(int)
942yaml_event_create_stream_start(yaml_event_t *event,
943        yaml_encoding_t encoding)
944{
945    yaml_mark_t mark = { 0, 0, 0 };
946
947    assert(event);  /* Non-NULL event object is expected. */
948
949    STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
950
951    return 1;
952}
953
954/*
955 * Create STREAM-END.
956 */
957
958YAML_DECLARE(int)
959yaml_event_create_stream_end(yaml_event_t *event)
960{
961    yaml_mark_t mark = { 0, 0, 0 };
962
963    assert(event);  /* Non-NULL event object is expected. */
964
965    STREAM_END_EVENT_INIT(*event, mark, mark);
966
967    return 1;
968}
969
970/*
971 * Create DOCUMENT-START.
972 */
973
974YAML_DECLARE(int)
975yaml_event_create_document_start(yaml_event_t *event,
976        const yaml_version_directive_t *version_directive,
977        const yaml_tag_directive_t *tag_directives,
978        int is_implicit)
979{
980    struct {
981        yaml_error_t error;
982    } self;
983    yaml_mark_t mark = { 0, 0, 0 };
984    yaml_version_directive_t *version_directive_copy = NULL;
985    struct {
986        yaml_tag_directive_t *list;
987        size_t length;
988        size_t capacity;
989    } tag_directives_copy = { NULL, 0, 0 };
990
991    assert(event);          /* Non-NULL event object is expected. */
992
993    if (version_directive) {
994        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
995        if (!version_directive_copy) goto error;
996        *version_directive_copy = *version_directive;
997    }
998
999    if (tag_directives && (tag_directives->handle || tag_directives->prefix)) {
1000        if (!STACK_INIT(&self, tag_directives_copy, INITIAL_STACK_CAPACITY))
1001            goto error;
1002        while (tag_directives->handle || tag_directives->prefix) {
1003            yaml_tag_directive_t value = *tag_directives;
1004            assert(value.handle);
1005            assert(value.prefix);
1006            if (!yaml_valid_utf8(value.handle, strlen((char *)value.handle)))
1007                goto error;
1008            if (!yaml_valid_utf8(value.prefix, strlen((char *)value.prefix)))
1009                goto error;
1010            if (!PUSH(&self, tag_directives_copy, value))
1011                goto error;
1012            value.handle = yaml_strdup(value.handle);
1013            value.prefix = yaml_strdup(value.prefix);
1014            tag_directives_copy.list[tag_directives_copy.length-1] = value;
1015            if (!value.handle || !value.prefix)
1016                goto error;
1017        }
1018    }
1019
1020    DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
1021            tag_directives_copy.list, tag_directives_copy.length,
1022            tag_directives_copy.capacity, is_implicit, mark, mark);
1023
1024    return 1;
1025
1026error:
1027    yaml_free(version_directive_copy);
1028    while (!STACK_EMPTY(&self, tag_directives_copy)) {
1029        yaml_tag_directive_t value = POP(&self, tag_directives_copy);
1030        yaml_free(value.handle);
1031        yaml_free(value.prefix);
1032    }
1033    STACK_DEL(&self, tag_directives_copy);
1034
1035    return 0;
1036}
1037
1038/*
1039 * Create DOCUMENT-END.
1040 */
1041
1042YAML_DECLARE(int)
1043yaml_event_create_document_end(yaml_event_t *event, int is_implicit)
1044{
1045    yaml_mark_t mark = { 0, 0, 0 };
1046
1047    assert(event);      /* Non-NULL emitter object is expected. */
1048
1049    DOCUMENT_END_EVENT_INIT(*event, is_implicit, mark, mark);
1050
1051    return 1;
1052}
1053
1054/*
1055 * Create ALIAS.
1056 */
1057
1058YAML_DECLARE(int)
1059yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor)
1060{
1061    yaml_mark_t mark = { 0, 0, 0 };
1062    yaml_char_t *anchor_copy = NULL;
1063
1064    assert(event);      /* Non-NULL event object is expected. */
1065    assert(anchor);     /* Non-NULL anchor is expected. */
1066
1067    if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) return 0;
1068
1069    anchor_copy = yaml_strdup(anchor);
1070    if (!anchor_copy)
1071        return 0;
1072
1073    ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
1074
1075    return 1;
1076}
1077
1078/*
1079 * Create SCALAR.
1080 */
1081
1082YAML_DECLARE(int)
1083yaml_event_create_scalar(yaml_event_t *event,
1084        const yaml_char_t *anchor, const yaml_char_t *tag,
1085        const yaml_char_t *value, size_t length,
1086        int is_plain_implicit, int is_quoted_implicit,
1087        yaml_scalar_style_t style)
1088{
1089    yaml_mark_t mark = { 0, 0, 0 };
1090    yaml_char_t *anchor_copy = NULL;
1091    yaml_char_t *tag_copy = NULL;
1092    yaml_char_t *value_copy = NULL;
1093
1094    assert(event);      /* Non-NULL event object is expected. */
1095    assert(value);      /* Non-NULL anchor is expected. */
1096
1097    if (anchor) {
1098        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1099            goto error;
1100        anchor_copy = yaml_strdup(anchor);
1101        if (!anchor_copy)
1102            goto error;
1103    }
1104
1105    if (tag) {
1106        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1107            goto error;
1108        tag_copy = yaml_strdup(tag);
1109        if (!tag_copy)
1110            goto error;
1111    }
1112
1113    if (length < 0) {
1114        length = strlen((char *)value);
1115    }
1116
1117    if (!yaml_valid_utf8(value, length))
1118        goto error;
1119    value_copy = yaml_malloc(length+1);
1120    if (!value_copy)
1121        goto error;
1122    memcpy(value_copy, value, length);
1123    value_copy[length] = '\0';
1124
1125    SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
1126            is_plain_implicit, is_quoted_implicit, style, mark, mark);
1127
1128    return 1;
1129
1130error:
1131    yaml_free(anchor_copy);
1132    yaml_free(tag_copy);
1133    yaml_free(value_copy);
1134
1135    return 0;
1136}
1137
1138/*
1139 * Create SEQUENCE-START.
1140 */
1141
1142YAML_DECLARE(int)
1143yaml_event_create_sequence_start(yaml_event_t *event,
1144        const yaml_char_t *anchor, const yaml_char_t *tag,
1145        int is_implicit, yaml_sequence_style_t style)
1146{
1147    yaml_mark_t mark = { 0, 0, 0 };
1148    yaml_char_t *anchor_copy = NULL;
1149    yaml_char_t *tag_copy = NULL;
1150
1151    assert(event);      /* Non-NULL event object is expected. */
1152
1153    if (anchor) {
1154        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1155            goto error;
1156        anchor_copy = yaml_strdup(anchor);
1157        if (!anchor_copy)
1158            goto error;
1159    }
1160
1161    if (tag) {
1162        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1163            goto error;
1164        tag_copy = yaml_strdup(tag);
1165        if (!tag_copy)
1166            goto error;
1167    }
1168
1169    SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
1170            is_implicit, style, mark, mark);
1171
1172    return 1;
1173
1174error:
1175    yaml_free(anchor_copy);
1176    yaml_free(tag_copy);
1177
1178    return 0;
1179}
1180
1181/*
1182 * Create SEQUENCE-END.
1183 */
1184
1185YAML_DECLARE(int)
1186yaml_event_create_sequence_end(yaml_event_t *event)
1187{
1188    yaml_mark_t mark = { 0, 0, 0 };
1189
1190    assert(event);      /* Non-NULL event object is expected. */
1191
1192    SEQUENCE_END_EVENT_INIT(*event, mark, mark);
1193
1194    return 1;
1195}
1196
1197/*
1198 * Create MAPPING-START.
1199 */
1200
1201YAML_DECLARE(int)
1202yaml_event_create_mapping_start(yaml_event_t *event,
1203        const yaml_char_t *anchor, const yaml_char_t *tag,
1204        int is_implicit, yaml_mapping_style_t style)
1205{
1206    yaml_mark_t mark = { 0, 0, 0 };
1207    yaml_char_t *anchor_copy = NULL;
1208    yaml_char_t *tag_copy = NULL;
1209
1210    assert(event);      /* Non-NULL event object is expected. */
1211
1212    if (anchor) {
1213        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1214            goto error;
1215        anchor_copy = yaml_strdup(anchor);
1216        if (!anchor_copy)
1217            goto error;
1218    }
1219
1220    if (tag) {
1221        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1222            goto error;
1223        tag_copy = yaml_strdup(tag);
1224        if (!tag_copy)
1225            goto error;
1226    }
1227
1228    MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
1229            is_implicit, style, mark, mark);
1230
1231    return 1;
1232
1233error:
1234    yaml_free(anchor_copy);
1235    yaml_free(tag_copy);
1236
1237    return 0;
1238}
1239
1240/*
1241 * Create MAPPING-END.
1242 */
1243
1244YAML_DECLARE(int)
1245yaml_event_create_mapping_end(yaml_event_t *event)
1246{
1247    yaml_mark_t mark = { 0, 0, 0 };
1248
1249    assert(event);      /* Non-NULL event object is expected. */
1250
1251    MAPPING_END_EVENT_INIT(*event, mark, mark);
1252
1253    return 1;
1254}
1255
1256/*
1257 * Destroy an event object.
1258 */
1259
1260YAML_DECLARE(void)
1261yaml_event_destroy(yaml_event_t *event)
1262{
1263    struct {
1264        yaml_error_t error;
1265    } self;
1266
1267    assert(event);  /* Non-NULL event object expected. */
1268
1269    switch (event->type)
1270    {
1271        case YAML_DOCUMENT_START_EVENT:
1272            yaml_free(event->data.document_start.version_directive);
1273            while (!STACK_EMPTY(&self, event->data.document_start.tag_directives)) {
1274                yaml_tag_directive_t value = POP(&self,
1275                        event->data.document_start.tag_directives);
1276                yaml_free(value.handle);
1277                yaml_free(value.prefix);
1278            }
1279            STACK_DEL(&self, event->data.document_start.tag_directives);
1280            break;
1281
1282        case YAML_ALIAS_EVENT:
1283            yaml_free(event->data.alias.anchor);
1284            break;
1285
1286        case YAML_SCALAR_EVENT:
1287            yaml_free(event->data.scalar.anchor);
1288            yaml_free(event->data.scalar.tag);
1289            yaml_free(event->data.scalar.value);
1290            break;
1291
1292        case YAML_SEQUENCE_START_EVENT:
1293            yaml_free(event->data.sequence_start.anchor);
1294            yaml_free(event->data.sequence_start.tag);
1295            break;
1296
1297        case YAML_MAPPING_START_EVENT:
1298            yaml_free(event->data.mapping_start.anchor);
1299            yaml_free(event->data.mapping_start.tag);
1300            break;
1301
1302        default:
1303            break;
1304    }
1305
1306    memset(event, 0, sizeof(yaml_event_t));
1307}
1308
1309#if 0
1310
1311/*
1312 * Create a document object.
1313 */
1314
1315YAML_DECLARE(int)
1316yaml_document_initialize(yaml_document_t *document,
1317        yaml_version_directive_t *version_directive,
1318        yaml_tag_directive_t *tag_directives_start,
1319        yaml_tag_directive_t *tag_directives_end,
1320        int start_implicit, int end_implicit)
1321{
1322    struct {
1323        yaml_error_type_t error;
1324    } context;
1325    struct {
1326        yaml_node_t *start;
1327        yaml_node_t *end;
1328        yaml_node_t *top;
1329    } nodes = { NULL, NULL, NULL };
1330    yaml_version_directive_t *version_directive_copy = NULL;
1331    struct {
1332        yaml_tag_directive_t *start;
1333        yaml_tag_directive_t *end;
1334        yaml_tag_directive_t *top;
1335    } tag_directives_copy = { NULL, NULL, NULL };
1336    yaml_tag_directive_t value = { NULL, NULL };
1337    yaml_mark_t mark = { 0, 0, 0 };
1338
1339    assert(document);       /* Non-NULL document object is expected. */
1340    assert((tag_directives_start && tag_directives_end) ||
1341            (tag_directives_start == tag_directives_end));
1342                            /* Valid tag directives are expected. */
1343
1344    if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
1345
1346    if (version_directive) {
1347        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1348        if (!version_directive_copy) goto error;
1349        version_directive_copy->major = version_directive->major;
1350        version_directive_copy->minor = version_directive->minor;
1351    }
1352
1353    if (tag_directives_start != tag_directives_end) {
1354        yaml_tag_directive_t *tag_directive;
1355        if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
1356            goto error;
1357        for (tag_directive = tag_directives_start;
1358                tag_directive != tag_directives_end; tag_directive ++) {
1359            assert(tag_directive->handle);
1360            assert(tag_directive->prefix);
1361            if (!yaml_valid_utf8(tag_directive->handle,
1362                        strlen((char *)tag_directive->handle)))
1363                goto error;
1364            if (!yaml_valid_utf8(tag_directive->prefix,
1365                        strlen((char *)tag_directive->prefix)))
1366                goto error;
1367            value.handle = yaml_strdup(tag_directive->handle);
1368            value.prefix = yaml_strdup(tag_directive->prefix);
1369            if (!value.handle || !value.prefix) goto error;
1370            if (!PUSH(&context, tag_directives_copy, value))
1371                goto error;
1372            value.handle = NULL;
1373            value.prefix = NULL;
1374        }
1375    }
1376
1377    DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1378            tag_directives_copy.start, tag_directives_copy.top,
1379            start_implicit, end_implicit, mark, mark);
1380
1381    return 1;
1382
1383error:
1384    STACK_DEL(&context, nodes);
1385    yaml_free(version_directive_copy);
1386    while (!STACK_EMPTY(&context, tag_directives_copy)) {
1387        yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1388        yaml_free(value.handle);
1389        yaml_free(value.prefix);
1390    }
1391    STACK_DEL(&context, tag_directives_copy);
1392    yaml_free(value.handle);
1393    yaml_free(value.prefix);
1394
1395    return 0;
1396}
1397
1398/*
1399 * Destroy a document object.
1400 */
1401
1402YAML_DECLARE(void)
1403yaml_document_delete(yaml_document_t *document)
1404{
1405    struct {
1406        yaml_error_type_t error;
1407    } context;
1408    yaml_tag_directive_t *tag_directive;
1409
1410    context.error = YAML_NO_ERROR;  /* Eliminate a compliler warning. */
1411
1412    assert(document);   /* Non-NULL document object is expected. */
1413
1414    while (!STACK_EMPTY(&context, document->nodes)) {
1415        yaml_node_t node = POP(&context, document->nodes);
1416        yaml_free(node.tag);
1417        switch (node.type) {
1418            case YAML_SCALAR_NODE:
1419                yaml_free(node.data.scalar.value);
1420                break;
1421            case YAML_SEQUENCE_NODE:
1422                STACK_DEL(&context, node.data.sequence.items);
1423                break;
1424            case YAML_MAPPING_NODE:
1425                STACK_DEL(&context, node.data.mapping.pairs);
1426                break;
1427            default:
1428                assert(0);  /* Should not happen. */
1429        }
1430    }
1431    STACK_DEL(&context, document->nodes);
1432
1433    yaml_free(document->version_directive);
1434    for (tag_directive = document->tag_directives.start;
1435            tag_directive != document->tag_directives.end;
1436            tag_directive++) {
1437        yaml_free(tag_directive->handle);
1438        yaml_free(tag_directive->prefix);
1439    }
1440    yaml_free(document->tag_directives.start);
1441
1442    memset(document, 0, sizeof(yaml_document_t));
1443}
1444
1445/**
1446 * Get a document node.
1447 */
1448
1449YAML_DECLARE(yaml_node_t *)
1450yaml_document_get_node(yaml_document_t *document, int index)
1451{
1452    assert(document);   /* Non-NULL document object is expected. */
1453
1454    if (index > 0 && document->nodes.start + index <= document->nodes.top) {
1455        return document->nodes.start + index - 1;
1456    }
1457    return NULL;
1458}
1459
1460/**
1461 * Get the root object.
1462 */
1463
1464YAML_DECLARE(yaml_node_t *)
1465yaml_document_get_root_node(yaml_document_t *document)
1466{
1467    assert(document);   /* Non-NULL document object is expected. */
1468
1469    if (document->nodes.top != document->nodes.start) {
1470        return document->nodes.start;
1471    }
1472    return NULL;
1473}
1474
1475/*
1476 * Add a scalar node to a document.
1477 */
1478
1479YAML_DECLARE(int)
1480yaml_document_add_scalar(yaml_document_t *document,
1481        yaml_char_t *tag, yaml_char_t *value, int length,
1482        yaml_scalar_style_t style)
1483{
1484    struct {
1485        yaml_error_type_t error;
1486    } context;
1487    yaml_mark_t mark = { 0, 0, 0 };
1488    yaml_char_t *tag_copy = NULL;
1489    yaml_char_t *value_copy = NULL;
1490    yaml_node_t node;
1491
1492    assert(document);   /* Non-NULL document object is expected. */
1493    assert(value);      /* Non-NULL value is expected. */
1494
1495    if (!tag) {
1496        tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
1497    }
1498
1499    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1500    tag_copy = yaml_strdup(tag);
1501    if (!tag_copy) goto error;
1502
1503    if (length < 0) {
1504        length = strlen((char *)value);
1505    }
1506
1507    if (!yaml_valid_utf8(value, length)) goto error;
1508    value_copy = yaml_malloc(length+1);
1509    if (!value_copy) goto error;
1510    memcpy(value_copy, value, length);
1511    value_copy[length] = '\0';
1512
1513    SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
1514    if (!PUSH(&context, document->nodes, node)) goto error;
1515
1516    return document->nodes.top - document->nodes.start;
1517
1518error:
1519    yaml_free(tag_copy);
1520    yaml_free(value_copy);
1521
1522    return 0;
1523}
1524
1525/*
1526 * Add a sequence node to a document.
1527 */
1528
1529YAML_DECLARE(int)
1530yaml_document_add_sequence(yaml_document_t *document,
1531        yaml_char_t *tag, yaml_sequence_style_t style)
1532{
1533    struct {
1534        yaml_error_type_t error;
1535    } context;
1536    yaml_mark_t mark = { 0, 0, 0 };
1537    yaml_char_t *tag_copy = NULL;
1538    struct {
1539        yaml_node_item_t *start;
1540        yaml_node_item_t *end;
1541        yaml_node_item_t *top;
1542    } items = { NULL, NULL, NULL };
1543    yaml_node_t node;
1544
1545    assert(document);   /* Non-NULL document object is expected. */
1546
1547    if (!tag) {
1548        tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
1549    }
1550
1551    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1552    tag_copy = yaml_strdup(tag);
1553    if (!tag_copy) goto error;
1554
1555    if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
1556
1557    SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
1558            style, mark, mark);
1559    if (!PUSH(&context, document->nodes, node)) goto error;
1560
1561    return document->nodes.top - document->nodes.start;
1562
1563error:
1564    STACK_DEL(&context, items);
1565    yaml_free(tag_copy);
1566
1567    return 0;
1568}
1569
1570/*
1571 * Add a mapping node to a document.
1572 */
1573
1574YAML_DECLARE(int)
1575yaml_document_add_mapping(yaml_document_t *document,
1576        yaml_char_t *tag, yaml_mapping_style_t style)
1577{
1578    struct {
1579        yaml_error_type_t error;
1580    } context;
1581    yaml_mark_t mark = { 0, 0, 0 };
1582    yaml_char_t *tag_copy = NULL;
1583    struct {
1584        yaml_node_pair_t *start;
1585        yaml_node_pair_t *end;
1586        yaml_node_pair_t *top;
1587    } pairs = { NULL, NULL, NULL };
1588    yaml_node_t node;
1589
1590    assert(document);   /* Non-NULL document object is expected. */
1591
1592    if (!tag) {
1593        tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
1594    }
1595
1596    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1597    tag_copy = yaml_strdup(tag);
1598    if (!tag_copy) goto error;
1599
1600    if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
1601
1602    MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
1603            style, mark, mark);
1604    if (!PUSH(&context, document->nodes, node)) goto error;
1605
1606    return document->nodes.top - document->nodes.start;
1607
1608error:
1609    STACK_DEL(&context, pairs);
1610    yaml_free(tag_copy);
1611
1612    return 0;
1613}
1614
1615/*
1616 * Append an item to a sequence node.
1617 */
1618
1619YAML_DECLARE(int)
1620yaml_document_append_sequence_item(yaml_document_t *document,
1621        int sequence, int item)
1622{
1623    struct {
1624        yaml_error_type_t error;
1625    } context;
1626
1627    assert(document);       /* Non-NULL document is required. */
1628    assert(sequence > 0
1629            && document->nodes.start + sequence <= document->nodes.top);
1630                            /* Valid sequence id is required. */
1631    assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
1632                            /* A sequence node is required. */
1633    assert(item > 0 && document->nodes.start + item <= document->nodes.top);
1634                            /* Valid item id is required. */
1635
1636    if (!PUSH(&context,
1637                document->nodes.start[sequence-1].data.sequence.items, item))
1638        return 0;
1639
1640    return 1;
1641}
1642
1643/*
1644 * Append a pair of a key and a value to a mapping node.
1645 */
1646
1647YAML_DECLARE(int)
1648yaml_document_append_mapping_pair(yaml_document_t *document,
1649        int mapping, int key, int value)
1650{
1651    struct {
1652        yaml_error_type_t error;
1653    } context;
1654    yaml_node_pair_t pair = { key, value };
1655
1656    assert(document);       /* Non-NULL document is required. */
1657    assert(mapping > 0
1658            && document->nodes.start + mapping <= document->nodes.top);
1659                            /* Valid mapping id is required. */
1660    assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
1661                            /* A mapping node is required. */
1662    assert(key > 0 && document->nodes.start + key <= document->nodes.top);
1663                            /* Valid key id is required. */
1664    assert(value > 0 && document->nodes.start + value <= document->nodes.top);
1665                            /* Valid value id is required. */
1666
1667    if (!PUSH(&context,
1668                document->nodes.start[mapping-1].data.mapping.pairs, pair))
1669        return 0;
1670
1671    return 1;
1672}
1673
1674#endif
1675
Note: See TracBrowser for help on using the repository browser.