~ubuntu-branches/ubuntu/saucy/libyaml-libyaml-perl/saucy-security

« back to all changes in this revision

Viewing changes to LibYAML/api.c

  • Committer: Bazaar Package Importer
  • Author(s): Ryan Niebur
  • Date: 2009-06-01 02:17:22 UTC
  • Revision ID: james.westby@ubuntu.com-20090601021722-8qlj45pmu8ffwzau
Tags: upstream-0.32
ImportĀ upstreamĀ versionĀ 0.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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