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