summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxi <xi@18f92427-320e-0410-9341-c67f048884a3>2008-01-19 13:54:22 +0000
committerxi <xi@18f92427-320e-0410-9341-c67f048884a3>2008-01-19 13:54:22 +0000
commit6608dc4b2c6f0c7f0761ebdee74e4022c09bbf76 (patch)
tree53ca93a29808b00f7771206a1687469940d9a986
parent80dc45b6360138db8c3a2c75648d24de03c7d778 (diff)
downloadlibyaml-6608dc4b2c6f0c7f0761ebdee74e4022c09bbf76.tar.gz
Minor API updates.
git-svn-id: http://svn.pyyaml.org/libyaml/trunk@267 18f92427-320e-0410-9341-c67f048884a3
-rw-r--r--include/yaml.h204
-rw-r--r--src/api.c2342
-rw-r--r--src/emitter.c91
-rw-r--r--src/yaml_private.h364
4 files changed, 2070 insertions, 931 deletions
diff --git a/include/yaml.h b/include/yaml.h
index 582d822..f009bf6 100644
--- a/include/yaml.h
+++ b/include/yaml.h
@@ -7,17 +7,43 @@
* the terms of the MIT license; see the file LICENCE for more details.
*****************************************************************************/
-/*
+/*****************************************************************************
* General guidelines.
+ *****************************************************************************/
+
+/*
+ * Basic conventions.
+ *
+ * All functions exported by exported by LibYAML starts with the the prefix
+ * `yaml_`; types starts with `yaml_` and ends with `_t`; macros and
+ * enumeration values start with `YAML_`.
+ *
+ * A function may serve as method for an object or a particular type; such
+ * functions start with `yaml_<type>`. A type constructor is named
+ * `yaml_<type>_new()`, a type destructor is named `yaml_<type>_delete()`.
+ *
+ * A function signifies whether it succeeded or failed with its return value;
+ * typically it is `1` for success, `0` for failure. Functions that return a
+ * pointer may indicate an error condition by returning `NULL`. Functions that
+ * never fail commonly do not return any value. For most of the functions, an
+ * error value means that the function is unable to allocate some memory
+ * buffer. For parsing and emitting functions, detailed information on the
+ * nature of the error could be obtained.
+ *
+ * LibYAML provides two active objects: parsers and emitters and three passive
+ * objects: tokens, events and documents.
+ *
+ *
*
- * Naming conventions: all functions exported by LibYAML starts with the `yaml_` prefix;
- * types starts with `yaml_` and ends with `_t`; macros and enumerations starts
- * with `YAML_`.
*
* FIXME: Calling conventions.
* FIXME: Memory allocation.
* FIXME: Errors and exceptions.
* FIXME: And so on, and so forth.
+ *
+ *
+ *
+ *
*/
@@ -269,9 +295,9 @@ typedef struct yaml_error_s {
YAML_DECLARE(int)
yaml_error_message(yaml_error_t *error, char *buffer, size_t capacity);
-/******************************************************************************
+/*****************************************************************************
* Basic Types
- ******************************************************************************/
+ *****************************************************************************/
/*
* The character type (UTF-8 octet).
@@ -347,9 +373,9 @@ typedef enum yaml_break_e {
YAML_CRLN_BREAK
} yaml_break_t;
-/******************************************************************************
+/*****************************************************************************
* Node Styles
- ******************************************************************************/
+ *****************************************************************************/
/*
* Scalar styles.
@@ -402,9 +428,9 @@ typedef enum yaml_sequence_style_e {
YAML_ANY_SEQUENCE_STYLE,
/* The flow sequence style. */
- YAML_FLOW_SEQUENCE_STYLE
+ YAML_FLOW_SEQUENCE_STYLE,
/* The block sequence style. */
- YAML_BLOCK_SEQUENCE_STYLE,
+ YAML_BLOCK_SEQUENCE_STYLE
} yaml_sequence_style_t;
/*
@@ -430,9 +456,9 @@ typedef enum yaml_mapping_style_e {
YAML_FLOW_MAPPING_STYLE
} yaml_mapping_style_t;
-/******************************************************************************
+/*****************************************************************************
* Tokens
- ******************************************************************************/
+ *****************************************************************************/
/*
* Token types.
@@ -680,9 +706,9 @@ yaml_token_duplicate(yaml_token_t *token, const yaml_token_t *model);
YAML_DECLARE(void)
yaml_token_clear(yaml_token_t *token);
-/******************************************************************************
+/*****************************************************************************
* Events
- ******************************************************************************/
+ *****************************************************************************/
/*
* Event types.
@@ -1220,9 +1246,9 @@ yaml_event_create_mapping_start(yaml_event_t *event,
YAML_DECLARE(int)
yaml_event_create_mapping_end(yaml_event_t *event);
-/******************************************************************************
+/*****************************************************************************
* Documents and Nodes
- ******************************************************************************/
+ *****************************************************************************/
/*
* Well-known scalar tags.
@@ -1260,7 +1286,7 @@ yaml_event_create_mapping_end(yaml_event_t *event);
typedef enum yaml_document_type_e {
/* An empty uninitialized document. */
- YAML_NO_DOCUMENT.
+ YAML_NO_DOCUMENT,
/* A YAML document. */
YAML_DOCUMENT
@@ -1382,7 +1408,7 @@ typedef struct yaml_arc_s {
* node object is destroyed when the document containing it is destroyed.
*/
-struct yaml_node_s {
+typedef struct yaml_node_s {
/* The node type. */
yaml_node_type_t type;
@@ -1442,7 +1468,7 @@ struct yaml_node_s {
/* The end of the node. */
yaml_mark_t end_mark;
-};
+} yaml_node_t;
/*
* The incomplete node object.
@@ -1818,6 +1844,62 @@ yaml_document_add_mapping(yaml_document_t *document, int *node_id,
yaml_mapping_style_t style);
/*
+ * Add an item to a SEQUENCE node.
+ *
+ * The order in which items are added to a sequence coincides with the order
+ * they are emitted into the output stream.
+ *
+ * Arguments:
+ *
+ * - `document`: a document object.
+ *
+ * - `sequence_id`: the id of a sequence node; could be negative. It is a
+ * fatal error if `sequence_id` does not refer to an existing sequence node.
+ *
+ * - `item_id`: the id of an item node; could be negative. It is a fatal error
+ * if `item_id` does not refer to an existing node. Note that it is possible
+ * for `item_id` to coincide with `sequence_id`, which means that the
+ * sequence recursively contains itself.
+ *
+ * Returns: `1` on success, `0` on error. The function may fail if it cannot
+ * allocate memory for internal buffers.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_sequence_item(yaml_document_t *document,
+ int sequence_id, int item_id);
+
+/*
+ * Add a pair of a key and a value to a MAPPING node.
+ *
+ * The order in which (key, value) pairs are added to a mapping coincides with
+ * the order in which they are presented in the output stream. Note that the
+ * mapping key order is a presentation detail and should not used to convey any
+ * information. An ordered mapping could be represented as a sequence of
+ * single-paired mappings.
+ *
+ * Arguments:
+ *
+ * - `document`: a document object.
+ *
+ * - `mapping_id`: the id of a mapping node; could be negative. It is a
+ * fatal error if `mapping_id` does not refer to an existing mapping node.
+ *
+ * - `key_id`: the id of a key node; could be negative. It is a fatal error
+ * if `key_id` does not refer to an existing node.
+ *
+ * - `value_id`: the id of a value node; could be negative. It is a fatal
+ * error if `value_id` does not refer to an existing node.
+ *
+ * Returns: `1` on success, `0` on error. The function may fail if it cannot
+ * allocate memory for internal buffers.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_mapping_pair(yaml_document_t *document,
+ int mapping_id, int key_id, int value_id);
+
+/*
* Get the value of a `!!null` SCALAR node.
*
* Use this function to ensure that the given node is a scalar, the node tag is
@@ -1893,7 +1975,7 @@ yaml_document_get_str_node(yaml_document_t *document, int node_id,
* `tag:yaml.org,2002:int` and the node value is a valid integer. In this
* case, the function parses the node value and returns an integer number. The
* function recognizes decimal, hexdecimal and octal numbers including negative
- * numbers.
+ * numbers. The function uses `strtol()` for string-to-integer conversion.
*
* Arguments:
*
@@ -1910,7 +1992,7 @@ yaml_document_get_str_node(yaml_document_t *document, int node_id,
YAML_DECLARE(int)
yaml_document_get_int_node(yaml_document_t *document, int node_id,
- int *value);
+ long *value);
/*
* Get the value of a `!!float` SCALAR node.
@@ -1919,7 +2001,9 @@ yaml_document_get_int_node(yaml_document_t *document, int node_id,
* `tag:yaml.org,2002:float` and the node value is a valid float value. In
* this case, the function parses the node value and returns a float number.
* The function recognizes float values in exponential and fixed notation as
- * well as special values `.nan`, `.inf` and `-.inf`.
+ * well as special values `.nan`, `.inf` and `-.inf`. The function uses
+ * `strtod()` for string-to-float conversion. The `.nan`, `.inf` and `-.inf`
+ * values are generated as `0.0/0.0`, `1.0/0.0` and `-1.0/0.0` respectively.
*
* Arguments:
*
@@ -2094,7 +2178,7 @@ yaml_document_add_str_node(yaml_document_t *document, int *node_id,
YAML_DECLARE(int)
yaml_document_add_int_node(yaml_document_t *document, int *node_id,
- int value);
+ long value);
/*
* Add a `!!float` SCALAR node to the document.
@@ -2166,65 +2250,9 @@ yaml_document_add_seq_node(yaml_document_t *document, int *node_id);
YAML_DECLARE(int)
yaml_document_add_map_node(yaml_document_t *document, int *node_id);
-/*
- * Add an item to a SEQUENCE node.
- *
- * The order in which items are added to a sequence coincides with the order
- * they are emitted into the output stream.
- *
- * Arguments:
- *
- * - `document`: a document object.
- *
- * - `sequence_id`: the id of a sequence node; could be negative. It is a
- * fatal error if `sequence_id` does not refer to an existing sequence node.
- *
- * - `item_id`: the id of an item node; could be negative. It is a fatal error
- * if `item_id` does not refer to an existing node. Note that it is possible
- * for `item_id` to coincide with `sequence_id`, which means that the
- * sequence recursively contains itself.
- *
- * Returns: `1` on success, `0` on error. The function may fail if it cannot
- * allocate memory for internal buffers.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_sequence_item(yaml_document_t *document,
- int sequence_id, int item_id);
-
-/*
- * Add a pair of a key and a value to a MAPPING node.
- *
- * The order in which (key, value) pairs are added to a mapping coincides with
- * the order in which they are presented in the output stream. Note that the
- * mapping key order is a presentation detail and should not used to convey any
- * information. An ordered mapping could be represented as a sequence of
- * single-paired mappings.
- *
- * Arguments:
- *
- * - `document`: a document object.
- *
- * - `mapping_id`: the id of a mapping node; could be negative. It is a
- * fatal error if `mapping_id` does not refer to an existing mapping node.
- *
- * - `key_id`: the id of a key node; could be negative. It is a fatal error
- * if `key_id` does not refer to an existing node.
- *
- * - `value_id`: the id of a value node; could be negative. It is a fatal
- * error if `value_id` does not refer to an existing node.
- *
- * Returns: `1` on success, `0` on error. The function may fail if it cannot
- * allocate memory for internal buffers.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_mapping_pair(yaml_document_t *document,
- int mapping_id, int key_id, int value_id);
-
-/******************************************************************************
+/*****************************************************************************
* Callback Definitions
- ******************************************************************************/
+ *****************************************************************************/
/*
* The prototype of a read handler.
@@ -2305,11 +2333,11 @@ typedef int yaml_writer_t(void *data, const unsigned char *buffer,
*/
typedef int yaml_resolver_t(void *data, yaml_incomplete_node_t *node,
- yaml_char_t **tag);
+ const yaml_char_t **tag);
-/******************************************************************************
+/*****************************************************************************
* Parser Definitions
- ******************************************************************************/
+ *****************************************************************************/
/*
* An opaque definition of the parser object.
@@ -2359,7 +2387,7 @@ yaml_parser_delete(yaml_parser_t *parser);
*/
YAML_DECLARE(void)
-yaml_parser_clear(yaml_parser_t *parser);
+yaml_parser_reset(yaml_parser_t *parser);
/*
* Get the parser error.
@@ -2617,9 +2645,9 @@ YAML_DECLARE(int)
yaml_parser_parse_single_document(yaml_parser_t *parser,
yaml_document_t *document);
-/******************************************************************************
+/*****************************************************************************
* Emitter Definitions
- ******************************************************************************/
+ *****************************************************************************/
/*
* An opaque definition of the emitter object.
@@ -2669,7 +2697,7 @@ yaml_emitter_delete(yaml_emitter_t *emitter);
*/
YAML_DECLARE(void)
-yaml_emitter_clear(yaml_emitter_t *emitter);
+yaml_emitter_reset(yaml_emitter_t *emitter);
/*
* Get the emitter error.
diff --git a/src/api.c b/src/api.c
index ccc9474..86fc4b4 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1,8 +1,20 @@
+/*****************************************************************************
+ * LibYAML API Implementation
+ *
+ * Copyright (c) 2006 Kirill Simonov
+ *
+ * LibYAML is free software; you can use, modify and/or redistribute it under
+ * the terms of the MIT license; see the file LICENCE for more details.
+ *****************************************************************************/
#include "yaml_private.h"
+/*****************************************************************************
+ * Version Information
+ *****************************************************************************/
+
/*
- * Get the library version.
+ * Get the library version as a static string.
*/
YAML_DECLARE(const char *)
@@ -23,6 +35,10 @@ yaml_get_version(int *major, int *minor, int *patch)
*patch = YAML_VERSION_PATCH;
}
+/*****************************************************************************
+ * Memory Management
+ *****************************************************************************/
+
/*
* Allocate a dynamic memory block.
*/
@@ -66,6 +82,10 @@ yaml_strdup(const yaml_char_t *str)
return (yaml_char_t *)strdup((char *)str);
}
+/*****************************************************************************
+ * Error Handling
+ *****************************************************************************/
+
/*
* Format an error message.
*/
@@ -170,6 +190,9 @@ yaml_error_message(yaml_error_t *error, char *buffer, size_t capacity)
return (length >= 0 && length < capacity);
}
+/*****************************************************************************
+ * String, Stack and Queue Management
+ *****************************************************************************/
/*
* Extend a string.
@@ -263,428 +286,9 @@ yaml_queue_extend(void **list, size_t size,
return 1;
}
-
-/*
- * Create a new parser object.
- */
-
-YAML_DECLARE(yaml_parser_t *)
-yaml_parser_new(void)
-{
- yaml_parser_t *parser = yaml_malloc(sizeof(yaml_parser_t));
-
- if (!parser)
- return NULL;
-
- memset(parser, 0, sizeof(yaml_parser_t));
- if (!IOSTRING_INIT(parser, parser->raw_input, RAW_INPUT_BUFFER_CAPACITY))
- goto error;
- if (!IOSTRING_INIT(parser, parser->input, INPUT_BUFFER_CAPACITY))
- goto error;
- if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_CAPACITY))
- goto error;
- if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_CAPACITY))
- goto error;
- if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_CAPACITY))
- goto error;
- if (!STACK_INIT(parser, parser->states, INITIAL_STACK_CAPACITY))
- goto error;
- if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_CAPACITY))
- goto error;
- if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_CAPACITY))
- goto error;
-
- return parser;
-
-error:
- yaml_parser_delete(parser);
-
- return NULL;
-}
-
-/*
- * Destroy a parser object.
- */
-
-YAML_DECLARE(void)
-yaml_parser_delete(yaml_parser_t *parser)
-{
- assert(parser); /* Non-NULL parser object expected. */
-
- IOSTRING_DEL(parser, parser->raw_input);
- IOSTRING_DEL(parser, parser->input);
- while (!QUEUE_EMPTY(parser, parser->tokens)) {
- yaml_token_destroy(&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);
-}
-
-/*
- * Get the current parser error.
- */
-
-YAML_DECLARE(void)
-yaml_parser_get_error(yaml_parser_t *parser, yaml_error_t *error)
-{
- assert(parser); /* Non-NULL parser object expected. */
-
- *error = parser->error;
-}
-
-/*
- * Standard string read handler.
- */
-
-static int
-yaml_string_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
- size_t *length)
-{
- yaml_standard_reader_data_t *data = untyped_data;
-
- if (data->string.pointer == data->string.length) {
- *length = 0;
- return 1;
- }
-
- if (capacity > (size_t)(data->string.length - data->string.pointer)) {
- capacity = data->string.length - data->string.pointer;
- }
-
- memcpy(buffer, data->string.buffer + data->string.pointer, capacity);
- data->string.pointer += capacity;
- *length = capacity;
- return 1;
-}
-
-/*
- * Standard file read handler.
- */
-
-static int
-yaml_file_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
- size_t *length)
-{
- yaml_standard_reader_data_t *data = untyped_data;
-
- *length = fread(buffer, 1, capacity, data->file);
- return !ferror(data->file);
-}
-
-/*
- * Set a string input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_string_reader(yaml_parser_t *parser,
- const unsigned char *buffer, size_t length)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the input handler only once. */
- assert(buffer); /* Non-NULL input string expected. */
-
- parser->reader = yaml_string_reader;
- parser->reader_data = &(parser->standard_reader_data);
-
- parser->standard_reader_data.string.buffer = buffer;
- parser->standard_reader_data.string.pointer = 0;
- parser->standard_reader_data.string.length = length;
-}
-
-/*
- * Set a file input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_file_reader(yaml_parser_t *parser, FILE *file)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the input handler only once. */
- assert(file); /* Non-NULL file object expected. */
-
- parser->reader = yaml_file_reader;
- parser->reader_data = &(parser->standard_reader_data);
-
- parser->standard_reader_data.file = file;
-}
-
-/*
- * Set a generic input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_reader(yaml_parser_t *parser,
- yaml_reader_t *reader, void *data)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->reader); /* You can set the input handler only once. */
- assert(reader); /* Non-NULL read handler expected. */
-
- parser->reader = reader;
- parser->reader_data = data;
-}
-
-/*
- * Set the source encoding.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->encoding); /* Encoding is already set or detected. */
-
- parser->encoding = encoding;
-}
-
-/*
- * Create a new emitter object.
- */
-
-YAML_DECLARE(yaml_emitter_t *)
-yaml_emitter_new(void)
-{
- yaml_emitter_t *emitter = yaml_malloc(sizeof(yaml_emitter_t));
-
- if (!emitter)
- return NULL;
-
- memset(emitter, 0, sizeof(yaml_emitter_t));
- if (!IOSTRING_INIT(emitter, emitter->output, OUTPUT_BUFFER_CAPACITY))
- goto error;
- if (!IOSTRING_INIT(emitter, emitter->raw_output, RAW_OUTPUT_BUFFER_CAPACITY))
- goto error;
- if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_CAPACITY))
- goto error;
- if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_CAPACITY))
- goto error;
- if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_CAPACITY))
- goto error;
- if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_CAPACITY))
- goto error;
-
- return emitter;
-
-error:
- yaml_emitter_delete(emitter);
-
- return NULL;
-}
-
-/*
- * Destroy an emitter object.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_delete(yaml_emitter_t *emitter)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- IOSTRING_DEL(emitter, emitter->output);
- IOSTRING_DEL(emitter, emitter->raw_output);
- STACK_DEL(emitter, emitter->states);
- while (!QUEUE_EMPTY(emitter, emitter->events)) {
- yaml_event_destroy(&DEQUEUE(emitter, emitter->events));
- }
- QUEUE_DEL(emitter, emitter->events);
- STACK_DEL(emitter, emitter->indents);
- while (!STACK_EMPTY(empty, emitter->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
- STACK_DEL(emitter, emitter->tag_directives);
- yaml_free(emitter->anchors);
-
- memset(emitter, 0, sizeof(yaml_emitter_t));
- yaml_free(emitter);
-}
-
-/*
- * Get the current emitter error.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_get_error(yaml_emitter_t *emitter, yaml_error_t *error)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- *error = emitter->error;
-}
-
-/*
- * String write handler.
- */
-
-static int
-yaml_string_writer(void *untyped_data, const unsigned char *buffer, size_t length)
-{
- yaml_standard_writer_data_t *data = untyped_data;
- int result = 1;
-
- if (data->string.capacity - data->string.pointer < length) {
- length = data->string.capacity - data->string.pointer;
- result = 0;
- }
-
- memcpy(data->string.buffer + data->string.pointer, buffer, length);
- data->string.pointer += length;
- *data->length += length;
-
- return result;
-}
-
-/*
- * File write handler.
- */
-
-static int
-yaml_file_writer(void *untyped_data, const unsigned char *buffer, size_t length)
-{
- yaml_standard_writer_data_t *data = untyped_data;
-
- return (fwrite(buffer, 1, length, data->file) == length);
-}
-/*
- * Set a string output.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_string_writer(yaml_emitter_t *emitter,
- unsigned char *buffer, size_t capacity, size_t *length)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->writer); /* You can set the output only once. */
- assert(buffer); /* Non-NULL output string expected. */
-
- emitter->writer = yaml_string_writer;
- emitter->writer_data = &(emitter->standard_writer_data);
-
- emitter->standard_writer_data.string.buffer = buffer;
- emitter->standard_writer_data.string.pointer = 0;
- emitter->standard_writer_data.string.capacity = capacity;
- emitter->standard_writer_data.length = length;
-
- *length = 0;
-}
-
-/*
- * Set a file output.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_file_writer(yaml_emitter_t *emitter, FILE *file)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->writer); /* You can set the output only once. */
- assert(file); /* Non-NULL file object expected. */
-
- emitter->writer = yaml_string_writer;
- emitter->writer_data = &(emitter->standard_writer_data);
-
- emitter->standard_writer_data.file = file;
-}
-
-/*
- * Set a generic output handler.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_writer(yaml_emitter_t *emitter,
- yaml_writer_t *writer, void *data)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->writer); /* You can set the output only once. */
- assert(writer); /* Non-NULL handler object expected. */
-
- emitter->writer = writer;
- emitter->writer_data = data;
-}
-
-/*
- * Set the output encoding.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->encoding); /* You can set encoding only once. */
-
- emitter->encoding = encoding;
-}
-
-/*
- * Set the canonical output style.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_canonical(yaml_emitter_t *emitter, int is_canonical)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->is_canonical = (is_canonical != 0);
-}
-
-/*
- * Set the indentation increment.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
-}
-
-/*
- * Set the preferred line width.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->best_width = (width >= 0) ? width : -1;
-}
-
-/*
- * Set if unescaped non-ASCII characters are allowed.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_unicode(yaml_emitter_t *emitter, int is_unicode)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->is_unicode = (is_unicode != 0);
-}
-
-/*
- * Set the preferred line break character.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->line_break = line_break;
-}
+/*****************************************************************************
+ * Token API
+ *****************************************************************************/
/*
* Allocate a token object.
@@ -712,7 +316,7 @@ yaml_token_delete(yaml_token_t *token)
{
assert(token); /* Non-NULL token object expected. */
- yaml_token_destroy(token);
+ yaml_token_clear(token);
yaml_free(token);
}
@@ -725,10 +329,13 @@ yaml_token_duplicate(yaml_token_t *token, const yaml_token_t *model)
{
assert(token); /* Non-NULL token object is expected. */
assert(model); /* Non-NULL model token object is expected. */
+ assert(!token->type); /* The token must be empty. */
memset(token, 0, sizeof(yaml_token_t));
token->type = model->type;
+ token->start_mark = model->start_mark;
+ token->end_mark = model->end_mark;
switch (token->type)
{
@@ -789,17 +396,17 @@ yaml_token_duplicate(yaml_token_t *token, const yaml_token_t *model)
return 1;
error:
- yaml_token_destroy(token);
+ yaml_token_clear(token);
return 0;
}
/*
- * Destroy a token object.
+ * Clear a token object.
*/
YAML_DECLARE(void)
-yaml_token_destroy(yaml_token_t *token)
+yaml_token_clear(yaml_token_t *token)
{
assert(token); /* Non-NULL token object expected. */
@@ -834,49 +441,9 @@ yaml_token_destroy(yaml_token_t *token)
memset(token, 0, sizeof(yaml_token_t));
}
-/*
- * Check if a string is a valid UTF-8 sequence.
- *
- * Check 'reader.c' for more details on UTF-8 encoding.
- */
-
-static int
-yaml_valid_utf8(const yaml_char_t *buffer, size_t length)
-{
- size_t pointer = 0;
-
- while (pointer < length) {
- unsigned char octet;
- unsigned int width;
- unsigned int value;
- size_t k;
-
- octet = buffer[pointer];
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
- if (!width) return 0;
- if (pointer+width > length) return 0;
- for (k = 1; k < width; k ++) {
- octet = buffer[pointer+k];
- if ((octet & 0xC0) != 0x80) return 0;
- value = (value << 6) + (octet & 0x3F);
- }
- if (!((width == 1) ||
- (width == 2 && value >= 0x80) ||
- (width == 3 && value >= 0x800) ||
- (width == 4 && value >= 0x10000))) return 0;
-
- pointer += width;
- }
-
- return 1;
-}
+/*****************************************************************************
+ * Event API
+ *****************************************************************************/
/*
* Allocate an event object.
@@ -904,7 +471,7 @@ yaml_event_delete(yaml_event_t *event)
{
assert(event); /* Non-NULL event object expected. */
- yaml_event_destroy(event);
+ yaml_event_clear(event);
yaml_free(event);
}
@@ -921,10 +488,13 @@ yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
assert(event); /* Non-NULL event object is expected. */
assert(model); /* Non-NULL model event object is expected. */
+ assert(!event->type); /* The event must be empty. */
memset(event, 0, sizeof(yaml_event_t));
event->type = model->type;
+ event->start_mark = model->start_mark;
+ event->end_mark = model->end_mark;
switch (event->type)
{
@@ -988,10 +558,10 @@ yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
memcpy(event->data.scalar.value, model->data.scalar.value,
model->data.scalar.length+1);
event->data.scalar.length = model->data.scalar.length;
- event->data.scalar.is_plain_implicit =
- model->data.scalar.is_plain_implicit;
- event->data.scalar.is_quoted_implicit =
- model->data.scalar.is_quoted_implicit;
+ event->data.scalar.is_plain_nonspecific =
+ model->data.scalar.is_plain_nonspecific;
+ event->data.scalar.is_quoted_nonspecific =
+ model->data.scalar.is_quoted_nonspecific;
event->data.scalar.style = model->data.scalar.style;
break;
@@ -1004,8 +574,8 @@ yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
!(event->data.sequence_start.tag =
yaml_strdup(model->data.sequence_start.tag)))
goto error;
- event->data.sequence_start.is_implicit =
- model->data.sequence_start.is_implicit;
+ event->data.sequence_start.is_nonspecific =
+ model->data.sequence_start.is_nonspecific;
event->data.sequence_start.style =
model->data.sequence_start.style;
break;
@@ -1019,8 +589,8 @@ yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
!(event->data.mapping_start.tag =
yaml_strdup(model->data.mapping_start.tag)))
goto error;
- event->data.mapping_start.is_implicit =
- model->data.mapping_start.is_implicit;
+ event->data.mapping_start.is_nonspecific =
+ model->data.mapping_start.is_nonspecific;
event->data.mapping_start.style =
model->data.mapping_start.style;
break;
@@ -1032,12 +602,65 @@ yaml_event_duplicate(yaml_event_t *event, const yaml_event_t *model)
return 1;
error:
- yaml_event_destroy(event);
+ yaml_event_clear(event);
return 0;
}
/*
+ * Clear an event object.
+ */
+
+YAML_DECLARE(void)
+yaml_event_clear(yaml_event_t *event)
+{
+ struct {
+ yaml_error_t error;
+ } self;
+
+ assert(event); /* Non-NULL event object expected. */
+
+ switch (event->type)
+ {
+ case YAML_DOCUMENT_START_EVENT:
+ yaml_free(event->data.document_start.version_directive);
+ while (!STACK_EMPTY(&self, event->data.document_start.tag_directives)) {
+ yaml_tag_directive_t value = POP(&self,
+ event->data.document_start.tag_directives);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+ }
+ STACK_DEL(&self, event->data.document_start.tag_directives);
+ 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;
+
+ default:
+ break;
+ }
+
+ memset(event, 0, sizeof(yaml_event_t));
+}
+
+/*
* Create STREAM-START.
*/
@@ -1048,6 +671,7 @@ yaml_event_create_stream_start(yaml_event_t *event,
yaml_mark_t mark = { 0, 0, 0 };
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
@@ -1064,6 +688,7 @@ yaml_event_create_stream_end(yaml_event_t *event)
yaml_mark_t mark = { 0, 0, 0 };
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
STREAM_END_EVENT_INIT(*event, mark, mark);
@@ -1077,8 +702,8 @@ yaml_event_create_stream_end(yaml_event_t *event)
YAML_DECLARE(int)
yaml_event_create_document_start(yaml_event_t *event,
const yaml_version_directive_t *version_directive,
- const yaml_tag_directive_t *tag_directives,
- int is_implicit)
+ const yaml_tag_directive_t *tag_directives_list,
+ size_t tag_directives_length, int is_implicit)
{
struct {
yaml_error_t error;
@@ -1090,8 +715,10 @@ yaml_event_create_document_start(yaml_event_t *event,
size_t length;
size_t capacity;
} tag_directives_copy = { NULL, 0, 0 };
+ int idx;
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
if (version_directive) {
version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
@@ -1099,22 +726,16 @@ yaml_event_create_document_start(yaml_event_t *event,
*version_directive_copy = *version_directive;
}
- if (tag_directives && (tag_directives->handle || tag_directives->prefix)) {
- if (!STACK_INIT(&self, tag_directives_copy, INITIAL_STACK_CAPACITY))
+ if (tag_directives_list && tag_directives_length) {
+ if (!STACK_INIT(&self, tag_directives_copy, tag_directives_length))
goto error;
- while (tag_directives->handle || tag_directives->prefix) {
- yaml_tag_directive_t value = *tag_directives;
+ for (idx = 0; idx < tag_directives_length; idx++) {
+ yaml_tag_directive_t value = tag_directives_list[idx];
assert(value.handle);
assert(value.prefix);
- if (!yaml_valid_utf8(value.handle, strlen((char *)value.handle)))
- goto error;
- if (!yaml_valid_utf8(value.prefix, strlen((char *)value.prefix)))
- goto error;
- if (!PUSH(&self, tag_directives_copy, value))
- goto error;
value.handle = yaml_strdup(value.handle);
value.prefix = yaml_strdup(value.prefix);
- tag_directives_copy.list[tag_directives_copy.length-1] = value;
+ PUSH(&self, tag_directives_copy, value);
if (!value.handle || !value.prefix)
goto error;
}
@@ -1148,6 +769,7 @@ yaml_event_create_document_end(yaml_event_t *event, int is_implicit)
yaml_mark_t mark = { 0, 0, 0 };
assert(event); /* Non-NULL emitter object is expected. */
+ assert(!event->type); /* The event must be empty. */
DOCUMENT_END_EVENT_INIT(*event, is_implicit, mark, mark);
@@ -1165,10 +787,9 @@ yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor)
yaml_char_t *anchor_copy = NULL;
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
assert(anchor); /* Non-NULL anchor is expected. */
- if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) return 0;
-
anchor_copy = yaml_strdup(anchor);
if (!anchor_copy)
return 0;
@@ -1185,8 +806,8 @@ yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor)
YAML_DECLARE(int)
yaml_event_create_scalar(yaml_event_t *event,
const yaml_char_t *anchor, const yaml_char_t *tag,
- const yaml_char_t *value, size_t length,
- int is_plain_implicit, int is_quoted_implicit,
+ const yaml_char_t *value, int length,
+ int is_plain_nonspecific, int is_quoted_nonspecific,
yaml_scalar_style_t style)
{
yaml_mark_t mark = { 0, 0, 0 };
@@ -1195,19 +816,16 @@ yaml_event_create_scalar(yaml_event_t *event,
yaml_char_t *value_copy = NULL;
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
assert(value); /* Non-NULL anchor is expected. */
if (anchor) {
- if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
- goto error;
anchor_copy = yaml_strdup(anchor);
if (!anchor_copy)
goto error;
}
if (tag) {
- if (!yaml_valid_utf8(tag, strlen((char *)tag)))
- goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy)
goto error;
@@ -1217,8 +835,6 @@ yaml_event_create_scalar(yaml_event_t *event,
length = strlen((char *)value);
}
- if (!yaml_valid_utf8(value, length))
- goto error;
value_copy = yaml_malloc(length+1);
if (!value_copy)
goto error;
@@ -1226,7 +842,7 @@ yaml_event_create_scalar(yaml_event_t *event,
value_copy[length] = '\0';
SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
- is_plain_implicit, is_quoted_implicit, style, mark, mark);
+ is_plain_nonspecific, is_quoted_nonspecific, style, mark, mark);
return 1;
@@ -1245,32 +861,29 @@ error:
YAML_DECLARE(int)
yaml_event_create_sequence_start(yaml_event_t *event,
const yaml_char_t *anchor, const yaml_char_t *tag,
- int is_implicit, yaml_sequence_style_t style)
+ int is_nonspecific, yaml_sequence_style_t style)
{
yaml_mark_t mark = { 0, 0, 0 };
yaml_char_t *anchor_copy = NULL;
yaml_char_t *tag_copy = NULL;
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
if (anchor) {
- if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
- goto error;
anchor_copy = yaml_strdup(anchor);
if (!anchor_copy)
goto error;
}
if (tag) {
- if (!yaml_valid_utf8(tag, strlen((char *)tag)))
- goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy)
goto error;
}
SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
- is_implicit, style, mark, mark);
+ is_nonspecific, style, mark, mark);
return 1;
@@ -1291,6 +904,7 @@ yaml_event_create_sequence_end(yaml_event_t *event)
yaml_mark_t mark = { 0, 0, 0 };
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
SEQUENCE_END_EVENT_INIT(*event, mark, mark);
@@ -1304,32 +918,29 @@ yaml_event_create_sequence_end(yaml_event_t *event)
YAML_DECLARE(int)
yaml_event_create_mapping_start(yaml_event_t *event,
const yaml_char_t *anchor, const yaml_char_t *tag,
- int is_implicit, yaml_mapping_style_t style)
+ int is_nonspecific, yaml_mapping_style_t style)
{
yaml_mark_t mark = { 0, 0, 0 };
yaml_char_t *anchor_copy = NULL;
yaml_char_t *tag_copy = NULL;
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
if (anchor) {
- if (!yaml_valid_utf8(anchor, strlen((char *)anchor)))
- goto error;
anchor_copy = yaml_strdup(anchor);
if (!anchor_copy)
goto error;
}
if (tag) {
- if (!yaml_valid_utf8(tag, strlen((char *)tag)))
- goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy)
goto error;
}
MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
- is_implicit, style, mark, mark);
+ is_nonspecific, style, mark, mark);
return 1;
@@ -1350,170 +961,176 @@ yaml_event_create_mapping_end(yaml_event_t *event)
yaml_mark_t mark = { 0, 0, 0 };
assert(event); /* Non-NULL event object is expected. */
+ assert(!event->type); /* The event must be empty. */
MAPPING_END_EVENT_INIT(*event, mark, mark);
return 1;
}
+/*****************************************************************************
+ * Document API
+ *****************************************************************************/
+
/*
- * Destroy an event object.
+ * Allocate a document object.
*/
-YAML_DECLARE(void)
-yaml_event_destroy(yaml_event_t *event)
+YAML_DECLARE(yaml_document_t *)
+yaml_document_new(void)
{
- struct {
- yaml_error_t error;
- } self;
+ yaml_document_t *document = yaml_malloc(sizeof(yaml_document_t));
- assert(event); /* Non-NULL event object expected. */
-
- switch (event->type)
- {
- case YAML_DOCUMENT_START_EVENT:
- yaml_free(event->data.document_start.version_directive);
- while (!STACK_EMPTY(&self, event->data.document_start.tag_directives)) {
- yaml_tag_directive_t value = POP(&self,
- event->data.document_start.tag_directives);
- yaml_free(value.handle);
- yaml_free(value.prefix);
- }
- STACK_DEL(&self, event->data.document_start.tag_directives);
- break;
-
- case YAML_ALIAS_EVENT:
- yaml_free(event->data.alias.anchor);
- break;
+ if (!document)
+ return NULL;
- case YAML_SCALAR_EVENT:
- yaml_free(event->data.scalar.anchor);
- yaml_free(event->data.scalar.tag);
- yaml_free(event->data.scalar.value);
- break;
+ memset(document, 0, sizeof(yaml_document_t));
- case YAML_SEQUENCE_START_EVENT:
- yaml_free(event->data.sequence_start.anchor);
- yaml_free(event->data.sequence_start.tag);
- break;
+ return document;
+}
- case YAML_MAPPING_START_EVENT:
- yaml_free(event->data.mapping_start.anchor);
- yaml_free(event->data.mapping_start.tag);
- break;
+/*
+ * Deallocate a document object.
+ */
- default:
- break;
- }
+YAML_DECLARE(void)
+yaml_document_delete(yaml_document_t *document)
+{
+ assert(document); /* Non-NULL document object is expected. */
- memset(event, 0, sizeof(yaml_event_t));
+ yaml_document_clear(document);
+ yaml_free(document);
}
-#if 0
-
/*
- * Create a document object.
+ * Duplicate a document object.
*/
YAML_DECLARE(int)
-yaml_document_initialize(yaml_document_t *document,
- yaml_version_directive_t *version_directive,
- yaml_tag_directive_t *tag_directives_start,
- yaml_tag_directive_t *tag_directives_end,
- int start_implicit, int end_implicit)
+yaml_document_duplicate(yaml_document_t *document, yaml_document_t *model)
{
struct {
- yaml_error_type_t error;
- } context;
- struct {
- yaml_node_t *start;
- yaml_node_t *end;
- yaml_node_t *top;
- } nodes = { NULL, NULL, NULL };
- yaml_version_directive_t *version_directive_copy = NULL;
- struct {
- yaml_tag_directive_t *start;
- yaml_tag_directive_t *end;
- yaml_tag_directive_t *top;
- } tag_directives_copy = { NULL, NULL, NULL };
- yaml_tag_directive_t value = { NULL, NULL };
- yaml_mark_t mark = { 0, 0, 0 };
+ yaml_error_t error;
+ } self;
+ yaml_char_t *anchor = NULL;
+ yaml_char_t *tag = NULL;
+ yaml_char_t *value = NULL;
+ yaml_node_item_t *item_list = NULL;
+ yaml_node_pair_t *pair_list = NULL;
+ int idx;
- assert(document); /* Non-NULL document object is expected. */
- assert((tag_directives_start && tag_directives_end) ||
- (tag_directives_start == tag_directives_end));
- /* Valid tag directives are expected. */
+ assert(document); /* Non-NULL document object is expected. */
+ assert(!document->type); /* The document must be empty. */
+ assert(model); /* Non-NULL model object is expected. */
- if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
+ if (model->type != YAML_DOCUMENT)
+ return 1;
- if (version_directive) {
- version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
- if (!version_directive_copy) goto error;
- version_directive_copy->major = version_directive->major;
- version_directive_copy->minor = version_directive->minor;
- }
+ if (!yaml_document_create(document, model->version_directive,
+ model->tag_directives.list, model->tag_directives.length,
+ model->is_start_implicit, model->is_end_implicit))
+ return 0;
- if (tag_directives_start != tag_directives_end) {
- yaml_tag_directive_t *tag_directive;
- if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
- goto error;
- for (tag_directive = tag_directives_start;
- tag_directive != tag_directives_end; tag_directive ++) {
- assert(tag_directive->handle);
- assert(tag_directive->prefix);
- if (!yaml_valid_utf8(tag_directive->handle,
- strlen((char *)tag_directive->handle)))
- goto error;
- if (!yaml_valid_utf8(tag_directive->prefix,
- strlen((char *)tag_directive->prefix)))
- goto error;
- value.handle = yaml_strdup(tag_directive->handle);
- value.prefix = yaml_strdup(tag_directive->prefix);
- if (!value.handle || !value.prefix) goto error;
- if (!PUSH(&context, tag_directives_copy, value))
- goto error;
- value.handle = NULL;
- value.prefix = NULL;
+ document->start_mark = model->start_mark;
+ document->end_mark = model->end_mark;
+
+ for (idx = 0; idx < model->nodes.length; idx++)
+ {
+ yaml_node_t *node = STACK_ITER(&self, model->nodes, idx);
+ yaml_node_t copy;
+ if (node->anchor) {
+ anchor = yaml_strdup(node->anchor);
+ if (!anchor) goto error;
}
- }
+ tag = yaml_strdup(node->tag);
+ if (!tag) goto error;
+ switch (node->type)
+ {
+ case YAML_SCALAR_NODE:
+ value = yaml_malloc(node->data.scalar.length+1);
+ if (!value)
+ goto error;
+ memcpy(value, node->data.scalar.value,
+ node->data.scalar.length);
+ value[node->data.scalar.length] = '\0';
+ SCALAR_NODE_INIT(copy, anchor, tag, value,
+ node->data.scalar.length, node->data.scalar.style,
+ node->start_mark, node->end_mark);
+ break;
- DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
- tag_directives_copy.start, tag_directives_copy.top,
- start_implicit, end_implicit, mark, mark);
+ case YAML_SEQUENCE_NODE:
+ item_list = yaml_malloc(node->data.sequence.items.capacity
+ * sizeof(yaml_node_item_t));
+ if (!item_list) goto error;
+ memcpy(item_list, node->data.sequence.items.list,
+ node->data.sequence.items.capacity
+ * sizeof(yaml_node_item_t));
+ SEQUENCE_NODE_INIT(copy, anchor, tag, item_list,
+ node->data.sequence.items.length,
+ node->data.sequence.items.capacity,
+ node->data.sequence.style,
+ node->start_mark, node->end_mark);
+ break;
- return 1;
+ case YAML_MAPPING_NODE:
+ pair_list = yaml_malloc(node->data.mapping.pairs.capacity
+ * sizeof(yaml_node_pair_t));
+ if (!pair_list) goto error;
+ memcpy(pair_list, node->data.mapping.pairs.list,
+ node->data.mapping.pairs.capacity
+ * sizeof(yaml_node_pair_t));
+ MAPPING_NODE_INIT(copy, anchor, tag, pair_list,
+ node->data.mapping.pairs.length,
+ node->data.mapping.pairs.capacity,
+ node->data.mapping.style,
+ node->start_mark, node->end_mark);
+ break;
-error:
- STACK_DEL(&context, nodes);
- yaml_free(version_directive_copy);
- while (!STACK_EMPTY(&context, tag_directives_copy)) {
- yaml_tag_directive_t value = POP(&context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
+ default:
+ assert(0); /* Should never happen. */
+ }
+
+ if (!PUSH(&self, document->nodes, copy))
+ goto error;
+
+ anchor = NULL;
+ tag = NULL;
+ value = NULL;
+ item_list = NULL;
+ pair_list = NULL;
}
- STACK_DEL(&context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
+
+error:
+ yaml_free(anchor);
+ yaml_free(tag);
+ yaml_free(value);
+ yaml_free(item_list);
+ yaml_free(pair_list);
+
+ yaml_document_clear(document);
return 0;
}
/*
- * Destroy a document object.
+ * Clear a document object.
*/
YAML_DECLARE(void)
-yaml_document_delete(yaml_document_t *document)
+yaml_document_clear(yaml_document_t *document)
{
struct {
yaml_error_type_t error;
- } context;
+ } self;
yaml_tag_directive_t *tag_directive;
- context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */
+ self.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */
assert(document); /* Non-NULL document object is expected. */
+ if (!document->type)
+ return;
+
while (!STACK_EMPTY(&context, document->nodes)) {
yaml_node_t node = POP(&context, document->nodes);
yaml_free(node.tag);
@@ -1531,46 +1148,112 @@ yaml_document_delete(yaml_document_t *document)
assert(0); /* Should not happen. */
}
}
- STACK_DEL(&context, document->nodes);
+ STACK_DEL(&self, document->nodes);
yaml_free(document->version_directive);
- for (tag_directive = document->tag_directives.start;
- tag_directive != document->tag_directives.end;
- tag_directive++) {
- yaml_free(tag_directive->handle);
- yaml_free(tag_directive->prefix);
+ while (!STACK_EMPTY(&self, document->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(&self, document->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
}
- yaml_free(document->tag_directives.start);
+ STACK_DEL(&self, document->tag_directives);
memset(document, 0, sizeof(yaml_document_t));
}
-/**
- * Get a document node.
+/*
+ * Create a document.
*/
-YAML_DECLARE(yaml_node_t *)
-yaml_document_get_node(yaml_document_t *document, int index)
+YAML_DECLARE(int)
+yaml_document_create(yaml_document_t *document,
+ const yaml_version_directive_t *version_directive,
+ const yaml_tag_directive_t *tag_directives_list,
+ size_t tag_directives_length,
+ int is_start_implicit, int is_end_implicit)
{
- assert(document); /* Non-NULL document object is expected. */
+ struct {
+ yaml_error_t error;
+ } self;
+ yaml_mark_t mark = { 0, 0, 0 };
+ struct {
+ yaml_node_t *list;
+ size_t length;
+ size_t capacity;
+ } nodes;
+ yaml_version_directive_t *version_directive_copy = NULL;
+ struct {
+ yaml_tag_directive_t *list;
+ size_t length;
+ size_t capacity;
+ } tag_directives_copy = { NULL, 0, 0 };
+ int idx;
- if (index > 0 && document->nodes.start + index <= document->nodes.top) {
- return document->nodes.start + index - 1;
+ assert(document); /* Non-NULL event object is expected. */
+ assert(!document->type); /* The document must be empty. */
+
+ if (!STACK_INIT(&self, nodes, INITIAL_STACK_CAPACITY))
+ goto error;
+
+ if (version_directive) {
+ version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
+ if (!version_directive_copy) goto error;
+ *version_directive_copy = *version_directive;
}
- return NULL;
+
+ if (tag_directives_list && tag_directives_length) {
+ if (!STACK_INIT(&self, tag_directives_copy, tag_directives_length))
+ goto error;
+ for (idx = 0; idx < tag_directives_length; idx++) {
+ yaml_tag_directive_t value = tag_directives_list[idx];
+ assert(value.handle);
+ assert(value.prefix);
+ value.handle = yaml_strdup(value.handle);
+ value.prefix = yaml_strdup(value.prefix);
+ PUSH(&self, tag_directives_copy, value);
+ if (!value.handle || !value.prefix)
+ goto error;
+ }
+ }
+
+ DOCUMENT_INIT(*document, nodes.list, nodes.length, nodes.capacity,
+ version_directive_copy, tag_directives_copy.list,
+ tag_directives_copy.length, tag_directives_copy.capacity,
+ is_start_implicit, is_end_implicit, mark, mark);
+
+ return 1;
+
+error:
+ STACK_DEL(&self, nodes);
+
+ yaml_free(version_directive_copy);
+
+ while (!STACK_EMPTY(&self, tag_directives_copy)) {
+ yaml_tag_directive_t value = POP(&self, tag_directives_copy);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+ }
+ STACK_DEL(&self, tag_directives_copy);
+
+ return 0;
}
-/**
- * Get the root object.
+/*
+ * Get a document node.
*/
YAML_DECLARE(yaml_node_t *)
-yaml_document_get_root_node(yaml_document_t *document)
+yaml_document_get_node(yaml_document_t *document, int node_id)
{
assert(document); /* Non-NULL document object is expected. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
- if (document->nodes.top != document->nodes.start) {
- return document->nodes.start;
+ if (node_id >= 0 && node_id < document->nodes.length) {
+ return document->nodes.list + node_id;
}
return NULL;
}
@@ -1580,26 +1263,30 @@ yaml_document_get_root_node(yaml_document_t *document)
*/
YAML_DECLARE(int)
-yaml_document_add_scalar(yaml_document_t *document,
- yaml_char_t *tag, yaml_char_t *value, int length,
+yaml_document_add_scalar(yaml_document_t *document, int *node_id,
+ const yaml_char_t *anchor, const yaml_char_t *tag,
+ const yaml_char_t *value, int length,
yaml_scalar_style_t style)
{
struct {
- yaml_error_type_t error;
- } context;
+ yaml_error_t error;
+ } self;
yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
yaml_char_t *tag_copy = NULL;
yaml_char_t *value_copy = NULL;
yaml_node_t node;
assert(document); /* Non-NULL document object is expected. */
+ assert(document->type); /* Initialized document is required. */
+ assert(tag); /* Non-NULL tag is expected. */
assert(value); /* Non-NULL value is expected. */
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
+ if (anchor) {
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
}
- if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy) goto error;
@@ -1607,18 +1294,23 @@ yaml_document_add_scalar(yaml_document_t *document,
length = strlen((char *)value);
}
- if (!yaml_valid_utf8(value, length)) goto error;
value_copy = yaml_malloc(length+1);
if (!value_copy) goto error;
memcpy(value_copy, value, length);
value_copy[length] = '\0';
- SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
+ SCALAR_NODE_INIT(node, anchor_copy, tag_copy, value_copy, length,
+ style, mark, mark);
+ if (!PUSH(&self, document->nodes, node)) goto error;
- return document->nodes.top - document->nodes.start;
+ if (node_id) {
+ *node_id = document->nodes.length-1;
+ }
+
+ return 1;
error:
+ yaml_free(anchor_copy);
yaml_free(tag_copy);
yaml_free(value_copy);
@@ -1630,41 +1322,50 @@ error:
*/
YAML_DECLARE(int)
-yaml_document_add_sequence(yaml_document_t *document,
- yaml_char_t *tag, yaml_sequence_style_t style)
+yaml_document_add_sequence(yaml_document_t *document, int *node_id,
+ const yaml_char_t *anchor, const yaml_char_t *tag,
+ yaml_sequence_style_t style)
{
struct {
- yaml_error_type_t error;
- } context;
+ yaml_error_t error;
+ } self;
yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
yaml_char_t *tag_copy = NULL;
struct {
- yaml_node_item_t *start;
- yaml_node_item_t *end;
- yaml_node_item_t *top;
- } items = { NULL, NULL, NULL };
+ yaml_node_item_t *list;
+ size_t length;
+ size_t capacity;
+ } items = { NULL, 0, 0 };
yaml_node_t node;
assert(document); /* Non-NULL document object is expected. */
+ assert(document->type); /* Initialized document is required. */
+ assert(tag); /* Non-NULL tag is expected. */
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
+ if (anchor) {
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
}
- if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy) goto error;
- if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
+ if (!STACK_INIT(&self, items, INITIAL_STACK_CAPACITY)) goto error;
- SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
- style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
+ SEQUENCE_NODE_INIT(node, anchor_copy, tag_copy,
+ items.list, items.length, items.capacity, style, mark, mark);
+ if (!PUSH(&self, document->nodes, node)) goto error;
- return document->nodes.top - document->nodes.start;
+ if (node_id) {
+ *node_id = document->nodes.length-1;
+ }
+
+ return 1;
error:
- STACK_DEL(&context, items);
+ STACK_DEL(&self, items);
+ yaml_free(anchor_copy);
yaml_free(tag_copy);
return 0;
@@ -1675,41 +1376,50 @@ error:
*/
YAML_DECLARE(int)
-yaml_document_add_mapping(yaml_document_t *document,
- yaml_char_t *tag, yaml_mapping_style_t style)
+yaml_document_add_mapping(yaml_document_t *document, int *node_id,
+ const yaml_char_t *anchor, const yaml_char_t *tag,
+ yaml_mapping_style_t style)
{
struct {
- yaml_error_type_t error;
- } context;
+ yaml_error_t error;
+ } self;
yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
yaml_char_t *tag_copy = NULL;
struct {
- yaml_node_pair_t *start;
- yaml_node_pair_t *end;
- yaml_node_pair_t *top;
- } pairs = { NULL, NULL, NULL };
+ yaml_node_pair_t *list;
+ size_t length;
+ size_t capacity;
+ } pairs = { NULL, 0, 0 };
yaml_node_t node;
assert(document); /* Non-NULL document object is expected. */
+ assert(document->type); /* Initialized document is required. */
+ assert(tag); /* Non-NULL tag is expected. */
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
+ if (anchor) {
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
}
- if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error;
tag_copy = yaml_strdup(tag);
if (!tag_copy) goto error;
- if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
+ if (!STACK_INIT(&self, pairs, INITIAL_STACK_CAPACITY)) goto error;
- MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
- style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
+ MAPPING_NODE_INIT(node, anchor_copy, tag_copy,
+ pairs.list, pairs.length, pairs.capacity, style, mark, mark);
+ if (!PUSH(&self, document->nodes, node)) goto error;
+
+ if (node_id) {
+ *node_id = document->nodes.length-1;
+ }
- return document->nodes.top - document->nodes.start;
+ return 1;
error:
- STACK_DEL(&context, pairs);
+ STACK_DEL(&self, pairs);
+ yaml_free(anchor_copy);
yaml_free(tag_copy);
return 0;
@@ -1721,23 +1431,31 @@ error:
YAML_DECLARE(int)
yaml_document_append_sequence_item(yaml_document_t *document,
- int sequence, int item)
+ int sequence_id, int item_id)
{
struct {
- yaml_error_type_t error;
- } context;
+ yaml_error_t error;
+ } self;
assert(document); /* Non-NULL document is required. */
- assert(sequence > 0
- && document->nodes.start + sequence <= document->nodes.top);
+ assert(document->type); /* Initialized document is expected. */
+
+ if (sequence_id) {
+ sequence_id += document->nodes.length;
+ }
+ if (item_id) {
+ item_id += document->nodes.length;
+ }
+
+ assert(sequence_id >= 0 && sequence_id < document->nodes.length);
/* Valid sequence id is required. */
- assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
- /* A sequence node is required. */
- assert(item > 0 && document->nodes.start + item <= document->nodes.top);
+ assert(item_id >= 0 && item_id < document->nodes.length);
/* Valid item id is required. */
+ assert(document->nodes.list[sequence_id].type == YAML_SEQUENCE_NODE);
+ /* A sequence node is expected. */
- if (!PUSH(&context,
- document->nodes.start[sequence-1].data.sequence.items, item))
+ if (!PUSH(&self,
+ document->nodes.list[sequence_id].data.sequence.items, item_id))
return 0;
return 1;
@@ -1749,30 +1467,1216 @@ yaml_document_append_sequence_item(yaml_document_t *document,
YAML_DECLARE(int)
yaml_document_append_mapping_pair(yaml_document_t *document,
- int mapping, int key, int value)
+ int mapping_id, int key_id, int value_id)
{
struct {
- yaml_error_type_t error;
- } context;
- yaml_node_pair_t pair = { key, value };
+ yaml_error_t error;
+ } self;
+ yaml_node_pair_t pair = { key_id, value_id };
assert(document); /* Non-NULL document is required. */
- assert(mapping > 0
- && document->nodes.start + mapping <= document->nodes.top);
+ assert(document->type); /* Initialized document is expected. */
+
+ if (mapping_id < 0) {
+ mapping_id += document->nodes.length;
+ }
+ if (key_id < 0) {
+ key_id += document->nodes.length;
+ }
+ if (value_id < 0) {
+ value_id += document->nodes.length;
+ }
+
+ assert(mapping_id >= 0 && mapping_id < document->nodes.length);
/* Valid mapping id is required. */
- assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
- /* A mapping node is required. */
- assert(key > 0 && document->nodes.start + key <= document->nodes.top);
+ assert(key_id >= 0 && key_id < document->nodes.length);
/* Valid key id is required. */
- assert(value > 0 && document->nodes.start + value <= document->nodes.top);
+ assert(value_id >= 0 && value_id < document->nodes.length);
/* Valid value id is required. */
+ assert(document->nodes.list[mapping_id].type == YAML_MAPPING_NODE);
+ /* A mapping node is expected. */
- if (!PUSH(&context,
- document->nodes.start[mapping-1].data.mapping.pairs, pair))
+ if (!PUSH(&self,
+ document->nodes.list[mapping_id].data.mapping.pairs, pair))
return 0;
return 1;
}
-#endif
+/*
+ * Ensure that the node is a `!!null` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_null_node(yaml_document_t *document, int node_id)
+{
+ yaml_node_t *node;
+ yaml_char_t *scalar;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SCALAR_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_NULL_TAG))
+ return 0;
+
+ if (node->data.scalar.length != strlen(node->data.scalar.value))
+ return 0;
+
+ scalar = node->data.scalar.value;
+
+ if (!strcmp(scalar, "") || !strcmp(scalar, "~") || !strcmp(scalar, "null")
+ || !strcmp(scalar, "Null") || !strcmp(scalar, "NULL"))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Ensure that the node is a `!!bool` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_bool_node(yaml_document_t *document, int node_id, int *value)
+{
+ yaml_node_t *node;
+ yaml_char_t *scalar;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SCALAR_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_BOOL_TAG))
+ return 0;
+
+ if (node->data.scalar.length != strlen(node->data.scalar.value))
+ return 0;
+
+ scalar = node->data.scalar.value;
+
+ if (!strcmp(scalar, "yes") || !strcmp(scalar, "Yes") || !strcmp(scalar, "YES") ||
+ !strcmp(scalar, "true") || !strcmp(scalar, "True") || !strcmp(scalar, "TRUE") ||
+ !strcmp(scalar, "on") || !strcmp(scalar, "On") || !strcmp(scalar, "ON")) {
+ if (value) {
+ *value = 1;
+ }
+ return 1;
+ }
+
+ if (!strcmp(scalar, "no") || !strcmp(scalar, "No") || !strcmp(scalar, "NO") ||
+ !strcmp(scalar, "false") || !strcmp(scalar, "False") || !strcmp(scalar, "FALSE") ||
+ !strcmp(scalar, "off") || !strcmp(scalar, "Off") || !strcmp(scalar, "OFF")) {
+ if (value) {
+ *value = 0;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Ensure that the node is a `!!str` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_str_node(yaml_document_t *document, int node_id,
+ char **value)
+{
+ yaml_node_t *node;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SCALAR_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_STR_TAG))
+ return 0;
+
+ if (node->data.scalar.length != strlen(node->data.scalar.value))
+ return 0;
+
+ if (value) {
+ *value = node->data.scalar.value;
+ }
+
+ return 1;
+}
+
+/*
+ * Ensure that the node is an `!!int` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_int_node(yaml_document_t *document, int node_id,
+ long *value)
+{
+ yaml_node_t *node;
+ yaml_char_t *scalar;
+ char *tail;
+ long integer;
+ int old_errno = errno, new_errno;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SCALAR_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_INT_TAG))
+ return 0;
+
+ if (node->data.scalar.length != strlen(node->data.scalar.value))
+ return 0;
+
+ if (!node->data.scalar.length)
+ return 0;
+
+ scalar = node->data.scalar.value;
+
+ errno = 0;
+
+ integer = strtol((char *)scalar, &tail, 0);
+
+ new_errno = errno;
+ errno = old_errno;
+
+ if (new_errno || *tail) {
+ return 0;
+ }
+
+ if (value) {
+ *value = integer;
+ }
+
+ return 1;
+}
+
+/*
+ * Ensure that the node is a `!!float` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_float_node(yaml_document_t *document, int node_id,
+ double *value)
+{
+ yaml_node_t *node;
+ yaml_char_t *scalar;
+ char buffer[128];
+ char *pointer;
+ char *tail;
+ double real;
+ int old_errno = errno, new_errno;
+ char decimal_point = localeconv()->decimal_point[0];
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SCALAR_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_FLOAT_TAG) && strcmp(node->tag, YAML_INT_TAG))
+ return 0;
+
+ if (node->data.scalar.length != strlen(node->data.scalar.value))
+ return 0;
+
+ if (!node->data.scalar.length)
+ return 0;
+
+ scalar = node->data.scalar.value;
+
+ if (!strcmp(scalar, ".nan") || !strcmp(scalar, ".NaN") || !strcmp(scalar, ".NAN")) {
+ if (value) {
+ *value = 0.0/0.0;
+ }
+ return 1;
+ }
+
+ if (!strcmp(scalar, ".inf") || !strcmp(scalar, ".Inf") || !strcmp(scalar, ".INF") ||
+ !strcmp(scalar, "+.inf") || !strcmp(scalar, "+.Inf") || !strcmp(scalar, "+.INF")) {
+ if (value) {
+ *value = 1.0/0.0;
+ }
+ return 1;
+ }
+
+ if (!strcmp(scalar, "-.inf") || !strcmp(scalar, "-.Inf") || !strcmp(scalar, "-.INF")) {
+ if (value) {
+ *value = -1.0/0.0;
+ }
+ return 1;
+ }
+
+ if (strlen(scalar) >= sizeof(buffer))
+ return 0;
+
+ strcpy(buffer, (const char *)scalar);
+
+ /* Replace a locale-dependent decimal point with a dot. */
+
+ for (pointer = buffer; *pointer; pointer++) {
+ if (*pointer == decimal_point) {
+ *pointer = '.';
+ break;
+ }
+ }
+
+ errno = 0;
+
+ real = strtod(buffer, &tail);
+
+ new_errno = errno;
+ errno = old_errno;
+
+ if (new_errno || *tail) {
+ return 0;
+ }
+
+ if (value) {
+ *value = real;
+ }
+
+ return 1;
+}
+
+/*
+ * Ensure that the node is a `!!seq` SEQUENCE node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_seq_node(yaml_document_t *document, int node_id,
+ yaml_node_item_t **items, size_t *length)
+{
+ yaml_node_t *node;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ assert((items && length) || (!items && !length));
+ /* items and length must be equal to NULL simultaneously. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_SEQUENCE_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_SEQ_TAG))
+ return 0;
+
+ if (items && length) {
+ *items = node->data.sequence.items.list;
+ *length = node->data.sequence.items.length;
+ }
+
+ return 1;
+}
+
+/*
+ * Ensure that the node is a `!!map` MAPPING node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_get_map_node(yaml_document_t *document, int node_id,
+ yaml_node_pair_t **pairs, size_t *length)
+{
+ yaml_node_t *node;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(document->type); /* Initialized document is expected. */
+
+ assert((pairs && length) || (!pairs && !length));
+ /* pairs and length must be equal to NULL simultaneously. */
+
+ if (node_id < 0) {
+ node_id += document->nodes.length;
+ }
+
+ assert(node_id >= 0 && node_id < document->nodes.length);
+ /* Valid node id is required. */
+
+ node = document->nodes.list + node_id;
+
+ if (node->type != YAML_MAPPING_NODE)
+ return 0;
+
+ if (strcmp(node->tag, YAML_MAP_TAG))
+ return 0;
+
+ if (pairs && length) {
+ *pairs = node->data.mapping.pairs.list;
+ *length = node->data.mapping.pairs.length;
+ }
+
+ return 1;
+}
+
+/*
+ * Add a `!!null` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_null_node(yaml_document_t *document, int *node_id)
+{
+ return yaml_document_add_scalar(document, node_id, NULL,
+ YAML_NULL_TAG, "null", -1, YAML_ANY_SCALAR_STYLE);
+}
+
+/*
+ * Add a `!!bool` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_bool_node(yaml_document_t *document, int *node_id,
+ int value)
+{
+ return yaml_document_add_scalar(document, node_id, NULL, YAML_BOOL_TAG,
+ (value ? "true" : "false"), -1, YAML_ANY_SCALAR_STYLE);
+}
+
+/*
+ * Add a `!!str` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_str_node(yaml_document_t *document, int *node_id,
+ const char *value)
+{
+ return yaml_document_add_scalar(document, node_id, NULL, YAML_STR_TAG,
+ (const yaml_char_t *) value, -1, YAML_ANY_SCALAR_STYLE);
+}
+
+/*
+ * Add an `!!int` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_int_node(yaml_document_t *document, int *node_id,
+ long value)
+{
+ char buffer[128]; /* 128 bytes should be enough for everybody. */
+ int length;
+
+ length = snprintf(buffer, sizeof(buffer), "%ld", value);
+ if (length < 0 || length >= sizeof(buffer)) return 0;
+
+ return yaml_document_add_scalar(document, node_id, NULL, YAML_INT_TAG,
+ (const yaml_char_t *) buffer, -1, YAML_ANY_SCALAR_STYLE);
+}
+
+/*
+ * Add a `!!float` SCALAR node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_float_node(yaml_document_t *document, int *node_id,
+ double value)
+{
+ char buffer[128]; /* 128 bytes should be enough for everybody. */
+ char *pointer;
+ int length;
+ char decimal_point = *localeconv()->decimal_point;
+
+ length = snprintf(buffer, sizeof(buffer), "%.12g", value);
+ /* .12 is a reasonable precision; it is used by str(float) in Python. */
+ if (length < 0 || length >= sizeof(buffer)-3) return 0;
+
+ /* Replace a locale-dependent decimal point with a dot. */
+
+ for (pointer = buffer; *pointer; pointer++) {
+ if (*pointer == decimal_point) {
+ *pointer = '.';
+ break;
+ }
+ }
+
+ /* Check if the formatted number contains a decimal dot. */
+
+ for (pointer = buffer; *pointer; pointer++) {
+ if (*pointer != '+' && *pointer != '-' && !isdigit(*pointer)) {
+ break;
+ }
+ }
+
+ /* Add .0 at the end of the buffer if needed. */
+
+ if (!*pointer) {
+ *(pointer++) = '.';
+ *(pointer++) = '0';
+ *(pointer++) = '\0';
+ }
+
+ return yaml_document_add_scalar(document, node_id, NULL, YAML_FLOAT_TAG,
+ (const yaml_char_t *) buffer, -1, YAML_ANY_SCALAR_STYLE);
+}
+
+/*
+ * Add a `!!seq` SEQUENCE node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_seq_node(yaml_document_t *document, int *node_id)
+{
+ return yaml_document_add_sequence(document, node_id, NULL,
+ YAML_SEQ_TAG, YAML_ANY_SEQUENCE_STYLE);
+}
+
+/*
+ * Add a `!!map` MAPPING node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_map_node(yaml_document_t *document, int *node_id)
+{
+ return yaml_document_add_mapping(document, node_id, NULL,
+ YAML_MAP_TAG, YAML_ANY_MAPPING_STYLE);
+}
+
+/*****************************************************************************
+ * Standard Handlers
+ *****************************************************************************/
+
+/*
+ * Standard string read handler.
+ */
+
+static int
+yaml_string_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
+ size_t *length)
+{
+ yaml_standard_reader_data_t *data = untyped_data;
+
+ if (data->string.pointer == data->string.length) {
+ *length = 0;
+ return 1;
+ }
+
+ if (capacity > (size_t)(data->string.length - data->string.pointer)) {
+ capacity = data->string.length - data->string.pointer;
+ }
+
+ memcpy(buffer, data->string.buffer + data->string.pointer, capacity);
+ data->string.pointer += capacity;
+ *length = capacity;
+ return 1;
+}
+
+/*
+ * Standard file read handler.
+ */
+
+static int
+yaml_file_reader(void *untyped_data, unsigned char *buffer, size_t capacity,
+ size_t *length)
+{
+ yaml_standard_reader_data_t *data = untyped_data;
+
+ *length = fread(buffer, 1, capacity, data->file);
+ return !ferror(data->file);
+}
+
+/*
+ * String write handler.
+ */
+
+static int
+yaml_string_writer(void *untyped_data, const unsigned char *buffer, size_t length)
+{
+ yaml_standard_writer_data_t *data = untyped_data;
+ int result = 1;
+
+ if (data->string.capacity - data->string.pointer < length) {
+ length = data->string.capacity - data->string.pointer;
+ result = 0;
+ }
+
+ memcpy(data->string.buffer + data->string.pointer, buffer, length);
+ data->string.pointer += length;
+ *data->length += length;
+
+ return result;
+}
+
+/*
+ * File write handler.
+ */
+
+static int
+yaml_file_writer(void *untyped_data, const unsigned char *buffer, size_t length)
+{
+ yaml_standard_writer_data_t *data = untyped_data;
+
+ return (fwrite(buffer, 1, length, data->file) == length);
+}
+
+/*
+ * Standard resolve handler.
+ *
+ * The standard resolve handler recognizes the following scalars:
+ *
+ * - `!!null`: `~|null|Null|NULL|<empty string>`.
+ *
+ * - `!!bool`: `yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|
+ * on|On|ON|off|Off|OFF`
+ *
+ * - `!!int`: any string that is successfully converted using `strtol()`.
+ *
+ * - `!!float`: `[+-]?(.inf|.Inf|.INF)|.nan|.NaN|.NAN` or any string
+ * successfully converted using `strtod()`.
+ */
+
+static int
+yaml_standard_resolver(void *untyped_data, yaml_incomplete_node_t *node,
+ const yaml_char_t **tag)
+{
+ if (node->type == YAML_SCALAR_NODE && node->data.scalar.is_plain)
+ {
+ yaml_char_t *value = node->data.scalar.value;
+ char buffer[128];
+ char *pointer;
+ char *tail;
+ int old_errno, new_errno;
+ char decimal_point = *(localeconv()->decimal_point);
+
+ if (strlen(value) != node->data.scalar.length) {
+ *tag = YAML_STR_TAG;
+ return 1;
+ }
+
+ if (!strcmp(value, "") || !strcmp(value, "~") ||
+ !strcmp(value, "null") || !strcmp(value, "Null") || !strcmp(value, "NULL")) {
+ *tag = YAML_NULL_TAG;
+ return 1;
+ }
+
+ if (!strcmp(value, "yes") || !strcmp(value, "Yes") || !strcmp(value, "YES") ||
+ !strcmp(value, "no") || !strcmp(value, "No") || !strcmp(value, "NO") ||
+ !strcmp(value, "true") || !strcmp(value, "True") || !strcmp(value, "TRUE") ||
+ !strcmp(value, "false") || !strcmp(value, "False") || !strcmp(value, "FALSE") ||
+ !strcmp(value, "on") || !strcmp(value, "On") || !strcmp(value, "ON") ||
+ !strcmp(value, "off") || !strcmp(value, "Off") || !strcmp(value, "OFF")) {
+ *tag = YAML_BOOL_TAG;
+ return 1;
+ }
+
+ if (!strcmp(value, ".inf") || !strcmp(value, ".Inf") || !strcmp(value, ".INF") ||
+ !strcmp(value, "+.inf") || !strcmp(value, "+.Inf") || !strcmp(value, "+.INF") ||
+ !strcmp(value, "-.inf") || !strcmp(value, "-.Inf") || !strcmp(value, "-.INF") ||
+ !strcmp(value, ".nan") || !strcmp(value, ".NaN") || !strcmp(value, ".NAN")) {
+ *tag = YAML_FLOAT_TAG;
+ return 1;
+ }
+
+ old_errno = errno;
+ errno = 0;
+
+ strtol((const char *)value, &tail, 0);
+
+ new_errno = errno;
+ errno = old_errno;
+
+ if (!new_errno && !*tail) {
+ *tag = YAML_INT_TAG;
+ return 1;
+ }
+
+ if (strlen(value) < sizeof(buffer))
+ {
+ strcpy(buffer, (const char *)value);
+
+ /* Replace a locale-dependent decimal point with a dot. */
+
+ for (pointer = buffer; *pointer; pointer++) {
+ if (*pointer == decimal_point) {
+ *pointer = '.';
+ break;
+ }
+ }
+
+ old_errno = errno;
+ errno = 0;
+
+ strtod(buffer, &tail);
+
+ new_errno = errno;
+ errno = old_errno;
+
+ if (!new_errno && !*tail) {
+ *tag = YAML_FLOAT_TAG;
+ return 1;
+ }
+ }
+ }
+
+ switch (node->type)
+ {
+ case YAML_SCALAR_NODE:
+ *tag = YAML_STR_TAG;
+ break;
+ case YAML_SEQUENCE_NODE:
+ *tag = YAML_SEQ_TAG;
+ break;
+ case YAML_MAPPING_NODE:
+ *tag = YAML_MAP_TAG;
+ break;
+ default:
+ assert(0); /* Should never happen. */
+ }
+
+ return 1;
+}
+
+
+/*****************************************************************************
+ * Parser API
+ *****************************************************************************/
+
+/*
+ * Allocate a new parser object.
+ */
+
+YAML_DECLARE(yaml_parser_t *)
+yaml_parser_new(void)
+{
+ yaml_parser_t *parser = yaml_malloc(sizeof(yaml_parser_t));
+
+ if (!parser)
+ return NULL;
+
+ memset(parser, 0, sizeof(yaml_parser_t));
+
+ if (!IOSTRING_INIT(parser, parser->raw_input, RAW_INPUT_BUFFER_CAPACITY))
+ goto error;
+ if (!IOSTRING_INIT(parser, parser->input, INPUT_BUFFER_CAPACITY))
+ goto error;
+ if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_CAPACITY))
+ goto error;
+ if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!STACK_INIT(parser, parser->states, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_CAPACITY))
+ goto error;
+
+ return parser;
+
+error:
+ yaml_parser_delete(parser);
+
+ return NULL;
+}
+
+/*
+ * Deallocate a parser object.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_delete(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+
+ IOSTRING_DEL(parser, parser->raw_input);
+ IOSTRING_DEL(parser, parser->input);
+ while (!QUEUE_EMPTY(parser, parser->tokens)) {
+ yaml_token_destroy(&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);
+}
+
+/*
+ * Reset a parser object.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_reset(yaml_parser_t *parser)
+{
+ yaml_parser_t copy = *parser;
+
+ assert(parser); /* Non-NULL parser object expected. */
+
+ while (!QUEUE_EMPTY(parser, parser->tokens)) {
+ yaml_token_destroy(&DEQUEUE(parser, parser->tokens));
+ }
+ 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);
+ }
+
+ memset(parser, 0, sizeof(yaml_parser_t));
+
+ IOSTRING_SET(parser, parser->raw_input,
+ copy.raw_input.buffer, copy.raw_input.capacity);
+ IOSTRING_SET(parser, parser->input,
+ copy.input.buffer, copy.input.capacity);
+ QUEUE_SET(parser, parser->tokens,
+ copy.tokens.list, copy.tokens.capacity);
+ STACK_SET(parser, parser->indents,
+ copy.indents.list, copy.indents.capacity);
+ STACK_SET(parser, parser->simple_keys,
+ copy.simple_keys.list, copy.simple_keys.capacity);
+ STACK_SET(parser, parser->states,
+ copy.states.list, copy.states.capacity);
+ STACK_SET(parser, parser->marks,
+ copy.marks.list, copy.marks.capacity);
+ STACK_SET(parse, parser->tag_directives,
+ copy.tag_directives.list, copy.tag_directives.capacity);
+}
+
+/*
+ * Get the current parser error.
+ */
+
+YAML_DECLARE(yaml_error_t *)
+yaml_parser_get_error(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+
+ return &(parser->error);
+}
+
+/*
+ * Set a string input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_string_reader(yaml_parser_t *parser,
+ const unsigned char *buffer, size_t length)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->reader); /* You can set the input handler only once. */
+ assert(buffer); /* Non-NULL input string expected. */
+
+ parser->reader = yaml_string_reader;
+ parser->reader_data = &(parser->standard_reader_data);
+
+ parser->standard_reader_data.string.buffer = buffer;
+ parser->standard_reader_data.string.pointer = 0;
+ parser->standard_reader_data.string.length = length;
+}
+
+/*
+ * Set a file input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_file_reader(yaml_parser_t *parser, FILE *file)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->reader); /* You can set the input handler only once. */
+ assert(file); /* Non-NULL file object expected. */
+
+ parser->reader = yaml_file_reader;
+ parser->reader_data = &(parser->standard_reader_data);
+
+ parser->standard_reader_data.file = file;
+}
+
+/*
+ * Set a generic input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_reader(yaml_parser_t *parser,
+ yaml_reader_t *reader, void *data)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->reader); /* You can set the input handler only once. */
+ assert(reader); /* Non-NULL read handler expected. */
+
+ parser->reader = reader;
+ parser->reader_data = data;
+}
+
+/*
+ * Set a standard tag resolver.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_standard_resolver(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->resolver); /* You can set the tag resolver only once. */
+
+ parser->resolver = yaml_standard_resolver;
+ parser->resolver_data = NULL;
+}
+
+/*
+ * Set a generic tag resolver.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_resolver(yaml_parser_t *parser,
+ yaml_resolver_t *resolver, void *data)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->resolver); /* You can set the tag resolver only once. */
+ assert(resolver); /* Non-NULL resolver is expected. */
+
+ parser->resolver = resolver;
+ parser->resolver_data = data;
+}
+
+/*
+ * Set the source encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->encoding); /* Encoding is already set or detected. */
+
+ parser->encoding = encoding;
+}
+
+/*****************************************************************************
+ * Parser API
+ *****************************************************************************/
+
+/*
+ * Create a new emitter object.
+ */
+
+YAML_DECLARE(yaml_emitter_t *)
+yaml_emitter_new(void)
+{
+ yaml_emitter_t *emitter = yaml_malloc(sizeof(yaml_emitter_t));
+
+ if (!emitter)
+ return NULL;
+
+ memset(emitter, 0, sizeof(yaml_emitter_t));
+ if (!IOSTRING_INIT(emitter, emitter->output, OUTPUT_BUFFER_CAPACITY))
+ goto error;
+ if (!IOSTRING_INIT(emitter, emitter->raw_output, RAW_OUTPUT_BUFFER_CAPACITY))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_CAPACITY))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_CAPACITY))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_CAPACITY))
+ goto error;
+
+ return emitter;
+
+error:
+ yaml_emitter_delete(emitter);
+
+ return NULL;
+}
+
+/*
+ * Destroy an emitter object.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_delete(yaml_emitter_t *emitter)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ IOSTRING_DEL(emitter, emitter->output);
+ IOSTRING_DEL(emitter, emitter->raw_output);
+ STACK_DEL(emitter, emitter->states);
+ while (!QUEUE_EMPTY(emitter, emitter->events)) {
+ yaml_event_destroy(&DEQUEUE(emitter, emitter->events));
+ }
+ QUEUE_DEL(emitter, emitter->events);
+ STACK_DEL(emitter, emitter->indents);
+ while (!STACK_EMPTY(empty, emitter->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+ STACK_DEL(emitter, emitter->tag_directives);
+ yaml_free(emitter->anchors);
+
+ memset(emitter, 0, sizeof(yaml_emitter_t));
+ yaml_free(emitter);
+}
+
+/*
+ * Reset an emitter object.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_reset(yaml_emitter_t *emitter)
+{
+ yaml_emitter_t copy = *emitter;
+
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ while (!QUEUE_EMPTY(emitter, emitter->events)) {
+ yaml_event_destroy(&DEQUEUE(emitter, emitter->events));
+ }
+ while (!STACK_EMPTY(empty, emitter->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+
+ memset(emitter, 0, sizeof(yaml_emitter_t));
+
+ IOSTRING_SET(emitter, emitter->output,
+ copy.output.buffer, copy.output.capacity);
+ IOSTRING_SET(emitter, emitter->raw_output,
+ copy.raw_output.buffer, copy.raw_output.capacity);
+ STACK_SET(emitter, emitter->states,
+ copy.states.list, copy.states.capacity);
+ QUEUE_SET(emitter, emitter->events,
+ copy.events.list, copy.events.capacity);
+ STACK_SET(emitter, emitter->indents,
+ copy.indents.list, copy.indents.capacity);
+ STACK_SET(emitter, emitter->tag_directives,
+ copy.tag_directives.list, copy.tag_directives.capacity);
+}
+
+/*
+ * Get the current emitter error.
+ */
+
+YAML_DECLARE(yaml_error_t *)
+yaml_emitter_get_error(yaml_emitter_t *emitter)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ return &(emitter->error);
+}
+
+/*
+ * Set a string output.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_string_writer(yaml_emitter_t *emitter,
+ unsigned char *buffer, size_t capacity, size_t *length)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->writer); /* You can set the output only once. */
+ assert(buffer); /* Non-NULL output string expected. */
+
+ emitter->writer = yaml_string_writer;
+ emitter->writer_data = &(emitter->standard_writer_data);
+
+ emitter->standard_writer_data.string.buffer = buffer;
+ emitter->standard_writer_data.string.pointer = 0;
+ emitter->standard_writer_data.string.capacity = capacity;
+ emitter->standard_writer_data.length = length;
+
+ *length = 0;
+}
+
+/*
+ * Set a file output.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_file_writer(yaml_emitter_t *emitter, FILE *file)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->writer); /* You can set the output only once. */
+ assert(file); /* Non-NULL file object expected. */
+
+ emitter->writer = yaml_string_writer;
+ emitter->writer_data = &(emitter->standard_writer_data);
+
+ emitter->standard_writer_data.file = file;
+}
+
+/*
+ * Set a generic output handler.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_writer(yaml_emitter_t *emitter,
+ yaml_writer_t *writer, void *data)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->writer); /* You can set the output only once. */
+ assert(writer); /* Non-NULL handler object expected. */
+
+ emitter->writer = writer;
+ emitter->writer_data = data;
+}
+
+/*
+ * Set a standard tag resolver.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_standard_resolver(yaml_emitter_t *emitter)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->resolver); /* You can set the tag resolver only once. */
+
+ emitter->resolver = yaml_standard_resolver;
+ emitter->resolver_data = NULL;
+}
+
+/*
+ * Set a generic tag resolver.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_resolver(yaml_emitter_t *emitter,
+ yaml_resolver_t *resolver, void *data)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->resolver); /* You can set the tag resolver only once. */
+ assert(resolver); /* Non-NULL resolver is expected. */
+
+ emitter->resolver = resolver;
+ emitter->resolver_data = data;
+}
+
+/*
+ * Set the output encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->encoding); /* You can set encoding only once. */
+
+ emitter->encoding = encoding;
+}
+
+/*
+ * Set the canonical output style.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_canonical(yaml_emitter_t *emitter, int is_canonical)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->is_canonical = (is_canonical != 0);
+}
+
+/*
+ * Set the indentation increment.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
+}
+
+/*
+ * Set the preferred line width.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->best_width = (width >= 0) ? width : -1;
+}
+
+/*
+ * Set if unescaped non-ASCII characters are allowed.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_unicode(yaml_emitter_t *emitter, int is_unicode)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->is_unicode = (is_unicode != 0);
+}
+
+/*
+ * Set the preferred line break character.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->line_break = line_break;
+}
diff --git a/src/emitter.c b/src/emitter.c
index 4093e41..dfb59dc 100644
--- a/src/emitter.c
+++ b/src/emitter.c
@@ -183,6 +183,9 @@ yaml_emitter_process_scalar(yaml_emitter_t *emitter);
*/
static int
+yaml_emitter_valid_utf8(yaml_emitter_t *emitter, yaml_istring_t string);
+
+static int
yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
yaml_version_directive_t version_directive);
@@ -1148,10 +1151,10 @@ yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
yaml_scalar_style_t style = event->data.scalar.style;
int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
- if (no_tag && !event->data.scalar.is_plain_implicit
- && !event->data.scalar.is_quoted_implicit) {
+ if (no_tag && !event->data.scalar.is_plain_nonspecific
+ && !event->data.scalar.is_quoted_nonspecific) {
return EMITTER_ERROR_INIT(emitter,
- "neither tag nor implicit flags are specified");
+ "neither tag nor nonspecific flags are specified");
}
if (style == YAML_ANY_SCALAR_STYLE)
@@ -1171,7 +1174,7 @@ yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
if (!emitter->scalar_data.length
&& (emitter->flow_level || emitter->is_simple_key_context))
style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- if (no_tag && !event->data.scalar.is_plain_implicit)
+ if (no_tag && !event->data.scalar.is_plain_nonspecific)
style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
}
@@ -1188,7 +1191,7 @@ yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
}
- if (no_tag && !event->data.scalar.is_quoted_implicit
+ if (no_tag && !event->data.scalar.is_quoted_nonspecific
&& style != YAML_PLAIN_SCALAR_STYLE)
{
emitter->tag_data.handle = (yaml_char_t *)"!";
@@ -1308,6 +1311,50 @@ yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
}
/*
+ * Verify that a string is a valid UTF-8 sequence.
+ *
+ * Check 'reader.c' for more details on UTF-8 encoding.
+ */
+
+static int
+yaml_emitter_valid_utf8(yaml_emitter_t *emitter, yaml_istring_t string)
+{
+ while (string.pointer < string.length)
+ {
+ unsigned char octet;
+ unsigned int width;
+ unsigned int value;
+ size_t idx;
+
+ octet = OCTET(string);
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+ if (!width) return 0;
+ if (string.pointer+width > string.length) return 0;
+ for (idx = 1; idx < width; idx ++) {
+ octet = OCTET_AT(string, idx);
+ if ((octet & 0xC0) != 0x80) return 0;
+ value = (value << 6) + (octet & 0x3F);
+ }
+ if (!((width == 1) ||
+ (width == 2 && value >= 0x80) ||
+ (width == 3 && value >= 0x800) ||
+ (width == 4 && value >= 0x10000))) return 0;
+
+ string.pointer += width;
+ }
+
+ return 1;
+}
+
+
+/*
* Check if a %TAG directive is valid.
*/
@@ -1320,6 +1367,16 @@ yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
yaml_istring_t prefix = ISTRING(tag_directive.prefix,
strlen((char *)tag_directive.prefix));
+ if (!yaml_emitter_valid_utf8(emitter, handle)) {
+ return EMITTER_ERROR_INIT(emitter,
+ "tag handle is not a valid UTF-8 string");
+ }
+
+ if (!yaml_emitter_valid_utf8(emitter, prefix)) {
+ return EMITTER_ERROR_INIT(emitter,
+ "tag prefix is not a valid UTF-8 string");
+ }
+
if (!handle.length) {
return EMITTER_ERROR_INIT(emitter, "tag handle must not be empty");
}
@@ -1359,6 +1416,12 @@ yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
{
yaml_istring_t string = ISTRING(anchor, strlen((char *)anchor));
+ if (!yaml_emitter_valid_utf8(emitter, string)) {
+ return EMITTER_ERROR_INIT(emitter, is_alias ?
+ "alias value is not a valid UTF-8 string" :
+ "anchor value is not a valid UTF-8 string");
+ }
+
if (!string.length) {
return EMITTER_ERROR_INIT(emitter, is_alias ?
"alias value must not be empty" :
@@ -1392,6 +1455,11 @@ yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
yaml_istring_t string = ISTRING(tag, strlen((char *)tag));
size_t idx;
+ if (!yaml_emitter_valid_utf8(emitter, string)) {
+ return EMITTER_ERROR_INIT(emitter,
+ "tag value is not a valid UTF-8 string");
+ }
+
if (!string.length) {
return EMITTER_ERROR_INIT(emitter, "tag value must not be empty");
}
@@ -1450,6 +1518,11 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
int mixed = 0;
int leading = 0;
+ if (!yaml_emitter_valid_utf8(emitter, string)) {
+ return EMITTER_ERROR_INIT(emitter,
+ "scalar value is not a valid UTF-8 string");
+ }
+
emitter->scalar_data.value = value;
emitter->scalar_data.length = length;
@@ -1689,8 +1762,8 @@ yaml_emitter_analyze_event(yaml_emitter_t *emitter,
return 0;
}
if (event->data.scalar.tag && (emitter->is_canonical ||
- (!event->data.scalar.is_plain_implicit
- && !event->data.scalar.is_quoted_implicit))) {
+ (!event->data.scalar.is_plain_nonspecific
+ && !event->data.scalar.is_quoted_nonspecific))) {
if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
return 0;
}
@@ -1706,7 +1779,7 @@ yaml_emitter_analyze_event(yaml_emitter_t *emitter,
return 0;
}
if (event->data.sequence_start.tag && (emitter->is_canonical ||
- !event->data.sequence_start.is_implicit)) {
+ !event->data.sequence_start.is_nonspecific)) {
if (!yaml_emitter_analyze_tag(emitter,
event->data.sequence_start.tag))
return 0;
@@ -1720,7 +1793,7 @@ yaml_emitter_analyze_event(yaml_emitter_t *emitter,
return 0;
}
if (event->data.mapping_start.tag && (emitter->is_canonical ||
- !event->data.mapping_start.is_implicit)) {
+ !event->data.mapping_start.is_nonspecific)) {
if (!yaml_emitter_analyze_tag(emitter,
event->data.mapping_start.tag))
return 0;
diff --git a/src/yaml_private.h b/src/yaml_private.h
index 3ae24a2..b1eea24 100644
--- a/src/yaml_private.h
+++ b/src/yaml_private.h
@@ -1,3 +1,11 @@
+/*****************************************************************************
+ * Private Definitions for LibYAML
+ *
+ * Copyright (c) 2006 Kirill Simonov
+ *
+ * LibYAML is free software; you can use, modify and/or redistribute it under
+ * the terms of the MIT license; see the file LICENCE for more details.
+ *****************************************************************************/
#if HAVE_CONFIG_H
#include <config.h>
@@ -7,10 +15,13 @@
#include <assert.h>
#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <locale.h>
-/*
- * Memory management.
- */
+/*****************************************************************************
+ * Memory Management
+ *****************************************************************************/
YAML_DECLARE(void *)
yaml_malloc(size_t size);
@@ -24,9 +35,9 @@ yaml_free(void *ptr);
YAML_DECLARE(yaml_char_t *)
yaml_strdup(const yaml_char_t *);
-/*
- * Error management.
- */
+/*****************************************************************************
+ * Error Management
+ *****************************************************************************/
/*
* Generic error initializers; not to be used directly.
@@ -128,6 +139,10 @@ yaml_strdup(const yaml_char_t *);
#define RESOLVER_ERROR_INIT(self, _problem) \
RESOLVER_ERROR_INIT((self)->error, YAML_RESOLVER_ERROR, _problem)
+/*****************************************************************************
+ * Buffer Sizes
+ *****************************************************************************/
+
/*
* The size of the input raw buffer.
*/
@@ -138,7 +153,10 @@ yaml_strdup(const yaml_char_t *);
* The size of the input buffer.
*
* The input buffer should be large enough to hold the content of the raw
- * buffer after it is decoded.
+ * buffer after it is decoded. The raw input buffer could be encoded in UTF-8
+ * or UTF-16 while the input buffer is always encoded in UTF-8. A UTF-16
+ * character may take 2 or 4 bytes, and a UTF-8 character takes up to 4 bytes.
+ * We use the *3 multiplier just to be safe.
*/
#define INPUT_BUFFER_CAPACITY (RAW_INPUT_BUFFER_CAPACITY*3)
@@ -166,9 +184,9 @@ yaml_strdup(const yaml_char_t *);
#define INITIAL_QUEUE_CAPACITY 16
#define INITIAL_STRING_CAPACITY 16
-/*
- * String management.
- */
+/*****************************************************************************
+ * String Management
+ *****************************************************************************/
/*
* An immutable string used as an input buffer.
@@ -202,7 +220,7 @@ typedef struct yaml_iostring_s {
} yaml_iostring_t;
/*
- * Separate type for non-UTF-8 i/o strings.
+ * A separate type for non-UTF-8 i/o strings.
*/
typedef struct yaml_raw_iostring_s {
@@ -212,14 +230,26 @@ typedef struct yaml_raw_iostring_s {
size_t capacity;
} yaml_raw_iostring_t;
+/*
+ * Double the string capacity.
+ */
+
YAML_DECLARE(int)
yaml_ostring_extend(yaml_char_t **buffer, size_t *capacity);
+/*
+ * Append a string to the end of the base string expanding it if needed.
+ */
+
YAML_DECLARE(int)
yaml_ostring_join(
yaml_char_t **base_buffer, size_t *base_pointer, size_t *base_capacity,
yaml_char_t *adj_buffer, size_t adj_pointer);
+/*
+ * Basic string operations.
+ */
+
#define ISTRING(buffer, length) { (buffer), 0, (length) }
#define NULL_OSTRING { NULL, 0, 0 }
@@ -238,6 +268,12 @@ yaml_ostring_join(
(string).buffer = NULL, \
((string).pointer = (string).length = (string).capacity = 0))
+#define IOSTRING_SET(self, string, _buffer, _capacity) \
+ (memset((_buffer), 0, (_capacity)), \
+ (string).buffer = (_buffer), \
+ (string).pointer = (string).length = 0, \
+ (string).capacity = (_capacity))
+
#define OSTRING_INIT(self, string, _capacity) \
(((string).buffer = yaml_malloc(_capacity)) ? \
((string).pointer = 0, \
@@ -272,9 +308,9 @@ yaml_ostring_join(
((self)->error.type = YAML_MEMORY_ERROR, \
0))
-/*
- * String check operations.
- */
+/*****************************************************************************
+ * String Tests
+ *****************************************************************************/
/*
* Get the octet at the specified position.
@@ -547,17 +583,29 @@ yaml_ostring_join(
COPY_OCTET((target_string), (source_string)), \
COPY_OCTET((target_string), (source_string))) : 0)
+/*****************************************************************************
+ * Stack and Queue Management
+ *****************************************************************************/
+
/*
- * Stack and queue management.
+ * Double the stack capacity.
*/
YAML_DECLARE(int)
yaml_stack_extend(void **list, size_t size, size_t *length, size_t *capacity);
+/*
+ * Double the queue capacity.
+ */
+
YAML_DECLARE(int)
yaml_queue_extend(void **list, size_t size,
size_t *head, size_t *tail, size_t *capacity);
+/*
+ * Basic stack operations.
+ */
+
#define STACK_INIT(self, stack, _capacity) \
(((stack).list = yaml_malloc((_capacity)*sizeof(*(stack).list))) ? \
((stack).length = 0, \
@@ -571,6 +619,11 @@ yaml_queue_extend(void **list, size_t size,
(stack).list = NULL, \
(stack).length = (stack).capacity = 0)
+#define STACK_SET(self, stack, _list, _capacity) \
+ ((stack).list = (_list), \
+ (stack).length = 0, \
+ (stack).capacity = (_capacity))
+
#define STACK_EMPTY(self, stack) \
((stack).length == 0)
@@ -589,6 +642,10 @@ yaml_queue_extend(void **list, size_t size,
#define POP(self, stack) \
((stack).list[--(stack).length])
+/*
+ * Basic queue operations.
+ */
+
#define QUEUE_INIT(self, queue, _capacity) \
(((queue).list = yaml_malloc((_capacity)*sizeof(*(queue).list))) ? \
((queue).head = (queue).tail = 0, \
@@ -602,6 +659,11 @@ yaml_queue_extend(void **list, size_t size,
(queue).list = NULL, \
(queue).head = (queue).tail = (queue).capacity = 0)
+#define QUEUE_SET(self, queue, _list, _capacity) \
+ ((queue).list = (_list), \
+ (queue).head = (queue).tail = 0, \
+ (queue).capacity = (_capacity))
+
#define QUEUE_EMPTY(self, queue) \
((queue).head == (queue).tail)
@@ -633,9 +695,9 @@ yaml_queue_extend(void **list, size_t size,
((self)->error.type = YAML_MEMORY_ERROR, \
0))
-/*
- * Token initializers.
- */
+/*****************************************************************************
+ * Token Initializers
+ *****************************************************************************/
#define TOKEN_INIT(token, _type, _start_mark, _end_mark) \
(memset(&(token), 0, sizeof(yaml_token_t)), \
@@ -679,9 +741,9 @@ yaml_queue_extend(void **list, size_t size,
(token).data.tag_directive.handle = (_handle), \
(token).data.tag_directive.prefix = (_prefix))
-/*
- * Event initializers.
- */
+/*****************************************************************************
+ * Event Initializers
+ *****************************************************************************/
#define EVENT_INIT(event, _type, _start_mark, _end_mark) \
(memset(&(event), 0, sizeof(yaml_event_t)), \
@@ -715,95 +777,153 @@ yaml_queue_extend(void **list, size_t size,
(event).data.alias.anchor = (_anchor))
#define SCALAR_EVENT_INIT(event, _anchor, _tag, _value, _length, \
- _is_plain_implicit, _is_quoted_implicit, _style, _start_mark, _end_mark) \
+ _is_plain_nonspecific, _is_quoted_nonspecific, _style, _start_mark, _end_mark) \
(EVENT_INIT((event), YAML_SCALAR_EVENT, (_start_mark), (_end_mark)), \
(event).data.scalar.anchor = (_anchor), \
(event).data.scalar.tag = (_tag), \
(event).data.scalar.value = (_value), \
(event).data.scalar.length = (_length), \
- (event).data.scalar.is_plain_implicit = (_is_plain_implicit), \
- (event).data.scalar.is_quoted_implicit = (_is_quoted_implicit), \
+ (event).data.scalar.is_plain_nonspecific = (_is_plain_nonspecific), \
+ (event).data.scalar.is_quoted_nonspecific = (_is_quoted_nonspecific), \
(event).data.scalar.style = (_style))
-#define SEQUENCE_START_EVENT_INIT(event, _anchor, _tag, _is_implicit, _style, \
+#define SEQUENCE_START_EVENT_INIT(event, _anchor, _tag, _is_nonspecific, _style, \
_start_mark, _end_mark) \
(EVENT_INIT((event), YAML_SEQUENCE_START_EVENT, (_start_mark), (_end_mark)), \
(event).data.sequence_start.anchor = (_anchor), \
(event).data.sequence_start.tag = (_tag), \
- (event).data.sequence_start.is_implicit = (_is_implicit), \
+ (event).data.sequence_start.is_nonspecific = (_is_nonspecific), \
(event).data.sequence_start.style = (_style))
#define SEQUENCE_END_EVENT_INIT(event, _start_mark, _end_mark) \
(EVENT_INIT((event), YAML_SEQUENCE_END_EVENT, (_start_mark), (_end_mark)))
-#define MAPPING_START_EVENT_INIT(event, _anchor, _tag, _is_implicit, _style, \
+#define MAPPING_START_EVENT_INIT(event, _anchor, _tag, _is_nonspecific, _style, \
_start_mark, _end_mark) \
(EVENT_INIT((event), YAML_MAPPING_START_EVENT, (_start_mark), (_end_mark)), \
(event).data.mapping_start.anchor = (_anchor), \
(event).data.mapping_start.tag = (_tag), \
- (event).data.mapping_start.is_implicit = (_is_implicit), \
+ (event).data.mapping_start.is_nonspecific = (_is_nonspecific), \
(event).data.mapping_start.style = (_style))
#define MAPPING_END_EVENT_INIT(event, _start_mark, _end_mark) \
(EVENT_INIT((event), YAML_MAPPING_END_EVENT, (_start_mark), (_end_mark)))
-#if 0
-
-/*
- * Document initializer.
- */
+/*****************************************************************************
+ * Document, Node and Arc Initializers
+ *****************************************************************************/
-#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
- document_version_directive,document_tag_directives_start, \
- document_tag_directives_end,document_start_implicit, \
- document_end_implicit,document_start_mark,document_end_mark) \
+#define DOCUMENT_INIT(document, _nodes_list, _nodes_length, _nodes_capacity, \
+ _version_directive, _tag_directives_list, _tag_directives_length, \
+ _tag_directives_capacity, _is_start_implicit, _is_end_implicit, \
+ _start_mark, _end_mark) \
(memset(&(document), 0, sizeof(yaml_document_t)), \
- (document).nodes.start = (document_nodes_start), \
- (document).nodes.end = (document_nodes_end), \
- (document).nodes.top = (document_nodes_start), \
- (document).version_directive = (document_version_directive), \
- (document).tag_directives.start = (document_tag_directives_start), \
- (document).tag_directives.end = (document_tag_directives_end), \
- (document).start_implicit = (document_start_implicit), \
- (document).end_implicit = (document_end_implicit), \
- (document).start_mark = (document_start_mark), \
- (document).end_mark = (document_end_mark))
-
-/*
- * Node initializers.
- */
-
-#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
+ (document).type = YAML_DOCUMENT, \
+ (document).nodes.list = (_nodes_list), \
+ (document).nodes.length = (_nodes_length), \
+ (document).nodes.capacity = (_nodes_capacity), \
+ (document).version_directive = (_version_directive), \
+ (document).tag_directives.list = (_tag_directives_list), \
+ (document).tag_directives.length = (_tag_directives_length), \
+ (document).tag_directives.capacity = (_tag_directives_capacity), \
+ (document).is_start_implicit = (_is_start_implicit), \
+ (document).is_end_implicit = (_is_end_implicit), \
+ (document).start_mark = (_start_mark), \
+ (document).end_mark = (_end_mark))
+
+#define NODE_INIT(node, _type, _anchor, _tag, _start_mark, _end_mark) \
(memset(&(node), 0, sizeof(yaml_node_t)), \
- (node).type = (node_type), \
- (node).tag = (node_tag), \
- (node).start_mark = (node_start_mark), \
- (node).end_mark = (node_end_mark))
-
-#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.scalar.value = (node_value), \
- (node).data.scalar.length = (node_length), \
- (node).data.scalar.style = (node_style))
-
-#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.sequence.items.start = (node_items_start), \
- (node).data.sequence.items.end = (node_items_end), \
- (node).data.sequence.items.top = (node_items_start), \
- (node).data.sequence.style = (node_style))
-
-#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.mapping.pairs.start = (node_pairs_start), \
- (node).data.mapping.pairs.end = (node_pairs_end), \
- (node).data.mapping.pairs.top = (node_pairs_start), \
- (node).data.mapping.style = (node_style))
+ (node).type = (_type), \
+ (node).anchor = (_anchor), \
+ (node).tag = (_tag), \
+ (node).start_mark = (_start_mark), \
+ (node).end_mark = (_end_mark))
-#endif
+#define SCALAR_NODE_INIT(node, _anchor, _tag, _value, _length, _style, \
+ _start_mark, _end_mark) \
+ (NODE_INIT((node), YAML_SCALAR_NODE, (_anchor), (_tag), \
+ (_start_mark), (_end_mark)), \
+ (node).data.scalar.value = (_value), \
+ (node).data.scalar.length = (_length), \
+ (node).data.scalar.style = (_style))
+
+#define SEQUENCE_NODE_INIT(node, _anchor, _tag, _items_list, _items_length, \
+ _items_capacity, _style, _start_mark, _end_mark) \
+ (NODE_INIT((node), YAML_SEQUENCE_NODE, (_anchor), (_tag), \
+ (_start_mark), (_end_mark)), \
+ (node).data.sequence.items.list = (_items_list), \
+ (node).data.sequence.items.length = (_items_length), \
+ (node).data.sequence.items.capacity = (_items_capacity), \
+ (node).data.sequence.style = (_style))
+
+#define MAPPING_NODE_INIT(node, _anchor, _tag, _pairs_list, _pairs_length, \
+ _pairs_capacity, _style, _start_mark, _end_mark) \
+ (NODE_INIT((node), YAML_MAPPING_NODE, (_anchor), (_tag), \
+ (_start_mark), (_end_mark)), \
+ (node).data.mapping.pairs.list = (_pairs_list), \
+ (node).data.mapping.pairs.length = (_pairs_length), \
+ (node).data.mapping.pairs.capacity = (_pairs_capacity), \
+ (node).data.mapping.style = (_style))
+
+#define ARC_INIT(arc, _type, _tag) \
+ (memset(&(arc), 0, sizeof(yaml_arc_t)), \
+ (arc).type = (_type), \
+ (arc).tag = (_tag))
+
+#define SEQUENCE_ITEM_ARC_INIT(arc, _tag, _index) \
+ (ARC_INIT((arc), YAML_SEQUENCE_ITEM_ARC, (_tag)), \
+ (arc).data.item.index = (_index))
+
+#define MAPPING_KEY_ARC_INIT(arc, _tag) \
+ ARC_INIT((arc), YAML_MAPPING_KEY_ARC, (_tag))
+
+#define MAPPING_VALUE_ARC_INIT(arc, _tag, _key_type, _key_tag) \
+ (ARC_INIT((arc), YAML_MAPPING_VALUE_ARC, (_tag)), \
+ (arc).data.value.key.type = (_key_type), \
+ (arc).data.value.key.tag = (_key_tag))
+
+#define MAPPING_VALUE_FOR_SCALAR_KEY_ARC_INIT(arc, _tag, _key_tag, \
+ _key_value, _key_length) \
+ (MAPPING_VALUE_ARC_INIT((arc), (_tag), YAML_SCALAR_NODE, (_key_tag)), \
+ (arc).data.value.key.data.scalar.value = (_key_value), \
+ (arc).data.value.key.data.scalar.length = (_key_length))
+
+#define MAPPING_VALUE_FOR_SEQUENCE_KEY_ARC_INIT(arc, _tag, _key_tag) \
+ MAPPING_VALUE_ARC_INIT((arc), (_tag), YAML_SEQUENCE_NODE, (_key_tag))
+
+#define MAPPING_VALUE_FOR_MAPPING_KEY_INIT(arc, _tag, _key_tag) \
+ MAPPING_VALUE_ARC_INIT((arc), (_tag), YAML_MAPPING_NODE, (_key_tag))
+
+#define INCOMPLETE_NODE_INIT(node, _type, _path_list, _path_length, \
+ _path_capacity, _mark) \
+ (memset(&(node), 0, sizeof(yaml_incomplete_node_t)), \
+ (node).type = (_type), \
+ (node).path.list = (_path_list), \
+ (node).path.length = (_path_length), \
+ (node).path.capacity = (_path_capacity), \
+ (node).mark = (_mark))
+
+#define INCOMPLETE_SCALAR_NODE_INIT(node, _path_list, _path_length, \
+ _path_capacity, _value, _length, _is_plain, _mark) \
+ (INCOMPLETE_NODE_INIT((node), YAML_SCALAR_NODE, (_path_list), \
+ (_path_length), (_path_capacity), (_mark)). \
+ (node).data.scalar.value = (_value), \
+ (node).data.scalar.length = (_length), \
+ (node).data.scalar.is_plain = (_is_plain))
+
+#define INCOMPLETE_SEQUENCE_NODE_INIT(node, _path_list, _path_length, \
+ _path_capacity, _mark) \
+ INCOMPLETE_NODE_INIT((node), YAML_SEQUENCE_NODE, (_path_list), \
+ (_path_length), (_path_capacity), (_mark))
+
+#define INCOMPLETE_MAPPING_NODE_INIT(node, _path_list, _path_length, \
+ _path_capacity, _mark) \
+ INCOMPLETE_NODE_INIT((node), YAML_MAPPING_NODE, (_path_list), \
+ (_path_length), (_path_capacity), (_mark))
+
+/*****************************************************************************
+ * Parser Structures
+ *****************************************************************************/
/*
* This structure holds information about a potential simple key.
@@ -1037,51 +1157,73 @@ struct yaml_parser_s {
size_t capacity;
} aliases;
- /* The currently parsed document. */
+ /* The document being parsed. */
yaml_document_t *document;
};
+/*****************************************************************************
+ * Internal Parser API
+ *****************************************************************************/
+
+/*
+ * Reader: Ensure that the buffer contains at least `length` characters.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
+
+/*
+ * Scanner: Ensure that the token stack contains at least one token ready.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
+
+/*****************************************************************************
+ * Emitter Structures
+ *****************************************************************************/
+
/*
* The emitter states.
*/
typedef enum yaml_emitter_state_e {
- /** Expect STREAM-START. */
+ /* Expect STREAM-START. */
YAML_EMIT_STREAM_START_STATE,
- /** Expect the first DOCUMENT-START or STREAM-END. */
+ /* Expect the first DOCUMENT-START or STREAM-END. */
YAML_EMIT_FIRST_DOCUMENT_START_STATE,
- /** Expect DOCUMENT-START or STREAM-END. */
+ /* Expect DOCUMENT-START or STREAM-END. */
YAML_EMIT_DOCUMENT_START_STATE,
- /** Expect the content of a document. */
+ /* Expect the content of a document. */
YAML_EMIT_DOCUMENT_CONTENT_STATE,
- /** Expect DOCUMENT-END. */
+ /* Expect DOCUMENT-END. */
YAML_EMIT_DOCUMENT_END_STATE,
- /** Expect the first item of a flow sequence. */
+ /* Expect the first item of a flow sequence. */
YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE,
- /** Expect an item of a flow sequence. */
+ /* Expect an item of a flow sequence. */
YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE,
- /** Expect the first key of a flow mapping. */
+ /* Expect the first key of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE,
- /** Expect a key of a flow mapping. */
+ /* Expect a key of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_KEY_STATE,
- /** Expect a value for a simple key of a flow mapping. */
+ /* Expect a value for a simple key of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE,
- /** Expect a value of a flow mapping. */
+ /* Expect a value of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_VALUE_STATE,
- /** Expect the first item of a block sequence. */
+ /* Expect the first item of a block sequence. */
YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE,
- /** Expect an item of a block sequence. */
+ /* Expect an item of a block sequence. */
YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
- /** Expect the first key of a block mapping. */
+ /* Expect the first key of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE,
- /** Expect the key of a block mapping. */
+ /* Expect the key of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
- /** Expect a value for a simple key of a block mapping. */
+ /* Expect a value for a simple key of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE,
- /** Expect a value of a block mapping. */
+ /* Expect a value of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
- /** Expect nothing. */
+ /* Expect nothing. */
YAML_EMIT_END_STATE
} yaml_emitter_state_t;
@@ -1251,6 +1393,12 @@ struct yaml_emitter_s {
* Dumper stuff.
*/
+ /* The resolve handler. */
+ yaml_resolver_t *resolver;
+
+ /* The application data to be passed to the resolver. */
+ void *resolver_data;
+
/* If the stream was already opened? */
int is_opened;
/* If the stream was already closed? */
@@ -1269,22 +1417,8 @@ struct yaml_emitter_s {
/* The last assigned anchor id. */
int last_anchor_id;
- /* The currently emitted document. */
+ /* The document being emitted. */
yaml_document_t *document;
};
-/*
- * Reader: Ensure that the buffer contains at least `length` characters.
- */
-
-YAML_DECLARE(int)
-yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
-
-/*
- * Scanner: Ensure that the token stack contains at least one token ready.
- */
-
-YAML_DECLARE(int)
-yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
-