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

Revision 203, 17.1 KB checked in by xi, 8 years ago (diff)

Complete the Parser (it requires refactoring though) and fix some bugs.

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