Actual source code: api.c
2: #include "yaml_private.h"
4: /*
5: * Allocate a dynamic memory block.
6: */
8: YAML_DECLARE(void *)
9: yaml_malloc(size_t size)
10: {
11: return malloc(size ? size : 1);
12: }
14: /*
15: * Reallocate a dynamic memory block.
16: */
18: YAML_DECLARE(void *)
19: yaml_realloc(void *ptr, size_t size)
20: {
21: return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
22: }
24: /*
25: * Free a dynamic memory block.
26: */
28: YAML_DECLARE(void)
29: yaml_free(void *ptr)
30: {
31: if (ptr) free(ptr);
32: }
34: /*
35: * Duplicate a string.
36: */
38: YAML_DECLARE(yaml_char_t *)
39: yaml_strdup(const yaml_char_t *str)
40: {
41: if (!str)
42: return NULL;
44: return (yaml_char_t *)strdup((char *)str);
45: }
47: /*
48: * Extend a string.
49: */
51: YAML_DECLARE(int)
52: yaml_string_extend(yaml_char_t **start,
53: yaml_char_t **pointer, yaml_char_t **end)
54: {
55: yaml_char_t *new_start = (yaml_char_t *)yaml_realloc((void*)*start, (*end - *start)*2);
57: if (!new_start) return 0;
59: memset(new_start + (*end - *start), 0, *end - *start);
61: *pointer = new_start + (*pointer - *start);
62: *end = new_start + (*end - *start)*2;
63: *start = new_start;
65: return 1;
66: }
68: /*
69: * Append a string B to a string A.
70: */
72: YAML_DECLARE(int)
73: yaml_string_join(
74: yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
75: yaml_char_t **b_start, yaml_char_t **b_pointer, SHIM(yaml_char_t **b_end))
76: {
77: UNUSED_PARAM(b_end)
78: if (*b_start == *b_pointer)
79: return 1;
81: while (*a_end - *a_pointer <= *b_pointer - *b_start) {
82: if (!yaml_string_extend(a_start, a_pointer, a_end))
83: return 0;
84: }
86: memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
87: *a_pointer += *b_pointer - *b_start;
89: return 1;
90: }
92: /*
93: * Extend a stack.
94: */
96: YAML_DECLARE(int)
97: yaml_stack_extend(void **start, void **top, void **end)
98: {
99: void *new_start;
101: if ((char *)*end - (char *)*start >= INT_MAX / 2)
102: return 0;
104: new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
106: if (!new_start) return 0;
108: *top = (char *)new_start + ((char *)*top - (char *)*start);
109: *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
110: *start = new_start;
112: return 1;
113: }
115: /*
116: * Extend or move a queue.
117: */
119: YAML_DECLARE(int)
120: yaml_queue_extend(void **start, void **head, void **tail, void **end)
121: {
122: /* Check if we need to resize the queue. */
124: if (*start == *head && *tail == *end) {
125: void *new_start = yaml_realloc(*start,
126: ((char *)*end - (char *)*start)*2);
128: if (!new_start) return 0;
130: *head = (char *)new_start + ((char *)*head - (char *)*start);
131: *tail = (char *)new_start + ((char *)*tail - (char *)*start);
132: *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
133: *start = new_start;
134: }
136: /* Check if we need to move the queue at the beginning of the buffer. */
138: if (*tail == *end) {
139: if (*head != *tail) {
140: memmove(*start, *head, (char *)*tail - (char *)*head);
141: }
142: *tail = (char *)*tail - (char *)*head + (char *)*start;
143: *head = *start;
144: }
146: return 1;
147: }
150: /*
151: * Create a new parser object.
152: */
154: YAML_DECLARE(int)
155: yaml_parser_initialize(yaml_parser_t *parser)
156: {
157: assert(parser); /* Non-NULL parser object expected. */
159: memset(parser, 0, sizeof(yaml_parser_t));
160: if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
161: goto error;
162: if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
163: goto error;
164: if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*))
165: goto error;
166: if (!STACK_INIT(parser, parser->indents, int*))
167: goto error;
168: if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*))
169: goto error;
170: if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*))
171: goto error;
172: if (!STACK_INIT(parser, parser->marks, yaml_mark_t*))
173: goto error;
174: if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*))
175: goto error;
177: return 1;
179: error:
181: BUFFER_DEL(parser, parser->raw_buffer);
182: BUFFER_DEL(parser, parser->buffer);
183: QUEUE_DEL(parser, parser->tokens);
184: STACK_DEL(parser, parser->indents);
185: STACK_DEL(parser, parser->simple_keys);
186: STACK_DEL(parser, parser->states);
187: STACK_DEL(parser, parser->marks);
188: STACK_DEL(parser, parser->tag_directives);
190: return 0;
191: }
193: /*
194: * Destroy a parser object.
195: */
197: YAML_DECLARE(void)
198: yaml_parser_delete(yaml_parser_t *parser)
199: {
200: assert(parser); /* Non-NULL parser object expected. */
202: BUFFER_DEL(parser, parser->raw_buffer);
203: BUFFER_DEL(parser, parser->buffer);
204: while (!QUEUE_EMPTY(parser, parser->tokens)) {
205: yaml_token_delete(&DEQUEUE(parser, parser->tokens));
206: }
207: QUEUE_DEL(parser, parser->tokens);
208: STACK_DEL(parser, parser->indents);
209: STACK_DEL(parser, parser->simple_keys);
210: STACK_DEL(parser, parser->states);
211: STACK_DEL(parser, parser->marks);
212: while (!STACK_EMPTY(parser, parser->tag_directives)) {
213: yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
214: yaml_free(tag_directive.handle);
215: yaml_free(tag_directive.prefix);
216: }
217: STACK_DEL(parser, parser->tag_directives);
219: memset(parser, 0, sizeof(yaml_parser_t));
220: }
222: /*
223: * String read handler.
224: */
226: static int
227: yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
228: size_t *size_read)
229: {
230: yaml_parser_t *parser = (yaml_parser_t *)data;
232: if (parser->input.string.current == parser->input.string.end) {
233: *size_read = 0;
234: return 1;
235: }
237: if (size > (size_t)(parser->input.string.end
238: - parser->input.string.current)) {
239: size = parser->input.string.end - parser->input.string.current;
240: }
242: memcpy(buffer, parser->input.string.current, size);
243: parser->input.string.current += size;
244: *size_read = size;
245: return 1;
246: }
248: /*
249: * File read handler.
250: */
252: static int
253: yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
254: size_t *size_read)
255: {
256: yaml_parser_t *parser = (yaml_parser_t *)data;
258: *size_read = fread(buffer, 1, size, parser->input.file);
259: return !ferror(parser->input.file);
260: }
262: /*
263: * Set a string input.
264: */
266: YAML_DECLARE(void)
267: yaml_parser_set_input_string(yaml_parser_t *parser,
268: const unsigned char *input, size_t size)
269: {
270: assert(parser); /* Non-NULL parser object expected. */
271: assert(!parser->read_handler); /* You can set the source only once. */
272: assert(input); /* Non-NULL input string expected. */
274: parser->read_handler = yaml_string_read_handler;
275: parser->read_handler_data = parser;
277: parser->input.string.start = input;
278: parser->input.string.current = input;
279: parser->input.string.end = input+size;
280: }
282: /*
283: * Set a file input.
284: */
286: YAML_DECLARE(void)
287: yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
288: {
289: assert(parser); /* Non-NULL parser object expected. */
290: assert(!parser->read_handler); /* You can set the source only once. */
291: assert(file); /* Non-NULL file object expected. */
293: parser->read_handler = yaml_file_read_handler;
294: parser->read_handler_data = parser;
296: parser->input.file = file;
297: }
299: /*
300: * Set a generic input.
301: */
303: YAML_DECLARE(void)
304: yaml_parser_set_input(yaml_parser_t *parser,
305: yaml_read_handler_t *handler, void *data)
306: {
307: assert(parser); /* Non-NULL parser object expected. */
308: assert(!parser->read_handler); /* You can set the source only once. */
309: assert(handler); /* Non-NULL read handler expected. */
311: parser->read_handler = handler;
312: parser->read_handler_data = data;
313: }
315: /*
316: * Set the source encoding.
317: */
319: YAML_DECLARE(void)
320: yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
321: {
322: assert(parser); /* Non-NULL parser object expected. */
323: assert(!parser->encoding); /* Encoding is already set or detected. */
325: parser->encoding = encoding;
326: }
328: /*
329: * Destroy a token object.
330: */
332: YAML_DECLARE(void)
333: yaml_token_delete(yaml_token_t *token)
334: {
335: assert(token); /* Non-NULL token object expected. */
337: switch (token->type)
338: {
339: case YAML_TAG_DIRECTIVE_TOKEN:
340: yaml_free(token->data.tag_directive.handle);
341: yaml_free(token->data.tag_directive.prefix);
342: break;
344: case YAML_ALIAS_TOKEN:
345: yaml_free(token->data.alias.value);
346: break;
348: case YAML_ANCHOR_TOKEN:
349: yaml_free(token->data.anchor.value);
350: break;
352: case YAML_TAG_TOKEN:
353: yaml_free(token->data.tag.handle);
354: yaml_free(token->data.tag.suffix);
355: break;
357: case YAML_SCALAR_TOKEN:
358: yaml_free(token->data.scalar.value);
359: break;
361: default:
362: break;
363: }
365: memset(token, 0, sizeof(yaml_token_t));
366: }
368: /*
369: * Destroy a document object.
370: */
372: YAML_DECLARE(void)
373: yaml_document_delete(yaml_document_t *document)
374: {
375: yaml_tag_directive_t *tag_directive;
377: assert(document); /* Non-NULL document object is expected. */
379: while (!STACK_EMPTY(&context, document->nodes)) {
380: yaml_node_t node = POP(&context, document->nodes);
381: yaml_free(node.tag);
382: switch (node.type) {
383: case YAML_SCALAR_NODE:
384: yaml_free(node.data.scalar.value);
385: break;
386: case YAML_SEQUENCE_NODE:
387: STACK_DEL(&context, node.data.sequence.items);
388: break;
389: case YAML_MAPPING_NODE:
390: STACK_DEL(&context, node.data.mapping.pairs);
391: break;
392: default:
393: assert(0); /* Should not happen. */
394: }
395: }
396: STACK_DEL(&context, document->nodes);
398: yaml_free(document->version_directive);
399: for (tag_directive = document->tag_directives.start;
400: tag_directive != document->tag_directives.end;
401: tag_directive++) {
402: yaml_free(tag_directive->handle);
403: yaml_free(tag_directive->prefix);
404: }
405: yaml_free(document->tag_directives.start);
407: memset(document, 0, sizeof(yaml_document_t));
408: }
410: /**
411: * Get a document node.
412: */
414: YAML_DECLARE(yaml_node_t *)
415: yaml_document_get_node(yaml_document_t *document, int index)
416: {
417: assert(document); /* Non-NULL document object is expected. */
419: if (index > 0 && document->nodes.start + index <= document->nodes.top) {
420: return document->nodes.start + index - 1;
421: }
422: return NULL;
423: }
425: /**
426: * Get the root object.
427: */
429: YAML_DECLARE(yaml_node_t *)
430: yaml_document_get_root_node(yaml_document_t *document)
431: {
432: assert(document); /* Non-NULL document object is expected. */
434: if (document->nodes.top != document->nodes.start) {
435: return document->nodes.start;
436: }
437: return NULL;
438: }