Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 00002 #include "yaml_private.h" 00003 00004 /* 00005 * Get the library version. 00006 */ 00007 00008 YAML_DECLARE(const char *) 00009 yaml_get_version_string(void) 00010 { 00011 return YAML_VERSION_STRING; 00012 } 00013 00014 /* 00015 * Get the library version numbers. 00016 */ 00017 00018 YAML_DECLARE(void) 00019 yaml_get_version(int *major, int *minor, int *patch) 00020 { 00021 *major = YAML_VERSION_MAJOR; 00022 *minor = YAML_VERSION_MINOR; 00023 *patch = YAML_VERSION_PATCH; 00024 } 00025 00026 /* 00027 * Allocate a dynamic memory block. 00028 */ 00029 00030 YAML_DECLARE(void *) 00031 yaml_malloc(size_t size) 00032 { 00033 return malloc(size ? size : 1); 00034 } 00035 00036 /* 00037 * Reallocate a dynamic memory block. 00038 */ 00039 00040 YAML_DECLARE(void *) 00041 yaml_realloc(void *ptr, size_t size) 00042 { 00043 return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1); 00044 } 00045 00046 /* 00047 * Free a dynamic memory block. 00048 */ 00049 00050 YAML_DECLARE(void) 00051 yaml_free(void *ptr) 00052 { 00053 if (ptr) free(ptr); 00054 } 00055 00056 /* 00057 * Duplicate a string. 00058 */ 00059 00060 YAML_DECLARE(yaml_char_t *) 00061 yaml_strdup(const yaml_char_t *str) 00062 { 00063 if (!str) 00064 return NULL; 00065 00066 return (yaml_char_t *)strdup((char *)str); 00067 } 00068 00069 /* 00070 * Extend a string. 00071 */ 00072 00073 YAML_DECLARE(int) 00074 yaml_string_extend(yaml_char_t **start, 00075 yaml_char_t **pointer, yaml_char_t **end) 00076 { 00077 yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2); 00078 00079 if (!new_start) return 0; 00080 00081 memset(new_start + (*end - *start), 0, *end - *start); 00082 00083 *pointer = new_start + (*pointer - *start); 00084 *end = new_start + (*end - *start)*2; 00085 *start = new_start; 00086 00087 return 1; 00088 } 00089 00090 /* 00091 * Append a string B to a string A. 00092 */ 00093 00094 YAML_DECLARE(int) 00095 yaml_string_join( 00096 yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end, 00097 yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end) 00098 { 00099 if (*b_start == *b_pointer) 00100 return 1; 00101 00102 while (*a_end - *a_pointer <= *b_pointer - *b_start) { 00103 if (!yaml_string_extend(a_start, a_pointer, a_end)) 00104 return 0; 00105 } 00106 00107 memcpy(*a_pointer, *b_start, *b_pointer - *b_start); 00108 *a_pointer += *b_pointer - *b_start; 00109 00110 return 1; 00111 } 00112 00113 /* 00114 * Extend a stack. 00115 */ 00116 00117 YAML_DECLARE(int) 00118 yaml_stack_extend(void **start, void **top, void **end) 00119 { 00120 void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2); 00121 00122 if (!new_start) return 0; 00123 00124 *top = (char *)new_start + ((char *)*top - (char *)*start); 00125 *end = (char *)new_start + ((char *)*end - (char *)*start)*2; 00126 *start = new_start; 00127 00128 return 1; 00129 } 00130 00131 /* 00132 * Extend or move a queue. 00133 */ 00134 00135 YAML_DECLARE(int) 00136 yaml_queue_extend(void **start, void **head, void **tail, void **end) 00137 { 00138 /* Check if we need to resize the queue. */ 00139 00140 if (*start == *head && *tail == *end) { 00141 void *new_start = yaml_realloc(*start, 00142 ((char *)*end - (char *)*start)*2); 00143 00144 if (!new_start) return 0; 00145 00146 *head = (char *)new_start + ((char *)*head - (char *)*start); 00147 *tail = (char *)new_start + ((char *)*tail - (char *)*start); 00148 *end = (char *)new_start + ((char *)*end - (char *)*start)*2; 00149 *start = new_start; 00150 } 00151 00152 /* Check if we need to move the queue at the beginning of the buffer. */ 00153 00154 if (*tail == *end) { 00155 if (*head != *tail) { 00156 memmove(*start, *head, (char *)*tail - (char *)*head); 00157 } 00158 *tail = (char *)*tail - (char *)*head + (char *)*start; 00159 *head = *start; 00160 } 00161 00162 return 1; 00163 } 00164 00165 00166 /* 00167 * Create a new parser object. 00168 */ 00169 00170 YAML_DECLARE(int) 00171 yaml_parser_initialize(yaml_parser_t *parser) 00172 { 00173 assert(parser); /* Non-NULL parser object expected. */ 00174 00175 memset(parser, 0, sizeof(yaml_parser_t)); 00176 if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE)) 00177 goto error; 00178 if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE)) 00179 goto error; 00180 if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE)) 00181 goto error; 00182 if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE)) 00183 goto error; 00184 if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE)) 00185 goto error; 00186 if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE)) 00187 goto error; 00188 if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE)) 00189 goto error; 00190 if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE)) 00191 goto error; 00192 00193 return 1; 00194 00195 error: 00196 00197 BUFFER_DEL(parser, parser->raw_buffer); 00198 BUFFER_DEL(parser, parser->buffer); 00199 QUEUE_DEL(parser, parser->tokens); 00200 STACK_DEL(parser, parser->indents); 00201 STACK_DEL(parser, parser->simple_keys); 00202 STACK_DEL(parser, parser->states); 00203 STACK_DEL(parser, parser->marks); 00204 STACK_DEL(parser, parser->tag_directives); 00205 00206 return 0; 00207 } 00208 00209 /* 00210 * Destroy a parser object. 00211 */ 00212 00213 YAML_DECLARE(void) 00214 yaml_parser_delete(yaml_parser_t *parser) 00215 { 00216 assert(parser); /* Non-NULL parser object expected. */ 00217 00218 BUFFER_DEL(parser, parser->raw_buffer); 00219 BUFFER_DEL(parser, parser->buffer); 00220 while (!QUEUE_EMPTY(parser, parser->tokens)) { 00221 yaml_token_delete(&DEQUEUE(parser, parser->tokens)); 00222 } 00223 QUEUE_DEL(parser, parser->tokens); 00224 STACK_DEL(parser, parser->indents); 00225 STACK_DEL(parser, parser->simple_keys); 00226 STACK_DEL(parser, parser->states); 00227 STACK_DEL(parser, parser->marks); 00228 while (!STACK_EMPTY(parser, parser->tag_directives)) { 00229 yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives); 00230 yaml_free(tag_directive.handle); 00231 yaml_free(tag_directive.prefix); 00232 } 00233 STACK_DEL(parser, parser->tag_directives); 00234 00235 memset(parser, 0, sizeof(yaml_parser_t)); 00236 } 00237 00238 /* 00239 * String read handler. 00240 */ 00241 00242 static int 00243 yaml_string_read_handler(void *data, unsigned char *buffer, size_t size, 00244 size_t *size_read) 00245 { 00246 yaml_parser_t *parser = data; 00247 00248 if (parser->input.string.current == parser->input.string.end) { 00249 *size_read = 0; 00250 return 1; 00251 } 00252 00253 if (size > (size_t)(parser->input.string.end 00254 - parser->input.string.current)) { 00255 size = parser->input.string.end - parser->input.string.current; 00256 } 00257 00258 memcpy(buffer, parser->input.string.current, size); 00259 parser->input.string.current += size; 00260 *size_read = size; 00261 return 1; 00262 } 00263 00264 /* 00265 * File read handler. 00266 */ 00267 00268 static int 00269 yaml_file_read_handler(void *data, unsigned char *buffer, size_t size, 00270 size_t *size_read) 00271 { 00272 yaml_parser_t *parser = data; 00273 00274 *size_read = fread(buffer, 1, size, parser->input.file); 00275 return !ferror(parser->input.file); 00276 } 00277 00278 /* 00279 * Set a string input. 00280 */ 00281 00282 YAML_DECLARE(void) 00283 yaml_parser_set_input_string(yaml_parser_t *parser, 00284 const unsigned char *input, size_t size) 00285 { 00286 assert(parser); /* Non-NULL parser object expected. */ 00287 assert(!parser->read_handler); /* You can set the source only once. */ 00288 assert(input); /* Non-NULL input string expected. */ 00289 00290 parser->read_handler = yaml_string_read_handler; 00291 parser->read_handler_data = parser; 00292 00293 parser->input.string.start = input; 00294 parser->input.string.current = input; 00295 parser->input.string.end = input+size; 00296 } 00297 00298 /* 00299 * Set a file input. 00300 */ 00301 00302 YAML_DECLARE(void) 00303 yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file) 00304 { 00305 assert(parser); /* Non-NULL parser object expected. */ 00306 assert(!parser->read_handler); /* You can set the source only once. */ 00307 assert(file); /* Non-NULL file object expected. */ 00308 00309 parser->read_handler = yaml_file_read_handler; 00310 parser->read_handler_data = parser; 00311 00312 parser->input.file = file; 00313 } 00314 00315 /* 00316 * Set a generic input. 00317 */ 00318 00319 YAML_DECLARE(void) 00320 yaml_parser_set_input(yaml_parser_t *parser, 00321 yaml_read_handler_t *handler, void *data) 00322 { 00323 assert(parser); /* Non-NULL parser object expected. */ 00324 assert(!parser->read_handler); /* You can set the source only once. */ 00325 assert(handler); /* Non-NULL read handler expected. */ 00326 00327 parser->read_handler = handler; 00328 parser->read_handler_data = data; 00329 } 00330 00331 /* 00332 * Set the source encoding. 00333 */ 00334 00335 YAML_DECLARE(void) 00336 yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding) 00337 { 00338 assert(parser); /* Non-NULL parser object expected. */ 00339 assert(!parser->encoding); /* Encoding is already set or detected. */ 00340 00341 parser->encoding = encoding; 00342 } 00343 00344 /* 00345 * Create a new emitter object. 00346 */ 00347 00348 YAML_DECLARE(int) 00349 yaml_emitter_initialize(yaml_emitter_t *emitter) 00350 { 00351 assert(emitter); /* Non-NULL emitter object expected. */ 00352 00353 memset(emitter, 0, sizeof(yaml_emitter_t)); 00354 if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE)) 00355 goto error; 00356 if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE)) 00357 goto error; 00358 if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE)) 00359 goto error; 00360 if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE)) 00361 goto error; 00362 if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE)) 00363 goto error; 00364 if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE)) 00365 goto error; 00366 00367 return 1; 00368 00369 error: 00370 00371 BUFFER_DEL(emitter, emitter->buffer); 00372 BUFFER_DEL(emitter, emitter->raw_buffer); 00373 STACK_DEL(emitter, emitter->states); 00374 QUEUE_DEL(emitter, emitter->events); 00375 STACK_DEL(emitter, emitter->indents); 00376 STACK_DEL(emitter, emitter->tag_directives); 00377 00378 return 0; 00379 } 00380 00381 /* 00382 * Destroy an emitter object. 00383 */ 00384 00385 YAML_DECLARE(void) 00386 yaml_emitter_delete(yaml_emitter_t *emitter) 00387 { 00388 assert(emitter); /* Non-NULL emitter object expected. */ 00389 00390 BUFFER_DEL(emitter, emitter->buffer); 00391 BUFFER_DEL(emitter, emitter->raw_buffer); 00392 STACK_DEL(emitter, emitter->states); 00393 while (!QUEUE_EMPTY(emitter, emitter->events)) { 00394 yaml_event_delete(&DEQUEUE(emitter, emitter->events)); 00395 } 00396 QUEUE_DEL(emitter, emitter->events); 00397 STACK_DEL(emitter, emitter->indents); 00398 while (!STACK_EMPTY(empty, emitter->tag_directives)) { 00399 yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives); 00400 yaml_free(tag_directive.handle); 00401 yaml_free(tag_directive.prefix); 00402 } 00403 STACK_DEL(emitter, emitter->tag_directives); 00404 yaml_free(emitter->anchors); 00405 00406 memset(emitter, 0, sizeof(yaml_emitter_t)); 00407 } 00408 00409 /* 00410 * String write handler. 00411 */ 00412 00413 static int 00414 yaml_string_write_handler(void *data, unsigned char *buffer, size_t size) 00415 { 00416 yaml_emitter_t *emitter = data; 00417 00418 if (emitter->output.string.size + *emitter->output.string.size_written 00419 < size) { 00420 memcpy(emitter->output.string.buffer 00421 + *emitter->output.string.size_written, 00422 buffer, 00423 emitter->output.string.size 00424 - *emitter->output.string.size_written); 00425 *emitter->output.string.size_written = emitter->output.string.size; 00426 return 0; 00427 } 00428 00429 memcpy(emitter->output.string.buffer 00430 + *emitter->output.string.size_written, buffer, size); 00431 *emitter->output.string.size_written += size; 00432 return 1; 00433 } 00434 00435 /* 00436 * File write handler. 00437 */ 00438 00439 static int 00440 yaml_file_write_handler(void *data, unsigned char *buffer, size_t size) 00441 { 00442 yaml_emitter_t *emitter = data; 00443 00444 return (fwrite(buffer, 1, size, emitter->output.file) == size); 00445 } 00446 /* 00447 * Set a string output. 00448 */ 00449 00450 YAML_DECLARE(void) 00451 yaml_emitter_set_output_string(yaml_emitter_t *emitter, 00452 unsigned char *output, size_t size, size_t *size_written) 00453 { 00454 assert(emitter); /* Non-NULL emitter object expected. */ 00455 assert(!emitter->write_handler); /* You can set the output only once. */ 00456 assert(output); /* Non-NULL output string expected. */ 00457 00458 emitter->write_handler = yaml_string_write_handler; 00459 emitter->write_handler_data = emitter; 00460 00461 emitter->output.string.buffer = output; 00462 emitter->output.string.size = size; 00463 emitter->output.string.size_written = size_written; 00464 *size_written = 0; 00465 } 00466 00467 /* 00468 * Set a file output. 00469 */ 00470 00471 YAML_DECLARE(void) 00472 yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file) 00473 { 00474 assert(emitter); /* Non-NULL emitter object expected. */ 00475 assert(!emitter->write_handler); /* You can set the output only once. */ 00476 assert(file); /* Non-NULL file object expected. */ 00477 00478 emitter->write_handler = yaml_file_write_handler; 00479 emitter->write_handler_data = emitter; 00480 00481 emitter->output.file = file; 00482 } 00483 00484 /* 00485 * Set a generic output handler. 00486 */ 00487 00488 YAML_DECLARE(void) 00489 yaml_emitter_set_output(yaml_emitter_t *emitter, 00490 yaml_write_handler_t *handler, void *data) 00491 { 00492 assert(emitter); /* Non-NULL emitter object expected. */ 00493 assert(!emitter->write_handler); /* You can set the output only once. */ 00494 assert(handler); /* Non-NULL handler object expected. */ 00495 00496 emitter->write_handler = handler; 00497 emitter->write_handler_data = data; 00498 } 00499 00500 /* 00501 * Set the output encoding. 00502 */ 00503 00504 YAML_DECLARE(void) 00505 yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding) 00506 { 00507 assert(emitter); /* Non-NULL emitter object expected. */ 00508 assert(!emitter->encoding); /* You can set encoding only once. */ 00509 00510 emitter->encoding = encoding; 00511 } 00512 00513 /* 00514 * Set the canonical output style. 00515 */ 00516 00517 YAML_DECLARE(void) 00518 yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical) 00519 { 00520 assert(emitter); /* Non-NULL emitter object expected. */ 00521 00522 emitter->canonical = (canonical != 0); 00523 } 00524 00525 /* 00526 * Set the indentation increment. 00527 */ 00528 00529 YAML_DECLARE(void) 00530 yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent) 00531 { 00532 assert(emitter); /* Non-NULL emitter object expected. */ 00533 00534 emitter->best_indent = (1 < indent && indent < 10) ? indent : 2; 00535 } 00536 00537 /* 00538 * Set the preferred line width. 00539 */ 00540 00541 YAML_DECLARE(void) 00542 yaml_emitter_set_width(yaml_emitter_t *emitter, int width) 00543 { 00544 assert(emitter); /* Non-NULL emitter object expected. */ 00545 00546 emitter->best_width = (width >= 0) ? width : -1; 00547 } 00548 00549 /* 00550 * Set if unescaped non-ASCII characters are allowed. 00551 */ 00552 00553 YAML_DECLARE(void) 00554 yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode) 00555 { 00556 assert(emitter); /* Non-NULL emitter object expected. */ 00557 00558 emitter->unicode = (unicode != 0); 00559 } 00560 00561 /* 00562 * Set the preferred line break character. 00563 */ 00564 00565 YAML_DECLARE(void) 00566 yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break) 00567 { 00568 assert(emitter); /* Non-NULL emitter object expected. */ 00569 00570 emitter->line_break = line_break; 00571 } 00572 00573 /* 00574 * Destroy a token object. 00575 */ 00576 00577 YAML_DECLARE(void) 00578 yaml_token_delete(yaml_token_t *token) 00579 { 00580 assert(token); /* Non-NULL token object expected. */ 00581 00582 switch (token->type) 00583 { 00584 case YAML_TAG_DIRECTIVE_TOKEN: 00585 yaml_free(token->data.tag_directive.handle); 00586 yaml_free(token->data.tag_directive.prefix); 00587 break; 00588 00589 case YAML_ALIAS_TOKEN: 00590 yaml_free(token->data.alias.value); 00591 break; 00592 00593 case YAML_ANCHOR_TOKEN: 00594 yaml_free(token->data.anchor.value); 00595 break; 00596 00597 case YAML_TAG_TOKEN: 00598 yaml_free(token->data.tag.handle); 00599 yaml_free(token->data.tag.suffix); 00600 break; 00601 00602 case YAML_SCALAR_TOKEN: 00603 yaml_free(token->data.scalar.value); 00604 break; 00605 00606 default: 00607 break; 00608 } 00609 00610 memset(token, 0, sizeof(yaml_token_t)); 00611 } 00612 00613 /* 00614 * Check if a string is a valid UTF-8 sequence. 00615 * 00616 * Check 'reader.c' for more details on UTF-8 encoding. 00617 */ 00618 00619 static int 00620 yaml_check_utf8(yaml_char_t *start, size_t length) 00621 { 00622 yaml_char_t *end = start+length; 00623 yaml_char_t *pointer = start; 00624 00625 while (pointer < end) { 00626 unsigned char octet; 00627 unsigned int width; 00628 unsigned int value; 00629 size_t k; 00630 00631 octet = pointer[0]; 00632 width = (octet & 0x80) == 0x00 ? 1 : 00633 (octet & 0xE0) == 0xC0 ? 2 : 00634 (octet & 0xF0) == 0xE0 ? 3 : 00635 (octet & 0xF8) == 0xF0 ? 4 : 0; 00636 value = (octet & 0x80) == 0x00 ? octet & 0x7F : 00637 (octet & 0xE0) == 0xC0 ? octet & 0x1F : 00638 (octet & 0xF0) == 0xE0 ? octet & 0x0F : 00639 (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; 00640 if (!width) return 0; 00641 if (pointer+width > end) return 0; 00642 for (k = 1; k < width; k ++) { 00643 octet = pointer[k]; 00644 if ((octet & 0xC0) != 0x80) return 0; 00645 value = (value << 6) + (octet & 0x3F); 00646 } 00647 if (!((width == 1) || 00648 (width == 2 && value >= 0x80) || 00649 (width == 3 && value >= 0x800) || 00650 (width == 4 && value >= 0x10000))) return 0; 00651 00652 pointer += width; 00653 } 00654 00655 return 1; 00656 } 00657 00658 /* 00659 * Create STREAM-START. 00660 */ 00661 00662 YAML_DECLARE(int) 00663 yaml_stream_start_event_initialize(yaml_event_t *event, 00664 yaml_encoding_t encoding) 00665 { 00666 yaml_mark_t mark = { 0, 0, 0 }; 00667 00668 assert(event); /* Non-NULL event object is expected. */ 00669 00670 STREAM_START_EVENT_INIT(*event, encoding, mark, mark); 00671 00672 return 1; 00673 } 00674 00675 /* 00676 * Create STREAM-END. 00677 */ 00678 00679 YAML_DECLARE(int) 00680 yaml_stream_end_event_initialize(yaml_event_t *event) 00681 { 00682 yaml_mark_t mark = { 0, 0, 0 }; 00683 00684 assert(event); /* Non-NULL event object is expected. */ 00685 00686 STREAM_END_EVENT_INIT(*event, mark, mark); 00687 00688 return 1; 00689 } 00690 00691 /* 00692 * Create DOCUMENT-START. 00693 */ 00694 00695 YAML_DECLARE(int) 00696 yaml_document_start_event_initialize(yaml_event_t *event, 00697 yaml_version_directive_t *version_directive, 00698 yaml_tag_directive_t *tag_directives_start, 00699 yaml_tag_directive_t *tag_directives_end, 00700 int implicit) 00701 { 00702 struct { 00703 yaml_error_type_t error; 00704 } context; 00705 yaml_mark_t mark = { 0, 0, 0 }; 00706 yaml_version_directive_t *version_directive_copy = NULL; 00707 struct { 00708 yaml_tag_directive_t *start; 00709 yaml_tag_directive_t *end; 00710 yaml_tag_directive_t *top; 00711 } tag_directives_copy = { NULL, NULL, NULL }; 00712 yaml_tag_directive_t value = { NULL, NULL }; 00713 00714 assert(event); /* Non-NULL event object is expected. */ 00715 assert((tag_directives_start && tag_directives_end) || 00716 (tag_directives_start == tag_directives_end)); 00717 /* Valid tag directives are expected. */ 00718 00719 if (version_directive) { 00720 version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)); 00721 if (!version_directive_copy) goto error; 00722 version_directive_copy->major = version_directive->major; 00723 version_directive_copy->minor = version_directive->minor; 00724 } 00725 00726 if (tag_directives_start != tag_directives_end) { 00727 yaml_tag_directive_t *tag_directive; 00728 if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) 00729 goto error; 00730 for (tag_directive = tag_directives_start; 00731 tag_directive != tag_directives_end; tag_directive ++) { 00732 assert(tag_directive->handle); 00733 assert(tag_directive->prefix); 00734 if (!yaml_check_utf8(tag_directive->handle, 00735 strlen((char *)tag_directive->handle))) 00736 goto error; 00737 if (!yaml_check_utf8(tag_directive->prefix, 00738 strlen((char *)tag_directive->prefix))) 00739 goto error; 00740 value.handle = yaml_strdup(tag_directive->handle); 00741 value.prefix = yaml_strdup(tag_directive->prefix); 00742 if (!value.handle || !value.prefix) goto error; 00743 if (!PUSH(&context, tag_directives_copy, value)) 00744 goto error; 00745 value.handle = NULL; 00746 value.prefix = NULL; 00747 } 00748 } 00749 00750 DOCUMENT_START_EVENT_INIT(*event, version_directive_copy, 00751 tag_directives_copy.start, tag_directives_copy.top, 00752 implicit, mark, mark); 00753 00754 return 1; 00755 00756 error: 00757 yaml_free(version_directive_copy); 00758 while (!STACK_EMPTY(context, tag_directives_copy)) { 00759 yaml_tag_directive_t value = POP(context, tag_directives_copy); 00760 yaml_free(value.handle); 00761 yaml_free(value.prefix); 00762 } 00763 STACK_DEL(context, tag_directives_copy); 00764 yaml_free(value.handle); 00765 yaml_free(value.prefix); 00766 00767 return 0; 00768 } 00769 00770 /* 00771 * Create DOCUMENT-END. 00772 */ 00773 00774 YAML_DECLARE(int) 00775 yaml_document_end_event_initialize(yaml_event_t *event, int implicit) 00776 { 00777 yaml_mark_t mark = { 0, 0, 0 }; 00778 00779 assert(event); /* Non-NULL emitter object is expected. */ 00780 00781 DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark); 00782 00783 return 1; 00784 } 00785 00786 /* 00787 * Create ALIAS. 00788 */ 00789 00790 YAML_DECLARE(int) 00791 yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) 00792 { 00793 yaml_mark_t mark = { 0, 0, 0 }; 00794 yaml_char_t *anchor_copy = NULL; 00795 00796 assert(event); /* Non-NULL event object is expected. */ 00797 assert(anchor); /* Non-NULL anchor is expected. */ 00798 00799 if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0; 00800 00801 anchor_copy = yaml_strdup(anchor); 00802 if (!anchor_copy) 00803 return 0; 00804 00805 ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark); 00806 00807 return 1; 00808 } 00809 00810 /* 00811 * Create SCALAR. 00812 */ 00813 00814 YAML_DECLARE(int) 00815 yaml_scalar_event_initialize(yaml_event_t *event, 00816 yaml_char_t *anchor, yaml_char_t *tag, 00817 yaml_char_t *value, int length, 00818 int plain_implicit, int quoted_implicit, 00819 yaml_scalar_style_t style) 00820 { 00821 yaml_mark_t mark = { 0, 0, 0 }; 00822 yaml_char_t *anchor_copy = NULL; 00823 yaml_char_t *tag_copy = NULL; 00824 yaml_char_t *value_copy = NULL; 00825 00826 assert(event); /* Non-NULL event object is expected. */ 00827 assert(value); /* Non-NULL anchor is expected. */ 00828 00829 if (anchor) { 00830 if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; 00831 anchor_copy = yaml_strdup(anchor); 00832 if (!anchor_copy) goto error; 00833 } 00834 00835 if (tag) { 00836 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 00837 tag_copy = yaml_strdup(tag); 00838 if (!tag_copy) goto error; 00839 } 00840 00841 if (length < 0) { 00842 length = strlen((char *)value); 00843 } 00844 00845 if (!yaml_check_utf8(value, length)) goto error; 00846 value_copy = yaml_malloc(length+1); 00847 if (!value_copy) goto error; 00848 memcpy(value_copy, value, length); 00849 value_copy[length] = '\0'; 00850 00851 SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length, 00852 plain_implicit, quoted_implicit, style, mark, mark); 00853 00854 return 1; 00855 00856 error: 00857 yaml_free(anchor_copy); 00858 yaml_free(tag_copy); 00859 yaml_free(value_copy); 00860 00861 return 0; 00862 } 00863 00864 /* 00865 * Create SEQUENCE-START. 00866 */ 00867 00868 YAML_DECLARE(int) 00869 yaml_sequence_start_event_initialize(yaml_event_t *event, 00870 yaml_char_t *anchor, yaml_char_t *tag, int implicit, 00871 yaml_sequence_style_t style) 00872 { 00873 yaml_mark_t mark = { 0, 0, 0 }; 00874 yaml_char_t *anchor_copy = NULL; 00875 yaml_char_t *tag_copy = NULL; 00876 00877 assert(event); /* Non-NULL event object is expected. */ 00878 00879 if (anchor) { 00880 if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; 00881 anchor_copy = yaml_strdup(anchor); 00882 if (!anchor_copy) goto error; 00883 } 00884 00885 if (tag) { 00886 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 00887 tag_copy = yaml_strdup(tag); 00888 if (!tag_copy) goto error; 00889 } 00890 00891 SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy, 00892 implicit, style, mark, mark); 00893 00894 return 1; 00895 00896 error: 00897 yaml_free(anchor_copy); 00898 yaml_free(tag_copy); 00899 00900 return 0; 00901 } 00902 00903 /* 00904 * Create SEQUENCE-END. 00905 */ 00906 00907 YAML_DECLARE(int) 00908 yaml_sequence_end_event_initialize(yaml_event_t *event) 00909 { 00910 yaml_mark_t mark = { 0, 0, 0 }; 00911 00912 assert(event); /* Non-NULL event object is expected. */ 00913 00914 SEQUENCE_END_EVENT_INIT(*event, mark, mark); 00915 00916 return 1; 00917 } 00918 00919 /* 00920 * Create MAPPING-START. 00921 */ 00922 00923 YAML_DECLARE(int) 00924 yaml_mapping_start_event_initialize(yaml_event_t *event, 00925 yaml_char_t *anchor, yaml_char_t *tag, int implicit, 00926 yaml_mapping_style_t style) 00927 { 00928 yaml_mark_t mark = { 0, 0, 0 }; 00929 yaml_char_t *anchor_copy = NULL; 00930 yaml_char_t *tag_copy = NULL; 00931 00932 assert(event); /* Non-NULL event object is expected. */ 00933 00934 if (anchor) { 00935 if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; 00936 anchor_copy = yaml_strdup(anchor); 00937 if (!anchor_copy) goto error; 00938 } 00939 00940 if (tag) { 00941 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 00942 tag_copy = yaml_strdup(tag); 00943 if (!tag_copy) goto error; 00944 } 00945 00946 MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy, 00947 implicit, style, mark, mark); 00948 00949 return 1; 00950 00951 error: 00952 yaml_free(anchor_copy); 00953 yaml_free(tag_copy); 00954 00955 return 0; 00956 } 00957 00958 /* 00959 * Create MAPPING-END. 00960 */ 00961 00962 YAML_DECLARE(int) 00963 yaml_mapping_end_event_initialize(yaml_event_t *event) 00964 { 00965 yaml_mark_t mark = { 0, 0, 0 }; 00966 00967 assert(event); /* Non-NULL event object is expected. */ 00968 00969 MAPPING_END_EVENT_INIT(*event, mark, mark); 00970 00971 return 1; 00972 } 00973 00974 /* 00975 * Destroy an event object. 00976 */ 00977 00978 YAML_DECLARE(void) 00979 yaml_event_delete(yaml_event_t *event) 00980 { 00981 yaml_tag_directive_t *tag_directive; 00982 00983 assert(event); /* Non-NULL event object expected. */ 00984 00985 switch (event->type) 00986 { 00987 case YAML_DOCUMENT_START_EVENT: 00988 yaml_free(event->data.document_start.version_directive); 00989 for (tag_directive = event->data.document_start.tag_directives.start; 00990 tag_directive != event->data.document_start.tag_directives.end; 00991 tag_directive++) { 00992 yaml_free(tag_directive->handle); 00993 yaml_free(tag_directive->prefix); 00994 } 00995 yaml_free(event->data.document_start.tag_directives.start); 00996 break; 00997 00998 case YAML_ALIAS_EVENT: 00999 yaml_free(event->data.alias.anchor); 01000 break; 01001 01002 case YAML_SCALAR_EVENT: 01003 yaml_free(event->data.scalar.anchor); 01004 yaml_free(event->data.scalar.tag); 01005 yaml_free(event->data.scalar.value); 01006 break; 01007 01008 case YAML_SEQUENCE_START_EVENT: 01009 yaml_free(event->data.sequence_start.anchor); 01010 yaml_free(event->data.sequence_start.tag); 01011 break; 01012 01013 case YAML_MAPPING_START_EVENT: 01014 yaml_free(event->data.mapping_start.anchor); 01015 yaml_free(event->data.mapping_start.tag); 01016 break; 01017 01018 default: 01019 break; 01020 } 01021 01022 memset(event, 0, sizeof(yaml_event_t)); 01023 } 01024 01025 /* 01026 * Create a document object. 01027 */ 01028 01029 YAML_DECLARE(int) 01030 yaml_document_initialize(yaml_document_t *document, 01031 yaml_version_directive_t *version_directive, 01032 yaml_tag_directive_t *tag_directives_start, 01033 yaml_tag_directive_t *tag_directives_end, 01034 int start_implicit, int end_implicit) 01035 { 01036 struct { 01037 yaml_error_type_t error; 01038 } context; 01039 struct { 01040 yaml_node_t *start; 01041 yaml_node_t *end; 01042 yaml_node_t *top; 01043 } nodes = { NULL, NULL, NULL }; 01044 yaml_version_directive_t *version_directive_copy = NULL; 01045 struct { 01046 yaml_tag_directive_t *start; 01047 yaml_tag_directive_t *end; 01048 yaml_tag_directive_t *top; 01049 } tag_directives_copy = { NULL, NULL, NULL }; 01050 yaml_tag_directive_t value = { NULL, NULL }; 01051 yaml_mark_t mark = { 0, 0, 0 }; 01052 01053 assert(document); /* Non-NULL document object is expected. */ 01054 assert((tag_directives_start && tag_directives_end) || 01055 (tag_directives_start == tag_directives_end)); 01056 /* Valid tag directives are expected. */ 01057 01058 if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error; 01059 01060 if (version_directive) { 01061 version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)); 01062 if (!version_directive_copy) goto error; 01063 version_directive_copy->major = version_directive->major; 01064 version_directive_copy->minor = version_directive->minor; 01065 } 01066 01067 if (tag_directives_start != tag_directives_end) { 01068 yaml_tag_directive_t *tag_directive; 01069 if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) 01070 goto error; 01071 for (tag_directive = tag_directives_start; 01072 tag_directive != tag_directives_end; tag_directive ++) { 01073 assert(tag_directive->handle); 01074 assert(tag_directive->prefix); 01075 if (!yaml_check_utf8(tag_directive->handle, 01076 strlen((char *)tag_directive->handle))) 01077 goto error; 01078 if (!yaml_check_utf8(tag_directive->prefix, 01079 strlen((char *)tag_directive->prefix))) 01080 goto error; 01081 value.handle = yaml_strdup(tag_directive->handle); 01082 value.prefix = yaml_strdup(tag_directive->prefix); 01083 if (!value.handle || !value.prefix) goto error; 01084 if (!PUSH(&context, tag_directives_copy, value)) 01085 goto error; 01086 value.handle = NULL; 01087 value.prefix = NULL; 01088 } 01089 } 01090 01091 DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, 01092 tag_directives_copy.start, tag_directives_copy.top, 01093 start_implicit, end_implicit, mark, mark); 01094 01095 return 1; 01096 01097 error: 01098 STACK_DEL(&context, nodes); 01099 yaml_free(version_directive_copy); 01100 while (!STACK_EMPTY(&context, tag_directives_copy)) { 01101 yaml_tag_directive_t value = POP(&context, tag_directives_copy); 01102 yaml_free(value.handle); 01103 yaml_free(value.prefix); 01104 } 01105 STACK_DEL(&context, tag_directives_copy); 01106 yaml_free(value.handle); 01107 yaml_free(value.prefix); 01108 01109 return 0; 01110 } 01111 01112 /* 01113 * Destroy a document object. 01114 */ 01115 01116 YAML_DECLARE(void) 01117 yaml_document_delete(yaml_document_t *document) 01118 { 01119 struct { 01120 yaml_error_type_t error; 01121 } context; 01122 yaml_tag_directive_t *tag_directive; 01123 01124 context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */ 01125 01126 assert(document); /* Non-NULL document object is expected. */ 01127 01128 while (!STACK_EMPTY(&context, document->nodes)) { 01129 yaml_node_t node = POP(&context, document->nodes); 01130 yaml_free(node.tag); 01131 switch (node.type) { 01132 case YAML_SCALAR_NODE: 01133 yaml_free(node.data.scalar.value); 01134 break; 01135 case YAML_SEQUENCE_NODE: 01136 STACK_DEL(&context, node.data.sequence.items); 01137 break; 01138 case YAML_MAPPING_NODE: 01139 STACK_DEL(&context, node.data.mapping.pairs); 01140 break; 01141 default: 01142 assert(0); /* Should not happen. */ 01143 } 01144 } 01145 STACK_DEL(&context, document->nodes); 01146 01147 yaml_free(document->version_directive); 01148 for (tag_directive = document->tag_directives.start; 01149 tag_directive != document->tag_directives.end; 01150 tag_directive++) { 01151 yaml_free(tag_directive->handle); 01152 yaml_free(tag_directive->prefix); 01153 } 01154 yaml_free(document->tag_directives.start); 01155 01156 memset(document, 0, sizeof(yaml_document_t)); 01157 } 01158 01163 YAML_DECLARE(yaml_node_t *) 01164 yaml_document_get_node(yaml_document_t *document, int index) 01165 { 01166 assert(document); /* Non-NULL document object is expected. */ 01167 01168 if (index > 0 && document->nodes.start + index <= document->nodes.top) { 01169 return document->nodes.start + index - 1; 01170 } 01171 return NULL; 01172 } 01173 01178 YAML_DECLARE(yaml_node_t *) 01179 yaml_document_get_root_node(yaml_document_t *document) 01180 { 01181 assert(document); /* Non-NULL document object is expected. */ 01182 01183 if (document->nodes.top != document->nodes.start) { 01184 return document->nodes.start; 01185 } 01186 return NULL; 01187 } 01188 01189 /* 01190 * Add a scalar node to a document. 01191 */ 01192 01193 YAML_DECLARE(int) 01194 yaml_document_add_scalar(yaml_document_t *document, 01195 yaml_char_t *tag, yaml_char_t *value, int length, 01196 yaml_scalar_style_t style) 01197 { 01198 struct { 01199 yaml_error_type_t error; 01200 } context; 01201 yaml_mark_t mark = { 0, 0, 0 }; 01202 yaml_char_t *tag_copy = NULL; 01203 yaml_char_t *value_copy = NULL; 01204 yaml_node_t node; 01205 01206 assert(document); /* Non-NULL document object is expected. */ 01207 assert(value); /* Non-NULL value is expected. */ 01208 01209 if (!tag) { 01210 tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG; 01211 } 01212 01213 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 01214 tag_copy = yaml_strdup(tag); 01215 if (!tag_copy) goto error; 01216 01217 if (length < 0) { 01218 length = strlen((char *)value); 01219 } 01220 01221 if (!yaml_check_utf8(value, length)) goto error; 01222 value_copy = yaml_malloc(length+1); 01223 if (!value_copy) goto error; 01224 memcpy(value_copy, value, length); 01225 value_copy[length] = '\0'; 01226 01227 SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark); 01228 if (!PUSH(&context, document->nodes, node)) goto error; 01229 01230 return document->nodes.top - document->nodes.start; 01231 01232 error: 01233 yaml_free(tag_copy); 01234 yaml_free(value_copy); 01235 01236 return 0; 01237 } 01238 01239 /* 01240 * Add a sequence node to a document. 01241 */ 01242 01243 YAML_DECLARE(int) 01244 yaml_document_add_sequence(yaml_document_t *document, 01245 yaml_char_t *tag, yaml_sequence_style_t style) 01246 { 01247 struct { 01248 yaml_error_type_t error; 01249 } context; 01250 yaml_mark_t mark = { 0, 0, 0 }; 01251 yaml_char_t *tag_copy = NULL; 01252 struct { 01253 yaml_node_item_t *start; 01254 yaml_node_item_t *end; 01255 yaml_node_item_t *top; 01256 } items = { NULL, NULL, NULL }; 01257 yaml_node_t node; 01258 01259 assert(document); /* Non-NULL document object is expected. */ 01260 01261 if (!tag) { 01262 tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG; 01263 } 01264 01265 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 01266 tag_copy = yaml_strdup(tag); 01267 if (!tag_copy) goto error; 01268 01269 if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error; 01270 01271 SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, 01272 style, mark, mark); 01273 if (!PUSH(&context, document->nodes, node)) goto error; 01274 01275 return document->nodes.top - document->nodes.start; 01276 01277 error: 01278 STACK_DEL(&context, items); 01279 yaml_free(tag_copy); 01280 01281 return 0; 01282 } 01283 01284 /* 01285 * Add a mapping node to a document. 01286 */ 01287 01288 YAML_DECLARE(int) 01289 yaml_document_add_mapping(yaml_document_t *document, 01290 yaml_char_t *tag, yaml_mapping_style_t style) 01291 { 01292 struct { 01293 yaml_error_type_t error; 01294 } context; 01295 yaml_mark_t mark = { 0, 0, 0 }; 01296 yaml_char_t *tag_copy = NULL; 01297 struct { 01298 yaml_node_pair_t *start; 01299 yaml_node_pair_t *end; 01300 yaml_node_pair_t *top; 01301 } pairs = { NULL, NULL, NULL }; 01302 yaml_node_t node; 01303 01304 assert(document); /* Non-NULL document object is expected. */ 01305 01306 if (!tag) { 01307 tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG; 01308 } 01309 01310 if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; 01311 tag_copy = yaml_strdup(tag); 01312 if (!tag_copy) goto error; 01313 01314 if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error; 01315 01316 MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, 01317 style, mark, mark); 01318 if (!PUSH(&context, document->nodes, node)) goto error; 01319 01320 return document->nodes.top - document->nodes.start; 01321 01322 error: 01323 STACK_DEL(&context, pairs); 01324 yaml_free(tag_copy); 01325 01326 return 0; 01327 } 01328 01329 /* 01330 * Append an item to a sequence node. 01331 */ 01332 01333 YAML_DECLARE(int) 01334 yaml_document_append_sequence_item(yaml_document_t *document, 01335 int sequence, int item) 01336 { 01337 struct { 01338 yaml_error_type_t error; 01339 } context; 01340 01341 assert(document); /* Non-NULL document is required. */ 01342 assert(sequence > 0 01343 && document->nodes.start + sequence <= document->nodes.top); 01344 /* Valid sequence id is required. */ 01345 assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE); 01346 /* A sequence node is required. */ 01347 assert(item > 0 && document->nodes.start + item <= document->nodes.top); 01348 /* Valid item id is required. */ 01349 01350 if (!PUSH(&context, 01351 document->nodes.start[sequence-1].data.sequence.items, item)) 01352 return 0; 01353 01354 return 1; 01355 } 01356 01357 /* 01358 * Append a pair of a key and a value to a mapping node. 01359 */ 01360 01361 YAML_DECLARE(int) 01362 yaml_document_append_mapping_pair(yaml_document_t *document, 01363 int mapping, int key, int value) 01364 { 01365 struct { 01366 yaml_error_type_t error; 01367 } context; 01368 01369 yaml_node_pair_t pair; 01370 01371 assert(document); /* Non-NULL document is required. */ 01372 assert(mapping > 0 01373 && document->nodes.start + mapping <= document->nodes.top); 01374 /* Valid mapping id is required. */ 01375 assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE); 01376 /* A mapping node is required. */ 01377 assert(key > 0 && document->nodes.start + key <= document->nodes.top); 01378 /* Valid key id is required. */ 01379 assert(value > 0 && document->nodes.start + value <= document->nodes.top); 01380 /* Valid value id is required. */ 01381 01382 pair.key = key; 01383 pair.value = value; 01384 01385 if (!PUSH(&context, 01386 document->nodes.start[mapping-1].data.mapping.pairs, pair)) 01387 return 0; 01388 01389 return 1; 01390 } 01391 01392 01393