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

Revision 185, 9.5 KB checked in by xi, 9 years ago (diff)

Implementing Scanner: macros and high-level functions.

RevLine 
[178]1
2#if HAVE_CONFIG_H
3#include <config.h>
4#endif
5
6#include <yaml/yaml.h>
7
[179]8#include <assert.h>
9
[178]10/*
[179]11 * Allocate a dynamic memory block.
[178]12 */
13
[183]14YAML_DECLARE(void *)
[179]15yaml_malloc(size_t size)
16{
17    return malloc(size ? size : 1);
18}
19
20/*
21 * Reallocate a dynamic memory block.
22 */
23
[183]24YAML_DECLARE(void *)
[179]25yaml_realloc(void *ptr, size_t size)
26{
27    return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
28}
29
30/*
31 * Free a dynamic memory block.
32 */
33
[183]34YAML_DECLARE(void)
[179]35yaml_free(void *ptr)
36{
37    if (ptr) free(ptr);
38}
39
40/*
41 * Create a new parser object.
42 */
43
[183]44YAML_DECLARE(yaml_parser_t *)
[178]45yaml_parser_new(void)
46{
47    yaml_parser_t *parser;
48
[180]49    /* Allocate the parser structure. */
50
[179]51    parser = yaml_malloc(sizeof(yaml_parser_t));
[185]52    if (!parser) goto error;
[178]53
54    memset(parser, 0, sizeof(yaml_parser_t));
55
[180]56    /* Allocate the raw buffer. */
57
58    parser->raw_buffer = yaml_malloc(YAML_RAW_BUFFER_SIZE);
[185]59    if (!parser->raw_buffer) goto error;
60    memset(parser->raw_buffer, 0, YAML_RAW_BUFFER_SIZE);
61
[180]62    parser->raw_pointer = parser->raw_buffer;
63    parser->raw_unread = 0;
64
65    /* Allocate the character buffer. */
66
67    parser->buffer = yaml_malloc(YAML_BUFFER_SIZE);
[185]68    if (!parser->buffer) goto error;
69    memset(parser->buffer, 0, YAML_BUFFER_SIZE);
70
[180]71    parser->buffer_end = parser->buffer;
72    parser->pointer = parser->buffer;
73    parser->unread = 0;
74
[185]75    /* Allocate the tokens queue. */
76
77    parser->tokens = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
78    if (!parser->tokens) goto error;
79    memset(parser->tokens, 0, YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
80
81    parser->tokens_size = YAML_DEFAULT_SIZE;
82    parser->tokens_head = 0;
83    parser->tokens_tail = 0;
84    parser->tokens_parsed = 0;
85
86    /* Allocate the indents stack. */
87
88    parser->indents = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(int));
89    if (!parser->indents) goto error;
90    memset(parser->indents, 0, YAML_DEFAULT_SIZE*sizeof(int));
91
92    parser->indents_size = YAML_DEFAULT_SIZE;
93    parser->indents_length = 0;
94
95    /* Allocate the stack of potential simple keys. */
96
97    parser->simple_keys = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
98    if (!parser->simple_keys) goto error;
99    memset(parser->simple_keys, 0, YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
100
101    parser->simple_keys_size = YAML_DEFAULT_SIZE;
102
103    /* Done. */
104
[178]105    return parser;
[185]106
107    /* On error, free allocated buffers. */
108
109error:
110
111    if (!parser) return NULL;
112
113    yaml_free(parser->simple_keys);
114    yaml_free(parser->indents);
115    yaml_free(parser->tokens);
116    yaml_free(parser->buffer);
117    yaml_free(parser->raw_buffer);
118
119    yaml_free(parser);
120
121    return NULL;
[178]122}
123
124/*
125 * Destroy a parser object.
126 */
127
[183]128YAML_DECLARE(void)
[178]129yaml_parser_delete(yaml_parser_t *parser)
130{
[179]131    assert(parser); /* Non-NULL parser object expected. */
132
[185]133    yaml_free(parser->simple_keys);
134    yaml_free(parser->indents);
135    yaml_free(parser->tokens);
[179]136    yaml_free(parser->buffer);
[180]137    yaml_free(parser->raw_buffer);
[179]138
139    memset(parser, 0, sizeof(yaml_parser_t));
140
141    yaml_free(parser);
[178]142}
143
[179]144/*
[180]145 * String read handler.
[179]146 */
147
148static int
149yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
150        size_t *size_read)
151{
[180]152    yaml_string_input_t *input = data;
153
154    if (input->current == input->end) {
155        *size_read = 0;
156        return 1;
157    }
158
159    if (size > (input->end - input->current)) {
160        size = input->end - input->current;
161    }
162
163    memcpy(buffer, input->current, size);
164    input->current += size;
165    *size_read = size;
[179]166    return 1;
167}
168
169/*
170 * File read handler.
171 */
172
173static int
174yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
175        size_t *size_read)
176{
[180]177    *size_read = fread(buffer, 1, size, (FILE *)data);
178    return !ferror((FILE *)data);
[179]179}
180
181/*
182 * Set a string input.
183 */
184
[183]185YAML_DECLARE(void)
[179]186yaml_parser_set_input_string(yaml_parser_t *parser,
187        unsigned char *input, size_t size)
188{
189    assert(parser); /* Non-NULL parser object expected. */
[180]190    assert(!parser->read_handler);  /* You can set the source only once. */
[179]191    assert(input);  /* Non-NULL input string expected. */
192
[180]193    parser->string_input.start = input;
194    parser->string_input.current = input;
195    parser->string_input.end = input+size;
196
[179]197    parser->read_handler = yaml_string_read_handler;
[180]198    parser->read_handler_data = &parser->string_input;
[179]199}
200
201/*
202 * Set a file input.
203 */
204
[183]205YAML_DECLARE(void)
[179]206yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
207{
208    assert(parser); /* Non-NULL parser object expected. */
[180]209    assert(!parser->read_handler);  /* You can set the source only once. */
[179]210    assert(file);   /* Non-NULL file object expected. */
211
212    parser->read_handler = yaml_file_read_handler;
213    parser->read_handler_data = file;
214}
215
216/*
217 * Set a generic input.
218 */
219
[183]220YAML_DECLARE(void)
[179]221yaml_parser_set_input(yaml_parser_t *parser,
222        yaml_read_handler_t *handler, void *data)
223{
224    assert(parser); /* Non-NULL parser object expected. */
[180]225    assert(!parser->read_handler);  /* You can set the source only once. */
[179]226    assert(handler);    /* Non-NULL read handler expected. */
227
228    parser->read_handler = handler;
[180]229    parser->read_handler_data = data;
[179]230}
231
232/*
233 * Set the source encoding.
234 */
235
[183]236YAML_DECLARE(void)
[179]237yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
238{
239    assert(parser); /* Non-NULL parser object expected. */
240    assert(!parser->encoding); /* Encoding is already set or detected. */
241
242    parser->encoding = encoding;
243}
244
[183]245/*
246 * Create a token.
247 */
248
249YAML_DECLARE(yaml_token_t *)
250yaml_token_new(yaml_token_type_t type,
251        yaml_mark_t start_mark, yaml_mark_t end_mark)
252{
253    yaml_token_t *token = yaml_malloc(sizeof(yaml_token_t));
254
255    if (!token) return NULL;
256
257    memset(token, 0, sizeof(yaml_token_t));
258
259    token->type = type;
260    token->start_mark = start_mark;
261    token->end_mark = end_mark;
262
263    return token;
264}
265
266/*
267 * Create a STREAM-START token.
268 */
269
270YAML_DECLARE(yaml_token_t *)
271yaml_stream_start_token(yaml_encoding_t encoding,
272        yaml_mark_t start_mark, yaml_mark_t end_mark)
273{
274    yaml_token_t *token = yaml_token_new(YAML_STREAM_START_TOKEN,
275            start_mark, end_mark);
276
277    if (!token) return NULL;
278
279    token->data.encoding = encoding;
280
281    return token;
282}
283
284/*
285 * Create a STREAM-END token.
286 */
287
288YAML_DECLARE(yaml_token_t *)
289yaml_stream_end_token(yaml_mark_t start_mark, yaml_mark_t end_mark)
290{
291    yaml_token_t *token = yaml_token_new(YAML_STREAM_END_TOKEN,
292            start_mark, end_mark);
293
294    if (!token) return NULL;
295
296    return token;
297}
298
299/*
300 * Create a VERSION-DIRECTIVE token.
301 */
302
303YAML_DECLARE(yaml_token_t *)
304yaml_version_directive_token_new(int major, int minor,
305        yaml_mark_t start_mark, yaml_mark_t end_mark)
306{
307    yaml_token_t *token = yaml_token_new(YAML_VERSION_DIRECTIVE_TOKEN,
308            start_mark, end_mark);
309
310    if (!token) return NULL;
311
312    token->data.version_directive.major = major;
313    token->data.version_directive.minor = minor;
314
315    return token;
316}
317
318/*
319 * Create a TAG-DIRECTIVE token.
320 */
321
322YAML_DECLARE(yaml_token_t *)
323yaml_tag_directive_token_new(yaml_char_t *handle, yaml_char_t *prefix,
324        yaml_mark_t start_mark, yaml_mark_t end_mark)
325{
326    yaml_token_t *token = yaml_token_new(YAML_TAG_DIRECTIVE_TOKEN,
327            start_mark, end_mark);
328
329    if (!token) return NULL;
330
331    token->data.tag_directive.handle = handle;
332    token->data.tag_directive.prefix = prefix;
333
334    return token;
335}
336
337/*
338 * Create an ALIAS token.
339 */
340
341YAML_DECLARE(yaml_token_t *)
342yaml_alias_token_new(yaml_char_t *anchor,
343        yaml_mark_t start_mark, yaml_mark_t end_mark)
344{
345    yaml_token_t *token = yaml_token_new(YAML_ALIAS_TOKEN,
346            start_mark, end_mark);
347
348    if (!token) return NULL;
349
350    token->data.anchor = anchor;
351
352    return token;
353}
354
355/*
356 * Create an ANCHOR token.
357 */
358
359YAML_DECLARE(yaml_token_t *)
360yaml_anchor_token_new(yaml_char_t *anchor,
361        yaml_mark_t start_mark, yaml_mark_t end_mark)
362{
363    yaml_token_t *token = yaml_token_new(YAML_ANCHOR_TOKEN,
364            start_mark, end_mark);
365
366    if (!token) return NULL;
367
368    token->data.anchor = anchor;
369
370    return token;
371}
372
373/*
374 * Create a TAG token.
375 */
376
377YAML_DECLARE(yaml_token_t *)
378yaml_tag_token_new(yaml_char_t *handle, yaml_char_t *suffix,
379        yaml_mark_t start_mark, yaml_mark_t end_mark)
380{
381    yaml_token_t *token = yaml_token_new(YAML_TAG_TOKEN,
382            start_mark, end_mark);
383
384    if (!token) return NULL;
385
386    token->data.tag.handle = handle;
387    token->data.tag.suffix = suffix;
388
389    return token;
390}
391
392/*
393 * Create a SCALAR token.
394 */
395
396YAML_DECLARE(yaml_token_t *)
397yaml_scalar_token_new(yaml_char_t *value, size_t length,
398        yaml_scalar_style_t style,
399        yaml_mark_t start_mark, yaml_mark_t end_mark)
400{
401    yaml_token_t *token = yaml_token_new(YAML_SCALAR_TOKEN,
402            start_mark, end_mark);
403
404    if (!token) return NULL;
405
406    token->data.scalar.value = value;
407    token->data.scalar.length = length;
408    token->data.scalar.style = style;
409
410    return token;
411}
412
413/*
414 * Destroy a token object.
415 */
416
417YAML_DECLARE(void)
418yaml_token_delete(yaml_token_t *token)
419{
420    assert(token);  /* Non-NULL token object expected. */
421
422    switch (token->type)
423    {
424        case YAML_TAG_DIRECTIVE_TOKEN:
425            yaml_free(token->data.tag_directive.handle);
426            yaml_free(token->data.tag_directive.prefix);
427            break;
428
429        case YAML_ALIAS_TOKEN:
430        case YAML_ANCHOR_TOKEN:
431            yaml_free(token->data.anchor);
432            break;
433
434        case YAML_TAG_TOKEN:
435            yaml_free(token->data.tag.handle);
436            yaml_free(token->data.tag.suffix);
437            break;
438
439        case YAML_SCALAR_TOKEN:
440            yaml_free(token->data.scalar.value);
441            break;
442    }
443
444    memset(token, 0, sizeof(yaml_token_t));
445
446    yaml_free(token);
447}
448
Note: See TracBrowser for help on using the repository browser.