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: }