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

Revision 264, 46.4 KB checked in by xi, 6 years ago (diff)

Another round of API update.

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 position %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 position %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 position %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_delete(&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 *length, size_t capacity)
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    token->start_mark = model->start_mark;
733    token->end_mark = model->end_mark;
734
735    switch (token->type)
736    {
737        case YAML_STREAM_START_TOKEN:
738            token->data.stream_start.encoding =
739                model->data.stream_start.encoding;
740            break;
741
742        case YAML_VERSION_DIRECTIVE_TOKEN:
743            token->data.version_directive.major =
744                model->data.version_directive.major;
745            token->data.version_directive.minor =
746                model->data.version_directive.minor;
747            break;
748
749        case YAML_TAG_DIRECTIVE_TOKEN:
750            if (!(token->data.tag_directive.handle =
751                        yaml_strdup(model->data.tag_directive.handle)))
752                goto error;
753            if (!(token->data.tag_directive.prefix =
754                        yaml_strdup(model->data.tag_directive.prefix)))
755                goto error;
756            break;
757
758        case YAML_ALIAS_TOKEN:
759            if (!(token->data.alias.value =
760                        yaml_strdup(model->data.alias.value)))
761                goto error;
762            break;
763
764        case YAML_ANCHOR_TOKEN:
765            if (!(token->data.anchor.value =
766                        yaml_strdup(model->data.anchor.value)))
767                goto error;
768            break;
769
770        case YAML_TAG_TOKEN:
771            if (!(token->data.tag.handle = yaml_strdup(model->data.tag.handle)))
772                goto error;
773            if (!(token->data.tag.suffix = yaml_strdup(model->data.tag.suffix)))
774                goto error;
775            break;
776
777        case YAML_SCALAR_TOKEN:
778            if (!(token->data.scalar.value =
779                        yaml_malloc(model->data.scalar.length+1)))
780                goto error;
781            memcpy(token->data.scalar.value, model->data.scalar.value,
782                    model->data.scalar.length+1);
783            token->data.scalar.length = model->data.scalar.length;
784            break;
785
786        default:
787            break;
788    }
789
790    return 1;
791
792error:
793    yaml_token_destroy(token);
794
795    return 0;
796}
797
798/*
799 * Destroy a token object.
800 */
801
802YAML_DECLARE(void)
803yaml_token_destroy(yaml_token_t *token)
804{
805    assert(token);  /* Non-NULL token object expected. */
806
807    switch (token->type)
808    {
809        case YAML_TAG_DIRECTIVE_TOKEN:
810            yaml_free(token->data.tag_directive.handle);
811            yaml_free(token->data.tag_directive.prefix);
812            break;
813
814        case YAML_ALIAS_TOKEN:
815            yaml_free(token->data.alias.value);
816            break;
817
818        case YAML_ANCHOR_TOKEN:
819            yaml_free(token->data.anchor.value);
820            break;
821
822        case YAML_TAG_TOKEN:
823            yaml_free(token->data.tag.handle);
824            yaml_free(token->data.tag.suffix);
825            break;
826
827        case YAML_SCALAR_TOKEN:
828            yaml_free(token->data.scalar.value);
829            break;
830
831        default:
832            break;
833    }
834
835    memset(token, 0, sizeof(yaml_token_t));
836}
837
838/*
839 * Check if a string is a valid UTF-8 sequence.
840 *
841 * Check 'reader.c' for more details on UTF-8 encoding.
842 */
843
844static int
845yaml_valid_utf8(const yaml_char_t *buffer, size_t length)
846{
847    size_t pointer = 0;
848
849    while (pointer < length) {
850        unsigned char octet;
851        unsigned int width;
852        unsigned int value;
853        size_t k;
854
855        octet = buffer[pointer];
856        width = (octet & 0x80) == 0x00 ? 1 :
857                (octet & 0xE0) == 0xC0 ? 2 :
858                (octet & 0xF0) == 0xE0 ? 3 :
859                (octet & 0xF8) == 0xF0 ? 4 : 0;
860        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
861                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
862                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
863                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
864        if (!width) return 0;
865        if (pointer+width > length) return 0;
866        for (k = 1; k < width; k ++) {
867            octet = buffer[pointer+k];
868            if ((octet & 0xC0) != 0x80) return 0;
869            value = (value << 6) + (octet & 0x3F);
870        }
871        if (!((width == 1) ||
872            (width == 2 && value >= 0x80) ||
873            (width == 3 && value >= 0x800) ||
874            (width == 4 && value >= 0x10000))) return 0;
875
876        pointer += width;
877    }
878
879    return 1;
880}
881
882/*
883 * Allocate an event object.
884 */
885
886YAML_DECLARE(yaml_event_t *)
887yaml_event_new(void)
888{
889    yaml_event_t *event = yaml_malloc(sizeof(yaml_event_t));
890
891    if (!event)
892        return NULL;
893
894    memset(event, 0, sizeof(yaml_event_t));
895
896    return event;
897}
898
899/*
900 * Deallocate an event object.
901 */
902
903YAML_DECLARE(void)
904yaml_event_delete(yaml_event_t *event)
905{
906    assert(event);  /* Non-NULL event object expected. */
907
908    yaml_event_destroy(event);
909    yaml_free(event);
910}
911
912/*
913 * Duplicate an event object.
914 */
915
916YAML_DECLARE(int)
917yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
918{
919    struct {
920        yaml_error_t error;
921    } self;
922
923    assert(event);  /* Non-NULL event object is expected. */
924    assert(model);  /* Non-NULL model event object is expected. */
925
926    memset(event, 0, sizeof(yaml_event_t));
927
928    event->type = model->type;
929    event->start_mark = model->start_mark;
930    event->end_mark = model->end_mark;
931
932    switch (event->type)
933    {
934        case YAML_STREAM_START_EVENT:
935            event->data.stream_start.encoding =
936                model->data.stream_start.encoding;
937            break;
938
939        case YAML_DOCUMENT_START_EVENT:
940            if (model->data.document_start.version_directive) {
941                if (!(event->data.document_start.version_directive =
942                            yaml_malloc(sizeof(yaml_version_directive_t))))
943                    goto error;
944                *event->data.document_start.version_directive =
945                    *model->data.document_start.version_directive;
946            }
947            if (model->data.document_start.tag_directives.length) {
948                yaml_tag_directive_t *tag_directives =
949                    model->data.document_start.tag_directives.list;
950                if (!STACK_INIT(&self, event->data.document_start.tag_directives,
951                            model->data.document_start.tag_directives.capacity))
952                    goto error;
953                while (event->data.document_start.tag_directives.length !=
954                        model->data.document_start.tag_directives.length) {
955                    yaml_tag_directive_t value;
956                    value.handle = yaml_strdup(tag_directives->handle);
957                    value.prefix = yaml_strdup(tag_directives->prefix);
958                    PUSH(&self, event->data.document_start.tag_directives, value);
959                    if (!value.handle || !value.prefix)
960                        goto error;
961                    tag_directives ++;
962                }
963            }
964            event->data.document_start.is_implicit =
965                model->data.document_start.is_implicit;
966            break;
967
968        case YAML_DOCUMENT_END_EVENT:
969            event->data.document_end.is_implicit =
970                model->data.document_end.is_implicit;
971
972        case YAML_ALIAS_EVENT:
973            if (!(event->data.alias.anchor =
974                        yaml_strdup(model->data.alias.anchor)))
975                goto error;
976            break;
977
978        case YAML_SCALAR_EVENT:
979            if (model->data.scalar.anchor &&
980                    !(event->data.scalar.anchor =
981                        yaml_strdup(model->data.scalar.anchor)))
982                goto error;
983            if (event->data.scalar.tag &&
984                    !(event->data.scalar.tag =
985                        yaml_strdup(model->data.scalar.tag)))
986                goto error;
987            if (!(event->data.scalar.value =
988                        yaml_malloc(model->data.scalar.length+1)))
989                goto error;
990            memcpy(event->data.scalar.value, model->data.scalar.value,
991                    model->data.scalar.length+1);
992            event->data.scalar.length = model->data.scalar.length;
993            event->data.scalar.is_plain_implicit =
994                model->data.scalar.is_plain_implicit;
995            event->data.scalar.is_quoted_implicit =
996                model->data.scalar.is_quoted_implicit;
997            event->data.scalar.style = model->data.scalar.style;
998            break;
999
1000        case YAML_SEQUENCE_START_EVENT:
1001            if (model->data.sequence_start.anchor &&
1002                    !(event->data.sequence_start.anchor =
1003                        yaml_strdup(model->data.sequence_start.anchor)))
1004                goto error;
1005            if (event->data.sequence_start.tag &&
1006                    !(event->data.sequence_start.tag =
1007                        yaml_strdup(model->data.sequence_start.tag)))
1008                goto error;
1009            event->data.sequence_start.is_implicit =
1010                model->data.sequence_start.is_implicit;
1011            event->data.sequence_start.style =
1012                model->data.sequence_start.style;
1013            break;
1014
1015        case YAML_MAPPING_START_EVENT:
1016            if (model->data.mapping_start.anchor &&
1017                    !(event->data.mapping_start.anchor =
1018                        yaml_strdup(model->data.mapping_start.anchor)))
1019                goto error;
1020            if (event->data.mapping_start.tag &&
1021                    !(event->data.mapping_start.tag =
1022                        yaml_strdup(model->data.mapping_start.tag)))
1023                goto error;
1024            event->data.mapping_start.is_implicit =
1025                model->data.mapping_start.is_implicit;
1026            event->data.mapping_start.style =
1027                model->data.mapping_start.style;
1028            break;
1029
1030        default:
1031            break;
1032    }
1033
1034    return 1;
1035
1036error:
1037    yaml_event_destroy(event);
1038
1039    return 0;
1040}
1041
1042/*
1043 * Create STREAM-START.
1044 */
1045
1046YAML_DECLARE(int)
1047yaml_event_create_stream_start(yaml_event_t *event,
1048        yaml_encoding_t encoding)
1049{
1050    yaml_mark_t mark = { 0, 0, 0 };
1051
1052    assert(event);  /* Non-NULL event object is expected. */
1053
1054    STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
1055
1056    return 1;
1057}
1058
1059/*
1060 * Create STREAM-END.
1061 */
1062
1063YAML_DECLARE(int)
1064yaml_event_create_stream_end(yaml_event_t *event)
1065{
1066    yaml_mark_t mark = { 0, 0, 0 };
1067
1068    assert(event);  /* Non-NULL event object is expected. */
1069
1070    STREAM_END_EVENT_INIT(*event, mark, mark);
1071
1072    return 1;
1073}
1074
1075/*
1076 * Create DOCUMENT-START.
1077 */
1078
1079YAML_DECLARE(int)
1080yaml_event_create_document_start(yaml_event_t *event,
1081        const yaml_version_directive_t *version_directive,
1082        const yaml_tag_directive_t *tag_directives,
1083        int is_implicit)
1084{
1085    struct {
1086        yaml_error_t error;
1087    } self;
1088    yaml_mark_t mark = { 0, 0, 0 };
1089    yaml_version_directive_t *version_directive_copy = NULL;
1090    struct {
1091        yaml_tag_directive_t *list;
1092        size_t length;
1093        size_t capacity;
1094    } tag_directives_copy = { NULL, 0, 0 };
1095
1096    assert(event);          /* Non-NULL event object is expected. */
1097
1098    if (version_directive) {
1099        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1100        if (!version_directive_copy) goto error;
1101        *version_directive_copy = *version_directive;
1102    }
1103
1104    if (tag_directives && (tag_directives->handle || tag_directives->prefix)) {
1105        if (!STACK_INIT(&self, tag_directives_copy, INITIAL_STACK_CAPACITY))
1106            goto error;
1107        while (tag_directives->handle || tag_directives->prefix) {
1108            yaml_tag_directive_t value = *tag_directives;
1109            assert(value.handle);
1110            assert(value.prefix);
1111            if (!yaml_valid_utf8(value.handle, strlen((char *)value.handle)))
1112                goto error;
1113            if (!yaml_valid_utf8(value.prefix, strlen((char *)value.prefix)))
1114                goto error;
1115            if (!PUSH(&self, tag_directives_copy, value))
1116                goto error;
1117            value.handle = yaml_strdup(value.handle);
1118            value.prefix = yaml_strdup(value.prefix);
1119            tag_directives_copy.list[tag_directives_copy.length-1] = value;
1120            if (!value.handle || !value.prefix)
1121                goto error;
1122        }
1123    }
1124
1125    DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
1126            tag_directives_copy.list, tag_directives_copy.length,
1127            tag_directives_copy.capacity, is_implicit, mark, mark);
1128
1129    return 1;
1130
1131error:
1132    yaml_free(version_directive_copy);
1133    while (!STACK_EMPTY(&self, tag_directives_copy)) {
1134        yaml_tag_directive_t value = POP(&self, tag_directives_copy);
1135        yaml_free(value.handle);
1136        yaml_free(value.prefix);
1137    }
1138    STACK_DEL(&self, tag_directives_copy);
1139
1140    return 0;
1141}
1142
1143/*
1144 * Create DOCUMENT-END.
1145 */
1146
1147YAML_DECLARE(int)
1148yaml_event_create_document_end(yaml_event_t *event, int is_implicit)
1149{
1150    yaml_mark_t mark = { 0, 0, 0 };
1151
1152    assert(event);      /* Non-NULL emitter object is expected. */
1153
1154    DOCUMENT_END_EVENT_INIT(*event, is_implicit, mark, mark);
1155
1156    return 1;
1157}
1158
1159/*
1160 * Create ALIAS.
1161 */
1162
1163YAML_DECLARE(int)
1164yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor)
1165{
1166    yaml_mark_t mark = { 0, 0, 0 };
1167    yaml_char_t *anchor_copy = NULL;
1168
1169    assert(event);      /* Non-NULL event object is expected. */
1170    assert(anchor);     /* Non-NULL anchor is expected. */
1171
1172    if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) return 0;
1173
1174    anchor_copy = yaml_strdup(anchor);
1175    if (!anchor_copy)
1176        return 0;
1177
1178    ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
1179
1180    return 1;
1181}
1182
1183/*
1184 * Create SCALAR.
1185 */
1186
1187YAML_DECLARE(int)
1188yaml_event_create_scalar(yaml_event_t *event,
1189        const yaml_char_t *anchor, const yaml_char_t *tag,
1190        const yaml_char_t *value, size_t length,
1191        int is_plain_implicit, int is_quoted_implicit,
1192        yaml_scalar_style_t style)
1193{
1194    yaml_mark_t mark = { 0, 0, 0 };
1195    yaml_char_t *anchor_copy = NULL;
1196    yaml_char_t *tag_copy = NULL;
1197    yaml_char_t *value_copy = NULL;
1198
1199    assert(event);      /* Non-NULL event object is expected. */
1200    assert(value);      /* Non-NULL anchor is expected. */
1201
1202    if (anchor) {
1203        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1204            goto error;
1205        anchor_copy = yaml_strdup(anchor);
1206        if (!anchor_copy)
1207            goto error;
1208    }
1209
1210    if (tag) {
1211        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1212            goto error;
1213        tag_copy = yaml_strdup(tag);
1214        if (!tag_copy)
1215            goto error;
1216    }
1217
1218    if (length < 0) {
1219        length = strlen((char *)value);
1220    }
1221
1222    if (!yaml_valid_utf8(value, length))
1223        goto error;
1224    value_copy = yaml_malloc(length+1);
1225    if (!value_copy)
1226        goto error;
1227    memcpy(value_copy, value, length);
1228    value_copy[length] = '\0';
1229
1230    SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
1231            is_plain_implicit, is_quoted_implicit, style, mark, mark);
1232
1233    return 1;
1234
1235error:
1236    yaml_free(anchor_copy);
1237    yaml_free(tag_copy);
1238    yaml_free(value_copy);
1239
1240    return 0;
1241}
1242
1243/*
1244 * Create SEQUENCE-START.
1245 */
1246
1247YAML_DECLARE(int)
1248yaml_event_create_sequence_start(yaml_event_t *event,
1249        const yaml_char_t *anchor, const yaml_char_t *tag,
1250        int is_implicit, yaml_sequence_style_t style)
1251{
1252    yaml_mark_t mark = { 0, 0, 0 };
1253    yaml_char_t *anchor_copy = NULL;
1254    yaml_char_t *tag_copy = NULL;
1255
1256    assert(event);      /* Non-NULL event object is expected. */
1257
1258    if (anchor) {
1259        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1260            goto error;
1261        anchor_copy = yaml_strdup(anchor);
1262        if (!anchor_copy)
1263            goto error;
1264    }
1265
1266    if (tag) {
1267        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1268            goto error;
1269        tag_copy = yaml_strdup(tag);
1270        if (!tag_copy)
1271            goto error;
1272    }
1273
1274    SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
1275            is_implicit, style, mark, mark);
1276
1277    return 1;
1278
1279error:
1280    yaml_free(anchor_copy);
1281    yaml_free(tag_copy);
1282
1283    return 0;
1284}
1285
1286/*
1287 * Create SEQUENCE-END.
1288 */
1289
1290YAML_DECLARE(int)
1291yaml_event_create_sequence_end(yaml_event_t *event)
1292{
1293    yaml_mark_t mark = { 0, 0, 0 };
1294
1295    assert(event);      /* Non-NULL event object is expected. */
1296
1297    SEQUENCE_END_EVENT_INIT(*event, mark, mark);
1298
1299    return 1;
1300}
1301
1302/*
1303 * Create MAPPING-START.
1304 */
1305
1306YAML_DECLARE(int)
1307yaml_event_create_mapping_start(yaml_event_t *event,
1308        const yaml_char_t *anchor, const yaml_char_t *tag,
1309        int is_implicit, yaml_mapping_style_t style)
1310{
1311    yaml_mark_t mark = { 0, 0, 0 };
1312    yaml_char_t *anchor_copy = NULL;
1313    yaml_char_t *tag_copy = NULL;
1314
1315    assert(event);      /* Non-NULL event object is expected. */
1316
1317    if (anchor) {
1318        if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
1319            goto error;
1320        anchor_copy = yaml_strdup(anchor);
1321        if (!anchor_copy)
1322            goto error;
1323    }
1324
1325    if (tag) {
1326        if (!yaml_valid_utf8(tag, strlen((char *)tag)))
1327            goto error;
1328        tag_copy = yaml_strdup(tag);
1329        if (!tag_copy)
1330            goto error;
1331    }
1332
1333    MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
1334            is_implicit, style, mark, mark);
1335
1336    return 1;
1337
1338error:
1339    yaml_free(anchor_copy);
1340    yaml_free(tag_copy);
1341
1342    return 0;
1343}
1344
1345/*
1346 * Create MAPPING-END.
1347 */
1348
1349YAML_DECLARE(int)
1350yaml_event_create_mapping_end(yaml_event_t *event)
1351{
1352    yaml_mark_t mark = { 0, 0, 0 };
1353
1354    assert(event);      /* Non-NULL event object is expected. */
1355
1356    MAPPING_END_EVENT_INIT(*event, mark, mark);
1357
1358    return 1;
1359}
1360
1361/*
1362 * Destroy an event object.
1363 */
1364
1365YAML_DECLARE(void)
1366yaml_event_destroy(yaml_event_t *event)
1367{
1368    struct {
1369        yaml_error_t error;
1370    } self;
1371
1372    assert(event);  /* Non-NULL event object expected. */
1373
1374    switch (event->type)
1375    {
1376        case YAML_DOCUMENT_START_EVENT:
1377            yaml_free(event->data.document_start.version_directive);
1378            while (!STACK_EMPTY(&self, event->data.document_start.tag_directives)) {
1379                yaml_tag_directive_t value = POP(&self,
1380                        event->data.document_start.tag_directives);
1381                yaml_free(value.handle);
1382                yaml_free(value.prefix);
1383            }
1384            STACK_DEL(&self, event->data.document_start.tag_directives);
1385            break;
1386
1387        case YAML_ALIAS_EVENT:
1388            yaml_free(event->data.alias.anchor);
1389            break;
1390
1391        case YAML_SCALAR_EVENT:
1392            yaml_free(event->data.scalar.anchor);
1393            yaml_free(event->data.scalar.tag);
1394            yaml_free(event->data.scalar.value);
1395            break;
1396
1397        case YAML_SEQUENCE_START_EVENT:
1398            yaml_free(event->data.sequence_start.anchor);
1399            yaml_free(event->data.sequence_start.tag);
1400            break;
1401
1402        case YAML_MAPPING_START_EVENT:
1403            yaml_free(event->data.mapping_start.anchor);
1404            yaml_free(event->data.mapping_start.tag);
1405            break;
1406
1407        default:
1408            break;
1409    }
1410
1411    memset(event, 0, sizeof(yaml_event_t));
1412}
1413
1414#if 0
1415
1416/*
1417 * Create a document object.
1418 */
1419
1420YAML_DECLARE(int)
1421yaml_document_initialize(yaml_document_t *document,
1422        yaml_version_directive_t *version_directive,
1423        yaml_tag_directive_t *tag_directives_start,
1424        yaml_tag_directive_t *tag_directives_end,
1425        int start_implicit, int end_implicit)
1426{
1427    struct {
1428        yaml_error_type_t error;
1429    } context;
1430    struct {
1431        yaml_node_t *start;
1432        yaml_node_t *end;
1433        yaml_node_t *top;
1434    } nodes = { NULL, NULL, NULL };
1435    yaml_version_directive_t *version_directive_copy = NULL;
1436    struct {
1437        yaml_tag_directive_t *start;
1438        yaml_tag_directive_t *end;
1439        yaml_tag_directive_t *top;
1440    } tag_directives_copy = { NULL, NULL, NULL };
1441    yaml_tag_directive_t value = { NULL, NULL };
1442    yaml_mark_t mark = { 0, 0, 0 };
1443
1444    assert(document);       /* Non-NULL document object is expected. */
1445    assert((tag_directives_start && tag_directives_end) ||
1446            (tag_directives_start == tag_directives_end));
1447                            /* Valid tag directives are expected. */
1448
1449    if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
1450
1451    if (version_directive) {
1452        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1453        if (!version_directive_copy) goto error;
1454        version_directive_copy->major = version_directive->major;
1455        version_directive_copy->minor = version_directive->minor;
1456    }
1457
1458    if (tag_directives_start != tag_directives_end) {
1459        yaml_tag_directive_t *tag_directive;
1460        if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
1461            goto error;
1462        for (tag_directive = tag_directives_start;
1463                tag_directive != tag_directives_end; tag_directive ++) {
1464            assert(tag_directive->handle);
1465            assert(tag_directive->prefix);
1466            if (!yaml_valid_utf8(tag_directive->handle,
1467                        strlen((char *)tag_directive->handle)))
1468                goto error;
1469            if (!yaml_valid_utf8(tag_directive->prefix,
1470                        strlen((char *)tag_directive->prefix)))
1471                goto error;
1472            value.handle = yaml_strdup(tag_directive->handle);
1473            value.prefix = yaml_strdup(tag_directive->prefix);
1474            if (!value.handle || !value.prefix) goto error;
1475            if (!PUSH(&context, tag_directives_copy, value))
1476                goto error;
1477            value.handle = NULL;
1478            value.prefix = NULL;
1479        }
1480    }
1481
1482    DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1483            tag_directives_copy.start, tag_directives_copy.top,
1484            start_implicit, end_implicit, mark, mark);
1485
1486    return 1;
1487
1488error:
1489    STACK_DEL(&context, nodes);
1490    yaml_free(version_directive_copy);
1491    while (!STACK_EMPTY(&context, tag_directives_copy)) {
1492        yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1493        yaml_free(value.handle);
1494        yaml_free(value.prefix);
1495    }
1496    STACK_DEL(&context, tag_directives_copy);
1497    yaml_free(value.handle);
1498    yaml_free(value.prefix);
1499
1500    return 0;
1501}
1502
1503/*
1504 * Destroy a document object.
1505 */
1506
1507YAML_DECLARE(void)
1508yaml_document_delete(yaml_document_t *document)
1509{
1510    struct {
1511        yaml_error_type_t error;
1512    } context;
1513    yaml_tag_directive_t *tag_directive;
1514
1515    context.error = YAML_NO_ERROR;  /* Eliminate a compliler warning. */
1516
1517    assert(document);   /* Non-NULL document object is expected. */
1518
1519    while (!STACK_EMPTY(&context, document->nodes)) {
1520        yaml_node_t node = POP(&context, document->nodes);
1521        yaml_free(node.tag);
1522        switch (node.type) {
1523            case YAML_SCALAR_NODE:
1524                yaml_free(node.data.scalar.value);
1525                break;
1526            case YAML_SEQUENCE_NODE:
1527                STACK_DEL(&context, node.data.sequence.items);
1528                break;
1529            case YAML_MAPPING_NODE:
1530                STACK_DEL(&context, node.data.mapping.pairs);
1531                break;
1532            default:
1533                assert(0);  /* Should not happen. */
1534        }
1535    }
1536    STACK_DEL(&context, document->nodes);
1537
1538    yaml_free(document->version_directive);
1539    for (tag_directive = document->tag_directives.start;
1540            tag_directive != document->tag_directives.end;
1541            tag_directive++) {
1542        yaml_free(tag_directive->handle);
1543        yaml_free(tag_directive->prefix);
1544    }
1545    yaml_free(document->tag_directives.start);
1546
1547    memset(document, 0, sizeof(yaml_document_t));
1548}
1549
1550/**
1551 * Get a document node.
1552 */
1553
1554YAML_DECLARE(yaml_node_t *)
1555yaml_document_get_node(yaml_document_t *document, int index)
1556{
1557    assert(document);   /* Non-NULL document object is expected. */
1558
1559    if (index > 0 && document->nodes.start + index <= document->nodes.top) {
1560        return document->nodes.start + index - 1;
1561    }
1562    return NULL;
1563}
1564
1565/**
1566 * Get the root object.
1567 */
1568
1569YAML_DECLARE(yaml_node_t *)
1570yaml_document_get_root_node(yaml_document_t *document)
1571{
1572    assert(document);   /* Non-NULL document object is expected. */
1573
1574    if (document->nodes.top != document->nodes.start) {
1575        return document->nodes.start;
1576    }
1577    return NULL;
1578}
1579
1580/*
1581 * Add a scalar node to a document.
1582 */
1583
1584YAML_DECLARE(int)
1585yaml_document_add_scalar(yaml_document_t *document,
1586        yaml_char_t *tag, yaml_char_t *value, int length,
1587        yaml_scalar_style_t style)
1588{
1589    struct {
1590        yaml_error_type_t error;
1591    } context;
1592    yaml_mark_t mark = { 0, 0, 0 };
1593    yaml_char_t *tag_copy = NULL;
1594    yaml_char_t *value_copy = NULL;
1595    yaml_node_t node;
1596
1597    assert(document);   /* Non-NULL document object is expected. */
1598    assert(value);      /* Non-NULL value is expected. */
1599
1600    if (!tag) {
1601        tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
1602    }
1603
1604    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1605    tag_copy = yaml_strdup(tag);
1606    if (!tag_copy) goto error;
1607
1608    if (length < 0) {
1609        length = strlen((char *)value);
1610    }
1611
1612    if (!yaml_valid_utf8(value, length)) goto error;
1613    value_copy = yaml_malloc(length+1);
1614    if (!value_copy) goto error;
1615    memcpy(value_copy, value, length);
1616    value_copy[length] = '\0';
1617
1618    SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
1619    if (!PUSH(&context, document->nodes, node)) goto error;
1620
1621    return document->nodes.top - document->nodes.start;
1622
1623error:
1624    yaml_free(tag_copy);
1625    yaml_free(value_copy);
1626
1627    return 0;
1628}
1629
1630/*
1631 * Add a sequence node to a document.
1632 */
1633
1634YAML_DECLARE(int)
1635yaml_document_add_sequence(yaml_document_t *document,
1636        yaml_char_t *tag, yaml_sequence_style_t style)
1637{
1638    struct {
1639        yaml_error_type_t error;
1640    } context;
1641    yaml_mark_t mark = { 0, 0, 0 };
1642    yaml_char_t *tag_copy = NULL;
1643    struct {
1644        yaml_node_item_t *start;
1645        yaml_node_item_t *end;
1646        yaml_node_item_t *top;
1647    } items = { NULL, NULL, NULL };
1648    yaml_node_t node;
1649
1650    assert(document);   /* Non-NULL document object is expected. */
1651
1652    if (!tag) {
1653        tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
1654    }
1655
1656    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1657    tag_copy = yaml_strdup(tag);
1658    if (!tag_copy) goto error;
1659
1660    if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
1661
1662    SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
1663            style, mark, mark);
1664    if (!PUSH(&context, document->nodes, node)) goto error;
1665
1666    return document->nodes.top - document->nodes.start;
1667
1668error:
1669    STACK_DEL(&context, items);
1670    yaml_free(tag_copy);
1671
1672    return 0;
1673}
1674
1675/*
1676 * Add a mapping node to a document.
1677 */
1678
1679YAML_DECLARE(int)
1680yaml_document_add_mapping(yaml_document_t *document,
1681        yaml_char_t *tag, yaml_mapping_style_t style)
1682{
1683    struct {
1684        yaml_error_type_t error;
1685    } context;
1686    yaml_mark_t mark = { 0, 0, 0 };
1687    yaml_char_t *tag_copy = NULL;
1688    struct {
1689        yaml_node_pair_t *start;
1690        yaml_node_pair_t *end;
1691        yaml_node_pair_t *top;
1692    } pairs = { NULL, NULL, NULL };
1693    yaml_node_t node;
1694
1695    assert(document);   /* Non-NULL document object is expected. */
1696
1697    if (!tag) {
1698        tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
1699    }
1700
1701    if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
1702    tag_copy = yaml_strdup(tag);
1703    if (!tag_copy) goto error;
1704
1705    if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
1706
1707    MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
1708            style, mark, mark);
1709    if (!PUSH(&context, document->nodes, node)) goto error;
1710
1711    return document->nodes.top - document->nodes.start;
1712
1713error:
1714    STACK_DEL(&context, pairs);
1715    yaml_free(tag_copy);
1716
1717    return 0;
1718}
1719
1720/*
1721 * Append an item to a sequence node.
1722 */
1723
1724YAML_DECLARE(int)
1725yaml_document_append_sequence_item(yaml_document_t *document,
1726        int sequence, int item)
1727{
1728    struct {
1729        yaml_error_type_t error;
1730    } context;
1731
1732    assert(document);       /* Non-NULL document is required. */
1733    assert(sequence > 0
1734            && document->nodes.start + sequence <= document->nodes.top);
1735                            /* Valid sequence id is required. */
1736    assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
1737                            /* A sequence node is required. */
1738    assert(item > 0 && document->nodes.start + item <= document->nodes.top);
1739                            /* Valid item id is required. */
1740
1741    if (!PUSH(&context,
1742                document->nodes.start[sequence-1].data.sequence.items, item))
1743        return 0;
1744
1745    return 1;
1746}
1747
1748/*
1749 * Append a pair of a key and a value to a mapping node.
1750 */
1751
1752YAML_DECLARE(int)
1753yaml_document_append_mapping_pair(yaml_document_t *document,
1754        int mapping, int key, int value)
1755{
1756    struct {
1757        yaml_error_type_t error;
1758    } context;
1759    yaml_node_pair_t pair = { key, value };
1760
1761    assert(document);       /* Non-NULL document is required. */
1762    assert(mapping > 0
1763            && document->nodes.start + mapping <= document->nodes.top);
1764                            /* Valid mapping id is required. */
1765    assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
1766                            /* A mapping node is required. */
1767    assert(key > 0 && document->nodes.start + key <= document->nodes.top);
1768                            /* Valid key id is required. */
1769    assert(value > 0 && document->nodes.start + value <= document->nodes.top);
1770                            /* Valid value id is required. */
1771
1772    if (!PUSH(&context,
1773                document->nodes.start[mapping-1].data.mapping.pairs, pair))
1774        return 0;
1775
1776    return 1;
1777}
1778
1779#endif
1780
Note: See TracBrowser for help on using the repository browser.