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