]> andersk Git - libyaml.git/blob - src/api.c
Fixed most compiler warnings -Wall -Wextra
[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 = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
122
123     if (!new_start) return 0;
124
125     *top = (char *)new_start + ((char *)*top - (char *)*start);
126     *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
127     *start = new_start;
128
129     return 1;
130 }
131
132 /*
133  * Extend or move a queue.
134  */
135
136 YAML_DECLARE(int)
137 yaml_queue_extend(void **start, void **head, void **tail, void **end)
138 {
139     /* Check if we need to resize the queue. */
140
141     if (*start == *head && *tail == *end) {
142         void *new_start = yaml_realloc(*start,
143                 ((char *)*end - (char *)*start)*2);
144
145         if (!new_start) return 0;
146
147         *head = (char *)new_start + ((char *)*head - (char *)*start);
148         *tail = (char *)new_start + ((char *)*tail - (char *)*start);
149         *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
150         *start = new_start;
151     }
152
153     /* Check if we need to move the queue at the beginning of the buffer. */
154
155     if (*tail == *end) {
156         if (*head != *tail) {
157             memmove(*start, *head, (char *)*tail - (char *)*head);
158         }
159         *tail = (char *)*tail - (char *)*head + (char *)*start;
160         *head = *start;
161     }
162
163     return 1;
164 }
165
166
167 /*
168  * Create a new parser object.
169  */
170
171 YAML_DECLARE(int)
172 yaml_parser_initialize(yaml_parser_t *parser)
173 {
174     assert(parser);     /* Non-NULL parser object expected. */
175
176     memset(parser, 0, sizeof(yaml_parser_t));
177     if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
178         goto error;
179     if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
180         goto error;
181     if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*))
182         goto error;
183     if (!STACK_INIT(parser, parser->indents, int*))
184         goto error;
185     if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*))
186         goto error;
187     if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*))
188         goto error;
189     if (!STACK_INIT(parser, parser->marks, yaml_mark_t*))
190         goto error;
191     if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*))
192         goto error;
193
194     return 1;
195
196 error:
197
198     BUFFER_DEL(parser, parser->raw_buffer);
199     BUFFER_DEL(parser, parser->buffer);
200     QUEUE_DEL(parser, parser->tokens);
201     STACK_DEL(parser, parser->indents);
202     STACK_DEL(parser, parser->simple_keys);
203     STACK_DEL(parser, parser->states);
204     STACK_DEL(parser, parser->marks);
205     STACK_DEL(parser, parser->tag_directives);
206
207     return 0;
208 }
209
210 /*
211  * Destroy a parser object.
212  */
213
214 YAML_DECLARE(void)
215 yaml_parser_delete(yaml_parser_t *parser)
216 {
217     assert(parser); /* Non-NULL parser object expected. */
218
219     BUFFER_DEL(parser, parser->raw_buffer);
220     BUFFER_DEL(parser, parser->buffer);
221     while (!QUEUE_EMPTY(parser, parser->tokens)) {
222         yaml_token_delete(&DEQUEUE(parser, parser->tokens));
223     }
224     QUEUE_DEL(parser, parser->tokens);
225     STACK_DEL(parser, parser->indents);
226     STACK_DEL(parser, parser->simple_keys);
227     STACK_DEL(parser, parser->states);
228     STACK_DEL(parser, parser->marks);
229     while (!STACK_EMPTY(parser, parser->tag_directives)) {
230         yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
231         yaml_free(tag_directive.handle);
232         yaml_free(tag_directive.prefix);
233     }
234     STACK_DEL(parser, parser->tag_directives);
235
236     memset(parser, 0, sizeof(yaml_parser_t));
237 }
238
239 /*
240  * String read handler.
241  */
242
243 static int
244 yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
245         size_t *size_read)
246 {
247     yaml_parser_t *parser = (yaml_parser_t *)data;
248
249     if (parser->input.string.current == parser->input.string.end) {
250         *size_read = 0;
251         return 1;
252     }
253
254     if (size > (size_t)(parser->input.string.end
255                 - parser->input.string.current)) {
256         size = parser->input.string.end - parser->input.string.current;
257     }
258
259     memcpy(buffer, parser->input.string.current, size);
260     parser->input.string.current += size;
261     *size_read = size;
262     return 1;
263 }
264
265 /*
266  * File read handler.
267  */
268
269 static int
270 yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
271         size_t *size_read)
272 {
273     yaml_parser_t *parser = (yaml_parser_t *)data;
274
275     *size_read = fread(buffer, 1, size, parser->input.file);
276     return !ferror(parser->input.file);
277 }
278
279 /*
280  * Set a string input.
281  */
282
283 YAML_DECLARE(void)
284 yaml_parser_set_input_string(yaml_parser_t *parser,
285         const unsigned char *input, size_t size)
286 {
287     assert(parser); /* Non-NULL parser object expected. */
288     assert(!parser->read_handler);  /* You can set the source only once. */
289     assert(input);  /* Non-NULL input string expected. */
290
291     parser->read_handler = yaml_string_read_handler;
292     parser->read_handler_data = parser;
293
294     parser->input.string.start = input;
295     parser->input.string.current = input;
296     parser->input.string.end = input+size;
297 }
298
299 /*
300  * Set a file input.
301  */
302
303 YAML_DECLARE(void)
304 yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
305 {
306     assert(parser); /* Non-NULL parser object expected. */
307     assert(!parser->read_handler);  /* You can set the source only once. */
308     assert(file);   /* Non-NULL file object expected. */
309
310     parser->read_handler = yaml_file_read_handler;
311     parser->read_handler_data = parser;
312
313     parser->input.file = file;
314 }
315
316 /*
317  * Set a generic input.
318  */
319
320 YAML_DECLARE(void)
321 yaml_parser_set_input(yaml_parser_t *parser,
322         yaml_read_handler_t *handler, void *data)
323 {
324     assert(parser); /* Non-NULL parser object expected. */
325     assert(!parser->read_handler);  /* You can set the source only once. */
326     assert(handler);    /* Non-NULL read handler expected. */
327
328     parser->read_handler = handler;
329     parser->read_handler_data = data;
330 }
331
332 /*
333  * Set the source encoding.
334  */
335
336 YAML_DECLARE(void)
337 yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
338 {
339     assert(parser); /* Non-NULL parser object expected. */
340     assert(!parser->encoding); /* Encoding is already set or detected. */
341
342     parser->encoding = encoding;
343 }
344
345 /*
346  * Create a new emitter object.
347  */
348
349 YAML_DECLARE(int)
350 yaml_emitter_initialize(yaml_emitter_t *emitter)
351 {
352     assert(emitter);    /* Non-NULL emitter object expected. */
353
354     memset(emitter, 0, sizeof(yaml_emitter_t));
355     if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
356         goto error;
357     if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
358         goto error;
359     if (!STACK_INIT(emitter, emitter->states, yaml_emitter_state_t*))
360         goto error;
361     if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE, yaml_event_t*))
362         goto error;
363     if (!STACK_INIT(emitter, emitter->indents, int*))
364         goto error;
365     if (!STACK_INIT(emitter, emitter->tag_directives, yaml_tag_directive_t*))
366         goto error;
367
368     return 1;
369
370 error:
371
372     BUFFER_DEL(emitter, emitter->buffer);
373     BUFFER_DEL(emitter, emitter->raw_buffer);
374     STACK_DEL(emitter, emitter->states);
375     QUEUE_DEL(emitter, emitter->events);
376     STACK_DEL(emitter, emitter->indents);
377     STACK_DEL(emitter, emitter->tag_directives);
378
379     return 0;
380 }
381
382 /*
383  * Destroy an emitter object.
384  */
385
386 YAML_DECLARE(void)
387 yaml_emitter_delete(yaml_emitter_t *emitter)
388 {
389     assert(emitter);    /* Non-NULL emitter object expected. */
390
391     BUFFER_DEL(emitter, emitter->buffer);
392     BUFFER_DEL(emitter, emitter->raw_buffer);
393     STACK_DEL(emitter, emitter->states);
394     while (!QUEUE_EMPTY(emitter, emitter->events)) {
395         yaml_event_delete(&DEQUEUE(emitter, emitter->events));
396     }
397     QUEUE_DEL(emitter, emitter->events);
398     STACK_DEL(emitter, emitter->indents);
399     while (!STACK_EMPTY(empty, emitter->tag_directives)) {
400         yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
401         yaml_free(tag_directive.handle);
402         yaml_free(tag_directive.prefix);
403     }
404     STACK_DEL(emitter, emitter->tag_directives);
405     yaml_free(emitter->anchors);
406
407     memset(emitter, 0, sizeof(yaml_emitter_t));
408 }
409
410 /*
411  * String write handler.
412  */
413
414 static int
415 yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
416 {
417   yaml_emitter_t *emitter = (yaml_emitter_t *)data;
418
419     if (emitter->output.string.size - *emitter->output.string.size_written
420             < size) {
421         memcpy(emitter->output.string.buffer
422                 + *emitter->output.string.size_written,
423                 buffer,
424                 emitter->output.string.size
425                 - *emitter->output.string.size_written);
426         *emitter->output.string.size_written = emitter->output.string.size;
427         return 0;
428     }
429
430     memcpy(emitter->output.string.buffer
431             + *emitter->output.string.size_written, buffer, size);
432     *emitter->output.string.size_written += size;
433     return 1;
434 }
435
436 /*
437  * File write handler.
438  */
439
440 static int
441 yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
442 {
443     yaml_emitter_t *emitter = (yaml_emitter_t *)data;
444
445     return (fwrite(buffer, 1, size, emitter->output.file) == size);
446 }
447 /*
448  * Set a string output.
449  */
450
451 YAML_DECLARE(void)
452 yaml_emitter_set_output_string(yaml_emitter_t *emitter,
453         unsigned char *output, size_t size, size_t *size_written)
454 {
455     assert(emitter);    /* Non-NULL emitter object expected. */
456     assert(!emitter->write_handler);    /* You can set the output only once. */
457     assert(output);     /* Non-NULL output string expected. */
458
459     emitter->write_handler = yaml_string_write_handler;
460     emitter->write_handler_data = emitter;
461
462     emitter->output.string.buffer = output;
463     emitter->output.string.size = size;
464     emitter->output.string.size_written = size_written;
465     *size_written = 0;
466 }
467
468 /*
469  * Set a file output.
470  */
471
472 YAML_DECLARE(void)
473 yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
474 {
475     assert(emitter);    /* Non-NULL emitter object expected. */
476     assert(!emitter->write_handler);    /* You can set the output only once. */
477     assert(file);       /* Non-NULL file object expected. */
478
479     emitter->write_handler = yaml_file_write_handler;
480     emitter->write_handler_data = emitter;
481
482     emitter->output.file = file;
483 }
484
485 /*
486  * Set a generic output handler.
487  */
488
489 YAML_DECLARE(void)
490 yaml_emitter_set_output(yaml_emitter_t *emitter,
491         yaml_write_handler_t *handler, void *data)
492 {
493     assert(emitter);    /* Non-NULL emitter object expected. */
494     assert(!emitter->write_handler);    /* You can set the output only once. */
495     assert(handler);    /* Non-NULL handler object expected. */
496
497     emitter->write_handler = handler;
498     emitter->write_handler_data = data;
499 }
500
501 /*
502  * Set the output encoding.
503  */
504
505 YAML_DECLARE(void)
506 yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
507 {
508     assert(emitter);    /* Non-NULL emitter object expected. */
509     assert(!emitter->encoding);     /* You can set encoding only once. */
510
511     emitter->encoding = encoding;
512 }
513
514 /*
515  * Set the canonical output style.
516  */
517
518 YAML_DECLARE(void)
519 yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
520 {
521     assert(emitter);    /* Non-NULL emitter object expected. */
522
523     emitter->canonical = (canonical != 0);
524 }
525
526 /*
527  * Set the indentation increment.
528  */
529
530 YAML_DECLARE(void)
531 yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
532 {
533     assert(emitter);    /* Non-NULL emitter object expected. */
534
535     emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
536 }
537
538 /*
539  * Set the preferred line width.
540  */
541
542 YAML_DECLARE(void)
543 yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
544 {
545     assert(emitter);    /* Non-NULL emitter object expected. */
546
547     emitter->best_width = (width >= 0) ? width : -1;
548 }
549
550 /*
551  * Set if unescaped non-ASCII characters are allowed.
552  */
553
554 YAML_DECLARE(void)
555 yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
556 {
557     assert(emitter);    /* Non-NULL emitter object expected. */
558
559     emitter->unicode = (unicode != 0);
560 }
561
562 /*
563  * Set the preferred line break character.
564  */
565
566 YAML_DECLARE(void)
567 yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
568 {
569     assert(emitter);    /* Non-NULL emitter object expected. */
570
571     emitter->line_break = line_break;
572 }
573
574 /*
575  * Destroy a token object.
576  */
577
578 YAML_DECLARE(void)
579 yaml_token_delete(yaml_token_t *token)
580 {
581     assert(token);  /* Non-NULL token object expected. */
582
583     switch (token->type)
584     {
585         case YAML_TAG_DIRECTIVE_TOKEN:
586             yaml_free(token->data.tag_directive.handle);
587             yaml_free(token->data.tag_directive.prefix);
588             break;
589
590         case YAML_ALIAS_TOKEN:
591             yaml_free(token->data.alias.value);
592             break;
593
594         case YAML_ANCHOR_TOKEN:
595             yaml_free(token->data.anchor.value);
596             break;
597
598         case YAML_TAG_TOKEN:
599             yaml_free(token->data.tag.handle);
600             yaml_free(token->data.tag.suffix);
601             break;
602
603         case YAML_SCALAR_TOKEN:
604             yaml_free(token->data.scalar.value);
605             break;
606
607         default:
608             break;
609     }
610
611     memset(token, 0, sizeof(yaml_token_t));
612 }
613
614 /*
615  * Check if a string is a valid UTF-8 sequence.
616  *
617  * Check 'reader.c' for more details on UTF-8 encoding.
618  */
619
620 static int
621 yaml_check_utf8(yaml_char_t *start, size_t length)
622 {
623     yaml_char_t *end = start+length;
624     yaml_char_t *pointer = start;
625
626     while (pointer < end) {
627         unsigned char octet;
628         unsigned int width;
629         unsigned int value;
630         size_t k;
631
632         octet = pointer[0];
633         width = (octet & 0x80) == 0x00 ? 1 :
634                 (octet & 0xE0) == 0xC0 ? 2 :
635                 (octet & 0xF0) == 0xE0 ? 3 :
636                 (octet & 0xF8) == 0xF0 ? 4 : 0;
637         value = (octet & 0x80) == 0x00 ? octet & 0x7F :
638                 (octet & 0xE0) == 0xC0 ? octet & 0x1F :
639                 (octet & 0xF0) == 0xE0 ? octet & 0x0F :
640                 (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
641         if (!width) return 0;
642         if (pointer+width > end) return 0;
643         for (k = 1; k < width; k ++) {
644             octet = pointer[k];
645             if ((octet & 0xC0) != 0x80) return 0;
646             value = (value << 6) + (octet & 0x3F);
647         }
648         if (!((width == 1) ||
649             (width == 2 && value >= 0x80) ||
650             (width == 3 && value >= 0x800) ||
651             (width == 4 && value >= 0x10000))) return 0;
652
653         pointer += width;
654     }
655
656     return 1;
657 }
658
659 /*
660  * Create STREAM-START.
661  */
662
663 YAML_DECLARE(int)
664 yaml_stream_start_event_initialize(yaml_event_t *event,
665         yaml_encoding_t encoding)
666 {
667     yaml_mark_t mark = { 0, 0, 0 };
668
669     assert(event);  /* Non-NULL event object is expected. */
670
671     STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
672
673     return 1;
674 }
675
676 /*
677  * Create STREAM-END.
678  */
679
680 YAML_DECLARE(int)
681 yaml_stream_end_event_initialize(yaml_event_t *event)
682 {
683     yaml_mark_t mark = { 0, 0, 0 };
684
685     assert(event);  /* Non-NULL event object is expected. */
686
687     STREAM_END_EVENT_INIT(*event, mark, mark);
688
689     return 1;
690 }
691
692 /*
693  * Create DOCUMENT-START.
694  */
695
696 YAML_DECLARE(int)
697 yaml_document_start_event_initialize(yaml_event_t *event,
698         yaml_version_directive_t *version_directive,
699         yaml_tag_directive_t *tag_directives_start,
700         yaml_tag_directive_t *tag_directives_end,
701         int implicit)
702 {
703     struct {
704         yaml_error_type_t error;
705     } context;
706     yaml_mark_t mark = { 0, 0, 0 };
707     yaml_version_directive_t *version_directive_copy = NULL;
708     struct {
709         yaml_tag_directive_t *start;
710         yaml_tag_directive_t *end;
711         yaml_tag_directive_t *top;
712     } tag_directives_copy = { NULL, NULL, NULL };
713     yaml_tag_directive_t value = { NULL, NULL };
714
715     assert(event);          /* Non-NULL event object is expected. */
716     assert((tag_directives_start && tag_directives_end) ||
717             (tag_directives_start == tag_directives_end));
718                             /* Valid tag directives are expected. */
719
720     if (version_directive) {
721         version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t);
722         if (!version_directive_copy) goto error;
723         version_directive_copy->major = version_directive->major;
724         version_directive_copy->minor = version_directive->minor;
725     }
726
727     if (tag_directives_start != tag_directives_end) {
728         yaml_tag_directive_t *tag_directive;
729         if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*))
730             goto error;
731         for (tag_directive = tag_directives_start;
732                 tag_directive != tag_directives_end; tag_directive ++) {
733             assert(tag_directive->handle);
734             assert(tag_directive->prefix);
735             if (!yaml_check_utf8(tag_directive->handle,
736                         strlen((char *)tag_directive->handle)))
737                 goto error;
738             if (!yaml_check_utf8(tag_directive->prefix,
739                         strlen((char *)tag_directive->prefix)))
740                 goto error;
741             value.handle = yaml_strdup(tag_directive->handle);
742             value.prefix = yaml_strdup(tag_directive->prefix);
743             if (!value.handle || !value.prefix) goto error;
744             if (!PUSH(&context, tag_directives_copy, value))
745                 goto error;
746             value.handle = NULL;
747             value.prefix = NULL;
748         }
749     }
750
751     DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
752             tag_directives_copy.start, tag_directives_copy.top,
753             implicit, mark, mark);
754
755     return 1;
756
757 error:
758     yaml_free(version_directive_copy);
759     while (!STACK_EMPTY(context, tag_directives_copy)) {
760         yaml_tag_directive_t value = POP(context, tag_directives_copy);
761         yaml_free(value.handle);
762         yaml_free(value.prefix);
763     }
764     STACK_DEL(context, tag_directives_copy);
765     yaml_free(value.handle);
766     yaml_free(value.prefix);
767
768     return 0;
769 }
770
771 /*
772  * Create DOCUMENT-END.
773  */
774
775 YAML_DECLARE(int)
776 yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
777 {
778     yaml_mark_t mark = { 0, 0, 0 };
779
780     assert(event);      /* Non-NULL emitter object is expected. */
781
782     DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
783
784     return 1;
785 }
786
787 /*
788  * Create ALIAS.
789  */
790
791 YAML_DECLARE(int)
792 yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
793 {
794     yaml_mark_t mark = { 0, 0, 0 };
795     yaml_char_t *anchor_copy = NULL;
796
797     assert(event);      /* Non-NULL event object is expected. */
798     assert(anchor);     /* Non-NULL anchor is expected. */
799
800     if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
801
802     anchor_copy = yaml_strdup(anchor);
803     if (!anchor_copy)
804         return 0;
805
806     ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
807
808     return 1;
809 }
810
811 /*
812  * Create SCALAR.
813  */
814
815 YAML_DECLARE(int)
816 yaml_scalar_event_initialize(yaml_event_t *event,
817         yaml_char_t *anchor, yaml_char_t *tag,
818         yaml_char_t *value, int length,
819         int plain_implicit, int quoted_implicit,
820         yaml_scalar_style_t style)
821 {
822     yaml_mark_t mark = { 0, 0, 0 };
823     yaml_char_t *anchor_copy = NULL;
824     yaml_char_t *tag_copy = NULL;
825     yaml_char_t *value_copy = NULL;
826
827     assert(event);      /* Non-NULL event object is expected. */
828     assert(value);      /* Non-NULL anchor is expected. */
829
830     if (anchor) {
831         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
832         anchor_copy = yaml_strdup(anchor);
833         if (!anchor_copy) goto error;
834     }
835
836     if (tag) {
837         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
838         tag_copy = yaml_strdup(tag);
839         if (!tag_copy) goto error;
840     }
841
842     if (length < 0) {
843         length = strlen((char *)value);
844     }
845
846     if (!yaml_check_utf8(value, length)) goto error;
847     value_copy = YAML_MALLOC(length+1);
848     if (!value_copy) goto error;
849     memcpy(value_copy, value, length);
850     value_copy[length] = '\0';
851
852     SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
853             plain_implicit, quoted_implicit, style, mark, mark);
854
855     return 1;
856
857 error:
858     yaml_free(anchor_copy);
859     yaml_free(tag_copy);
860     yaml_free(value_copy);
861
862     return 0;
863 }
864
865 /*
866  * Create SEQUENCE-START.
867  */
868
869 YAML_DECLARE(int)
870 yaml_sequence_start_event_initialize(yaml_event_t *event,
871         yaml_char_t *anchor, yaml_char_t *tag, int implicit,
872         yaml_sequence_style_t style)
873 {
874     yaml_mark_t mark = { 0, 0, 0 };
875     yaml_char_t *anchor_copy = NULL;
876     yaml_char_t *tag_copy = NULL;
877
878     assert(event);      /* Non-NULL event object is expected. */
879
880     if (anchor) {
881         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
882         anchor_copy = yaml_strdup(anchor);
883         if (!anchor_copy) goto error;
884     }
885
886     if (tag) {
887         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
888         tag_copy = yaml_strdup(tag);
889         if (!tag_copy) goto error;
890     }
891
892     SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
893             implicit, style, mark, mark);
894
895     return 1;
896
897 error:
898     yaml_free(anchor_copy);
899     yaml_free(tag_copy);
900
901     return 0;
902 }
903
904 /*
905  * Create SEQUENCE-END.
906  */
907
908 YAML_DECLARE(int)
909 yaml_sequence_end_event_initialize(yaml_event_t *event)
910 {
911     yaml_mark_t mark = { 0, 0, 0 };
912
913     assert(event);      /* Non-NULL event object is expected. */
914
915     SEQUENCE_END_EVENT_INIT(*event, mark, mark);
916
917     return 1;
918 }
919
920 /*
921  * Create MAPPING-START.
922  */
923
924 YAML_DECLARE(int)
925 yaml_mapping_start_event_initialize(yaml_event_t *event,
926         yaml_char_t *anchor, yaml_char_t *tag, int implicit,
927         yaml_mapping_style_t style)
928 {
929     yaml_mark_t mark = { 0, 0, 0 };
930     yaml_char_t *anchor_copy = NULL;
931     yaml_char_t *tag_copy = NULL;
932
933     assert(event);      /* Non-NULL event object is expected. */
934
935     if (anchor) {
936         if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
937         anchor_copy = yaml_strdup(anchor);
938         if (!anchor_copy) goto error;
939     }
940
941     if (tag) {
942         if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
943         tag_copy = yaml_strdup(tag);
944         if (!tag_copy) goto error;
945     }
946
947     MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
948             implicit, style, mark, mark);
949
950     return 1;
951
952 error:
953     yaml_free(anchor_copy);
954     yaml_free(tag_copy);
955
956     return 0;
957 }
958
959 /*
960  * Create MAPPING-END.
961  */
962
963 YAML_DECLARE(int)
964 yaml_mapping_end_event_initialize(yaml_event_t *event)
965 {
966     yaml_mark_t mark = { 0, 0, 0 };
967
968     assert(event);      /* Non-NULL event object is expected. */
969
970     MAPPING_END_EVENT_INIT(*event, mark, mark);
971
972     return 1;
973 }
974
975 /*
976  * Destroy an event object.
977  */
978
979 YAML_DECLARE(void)
980 yaml_event_delete(yaml_event_t *event)
981 {
982     yaml_tag_directive_t *tag_directive;
983
984     assert(event);  /* Non-NULL event object expected. */
985
986     switch (event->type)
987     {
988         case YAML_DOCUMENT_START_EVENT:
989             yaml_free(event->data.document_start.version_directive);
990             for (tag_directive = event->data.document_start.tag_directives.start;
991                     tag_directive != event->data.document_start.tag_directives.end;
992                     tag_directive++) {
993                 yaml_free(tag_directive->handle);
994                 yaml_free(tag_directive->prefix);
995             }
996             yaml_free(event->data.document_start.tag_directives.start);
997             break;
998
999         case YAML_ALIAS_EVENT:
1000             yaml_free(event->data.alias.anchor);
1001             break;
1002
1003         case YAML_SCALAR_EVENT:
1004             yaml_free(event->data.scalar.anchor);
1005             yaml_free(event->data.scalar.tag);
1006             yaml_free(event->data.scalar.value);
1007             break;
1008
1009         case YAML_SEQUENCE_START_EVENT:
1010             yaml_free(event->data.sequence_start.anchor);
1011             yaml_free(event->data.sequence_start.tag);
1012             break;
1013
1014         case YAML_MAPPING_START_EVENT:
1015             yaml_free(event->data.mapping_start.anchor);
1016             yaml_free(event->data.mapping_start.tag);
1017             break;
1018
1019         default:
1020             break;
1021     }
1022
1023     memset(event, 0, sizeof(yaml_event_t));
1024 }
1025
1026 /*
1027  * Create a document object.
1028  */
1029
1030 YAML_DECLARE(int)
1031 yaml_document_initialize(yaml_document_t *document,
1032         yaml_version_directive_t *version_directive,
1033         yaml_tag_directive_t *tag_directives_start,
1034         yaml_tag_directive_t *tag_directives_end,
1035         int start_implicit, int end_implicit)
1036 {
1037     struct {
1038         yaml_error_type_t error;
1039     } context;
1040     struct {
1041         yaml_node_t *start;
1042         yaml_node_t *end;
1043         yaml_node_t *top;
1044     } nodes = { NULL, NULL, NULL };
1045     yaml_version_directive_t *version_directive_copy = NULL;
1046     struct {
1047         yaml_tag_directive_t *start;
1048         yaml_tag_directive_t *end;
1049         yaml_tag_directive_t *top;
1050     } tag_directives_copy = { NULL, NULL, NULL };
1051     yaml_tag_directive_t value = { NULL, NULL };
1052     yaml_mark_t mark = { 0, 0, 0 };
1053
1054     assert(document);       /* Non-NULL document object is expected. */
1055     assert((tag_directives_start && tag_directives_end) ||
1056             (tag_directives_start == tag_directives_end));
1057                             /* Valid tag directives are expected. */
1058
1059     if (!STACK_INIT(&context, nodes, yaml_node_t*)) goto error;
1060
1061     if (version_directive) {
1062         version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t);
1063         if (!version_directive_copy) goto error;
1064         version_directive_copy->major = version_directive->major;
1065         version_directive_copy->minor = version_directive->minor;
1066     }
1067
1068     if (tag_directives_start != tag_directives_end) {
1069         yaml_tag_directive_t *tag_directive;
1070         if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*))
1071             goto error;
1072         for (tag_directive = tag_directives_start;
1073                 tag_directive != tag_directives_end; tag_directive ++) {
1074             assert(tag_directive->handle);
1075             assert(tag_directive->prefix);
1076             if (!yaml_check_utf8(tag_directive->handle,
1077                         strlen((char *)tag_directive->handle)))
1078                 goto error;
1079             if (!yaml_check_utf8(tag_directive->prefix,
1080                         strlen((char *)tag_directive->prefix)))
1081                 goto error;
1082             value.handle = yaml_strdup(tag_directive->handle);
1083             value.prefix = yaml_strdup(tag_directive->prefix);
1084             if (!value.handle || !value.prefix) goto error;
1085             if (!PUSH(&context, tag_directives_copy, value))
1086                 goto error;
1087             value.handle = NULL;
1088             value.prefix = NULL;
1089         }
1090     }
1091
1092     DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1093             tag_directives_copy.start, tag_directives_copy.top,
1094             start_implicit, end_implicit, mark, mark);
1095
1096     return 1;
1097
1098 error:
1099     STACK_DEL(&context, nodes);
1100     yaml_free(version_directive_copy);
1101     while (!STACK_EMPTY(&context, tag_directives_copy)) {
1102         yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1103         yaml_free(value.handle);
1104         yaml_free(value.prefix);
1105     }
1106     STACK_DEL(&context, tag_directives_copy);
1107     yaml_free(value.handle);
1108     yaml_free(value.prefix);
1109
1110     return 0;
1111 }
1112
1113 /*
1114  * Destroy a document object.
1115  */
1116
1117 YAML_DECLARE(void)
1118 yaml_document_delete(yaml_document_t *document)
1119 {
1120     struct {
1121         yaml_error_type_t error;
1122     } context;
1123     yaml_tag_directive_t *tag_directive;
1124
1125     context.error = YAML_NO_ERROR;  /* Eliminate a compliler warning. */
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.132081 seconds and 5 git commands to generate.