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