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

Revision 238, 35.2 KB checked in by xi, 8 years ago (diff)

Add functions for constructing, parsing and emitting YAML documents.

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