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(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 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 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 856error: 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 868YAML_DECLARE(int) 869yaml_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 896error: 897 yaml_free(anchor_copy); 898 yaml_free(tag_copy); 899 900 return 0; 901} 902 903/* 904 * Create SEQUENCE-END. 905 */ 906 907YAML_DECLARE(int) 908yaml_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 923YAML_DECLARE(int) 924yaml_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 951error: 952 yaml_free(anchor_copy); 953 yaml_free(tag_copy); 954 955 return 0; 956} 957 958/* 959 * Create MAPPING-END. 960 */ 961 962YAML_DECLARE(int) 963yaml_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 978YAML_DECLARE(void) 979yaml_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 1029YAML_DECLARE(int) 1030yaml_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 1097error: 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 1116YAML_DECLARE(void) 1117yaml_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 1163YAML_DECLARE(yaml_node_t *) 1164yaml_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 1178YAML_DECLARE(yaml_node_t *) 1179yaml_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 1193YAML_DECLARE(int) 1194yaml_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 1232error: 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 1243YAML_DECLARE(int) 1244yaml_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 1277error: 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 1288YAML_DECLARE(int) 1289yaml_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 1322error: 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 1333YAML_DECLARE(int) 1334yaml_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 1361YAML_DECLARE(int) 1362yaml_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