source: libyaml/trunk/src/api.c @ 201

Revision 201, 16.8 KB checked in by xi, 8 years ago (diff)

Start working on the parser.

Line 
1
2#if HAVE_CONFIG_H
3#include <config.h>
4#endif
5
6#include <yaml.h>
7
8#include <assert.h>
9
10YAML_DECLARE(const char *)
11yaml_get_version_string(void)
12{
13    return YAML_VERSION_STRING;
14}
15
16YAML_DECLARE(void)
17yaml_get_version(int *major, int *minor, int *patch)
18{
19    *major = YAML_VERSION_MAJOR;
20    *minor = YAML_VERSION_MINOR;
21    *patch = YAML_VERSION_PATCH;
22}
23
24/*
25 * Allocate a dynamic memory block.
26 */
27
28YAML_DECLARE(void *)
29yaml_malloc(size_t size)
30{
31    return malloc(size ? size : 1);
32}
33
34/*
35 * Reallocate a dynamic memory block.
36 */
37
38YAML_DECLARE(void *)
39yaml_realloc(void *ptr, size_t size)
40{
41    return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
42}
43
44/*
45 * Free a dynamic memory block.
46 */
47
48YAML_DECLARE(void)
49yaml_free(void *ptr)
50{
51    if (ptr) free(ptr);
52}
53
54/*
55 * Create a new parser object.
56 */
57
58YAML_DECLARE(yaml_parser_t *)
59yaml_parser_new(void)
60{
61    yaml_parser_t *parser;
62
63    /* Allocate the parser structure. */
64
65    parser = yaml_malloc(sizeof(yaml_parser_t));
66    if (!parser) goto error;
67
68    memset(parser, 0, sizeof(yaml_parser_t));
69
70    /* Allocate the raw buffer. */
71
72    parser->raw_buffer = yaml_malloc(YAML_RAW_BUFFER_SIZE);
73    if (!parser->raw_buffer) goto error;
74    memset(parser->raw_buffer, 0, YAML_RAW_BUFFER_SIZE);
75
76    parser->raw_pointer = parser->raw_buffer;
77    parser->raw_unread = 0;
78
79    /* Allocate the character buffer. */
80
81    parser->buffer = yaml_malloc(YAML_BUFFER_SIZE);
82    if (!parser->buffer) goto error;
83    memset(parser->buffer, 0, YAML_BUFFER_SIZE);
84
85    parser->buffer_end = parser->buffer;
86    parser->pointer = parser->buffer;
87    parser->unread = 0;
88
89    /* Allocate the tokens queue. */
90
91    parser->tokens = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
92    if (!parser->tokens) goto error;
93    memset(parser->tokens, 0, YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
94
95    parser->tokens_size = YAML_DEFAULT_SIZE;
96    parser->tokens_head = 0;
97    parser->tokens_tail = 0;
98    parser->tokens_parsed = 0;
99
100    /* Allocate the indents stack. */
101
102    parser->indents = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(int));
103    if (!parser->indents) goto error;
104    memset(parser->indents, 0, YAML_DEFAULT_SIZE*sizeof(int));
105
106    parser->indents_size = YAML_DEFAULT_SIZE;
107    parser->indents_length = 0;
108
109    /* Allocate the stack of potential simple keys. */
110
111    parser->simple_keys = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
112    if (!parser->simple_keys) goto error;
113    memset(parser->simple_keys, 0, YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
114
115    parser->simple_keys_size = YAML_DEFAULT_SIZE;
116
117    /* Allocate the stack of parser states. */
118
119    parser->states = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_parser_state_t));
120    if (!parser->states) goto error;
121    memset(parser->states, 0, YAML_DEFAULT_SIZE*sizeof(yaml_parser_state_t));
122
123    parser->states_size = YAML_DEFAULT_SIZE;
124
125    /* Set the initial state. */
126
127    parser->state = YAML_PARSE_STREAM_START_STATE;
128
129    /* Allocate the list of TAG directives. */
130
131    parser->tag_directives = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_tag_directive_t *));
132    if (!parser->tag_directives) goto error;
133    memset(parser->tag_directives, 0, YAML_DEFAULT_SIZE*sizeof(yaml_tag_directive_t *));
134
135    parser->tag_directives_size = YAML_DEFAULT_SIZE;
136
137    /* Done. */
138
139    return parser;
140
141    /* On error, free allocated buffers. */
142
143error:
144
145    if (!parser) return NULL;
146
147    yaml_free(parser->tag_directives);
148    yaml_free(parser->states);
149    yaml_free(parser->simple_keys);
150    yaml_free(parser->indents);
151    yaml_free(parser->tokens);
152    yaml_free(parser->buffer);
153    yaml_free(parser->raw_buffer);
154
155    yaml_free(parser);
156
157    return NULL;
158}
159
160/*
161 * Destroy a parser object.
162 */
163
164YAML_DECLARE(void)
165yaml_parser_delete(yaml_parser_t *parser)
166{
167    assert(parser); /* Non-NULL parser object expected. */
168
169    yaml_free(parser->tag_directives);
170    yaml_free(parser->states);
171    yaml_free(parser->simple_keys);
172    yaml_free(parser->indents);
173    yaml_free(parser->tokens);
174    yaml_free(parser->buffer);
175    yaml_free(parser->raw_buffer);
176
177    memset(parser, 0, sizeof(yaml_parser_t));
178
179    yaml_free(parser);
180}
181
182/*
183 * String read handler.
184 */
185
186static int
187yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
188        size_t *size_read)
189{
190    yaml_string_input_t *input = data;
191
192    if (input->current == input->end) {
193        *size_read = 0;
194        return 1;
195    }
196
197    if (size > (input->end - input->current)) {
198        size = input->end - input->current;
199    }
200
201    memcpy(buffer, input->current, size);
202    input->current += size;
203    *size_read = size;
204    return 1;
205}
206
207/*
208 * File read handler.
209 */
210
211static int
212yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
213        size_t *size_read)
214{
215    *size_read = fread(buffer, 1, size, (FILE *)data);
216    return !ferror((FILE *)data);
217}
218
219/*
220 * Set a string input.
221 */
222
223YAML_DECLARE(void)
224yaml_parser_set_input_string(yaml_parser_t *parser,
225        unsigned char *input, size_t size)
226{
227    assert(parser); /* Non-NULL parser object expected. */
228    assert(!parser->read_handler);  /* You can set the source only once. */
229    assert(input);  /* Non-NULL input string expected. */
230
231    parser->string_input.start = input;
232    parser->string_input.current = input;
233    parser->string_input.end = input+size;
234
235    parser->read_handler = yaml_string_read_handler;
236    parser->read_handler_data = &parser->string_input;
237}
238
239/*
240 * Set a file input.
241 */
242
243YAML_DECLARE(void)
244yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
245{
246    assert(parser); /* Non-NULL parser object expected. */
247    assert(!parser->read_handler);  /* You can set the source only once. */
248    assert(file);   /* Non-NULL file object expected. */
249
250    parser->read_handler = yaml_file_read_handler;
251    parser->read_handler_data = file;
252}
253
254/*
255 * Set a generic input.
256 */
257
258YAML_DECLARE(void)
259yaml_parser_set_input(yaml_parser_t *parser,
260        yaml_read_handler_t *handler, void *data)
261{
262    assert(parser); /* Non-NULL parser object expected. */
263    assert(!parser->read_handler);  /* You can set the source only once. */
264    assert(handler);    /* Non-NULL read handler expected. */
265
266    parser->read_handler = handler;
267    parser->read_handler_data = data;
268}
269
270/*
271 * Set the source encoding.
272 */
273
274YAML_DECLARE(void)
275yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
276{
277    assert(parser); /* Non-NULL parser object expected. */
278    assert(!parser->encoding); /* Encoding is already set or detected. */
279
280    parser->encoding = encoding;
281}
282
283/*
284 * Create a token.
285 */
286
287YAML_DECLARE(yaml_token_t *)
288yaml_token_new(yaml_token_type_t type,
289        yaml_mark_t start_mark, yaml_mark_t end_mark)
290{
291    yaml_token_t *token = yaml_malloc(sizeof(yaml_token_t));
292
293    if (!token) return NULL;
294
295    memset(token, 0, sizeof(yaml_token_t));
296
297    token->type = type;
298    token->start_mark = start_mark;
299    token->end_mark = end_mark;
300
301    return token;
302}
303
304/*
305 * Create a STREAM-START token.
306 */
307
308YAML_DECLARE(yaml_token_t *)
309yaml_stream_start_token_new(yaml_encoding_t encoding,
310        yaml_mark_t start_mark, yaml_mark_t end_mark)
311{
312    yaml_token_t *token = yaml_token_new(YAML_STREAM_START_TOKEN,
313            start_mark, end_mark);
314
315    if (!token) return NULL;
316
317    token->data.stream_start.encoding = encoding;
318
319    return token;
320}
321
322/*
323 * Create a STREAM-END token.
324 */
325
326YAML_DECLARE(yaml_token_t *)
327yaml_stream_end_token_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
328{
329    yaml_token_t *token = yaml_token_new(YAML_STREAM_END_TOKEN,
330            start_mark, end_mark);
331
332    if (!token) return NULL;
333
334    return token;
335}
336
337/*
338 * Create a VERSION-DIRECTIVE token.
339 */
340
341YAML_DECLARE(yaml_token_t *)
342yaml_version_directive_token_new(int major, int minor,
343        yaml_mark_t start_mark, yaml_mark_t end_mark)
344{
345    yaml_token_t *token = yaml_token_new(YAML_VERSION_DIRECTIVE_TOKEN,
346            start_mark, end_mark);
347
348    if (!token) return NULL;
349
350    token->data.version_directive.major = major;
351    token->data.version_directive.minor = minor;
352
353    return token;
354}
355
356/*
357 * Create a TAG-DIRECTIVE token.
358 */
359
360YAML_DECLARE(yaml_token_t *)
361yaml_tag_directive_token_new(yaml_char_t *handle, yaml_char_t *prefix,
362        yaml_mark_t start_mark, yaml_mark_t end_mark)
363{
364    yaml_token_t *token = yaml_token_new(YAML_TAG_DIRECTIVE_TOKEN,
365            start_mark, end_mark);
366
367    if (!token) return NULL;
368
369    token->data.tag_directive.handle = handle;
370    token->data.tag_directive.prefix = prefix;
371
372    return token;
373}
374
375/*
376 * Create an ALIAS token.
377 */
378
379YAML_DECLARE(yaml_token_t *)
380yaml_alias_token_new(yaml_char_t *anchor,
381        yaml_mark_t start_mark, yaml_mark_t end_mark)
382{
383    yaml_token_t *token = yaml_token_new(YAML_ALIAS_TOKEN,
384            start_mark, end_mark);
385
386    if (!token) return NULL;
387
388    token->data.alias.value = anchor;
389
390    return token;
391}
392
393/*
394 * Create an ANCHOR token.
395 */
396
397YAML_DECLARE(yaml_token_t *)
398yaml_anchor_token_new(yaml_char_t *anchor,
399        yaml_mark_t start_mark, yaml_mark_t end_mark)
400{
401    yaml_token_t *token = yaml_token_new(YAML_ANCHOR_TOKEN,
402            start_mark, end_mark);
403
404    if (!token) return NULL;
405
406    token->data.anchor.value = anchor;
407
408    return token;
409}
410
411/*
412 * Create a TAG token.
413 */
414
415YAML_DECLARE(yaml_token_t *)
416yaml_tag_token_new(yaml_char_t *handle, yaml_char_t *suffix,
417        yaml_mark_t start_mark, yaml_mark_t end_mark)
418{
419    yaml_token_t *token = yaml_token_new(YAML_TAG_TOKEN,
420            start_mark, end_mark);
421
422    if (!token) return NULL;
423
424    token->data.tag.handle = handle;
425    token->data.tag.suffix = suffix;
426
427    return token;
428}
429
430/*
431 * Create a SCALAR token.
432 */
433
434YAML_DECLARE(yaml_token_t *)
435yaml_scalar_token_new(yaml_char_t *value, size_t length,
436        yaml_scalar_style_t style,
437        yaml_mark_t start_mark, yaml_mark_t end_mark)
438{
439    yaml_token_t *token = yaml_token_new(YAML_SCALAR_TOKEN,
440            start_mark, end_mark);
441
442    if (!token) return NULL;
443
444    token->data.scalar.value = value;
445    token->data.scalar.length = length;
446    token->data.scalar.style = style;
447
448    return token;
449}
450
451/*
452 * Destroy a token object.
453 */
454
455YAML_DECLARE(void)
456yaml_token_delete(yaml_token_t *token)
457{
458    assert(token);  /* Non-NULL token object expected. */
459
460    switch (token->type)
461    {
462        case YAML_TAG_DIRECTIVE_TOKEN:
463            yaml_free(token->data.tag_directive.handle);
464            yaml_free(token->data.tag_directive.prefix);
465            break;
466
467        case YAML_ALIAS_TOKEN:
468            yaml_free(token->data.alias.value);
469            break;
470
471        case YAML_ANCHOR_TOKEN:
472            yaml_free(token->data.anchor.value);
473            break;
474
475        case YAML_TAG_TOKEN:
476            yaml_free(token->data.tag.handle);
477            yaml_free(token->data.tag.suffix);
478            break;
479
480        case YAML_SCALAR_TOKEN:
481            yaml_free(token->data.scalar.value);
482            break;
483    }
484
485    memset(token, 0, sizeof(yaml_token_t));
486
487    yaml_free(token);
488}
489
490/*
491 * Create an event.
492 */
493
494static yaml_event_t *
495yaml_event_new(yaml_event_type_t type,
496        yaml_mark_t start_mark, yaml_mark_t end_mark)
497{
498    yaml_event_t *event = yaml_malloc(sizeof(yaml_event_t));
499
500    if (!event) return NULL;
501
502    memset(event, 0, sizeof(yaml_event_t));
503
504    event->type = type;
505    event->start_mark = start_mark;
506    event->end_mark = end_mark;
507
508    return event;
509}
510
511/*
512 * Create a STREAM-START event.
513 */
514
515YAML_DECLARE(yaml_event_t *)
516yaml_stream_start_event_new(yaml_encoding_t encoding,
517        yaml_mark_t start_mark, yaml_mark_t end_mark)
518{
519    yaml_event_t *event = yaml_event_new(YAML_STREAM_START_EVENT,
520            start_mark, end_mark);
521
522    if (!event) return NULL;
523
524    event->data.stream_start.encoding = encoding;
525
526    return event;
527}
528
529/*
530 * Create a STREAM-END event.
531 */
532
533YAML_DECLARE(yaml_event_t *)
534yaml_stream_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
535{
536    return yaml_event_new(YAML_STREAM_END_EVENT, start_mark, end_mark);
537}
538
539/*
540 * Create a DOCUMENT-START event.
541 */
542
543YAML_DECLARE(yaml_event_t *)
544yaml_document_start_event_new(yaml_version_directive_t *version_directive,
545        yaml_tag_directive_t **tag_directives, int implicit,
546        yaml_mark_t start_mark, yaml_mark_t end_mark)
547{
548    yaml_event_t *event = yaml_event_new(YAML_DOCUMENT_START_EVENT,
549            start_mark, end_mark);
550
551    if (!event) return NULL;
552
553    event->data.document_start.version_directive = version_directive;
554    event->data.document_start.tag_directives = tag_directives;
555    event->data.document_start.implicit = implicit;
556
557    return event;
558}
559
560/*
561 * Create a DOCUMENT-END event.
562 */
563
564YAML_DECLARE(yaml_event_t *)
565yaml_document_end_event_new(int implicit,
566        yaml_mark_t start_mark, yaml_mark_t end_mark)
567{
568    yaml_event_t *event = yaml_event_new(YAML_DOCUMENT_END_EVENT,
569            start_mark, end_mark);
570
571    if (!event) return NULL;
572
573    event->data.document_end.implicit = implicit;
574
575    return event;
576}
577
578/*
579 * Create an ALIAS event.
580 */
581
582YAML_DECLARE(yaml_event_t *)
583yaml_alias_event_new(yaml_char_t *anchor,
584        yaml_mark_t start_mark, yaml_mark_t end_mark)
585{
586    yaml_event_t *event = yaml_event_new(YAML_ALIAS_EVENT,
587            start_mark, end_mark);
588
589    if (!event) return NULL;
590
591    event->data.alias.anchor = anchor;
592
593    return event;
594}
595
596/*
597 * Create a SCALAR event.
598 */
599
600YAML_DECLARE(yaml_event_t *)
601yaml_scalar_event_new(yaml_char_t *anchor, yaml_char_t *tag,
602        yaml_char_t *value, size_t length,
603        int plain_implicit, int quoted_implicit,
604        yaml_scalar_style_t style,
605        yaml_mark_t start_mark, yaml_mark_t end_mark)
606{
607    yaml_event_t *event = yaml_event_new(YAML_SCALAR_EVENT,
608            start_mark, end_mark);
609
610    if (!event) return NULL;
611
612    event->data.scalar.anchor = anchor;
613    event->data.scalar.tag = tag;
614    event->data.scalar.value = value;
615    event->data.scalar.length = length;
616    event->data.scalar.plain_implicit = plain_implicit;
617    event->data.scalar.quoted_implicit = quoted_implicit;
618    event->data.scalar.style = style;
619
620    return event;
621}
622
623/*
624 * Create a SEQUENCE-START event.
625 */
626
627YAML_DECLARE(yaml_event_t *)
628yaml_sequence_start_new(yaml_char_t *anchor, yaml_char_t *tag,
629        int implicit, yaml_sequence_style_t style,
630        yaml_mark_t start_mark, yaml_mark_t end_mark)
631{
632    yaml_event_t *event = yaml_event_new(YAML_SEQUENCE_START_EVENT,
633            start_mark, end_mark);
634
635    if (!event) return NULL;
636
637    event->data.sequence_start.anchor = anchor;
638    event->data.sequence_start.tag = tag;
639    event->data.sequence_start.implicit = implicit;
640    event->data.sequence_start.style = style;
641
642    return event;
643}
644
645/*
646 * Create a SEQUENCE-END event.
647 */
648
649YAML_DECLARE(yaml_event_t *)
650yaml_sequence_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
651{
652    return yaml_event_new(YAML_SEQUENCE_END_EVENT, start_mark, end_mark);
653}
654
655/*
656 * Create a MAPPING-START event.
657 */
658
659YAML_DECLARE(yaml_event_t *)
660yaml_mapping_start_new(yaml_char_t *anchor, yaml_char_t *tag,
661        int implicit, yaml_mapping_style_t style,
662        yaml_mark_t start_mark, yaml_mark_t end_mark)
663{
664    yaml_event_t *event = yaml_event_new(YAML_MAPPING_START_EVENT,
665            start_mark, end_mark);
666
667    if (!event) return NULL;
668
669    event->data.mapping_start.anchor = anchor;
670    event->data.mapping_start.tag = tag;
671    event->data.mapping_start.implicit = implicit;
672    event->data.mapping_start.style = style;
673
674    return event;
675}
676
677/*
678 * Create a MAPPING-END event.
679 */
680
681YAML_DECLARE(yaml_event_t *)
682yaml_mapping_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
683{
684    return yaml_event_new(YAML_MAPPING_END_EVENT, start_mark, end_mark);
685}
686
687/*
688 * Destroy an event object.
689 */
690
691YAML_DECLARE(void)
692yaml_event_delete(yaml_event_t *event)
693{
694    assert(event);  /* Non-NULL event object expected. */
695
696    switch (event->type)
697    {
698        case YAML_DOCUMENT_START_EVENT:
699            yaml_free(event->data.document_start.version_directive);
700            if (event->data.document_start.tag_directives) {
701                yaml_tag_directive_t **tag_directive;
702                for (tag_directive = event->data.document_start.tag_directives;
703                        *tag_directive; tag_directive++) {
704                    yaml_free((*tag_directive)->handle);
705                    yaml_free((*tag_directive)->prefix);
706                    yaml_free(*tag_directive);
707                }
708                yaml_free(event->data.document_start.tag_directives);
709            }
710            break;
711
712        case YAML_ALIAS_EVENT:
713            yaml_free(event->data.alias.anchor);
714            break;
715
716        case YAML_SCALAR_EVENT:
717            yaml_free(event->data.scalar.anchor);
718            yaml_free(event->data.scalar.tag);
719            yaml_free(event->data.scalar.value);
720            break;
721
722        case YAML_SEQUENCE_START_EVENT:
723            yaml_free(event->data.sequence_start.anchor);
724            yaml_free(event->data.sequence_start.tag);
725            break;
726
727        case YAML_MAPPING_START_EVENT:
728            yaml_free(event->data.mapping_start.anchor);
729            yaml_free(event->data.mapping_start.tag);
730            break;
731    }
732
733    memset(event, 0, sizeof(yaml_event_t));
734
735    yaml_free(event);
736}
737
Note: See TracBrowser for help on using the repository browser.