-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "yaml_private.h"
-#include <yaml/yaml.h>
+/*
+ * Get the library version.
+ */
-#include <assert.h>
+YAML_DECLARE(const char *)
+yaml_get_version_string(void)
+{
+ return YAML_VERSION_STRING;
+}
+
+/*
+ * Get the library version numbers.
+ */
+
+YAML_DECLARE(void)
+yaml_get_version(int *major, int *minor, int *patch)
+{
+ *major = YAML_VERSION_MAJOR;
+ *minor = YAML_VERSION_MINOR;
+ *patch = YAML_VERSION_PATCH;
+}
/*
* Allocate a dynamic memory block.
*/
-void *
+YAML_DECLARE(void *)
yaml_malloc(size_t size)
{
return malloc(size ? size : 1);
* Reallocate a dynamic memory block.
*/
-void *
+YAML_DECLARE(void *)
yaml_realloc(void *ptr, size_t size)
{
return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
* Free a dynamic memory block.
*/
-void
+YAML_DECLARE(void)
yaml_free(void *ptr)
{
if (ptr) free(ptr);
}
/*
- * Create a new parser object.
+ * Duplicate a string.
+ */
+
+YAML_DECLARE(char *)
+yaml_strdup(const char *str)
+{
+ return strdup(str);
+}
+
+/*
+ * Extend a string.
+ */
+
+YAML_DECLARE(int)
+yaml_string_extend(yaml_char_t **start,
+ yaml_char_t **pointer, yaml_char_t **end)
+{
+ void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+ if (!new_start) return 0;
+
+ memset(new_start + (*end - *start), 0, *end - *start);
+
+ *pointer = new_start + (*pointer - *start);
+ *end = new_start + (*end - *start)*2;
+ *start = new_start;
+
+ return 1;
+}
+
+/*
+ * Append a string B to a string A.
+ */
+
+YAML_DECLARE(int)
+yaml_string_join(
+ yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
+ yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
+{
+ if (*b_start == *b_pointer)
+ return 1;
+
+ while (*a_end - *a_pointer <= *b_pointer - *b_start) {
+ if (!yaml_string_extend(a_start, a_pointer, a_end))
+ return 0;
+ }
+
+ memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
+ *a_pointer += *b_pointer - *b_start;
+
+ return 1;
+}
+
+/*
+ * Extend a stack.
+ */
+
+YAML_DECLARE(int)
+yaml_stack_extend(void **start, void **top, void **end)
+{
+ void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+ if (!new_start) return 0;
+
+ *top = new_start + (*top - *start);
+ *end = new_start + (*end - *start)*2;
+ *start = new_start;
+
+ return 1;
+}
+
+/*
+ * Extend or move a queue.
*/
-yaml_parser_t *
-yaml_parser_new(void)
+YAML_DECLARE(int)
+yaml_queue_extend(void **start, void **head, void **tail, void **end)
{
- yaml_parser_t *parser;
+ /* Check if we need to resize the queue. */
- parser = yaml_malloc(sizeof(yaml_parser_t));
- if (!parser) return NULL;
+ if (*start == *head && *tail == *end) {
+ void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+ if (!new_start) return 0;
+
+ *head = new_start + (*head - *start);
+ *tail = new_start + (*tail - *start);
+ *end = new_start + (*end - *start)*2;
+ *start = new_start;
+ }
+
+ /* Check if we need to move the queue at the beginning of the buffer. */
+
+ if (*tail == *end) {
+ if (*head != *tail) {
+ memmove(*start, *head, *tail - *head);
+ }
+ *tail -= *head - *start;
+ *head = *start;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Create a new parser object.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_initialize(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
memset(parser, 0, sizeof(yaml_parser_t));
+ if (!BUFFER_INIT(parser, parser->raw_buffer, RAW_BUFFER_SIZE))
+ goto error;
+ if (!BUFFER_INIT(parser, parser->buffer, BUFFER_SIZE))
+ goto error;
+ if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
+ goto error;
+
+ return 1;
+
+error:
+
+ BUFFER_DEL(parser, parser->raw_buffer);
+ BUFFER_DEL(parser, parser->buffer);
+ QUEUE_DEL(parser, parser->tokens);
+ STACK_DEL(parser, parser->indents);
+ STACK_DEL(parser, parser->simple_keys);
+ STACK_DEL(parser, parser->states);
+ STACK_DEL(parser, parser->marks);
+ STACK_DEL(parser, parser->tag_directives);
- return parser;
+ return 0;
}
/*
* Destroy a parser object.
*/
-void
+YAML_DECLARE(void)
yaml_parser_delete(yaml_parser_t *parser)
{
assert(parser); /* Non-NULL parser object expected. */
- yaml_free(parser->buffer);
- if (!parser->raw_buffer_foreign)
- yaml_free(parser->raw_buffer);
+ BUFFER_DEL(parser, parser->raw_buffer);
+ BUFFER_DEL(parser, parser->buffer);
+ while (!QUEUE_EMPTY(parser, parser->tokens)) {
+ yaml_token_delete(&DEQUEUE(parser, parser->tokens));
+ }
+ QUEUE_DEL(parser, parser->tokens);
+ STACK_DEL(parser, parser->indents);
+ STACK_DEL(parser, parser->simple_keys);
+ STACK_DEL(parser, parser->states);
+ STACK_DEL(parser, parser->marks);
+ while (!STACK_EMPTY(parser, parser->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+ STACK_DEL(parser, parser->tag_directives);
memset(parser, 0, sizeof(yaml_parser_t));
-
- yaml_free(parser);
}
/*
- * String read handler (always returns error).
+ * String read handler.
*/
static int
yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
size_t *size_read)
{
- *size_read = 0;
+ yaml_parser_t *parser = data;
+
+ if (parser->input.string.current == parser->input.string.end) {
+ *size_read = 0;
+ return 1;
+ }
+
+ if (size > (parser->input.string.end - parser->input.string.current)) {
+ size = parser->input.string.end - parser->input.string.current;
+ }
+
+ memcpy(buffer, parser->input.string.current, size);
+ parser->input.string.current += size;
+ *size_read = size;
return 1;
}
yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
size_t *size_read)
{
- *size_read = fread(buffer, 1, size, (FILE *)ext);
- return !ferror((FILE *)ext);
+ yaml_parser_t *parser = data;
+
+ *size_read = fread(buffer, 1, size, parser->input.file);
+ return !ferror(parser->input.file);
}
/*
* Set a string input.
*/
-void
+YAML_DECLARE(void)
yaml_parser_set_input_string(yaml_parser_t *parser,
unsigned char *input, size_t size)
{
assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the source only once. */
+ assert(!parser->read_handler); /* You can set the source only once. */
assert(input); /* Non-NULL input string expected. */
parser->read_handler = yaml_string_read_handler;
- parser->read_handler_data = NULL;
+ parser->read_handler_data = parser;
- /* We use the input string as a raw (undecoded) buffer. */
- parser->raw_buffer = input;
- parser->raw_buffer_size = size;
- parser->raw_buffer_foreign = 1;
+ parser->input.string.start = input;
+ parser->input.string.current = input;
+ parser->input.string.end = input+size;
}
/*
* Set a file input.
*/
-void
+YAML_DECLARE(void)
yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
{
assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the source only once. */
+ assert(!parser->read_handler); /* You can set the source only once. */
assert(file); /* Non-NULL file object expected. */
parser->read_handler = yaml_file_read_handler;
- parser->read_handler_data = file;
+ parser->read_handler_data = parser;
+
+ parser->input.file = file;
}
/*
* Set a generic input.
*/
-void
+YAML_DECLARE(void)
yaml_parser_set_input(yaml_parser_t *parser,
yaml_read_handler_t *handler, void *data)
{
assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the source only once. */
+ assert(!parser->read_handler); /* You can set the source only once. */
assert(handler); /* Non-NULL read handler expected. */
parser->read_handler = handler;
- parser->read_handler_data = data
+ parser->read_handler_data = data;
}
/*
* Set the source encoding.
*/
-void
+YAML_DECLARE(void)
yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
{
assert(parser); /* Non-NULL parser object expected. */
parser->encoding = encoding;
}
+/*
+ * Destroy a token object.
+ */
+
+YAML_DECLARE(void)
+yaml_token_delete(yaml_token_t *token)
+{
+ assert(token); /* Non-NULL token object expected. */
+
+ switch (token->type)
+ {
+ case YAML_TAG_DIRECTIVE_TOKEN:
+ yaml_free(token->data.tag_directive.handle);
+ yaml_free(token->data.tag_directive.prefix);
+ break;
+
+ case YAML_ALIAS_TOKEN:
+ yaml_free(token->data.alias.value);
+ break;
+
+ case YAML_ANCHOR_TOKEN:
+ yaml_free(token->data.anchor.value);
+ break;
+
+ case YAML_TAG_TOKEN:
+ yaml_free(token->data.tag.handle);
+ yaml_free(token->data.tag.suffix);
+ break;
+
+ case YAML_SCALAR_TOKEN:
+ yaml_free(token->data.scalar.value);
+ break;
+ }
+
+ memset(token, 0, sizeof(yaml_token_t));
+}
+
+/*
+ * Destroy an event object.
+ */
+
+YAML_DECLARE(void)
+yaml_event_delete(yaml_event_t *event)
+{
+ yaml_tag_directive_t *tag_directive;
+
+ assert(event); /* Non-NULL event object expected. */
+
+ switch (event->type)
+ {
+ case YAML_DOCUMENT_START_EVENT:
+ yaml_free(event->data.document_start.version_directive);
+ for (tag_directive = event->data.document_start.tag_directives.start;
+ tag_directive != event->data.document_start.tag_directives.end;
+ tag_directive++) {
+ yaml_free(tag_directive->handle);
+ yaml_free(tag_directive->prefix);
+ }
+ yaml_free(event->data.document_start.tag_directives.start);
+ break;
+
+ case YAML_ALIAS_EVENT:
+ yaml_free(event->data.alias.anchor);
+ break;
+
+ case YAML_SCALAR_EVENT:
+ yaml_free(event->data.scalar.anchor);
+ yaml_free(event->data.scalar.tag);
+ yaml_free(event->data.scalar.value);
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+ yaml_free(event->data.sequence_start.anchor);
+ yaml_free(event->data.sequence_start.tag);
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+ yaml_free(event->data.mapping_start.anchor);
+ yaml_free(event->data.mapping_start.tag);
+ break;
+ }
+
+ memset(event, 0, sizeof(yaml_event_t));
+}
+