libsheepy

C lib for handling text files, strings and json like data structure with an object oriented system
git clone https://spartatek.se/git/libsheepy.git
Log | Files | Refs | README | LICENSE

ymlApi.c (36609B)


      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