source: trunk/packages/libyaml/src/api.c @ 1275

Last change on this file since 1275 was 898, checked in by hartmans, 16 years ago

Add pyyaml and libyaml packages
backported from lenny.
There is discussion about how these should go in the repository; these are added in this form
in order to make forward progress.

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