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