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