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

Revision 265, 46.3 KB checked in by xi, 6 years ago (diff)

Fixed bugs and updated tests.

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