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