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