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) memmove(*start, *head, (char *)*tail - (char *)*head);
140: *tail = (char *)*tail - (char *)*head + (char *)*start;
141: *head = *start;
142: }
144: return 1;
145: }
148: /*
149: * Create a new parser object.
150: */
152: YAML_DECLARE(int)
153: yaml_parser_initialize(yaml_parser_t *parser)
154: {
155: assert(parser); /* Non-NULL parser object expected. */
157: memset(parser, 0, sizeof(yaml_parser_t));
158: if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
159: goto error;
160: if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
161: goto error;
162: if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*))
163: goto error;
164: if (!STACK_INIT(parser, parser->indents, int*))
165: goto error;
166: if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*))
167: goto error;
168: if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*))
169: goto error;
170: if (!STACK_INIT(parser, parser->marks, yaml_mark_t*))
171: goto error;
172: if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*))
173: goto error;
175: return 1;
177: error:
179: BUFFER_DEL(parser, parser->raw_buffer);
180: BUFFER_DEL(parser, parser->buffer);
181: QUEUE_DEL(parser, parser->tokens);
182: STACK_DEL(parser, parser->indents);
183: STACK_DEL(parser, parser->simple_keys);
184: STACK_DEL(parser, parser->states);
185: STACK_DEL(parser, parser->marks);
186: STACK_DEL(parser, parser->tag_directives);
188: return 0;
189: }
191: /*
192: * Destroy a parser object.
193: */
195: YAML_DECLARE(void)
196: yaml_parser_delete(yaml_parser_t *parser)
197: {
198: assert(parser); /* Non-NULL parser object expected. */
200: BUFFER_DEL(parser, parser->raw_buffer);
201: BUFFER_DEL(parser, parser->buffer);
202: while (!QUEUE_EMPTY(parser, parser->tokens)) yaml_token_delete(&DEQUEUE(parser, parser->tokens));
203: QUEUE_DEL(parser, parser->tokens);
204: STACK_DEL(parser, parser->indents);
205: STACK_DEL(parser, parser->simple_keys);
206: STACK_DEL(parser, parser->states);
207: STACK_DEL(parser, parser->marks);
208: while (!STACK_EMPTY(parser, parser->tag_directives)) {
209: yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
210: yaml_free(tag_directive.handle);
211: yaml_free(tag_directive.prefix);
212: }
213: STACK_DEL(parser, parser->tag_directives);
215: memset(parser, 0, sizeof(yaml_parser_t));
216: }
218: /*
219: * String read handler.
220: */
222: static int
223: yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
224: size_t *size_read)
225: {
226: yaml_parser_t *parser = (yaml_parser_t *)data;
228: if (parser->input.string.current == parser->input.string.end) {
229: *size_read = 0;
230: return 1;
231: }
233: if (size > (size_t)(parser->input.string.end
234: - parser->input.string.current)) {
235: size = parser->input.string.end - parser->input.string.current;
236: }
238: memcpy(buffer, parser->input.string.current, size);
239: parser->input.string.current += size;
240: *size_read = size;
241: return 1;
242: }
244: /*
245: * File read handler.
246: */
248: static int
249: yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
250: size_t *size_read)
251: {
252: yaml_parser_t *parser = (yaml_parser_t *)data;
254: *size_read = fread(buffer, 1, size, parser->input.file);
255: return !ferror(parser->input.file);
256: }
258: /*
259: * Set a string input.
260: */
262: YAML_DECLARE(void)
263: yaml_parser_set_input_string(yaml_parser_t *parser,
264: const unsigned char *input, size_t size)
265: {
266: assert(parser); /* Non-NULL parser object expected. */
267: assert(!parser->read_handler); /* You can set the source only once. */
268: assert(input); /* Non-NULL input string expected. */
270: parser->read_handler = yaml_string_read_handler;
271: parser->read_handler_data = parser;
273: parser->input.string.start = input;
274: parser->input.string.current = input;
275: parser->input.string.end = input+size;
276: }
278: /*
279: * Set a file input.
280: */
282: YAML_DECLARE(void)
283: yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
284: {
285: assert(parser); /* Non-NULL parser object expected. */
286: assert(!parser->read_handler); /* You can set the source only once. */
287: assert(file); /* Non-NULL file object expected. */
289: parser->read_handler = yaml_file_read_handler;
290: parser->read_handler_data = parser;
292: parser->input.file = file;
293: }
295: /*
296: * Set a generic input.
297: */
299: YAML_DECLARE(void)
300: yaml_parser_set_input(yaml_parser_t *parser,
301: yaml_read_handler_t *handler, void *data)
302: {
303: assert(parser); /* Non-NULL parser object expected. */
304: assert(!parser->read_handler); /* You can set the source only once. */
305: assert(handler); /* Non-NULL read handler expected. */
307: parser->read_handler = handler;
308: parser->read_handler_data = data;
309: }
311: /*
312: * Set the source encoding.
313: */
315: YAML_DECLARE(void)
316: yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
317: {
318: assert(parser); /* Non-NULL parser object expected. */
319: assert(!parser->encoding); /* Encoding is already set or detected. */
321: parser->encoding = encoding;
322: }
324: /*
325: * Destroy a token object.
326: */
328: YAML_DECLARE(void)
329: yaml_token_delete(yaml_token_t *token)
330: {
331: assert(token); /* Non-NULL token object expected. */
333: switch (token->type)
334: {
335: case YAML_TAG_DIRECTIVE_TOKEN:
336: yaml_free(token->data.tag_directive.handle);
337: yaml_free(token->data.tag_directive.prefix);
338: break;
340: case YAML_ALIAS_TOKEN:
341: yaml_free(token->data.alias.value);
342: break;
344: case YAML_ANCHOR_TOKEN:
345: yaml_free(token->data.anchor.value);
346: break;
348: case YAML_TAG_TOKEN:
349: yaml_free(token->data.tag.handle);
350: yaml_free(token->data.tag.suffix);
351: break;
353: case YAML_SCALAR_TOKEN:
354: yaml_free(token->data.scalar.value);
355: break;
357: default:
358: break;
359: }
361: memset(token, 0, sizeof(yaml_token_t));
362: }
364: /*
365: * Destroy a document object.
366: */
368: YAML_DECLARE(void)
369: yaml_document_delete(yaml_document_t *document)
370: {
371: yaml_tag_directive_t *tag_directive;
373: assert(document); /* Non-NULL document object is expected. */
375: while (!STACK_EMPTY(&context, document->nodes)) {
376: yaml_node_t node = POP(&context, document->nodes);
377: yaml_free(node.tag);
378: switch (node.type) {
379: case YAML_SCALAR_NODE:
380: yaml_free(node.data.scalar.value);
381: break;
382: case YAML_SEQUENCE_NODE:
383: STACK_DEL(&context, node.data.sequence.items);
384: break;
385: case YAML_MAPPING_NODE:
386: STACK_DEL(&context, node.data.mapping.pairs);
387: break;
388: default:
389: assert(0); /* Should not happen. */
390: }
391: }
392: STACK_DEL(&context, document->nodes);
394: yaml_free(document->version_directive);
395: for (tag_directive = document->tag_directives.start;
396: tag_directive != document->tag_directives.end;
397: tag_directive++) {
398: yaml_free(tag_directive->handle);
399: yaml_free(tag_directive->prefix);
400: }
401: yaml_free(document->tag_directives.start);
403: memset(document, 0, sizeof(yaml_document_t));
404: }
406: /**
407: * Get a document node.
408: */
410: YAML_DECLARE(yaml_node_t *)
411: yaml_document_get_node(yaml_document_t *document, int index)
412: {
413: assert(document); /* Non-NULL document object is expected. */
415: if (index > 0 && document->nodes.start + index <= document->nodes.top) return document->nodes.start + index - 1;
416: return NULL;
417: }
419: /**
420: * Get the root object.
421: */
423: YAML_DECLARE(yaml_node_t *)
424: yaml_document_get_root_node(yaml_document_t *document)
425: {
426: assert(document); /* Non-NULL document object is expected. */
428: if (document->nodes.top != document->nodes.start) return document->nodes.start;
429: return NULL;
430: }