From 0b2da39c84579f071da6cbfdf61bf04228ca4498 Mon Sep 17 00:00:00 2001 From: xi Date: Tue, 25 Dec 2007 23:19:23 +0000 Subject: API refactoring (Note: it breaks the build). git-svn-id: http://svn.pyyaml.org/libyaml/trunk@261 18f92427-320e-0410-9341-c67f048884a3 --- include/yaml.h | 1436 ++++++++++++++++++++++------------------------------ src/api.c | 809 +++++++++++++++++++---------- src/yaml_private.h | 965 ++++++++++++++++++++++++++++------- 3 files changed, 1924 insertions(+), 1286 deletions(-) diff --git a/include/yaml.h b/include/yaml.h index d0fe93c..7950223 100644 --- a/include/yaml.h +++ b/include/yaml.h @@ -67,6 +67,114 @@ yaml_get_version_string(void); YAML_DECLARE(void) yaml_get_version(int *major, int *minor, int *patch); +/** @} */ + +/** + * @defgroup styles Error Handling + * @{ + */ + +/** Many bad things could happen with the parser and the emitter. */ +typedef enum yaml_error_type_e { + /** No error is produced. */ + YAML_NO_ERROR, + + /** Cannot allocate or reallocate a block of memory. */ + YAML_MEMORY_ERROR, + + /** Cannot read from the input stream. */ + YAML_READER_ERROR, + /** Cannot decode the input stream. */ + YAML_DECODER_ERROR, + + /** Cannot scan a YAML token. */ + YAML_SCANNER_ERROR, + /** Cannot parse a YAML production. */ + YAML_PARSER_ERROR, + /** Cannot compose a YAML document. */ + YAML_COMPOSER_ERROR, + + /** Cannot write into the output stream. */ + YAML_WRITER_ERROR, + + /** Cannot emit a YAML event. */ + YAML_EMITTER_ERROR, + /** Cannot serialize a YAML document. */ + YAML_SERIALIZER_ERROR +} yaml_error_type_t; + +/** The pointer position. */ +typedef struct yaml_mark_s { + /** The character number (starting from zero). */ + size_t index; + + /** The mark line (starting from zero). */ + size_t line; + + /** The mark column (starting from zero). */ + size_t column; +} yaml_mark_t; + +/** The error details. */ +typedef struct yaml_error_s { + + /** The error type. */ + yaml_error_type_t type; + + /** The detailed error information. */ + union { + + /** + * A problem while reading the stream (@c YAML_READER_ERROR or + * @c YAML_DECODER_ERROR). + */ + struct { + /** The problem description. */ + const char *problem; + /** The stream offset. */ + size_t offset; + /** The problematic octet or character (@c -1 if not applicable). */ + int value; + } reading; + + /** + * A problem while loading the stream (@c YAML_SCANNER_ERROR, + * @c YAML_PARSER_ERROR, or @c YAML_COMPOSER_ERROR). + */ + struct { + /** The problem description. */ + const char *problem; + /** The problem mark. */ + yaml_mark_t problem_mark; + /** The context in which the problem occured + * (@c NULL if not applicable). + */ + const char *context; + /** The context mark (if @c problem_mark is not @c NULL). **/ + yaml_mark_t context_mark; + } loading; + + /** A problem while writing into the stream (@c YAML_WRITER_ERROR). */ + struct { + /** The problem description. */ + const char *problem; + /** The stream offset. */ + size_t offset; + } writing; + + /** A problem while dumping into the stream (@c YAML_EMITTER_ERROR and + * @c YAML_SERIALIZER_ERROR). + */ + struct { + /** The problem description. */ + const char *problem; + } dumping; + + } data; + +} yaml_error_t; + + /** @} */ /** @@ -106,7 +214,6 @@ typedef enum yaml_encoding_e { } yaml_encoding_t; /** Line break types. */ - typedef enum yaml_break_e { /** Let the parser choose the break type. */ YAML_ANY_BREAK, @@ -118,41 +225,6 @@ typedef enum yaml_break_e { YAML_CRLN_BREAK } yaml_break_t; -/** Many bad things could happen with the parser and emitter. */ -typedef enum yaml_error_type_e { - /** No error is produced. */ - YAML_NO_ERROR, - - /** Cannot allocate or reallocate a block of memory. */ - YAML_MEMORY_ERROR, - - /** Cannot read or decode the input stream. */ - YAML_READER_ERROR, - /** Cannot scan the input stream. */ - YAML_SCANNER_ERROR, - /** Cannot parse the input stream. */ - YAML_PARSER_ERROR, - /** Cannot compose a YAML document. */ - YAML_COMPOSER_ERROR, - - /** Cannot write to the output stream. */ - YAML_WRITER_ERROR, - /** Cannot emit a YAML stream. */ - YAML_EMITTER_ERROR -} yaml_error_type_t; - -/** The pointer position. */ -typedef struct yaml_mark_s { - /** The position index. */ - size_t index; - - /** The position line. */ - size_t line; - - /** The position column. */ - size_t column; -} yaml_mark_t; - /** @} */ /** @@ -278,6 +350,22 @@ typedef struct yaml_token_s { yaml_encoding_t encoding; } stream_start; + /** The version directive (for @c YAML_VERSION_DIRECTIVE_TOKEN). */ + struct { + /** The major version number. */ + int major; + /** The minor version number. */ + int minor; + } version_directive; + + /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */ + struct { + /** The tag handle. */ + yaml_char_t *handle; + /** The tag prefix. */ + yaml_char_t *prefix; + } tag_directive; + /** The alias (for @c YAML_ALIAS_TOKEN). */ struct { /** The alias value. */ @@ -308,22 +396,6 @@ typedef struct yaml_token_s { yaml_scalar_style_t style; } scalar; - /** The version directive (for @c YAML_VERSION_DIRECTIVE_TOKEN). */ - struct { - /** The major version number. */ - int major; - /** The minor version number. */ - int minor; - } version_directive; - - /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */ - struct { - /** The tag handle. */ - yaml_char_t *handle; - /** The tag prefix. */ - yaml_char_t *prefix; - } tag_directive; - } data; /** The beginning of the token. */ @@ -334,7 +406,16 @@ typedef struct yaml_token_s { } yaml_token_t; /** - * Free any memory allocated for a token object. + * Allocate a new empty token object. + * + * @returns a new token object or @c NULL on error. + */ + +YAML_DECLARE(yaml_token_t *) +yaml_token_new(void); + +/** + * Delete and deallocate a token object. * * @param[in,out] token A token object. */ @@ -342,6 +423,27 @@ typedef struct yaml_token_s { YAML_DECLARE(void) yaml_token_delete(yaml_token_t *token); +/** + * Duplicate a token object. + * + * @param[in,out] token An empty token object. + * @param[in] model A token to copy. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_token_duplicate(yaml_token_t *token, yaml_token_t *model); + +/** + * Free any memory allocated for a token object. + * + * @param[in,out] token A token object. + */ + +YAML_DECLARE(void) +yaml_token_destroy(yaml_token_t *token); + /** @} */ /** @@ -402,20 +504,22 @@ typedef struct yaml_event_s { /** The list of tag directives. */ struct { - /** The beginning of the tag directives list. */ - yaml_tag_directive_t *start; - /** The end of the tag directives list. */ - yaml_tag_directive_t *end; + /** The beginning of the list. */ + yaml_tag_directive_t *list; + /** The length of the list. */ + size_t length; + /** The capacity of the list. */ + size_t capacity; } tag_directives; /** Is the document indicator implicit? */ - int implicit; + int is_implicit; } document_start; /** The document end parameters (for @c YAML_DOCUMENT_END_EVENT). */ struct { /** Is the document end indicator implicit? */ - int implicit; + int is_implicit; } document_end; /** The alias parameters (for @c YAML_ALIAS_EVENT). */ @@ -435,9 +539,9 @@ typedef struct yaml_event_s { /** The length of the scalar value. */ size_t length; /** Is the tag optional for the plain style? */ - int plain_implicit; + int is_plain_implicit; /** Is the tag optional for any non-plain style? */ - int quoted_implicit; + int is_quoted_implicit; /** The scalar style. */ yaml_scalar_style_t style; } scalar; @@ -449,7 +553,7 @@ typedef struct yaml_event_s { /** The tag. */ yaml_char_t *tag; /** Is the tag optional? */ - int implicit; + int is_implicit; /** The sequence style. */ yaml_sequence_style_t style; } sequence_start; @@ -461,7 +565,7 @@ typedef struct yaml_event_s { /** The tag. */ yaml_char_t *tag; /** Is the tag optional? */ - int implicit; + int is_implicit; /** The mapping style. */ yaml_mapping_style_t style; } mapping_start; @@ -476,7 +580,39 @@ typedef struct yaml_event_s { } yaml_event_t; /** - * Create the STREAM-START event. + * Allocate a new empty event object. + * + * @returns a new event object or @c NULL on error. + */ + +YAML_DECLARE(yaml_event_t *) +yaml_event_new(void); + +/** + * Delete and deallocate an event object. + * + * @param[in,out] event An event object. + */ + +YAML_DECLARE(void) +yaml_event_delete(yaml_event_t *event); + +/** + * Duplicate a event object. + * + * @param[in,out] event An empty event object. + * @param[in] model An event to copy. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_event_duplicate(yaml_event_t *event, yaml_event_t *model); + +/** + * Create a STREAM-START event. + * + * This function never fails. * * @param[out] event An empty event object. * @param[in] encoding The stream encoding. @@ -485,11 +621,13 @@ typedef struct yaml_event_s { */ YAML_DECLARE(int) -yaml_stream_start_event_initialize(yaml_event_t *event, +yaml_event_create_stream_start(yaml_event_t *event, yaml_encoding_t encoding); /** - * Create the STREAM-END event. + * Create a STREAM-END event. + * + * This function never fails. * * @param[out] event An empty event object. * @@ -497,48 +635,44 @@ yaml_stream_start_event_initialize(yaml_event_t *event, */ YAML_DECLARE(int) -yaml_stream_end_event_initialize(yaml_event_t *event); +yaml_event_create_stream_end(yaml_event_t *event); /** * Create the DOCUMENT-START event. * - * The @a implicit argument is considered as a stylistic parameter and may be - * ignored by the emitter. - * * @param[out] event An empty event object. * @param[in] version_directive The %YAML directive value or * @c NULL. - * @param[in] tag_directives_start The beginning of the %TAG - * directives list. - * @param[in] tag_directives_end The end of the %TAG directives - * list. - * @param[in] implicit If the document start indicator is - * implicit. + * @param[in] tag_directives_list The beginning of the %TAG + * directives list or @c NULL. The + * list ends with @c (NULL,NULL). + * @param[in] is_implicit Set if the document start + * indicator is optional. This + * parameter is stylistic and may be + * ignored by the parser. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_document_start_event_initialize(yaml_event_t *event, - yaml_version_directive_t *version_directive, - yaml_tag_directive_t *tag_directives_start, - yaml_tag_directive_t *tag_directives_end, - int implicit); +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); /** * Create the DOCUMENT-END event. * - * The @a implicit argument is considered as a stylistic parameter and may be - * ignored by the emitter. - * * @param[out] event An empty event object. - * @param[in] implicit If the document end indicator is implicit. + * @param[in] is_implicit Set if the document end indicator is optional. + * This parameter is stylistic and may be ignored + * by the parser. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_document_end_event_initialize(yaml_event_t *event, int implicit); +yaml_event_create_document_end(yaml_event_t *event, int is_implicit); /** * Create an ALIAS event. @@ -550,57 +684,55 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit); */ YAML_DECLARE(int) -yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor); +yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor); /** * Create a SCALAR event. * - * The @a style argument may be ignored by the emitter. - * - * Either the @a tag attribute or one of the @a plain_implicit and - * @a quoted_implicit flags must be set. - * - * @param[out] event An empty event object. - * @param[in] anchor The scalar anchor or @c NULL. - * @param[in] tag The scalar tag or @c NULL. - * @param[in] value The scalar value. - * @param[in] length The length of the scalar value. - * @param[in] plain_implicit If the tag may be omitted for the plain - * style. - * @param[in] quoted_implicit If the tag may be omitted for any - * non-plain style. - * @param[in] style The scalar style. + * @param[out] event An empty event object. + * @param[in] anchor The scalar anchor or @c NULL. + * @param[in] tag The scalar tag or @c NULL. If + * latter, one of the + * @a is_plain_implicit and + * @a is_quoted_implicit flags must + * be set. + * @param[in] value The scalar value. + * @param[in] length The length of the scalar value. + * @param[in] is_plain_implicit Set if the tag may be omitted for + * the plain style. + * @param[in] is_quoted_implicit Set if the tag may be omitted for + * any non-plain style. + * @param[in] style The scalar style. This attribute + * may be ignored by the emitter. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_scalar_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, - yaml_char_t *value, int length, - int plain_implicit, int quoted_implicit, +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, yaml_scalar_style_t style); /** * Create a SEQUENCE-START event. * - * The @a style argument may be ignored by the emitter. - * - * Either the @a tag attribute or the @a implicit flag must be set. - * * @param[out] event An empty event object. * @param[in] anchor The sequence anchor or @c NULL. - * @param[in] tag The sequence tag or @c NULL. - * @param[in] implicit If the tag may be omitted. - * @param[in] style The sequence style. + * @param[in] tag The sequence tag or @c NULL. If latter, the + * @a is_implicit flag must be set. + * @param[in] is_implicit Set if the tag may be omitted. + * @param[in] style The sequence style. This attribute may be + * ignored by the parser. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_sequence_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, - yaml_sequence_style_t style); +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); /** * Create a SEQUENCE-END event. @@ -611,28 +743,25 @@ yaml_sequence_start_event_initialize(yaml_event_t *event, */ YAML_DECLARE(int) -yaml_sequence_end_event_initialize(yaml_event_t *event); +yaml_event_create_sequence_end(yaml_event_t *event); /** * Create a MAPPING-START event. * - * The @a style argument may be ignored by the emitter. - * - * Either the @a tag attribute or the @a implicit flag must be set. - * * @param[out] event An empty event object. * @param[in] anchor The mapping anchor or @c NULL. - * @param[in] tag The mapping tag or @c NULL. - * @param[in] implicit If the tag may be omitted. + * @param[in] tag The mapping tag or @c NULL. If latter, the + * @a is_implicit flag must be set. + * @param[in] is_implicit Set if the tag may be omitted. * @param[in] style The mapping style. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_mapping_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, - yaml_mapping_style_t style); +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); /** * Create a MAPPING-END event. @@ -643,7 +772,7 @@ yaml_mapping_start_event_initialize(yaml_event_t *event, */ YAML_DECLARE(int) -yaml_mapping_end_event_initialize(yaml_event_t *event); +yaml_event_create_mapping_end(yaml_event_t *event); /** * Free any memory allocated for an event object. @@ -652,7 +781,7 @@ yaml_mapping_end_event_initialize(yaml_event_t *event); */ YAML_DECLARE(void) -yaml_event_delete(yaml_event_t *event); +yaml_event_destroy(yaml_event_t *event); /** @} */ @@ -671,8 +800,6 @@ yaml_event_delete(yaml_event_t *event); #define YAML_INT_TAG "tag:yaml.org,2002:int" /** The tag @c !!float for float values. */ #define YAML_FLOAT_TAG "tag:yaml.org,2002:float" -/** The tag @c !!timestamp for date and time values. */ -#define YAML_TIMESTAMP_TAG "tag:yaml.org,2002:timestamp" /** The tag @c !!seq is used to denote sequences. */ #define YAML_SEQ_TAG "tag:yaml.org,2002:seq" @@ -699,6 +826,19 @@ typedef enum yaml_node_type_e { YAML_MAPPING_NODE } yaml_node_type_t; +/** Arc types. */ +typedef enum yaml_arc_type_e { + /** An empty arc. */ + YAML_NO_ARC, + + /** An item of a sequence. */ + YAML_SEQUENCE_ITEM_ARC, + /** A key of a mapping. */ + YAML_MAPPING_KEY_ARC, + /** A value of a mapping. */ + YAML_MAPPING_VALUE_ARC +} yaml_arc_type_t; + /** The forward definition of a document node structure. */ typedef struct yaml_node_s yaml_node_t; @@ -713,12 +853,24 @@ typedef struct yaml_node_pair_s { int value; } yaml_node_pair_t; +/** An element of a path in a YAML document. */ +typedef struct yaml_arc_s { + /** The arc type. */ + yaml_arc_type_t type; + /** The collection node. */ + int node; + /** A pointer in the collection node. */ + int item; +} yaml_arc_t; + /** The node structure. */ struct yaml_node_s { /** The node type. */ yaml_node_type_t type; + /** The node anchor. */ + yaml_char_t *anchor; /** The node tag. */ yaml_char_t *tag; @@ -737,14 +889,14 @@ struct yaml_node_s { /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */ struct { - /** The stack of sequence items. */ + /** The list of sequence items. */ struct { - /** The beginning of the stack. */ - yaml_node_item_t *start; - /** The end of the stack. */ - yaml_node_item_t *end; - /** The top of the stack. */ - yaml_node_item_t *top; + /** The beginning of the list. */ + yaml_node_item_t *list; + /** The length of the list. */ + size_t length; + /** The capacity of the list. */ + size_t capacity; } items; /** The sequence style. */ yaml_sequence_style_t style; @@ -752,14 +904,14 @@ struct yaml_node_s { /** The mapping parameters (for @c YAML_MAPPING_NODE). */ struct { - /** The stack of mapping pairs (key, value). */ + /** The list of mapping pairs (key, value). */ struct { - /** The beginning of the stack. */ - yaml_node_pair_t *start; - /** The end of the stack. */ - yaml_node_pair_t *end; - /** The top of the stack. */ - yaml_node_pair_t *top; + /** The beginning of the list. */ + yaml_node_pair_t *list; + /** The length of the list. */ + size_t length; + /** The capacity of the list. */ + size_t capacity; } pairs; /** The mapping style. */ yaml_mapping_style_t style; @@ -774,17 +926,53 @@ struct yaml_node_s { }; +/** The incomplete node structure. */ +typedef struct yaml_incomplete_node_s { + + /** The node type. */ + yaml_node_type_t type; + + /** The path to the new node. */ + struct { + /** The beginning of the list. */ + yaml_arc_t *list; + /** The length of the list. */ + size_t length; + /** The capacity of the list. */ + size_t capacity; + } path; + + /** The node data. */ + union { + + /** The scalar parameters (for @c YAML_SCALAR_NODE). */ + struct { + /** The scalar value. */ + yaml_char_t *value; + /** The length of the scalar value. */ + size_t length; + /** Set if the scalar is plain. */ + int is_plain; + } scalar; + + } data; + + /** The position of the node. */ + yaml_mark_t mark; + +} yaml_incomplete_node_t; + /** The document structure. */ typedef struct yaml_document_s { /** The document nodes. */ struct { - /** The beginning of the stack. */ - yaml_node_t *start; - /** The end of the stack. */ - yaml_node_t *end; - /** The top of the stack. */ - yaml_node_t *top; + /** The beginning of the list. */ + yaml_node_t *list; + /** The length of the list. */ + size_t length; + /** The capacity of the list. */ + size_t capacity; } nodes; /** The version directive. */ @@ -792,16 +980,18 @@ typedef struct yaml_document_s { /** The list of tag directives. */ struct { - /** The beginning of the tag directives list. */ - yaml_tag_directive_t *start; - /** The end of the tag directives list. */ - yaml_tag_directive_t *end; + /** The beginning of the tag directive list. */ + yaml_tag_directive_t *list; + /** The length of the tag directive list. */ + size_t length; + /** The capacity of the tag directive list. */ + size_t capacity; } tag_directives; /** Is the document start indicator implicit? */ - int start_implicit; + int is_start_implicit; /** Is the document end indicator implicit? */ - int end_implicit; + int is_end_implicit; /** The beginning of the document. */ yaml_mark_t start_mark; @@ -810,30 +1000,60 @@ typedef struct yaml_document_s { } yaml_document_t; +#if 0 + +/** + * Allocate a new empty document object. + * + * @returns a new document object or @c NULL on error. + */ + +YAML_DECLARE(yaml_document_t *) +yaml_document_new(void); + +/** + * Delete and deallocatge a document object. + * + * @param[in,out] document A document object. + */ + +YAML_DECLARE(void) +yaml_document_delete(yaml_document_t *document); + +/** + * Duplicate a document object. + * + * @param[in,out] document An empty document object. + * @param[in] model A document to copy. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_duplicate(yaml_document_t *document, yaml_document_t *model); + /** * Create a YAML document. * * @param[out] document An empty document object. * @param[in] version_directive The %YAML directive value or * @c NULL. - * @param[in] tag_directives_start The beginning of the %TAG - * directives list. - * @param[in] tag_directives_end The end of the %TAG directives - * list. - * @param[in] start_implicit If the document start indicator is + * @param[in] tag_directives The list of the %TAG directives or + * @c NULL. The list must end with + * the pair @c (NULL,NULL). + * @param[in] is_start_implicit If the document start indicator is * implicit. - * @param[in] end_implicit If the document end indicator is + * @param[in] is_end_implicit If the document end indicator is * implicit. * * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_document_initialize(yaml_document_t *document, +yaml_document_create(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_tag_directive_t *tag_directives, + int is_start_implicit, int is_end_implicit); /** * Delete a YAML document and all its nodes. @@ -842,13 +1062,13 @@ yaml_document_initialize(yaml_document_t *document, */ YAML_DECLARE(void) -yaml_document_delete(yaml_document_t *document); +yaml_document_destroy(yaml_document_t *document); /** * Get a node of a YAML document. * * The pointer returned by this function is valid until any of the functions - * modifying the documents are called. + * modifying the documents is called. * * @param[in] document A document object. * @param[in] index The node id. @@ -865,7 +1085,7 @@ yaml_document_get_node(yaml_document_t *document, int index); * The root object is the first object added to the document. * * The pointer returned by this function is valid until any of the functions - * modifying the documents are called. + * modifying the documents is called. * * An empty document produced by the parser signifies the end of a YAML * stream. @@ -884,6 +1104,7 @@ yaml_document_get_root_node(yaml_document_t *document); * The @a style argument may be ignored by the emitter. * * @param[in,out] document A document object. + * @param[in] anchor A preferred anchor for the node or @c NULL. * @param[in] tag The scalar tag. * @param[in] value The scalar value. * @param[in] length The length of the scalar value. @@ -894,8 +1115,8 @@ 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_scalar_style_t style); + yaml_char_t *anchor, yaml_char_t *tag, yaml_char_t *value, + size_t length, yaml_scalar_style_t style); /** * Create a SEQUENCE node and attach it to the document. @@ -903,6 +1124,7 @@ yaml_document_add_scalar(yaml_document_t *document, * The @a style argument may be ignored by the emitter. * * @param[in,out] document A document object. + * @param[in] anchor A preferred anchor for the node or @c NULL. * @param[in] tag The sequence tag. * @param[in] style The sequence style. * @@ -911,7 +1133,7 @@ yaml_document_add_scalar(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_sequence(yaml_document_t *document, - yaml_char_t *tag, yaml_sequence_style_t style); + yaml_char_t *anchor, yaml_char_t *tag, yaml_sequence_style_t style); /** * Create a MAPPING node and attach it to the document. @@ -919,6 +1141,7 @@ yaml_document_add_sequence(yaml_document_t *document, * The @a style argument may be ignored by the emitter. * * @param[in,out] document A document object. + * @param[in] anchor A preferred anchor for the node or @c NULL. * @param[in] tag The sequence tag. * @param[in] style The sequence style. * @@ -927,7 +1150,7 @@ yaml_document_add_sequence(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_mapping(yaml_document_t *document, - yaml_char_t *tag, yaml_mapping_style_t style); + yaml_char_t *anchor, yaml_char_t *tag, yaml_mapping_style_t style); /** * Add an item to a SEQUENCE node. @@ -958,10 +1181,10 @@ YAML_DECLARE(int) yaml_document_append_mapping_pair(yaml_document_t *document, int mapping, int key, int value); -/** @} */ +#endif /** - * @defgroup parser Parser Definitions + * @defgroup callbacks Callback Definitions * @{ */ @@ -969,352 +1192,86 @@ yaml_document_append_mapping_pair(yaml_document_t *document, * The prototype of a read handler. * * The read handler is called when the parser needs to read more bytes from the - * source. The handler should write not more than @a size bytes to the @a - * buffer. The number of written bytes should be set to the @a length variable. + * source. The handler should read no more than @a size bytes and write them + * to the @a buffer. The number of the read bytes should be returned using the + * @a size_read variable. If the handler reaches the stream end, @a size_read + * must be set to @c 0. * * @param[in,out] data A pointer to an application data specified by - * yaml_parser_set_input(). + * @c yaml_parser_set_reader(). * @param[out] buffer The buffer to write the data from the source. - * @param[in] size The size of the buffer. - * @param[out] size_read The actual number of bytes read from the source. + * @param[in] capacity The maximum number of bytes the buffer can hold. + * @param[out] length The actual number of bytes read from the source. * * @returns On success, the handler should return @c 1. If the handler failed, * the returned value should be @c 0. On EOF, the handler should set the * @a size_read to @c 0 and return @c 1. */ -typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size, - size_t *size_read); +typedef int yaml_reader_t(void *data, unsigned char *buffer, size_t capacity, + size_t *length); /** - * This structure holds information about a potential simple key. + * The prototype of a write handler. + * + * The write handler is called when the emitter needs to flush the accumulated + * characters to the output. The handler should write @a size bytes of the + * @a buffer to the output. + * + * @param[in,out] data A pointer to an application data specified by + * @c yaml_emitter_set_writer(). + * @param[in] buffer The buffer with bytes to be written. + * @param[in] length The number of bytes to be written. + * + * @returns On success, the handler should return @c 1. If the handler failed, + * it should return @c 0. */ -typedef struct yaml_simple_key_s { - /** Is a simple key possible? */ - int possible; - - /** Is a simple key required? */ - int required; - - /** The number of the token. */ - size_t token_number; - - /** The position mark. */ - yaml_mark_t mark; -} yaml_simple_key_t; - -/** - * The states of the parser. - */ -typedef enum yaml_parser_state_e { - /** Expect STREAM-START. */ - YAML_PARSE_STREAM_START_STATE, - /** Expect the beginning of an implicit document. */ - YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, - /** Expect DOCUMENT-START. */ - YAML_PARSE_DOCUMENT_START_STATE, - /** Expect the content of a document. */ - YAML_PARSE_DOCUMENT_CONTENT_STATE, - /** Expect DOCUMENT-END. */ - YAML_PARSE_DOCUMENT_END_STATE, - /** Expect a block node. */ - YAML_PARSE_BLOCK_NODE_STATE, - /** Expect a block node or indentless sequence. */ - YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE, - /** Expect a flow node. */ - YAML_PARSE_FLOW_NODE_STATE, - /** Expect the first entry of a block sequence. */ - YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, - /** Expect an entry of a block sequence. */ - YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, - /** Expect an entry of an indentless sequence. */ - YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, - /** Expect the first key of a block mapping. */ - YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, - /** Expect a block mapping key. */ - YAML_PARSE_BLOCK_MAPPING_KEY_STATE, - /** Expect a block mapping value. */ - YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, - /** Expect the first entry of a flow sequence. */ - YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, - /** Expect an entry of a flow sequence. */ - YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, - /** Expect a key of an ordered mapping. */ - YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE, - /** Expect a value of an ordered mapping. */ - YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, - /** Expect the and of an ordered mapping entry. */ - YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE, - /** Expect the first key of a flow mapping. */ - YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, - /** Expect a key of a flow mapping. */ - YAML_PARSE_FLOW_MAPPING_KEY_STATE, - /** Expect a value of a flow mapping. */ - YAML_PARSE_FLOW_MAPPING_VALUE_STATE, - /** Expect an empty value of a flow mapping. */ - YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, - /** Expect nothing. */ - YAML_PARSE_END_STATE -} yaml_parser_state_t; - -/** - * This structure holds aliases data. - */ - -typedef struct yaml_alias_data_s { - /** The anchor. */ - yaml_char_t *anchor; - /** The node id. */ - int index; - /** The anchor mark. */ - yaml_mark_t mark; -} yaml_alias_data_t; +typedef int yaml_writer_t(void *data, unsigned char *buffer, size_t length); /** - * The parser structure. + * The prototype of a tag resolver. + * + * The resolve handler is called when the parser encounters a new node without + * an explicit tag. The handler should determine the correct tag of the node + * basing on the node kind, the path to the node from the document root and, + * in the case of the scalar node, the node value. The handler is also called + * by the emitter to determine whether the node tag could be omitted. * - * All members are internal. Manage the structure using the @c yaml_parser_ - * family of functions. + * @param[in,out] data A pointer to an application data specified by + * @c yaml_parser_set_writter() or + * @c yaml_emitter_set_writer(). + * @param[in] node Information about the new node. + * @param[out] tag The guessed node tag. + * + * @returns On success, the handler should return @c 1. If the handler failed, + * it should return @c 0. */ -typedef struct yaml_parser_s { - - /** - * @name Error handling - * @{ - */ - - /** Error type. */ - yaml_error_type_t error; - /** Error description. */ - const char *problem; - /** The byte about which the problem occured. */ - size_t problem_offset; - /** The problematic value (@c -1 is none). */ - int problem_value; - /** The problem position. */ - yaml_mark_t problem_mark; - /** The error context. */ - const char *context; - /** The context position. */ - yaml_mark_t context_mark; - - /** - * @} - */ - - /** - * @name Reader stuff - * @{ - */ - - /** Read handler. */ - yaml_read_handler_t *read_handler; - - /** A pointer for passing to the read handler. */ - void *read_handler_data; - - /** Standard (string or file) input data. */ - union { - /** String input data. */ - struct { - /** The string start pointer. */ - const unsigned char *start; - /** The string end pointer. */ - const unsigned char *end; - /** The string current position. */ - const unsigned char *current; - } string; - - /** File input data. */ - FILE *file; - } input; - - /** EOF flag */ - int eof; - - /** The working buffer. */ - struct { - /** The beginning of the buffer. */ - yaml_char_t *start; - /** The end of the buffer. */ - yaml_char_t *end; - /** The current position of the buffer. */ - yaml_char_t *pointer; - /** The last filled position of the buffer. */ - yaml_char_t *last; - } buffer; - - /* The number of unread characters in the buffer. */ - size_t unread; - - /** The raw buffer. */ - struct { - /** The beginning of the buffer. */ - unsigned char *start; - /** The end of the buffer. */ - unsigned char *end; - /** The current position of the buffer. */ - unsigned char *pointer; - /** The last filled position of the buffer. */ - unsigned char *last; - } raw_buffer; - - /** The input encoding. */ - yaml_encoding_t encoding; - - /** The offset of the current position (in bytes). */ - size_t offset; - - /** The mark of the current position. */ - yaml_mark_t mark; - - /** - * @} - */ - - /** - * @name Scanner stuff - * @{ - */ - - /** Have we started to scan the input stream? */ - int stream_start_produced; - - /** Have we reached the end of the input stream? */ - int stream_end_produced; - - /** The number of unclosed '[' and '{' indicators. */ - int flow_level; - - /** The tokens queue. */ - struct { - /** The beginning of the tokens queue. */ - yaml_token_t *start; - /** The end of the tokens queue. */ - yaml_token_t *end; - /** The head of the tokens queue. */ - yaml_token_t *head; - /** The tail of the tokens queue. */ - yaml_token_t *tail; - } tokens; - - /** The number of tokens fetched from the queue. */ - size_t tokens_parsed; - - /* Does the tokens queue contain a token ready for dequeueing. */ - int token_available; - - /** The indentation levels stack. */ - struct { - /** The beginning of the stack. */ - int *start; - /** The end of the stack. */ - int *end; - /** The top of the stack. */ - int *top; - } indents; - - /** The current indentation level. */ - int indent; - - /** May a simple key occur at the current position? */ - int simple_key_allowed; - - /** The stack of simple keys. */ - struct { - /** The beginning of the stack. */ - yaml_simple_key_t *start; - /** The end of the stack. */ - yaml_simple_key_t *end; - /** The top of the stack. */ - yaml_simple_key_t *top; - } simple_keys; - - /** - * @} - */ - - /** - * @name Parser stuff - * @{ - */ - - /** The parser states stack. */ - struct { - /** The beginning of the stack. */ - yaml_parser_state_t *start; - /** The end of the stack. */ - yaml_parser_state_t *end; - /** The top of the stack. */ - yaml_parser_state_t *top; - } states; - - /** The current parser state. */ - yaml_parser_state_t state; - - /** The stack of marks. */ - struct { - /** The beginning of the stack. */ - yaml_mark_t *start; - /** The end of the stack. */ - yaml_mark_t *end; - /** The top of the stack. */ - yaml_mark_t *top; - } marks; - - /** The list of TAG directives. */ - struct { - /** The beginning of the list. */ - yaml_tag_directive_t *start; - /** The end of the list. */ - yaml_tag_directive_t *end; - /** The top of the list. */ - yaml_tag_directive_t *top; - } tag_directives; - - /** - * @} - */ +typedef int yaml_resolver_t(void *data, yaml_incomplete_node_t *node, + yaml_char_t **tag); - /** - * @name Dumper stuff - * @{ - */ - - /** The alias data. */ - struct { - /** The beginning of the list. */ - yaml_alias_data_t *start; - /** The end of the list. */ - yaml_alias_data_t *end; - /** The top of the list. */ - yaml_alias_data_t *top; - } aliases; - - /** The currently parsed document. */ - yaml_document_t *document; +/** @} */ - /** - * @} - */ +/** + * @defgroup parser Parser Definitions + * @{ + */ -} yaml_parser_t; +/** The parser object. */ +typedef struct yaml_parser_s yaml_parser_t; /** - * Initialize a parser. + * Create a new parser object. * * This function creates a new parser object. An application is responsible - * for destroying the object using the yaml_parser_delete() function. + * for destroying the object using the @c yaml_parser_delete() function. * - * @param[out] parser An empty parser object. - * - * @returns @c 1 if the function succeeded, @c 0 on error. + * @returns a new parser object or @c NULL on error. */ -YAML_DECLARE(int) -yaml_parser_initialize(yaml_parser_t *parser); +YAML_DECLARE(yaml_parser_t *) +yaml_parser_new(void); /** * Destroy a parser. @@ -1325,6 +1282,16 @@ yaml_parser_initialize(yaml_parser_t *parser); YAML_DECLARE(void) yaml_parser_delete(yaml_parser_t *parser); +/** + * Get a parser error. + * + * @param[in] parser A parser object. + * @param[out] error An error object. + */ + +YAML_DECLARE(void) +yaml_parser_get_error(yaml_parser_t *parser, yaml_error_t *error); + /** * Set a string input. * @@ -1333,13 +1300,13 @@ yaml_parser_delete(yaml_parser_t *parser); * destroying the @a parser. * * @param[in,out] parser A parser object. - * @param[in] input A source data. - * @param[in] size The length of the source data in bytes. + * @param[in] buffer A source data. + * @param[in] length The length of the source data in bytes. */ YAML_DECLARE(void) -yaml_parser_set_input_string(yaml_parser_t *parser, - const unsigned char *input, size_t size); +yaml_parser_set_string_reader(yaml_parser_t *parser, + const unsigned char *buffer, size_t length); /** * Set a file input. @@ -1352,20 +1319,52 @@ yaml_parser_set_input_string(yaml_parser_t *parser, */ YAML_DECLARE(void) -yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file); +yaml_parser_set_file_reader(yaml_parser_t *parser, FILE *file); /** * Set a generic input handler. * * @param[in,out] parser A parser object. - * @param[in] handler A read handler. + * @param[in] reader A read handler. * @param[in] data Any application data for passing to the read * handler. */ YAML_DECLARE(void) -yaml_parser_set_input(yaml_parser_t *parser, - yaml_read_handler_t *handler, void *data); +yaml_parser_set_reader(yaml_parser_t *parser, + yaml_reader_t *reader, void *data); + +#if 0 + +/** + * Set the standard resolve handler. + * + * The standard resolver recognize the following scalar kinds: !!null, !!bool, + * !!str, !!int and !!float. + * + * @param[in,out] parser A parser object. + */ + +YAML_DECLARE(void) +yaml_parser_set_standard_resolver(yaml_parser_t *parser); + +/** + * Set the resolve handler. + * + * The standard resolver recognize the following scalar kinds: !!null, !!bool, + * !!str, !!int and !!float. + * + * @param[in,out] parser A parser object. + * @param[in] resolver A resolve handler. + * @param[in] data Any application data for passing to the resolve + * handler. + */ + +YAML_DECLARE(void) +yaml_parser_set_resolver(yaml_parser_t *parser, + yaml_resolver_t *resolver, void *data); + +#endif /** * Set the source encoding. @@ -1386,11 +1385,11 @@ yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding); * @c YAML_STREAM_END_TOKEN. * * An application is responsible for freeing any buffers associated with the - * produced token object using the @c yaml_token_delete function. + * produced token object using the @c yaml_token_delete() function. * - * An application must not alternate the calls of yaml_parser_scan() with the - * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break - * the parser. + * An application must not alternate the calls of @c yaml_parser_scan() with + * the calls of @c yaml_parser_parse() or @c yaml_parser_load(). Doing this + * will break the parser. * * @param[in,out] parser A parser object. * @param[out] token An empty token object. @@ -1410,11 +1409,11 @@ yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); * @c YAML_STREAM_END_EVENT. * * An application is responsible for freeing any buffers associated with the - * produced event object using the yaml_event_delete() function. + * produced event object using the @c yaml_event_delete() function. * - * An application must not alternate the calls of yaml_parser_parse() with the - * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the - * parser. + * An application must not alternate the calls of @c yaml_parser_parse() with + * the calls of @c yaml_parser_scan() or @c yaml_parser_load(). Doing this will + * break the parser. * * @param[in,out] parser A parser object. * @param[out] event An empty event object. @@ -1425,6 +1424,8 @@ yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); YAML_DECLARE(int) yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); +#if 0 + /** * Parse the input stream and produce the next YAML document. * @@ -1435,11 +1436,11 @@ yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); * end has been reached. * * An application is responsible for freeing any data associated with the - * produced document object using the yaml_document_delete() function. + * produced document object using the @c yaml_document_delete() function. * - * An application must not alternate the calls of yaml_parser_load() with the - * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break - * the parser. + * An application must not alternate the calls of @c yaml_parser_load() with + * the calls of @c yaml_parser_scan() or @c yaml_parser_parse(). Doing this + * will break the parser. * * @param[in,out] parser A parser object. * @param[out] document An empty document object. @@ -1450,6 +1451,8 @@ yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); YAML_DECLARE(int) yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); +#endif + /** @} */ /** @@ -1457,321 +1460,20 @@ yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); * @{ */ -/** - * The prototype of a write handler. - * - * The write handler is called when the emitter needs to flush the accumulated - * characters to the output. The handler should write @a size bytes of the - * @a buffer to the output. - * - * @param[in,out] data A pointer to an application data specified by - * yaml_emitter_set_output(). - * @param[in] buffer The buffer with bytes to be written. - * @param[in] size The size of the buffer. - * - * @returns On success, the handler should return @c 1. If the handler failed, - * the returned value should be @c 0. - */ - -typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size); - -/** The emitter states. */ -typedef enum yaml_emitter_state_e { - /** Expect STREAM-START. */ - YAML_EMIT_STREAM_START_STATE, - /** Expect the first DOCUMENT-START or STREAM-END. */ - YAML_EMIT_FIRST_DOCUMENT_START_STATE, - /** Expect DOCUMENT-START or STREAM-END. */ - YAML_EMIT_DOCUMENT_START_STATE, - /** Expect the content of a document. */ - YAML_EMIT_DOCUMENT_CONTENT_STATE, - /** Expect DOCUMENT-END. */ - YAML_EMIT_DOCUMENT_END_STATE, - /** Expect the first item of a flow sequence. */ - YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, - /** Expect an item of a flow sequence. */ - YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, - /** Expect the first key of a flow mapping. */ - YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, - /** Expect a key of a flow mapping. */ - YAML_EMIT_FLOW_MAPPING_KEY_STATE, - /** 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. */ - YAML_EMIT_FLOW_MAPPING_VALUE_STATE, - /** Expect the first item of a block sequence. */ - YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, - /** Expect an item of a block sequence. */ - YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, - /** Expect the first key of a block mapping. */ - YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, - /** Expect the key of a block mapping. */ - YAML_EMIT_BLOCK_MAPPING_KEY_STATE, - /** 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. */ - YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, - /** Expect nothing. */ - YAML_EMIT_END_STATE -} yaml_emitter_state_t; - -/** - * The emitter structure. - * - * All members are internal. Manage the structure using the @c yaml_emitter_ - * family of functions. - */ - -typedef struct yaml_emitter_s { - - /** - * @name Error handling - * @{ - */ - - /** Error type. */ - yaml_error_type_t error; - /** Error description. */ - const char *problem; - - /** - * @} - */ - - /** - * @name Writer stuff - * @{ - */ - - /** Write handler. */ - yaml_write_handler_t *write_handler; - - /** A pointer for passing to the white handler. */ - void *write_handler_data; - - /** Standard (string or file) output data. */ - union { - /** String output data. */ - struct { - /** The buffer pointer. */ - unsigned char *buffer; - /** The buffer size. */ - size_t size; - /** The number of written bytes. */ - size_t *size_written; - } string; - - /** File output data. */ - FILE *file; - } output; - - /** The working buffer. */ - struct { - /** The beginning of the buffer. */ - yaml_char_t *start; - /** The end of the buffer. */ - yaml_char_t *end; - /** The current position of the buffer. */ - yaml_char_t *pointer; - /** The last filled position of the buffer. */ - yaml_char_t *last; - } buffer; - - /** The raw buffer. */ - struct { - /** The beginning of the buffer. */ - unsigned char *start; - /** The end of the buffer. */ - unsigned char *end; - /** The current position of the buffer. */ - unsigned char *pointer; - /** The last filled position of the buffer. */ - unsigned char *last; - } raw_buffer; - - /** The stream encoding. */ - yaml_encoding_t encoding; - - /** - * @} - */ - - /** - * @name Emitter stuff - * @{ - */ - - /** If the output is in the canonical style? */ - int canonical; - /** The number of indentation spaces. */ - int best_indent; - /** The preferred width of the output lines. */ - int best_width; - /** Allow unescaped non-ASCII characters? */ - int unicode; - /** The preferred line break. */ - yaml_break_t line_break; - - /** The stack of states. */ - struct { - /** The beginning of the stack. */ - yaml_emitter_state_t *start; - /** The end of the stack. */ - yaml_emitter_state_t *end; - /** The top of the stack. */ - yaml_emitter_state_t *top; - } states; - - /** The current emitter state. */ - yaml_emitter_state_t state; - - /** The event queue. */ - struct { - /** The beginning of the event queue. */ - yaml_event_t *start; - /** The end of the event queue. */ - yaml_event_t *end; - /** The head of the event queue. */ - yaml_event_t *head; - /** The tail of the event queue. */ - yaml_event_t *tail; - } events; - - /** The stack of indentation levels. */ - struct { - /** The beginning of the stack. */ - int *start; - /** The end of the stack. */ - int *end; - /** The top of the stack. */ - int *top; - } indents; - - /** The list of tag directives. */ - struct { - /** The beginning of the list. */ - yaml_tag_directive_t *start; - /** The end of the list. */ - yaml_tag_directive_t *end; - /** The top of the list. */ - yaml_tag_directive_t *top; - } tag_directives; - - /** The current indentation level. */ - int indent; - - /** The current flow level. */ - int flow_level; - - /** Is it the document root context? */ - int root_context; - /** Is it a sequence context? */ - int sequence_context; - /** Is it a mapping context? */ - int mapping_context; - /** Is it a simple mapping key context? */ - int simple_key_context; - - /** The current line. */ - int line; - /** The current column. */ - int column; - /** If the last character was a whitespace? */ - int whitespace; - /** If the last character was an indentation character (' ', '-', '?', ':')? */ - int indention; - - /** Anchor analysis. */ - struct { - /** The anchor value. */ - yaml_char_t *anchor; - /** The anchor length. */ - size_t anchor_length; - /** Is it an alias? */ - int alias; - } anchor_data; - - /** Tag analysis. */ - struct { - /** The tag handle. */ - yaml_char_t *handle; - /** The tag handle length. */ - size_t handle_length; - /** The tag suffix. */ - yaml_char_t *suffix; - /** The tag suffix length. */ - size_t suffix_length; - } tag_data; - - /** Scalar analysis. */ - struct { - /** The scalar value. */ - yaml_char_t *value; - /** The scalar length. */ - size_t length; - /** Does the scalar contain line breaks? */ - int multiline; - /** Can the scalar be expessed in the flow plain style? */ - int flow_plain_allowed; - /** Can the scalar be expressed in the block plain style? */ - int block_plain_allowed; - /** Can the scalar be expressed in the single quoted style? */ - int single_quoted_allowed; - /** Can the scalar be expressed in the literal or folded styles? */ - int block_allowed; - /** The output style. */ - yaml_scalar_style_t style; - } scalar_data; - - /** - * @} - */ - - /** - * @name Dumper stuff - * @{ - */ - - /** If the stream was already opened? */ - int opened; - /** If the stream was already closed? */ - int closed; - - /** The information associated with the document nodes. */ - struct { - /** The number of references. */ - int references; - /** The anchor id. */ - int anchor; - /** If the node has been emitted? */ - int serialized; - } *anchors; - - /** The last assigned anchor id. */ - int last_anchor_id; - - /** The currently emitted document. */ - yaml_document_t *document; - - /** - * @} - */ - -} yaml_emitter_t; +/** The emitter object. */ +typedef struct yaml_emitter_s yaml_emitter_t; /** - * Initialize an emitter. + * Create a new emitter object. * * This function creates a new emitter object. An application is responsible - * for destroying the object using the yaml_emitter_delete() function. - * - * @param[out] emitter An empty parser object. + * for destroying the object using the @c yaml_emitter_delete() function. * - * @returns @c 1 if the function succeeded, @c 0 on error. + * @returns a new emitter object or @c NULL on error. */ -YAML_DECLARE(int) -yaml_emitter_initialize(yaml_emitter_t *emitter); +YAML_DECLARE(yaml_emitter_t *) +yaml_emitter_new(void); /** * Destroy an emitter. @@ -1782,24 +1484,34 @@ yaml_emitter_initialize(yaml_emitter_t *emitter); YAML_DECLARE(void) yaml_emitter_delete(yaml_emitter_t *emitter); +/** + * Get an emitter error. + * + * @param[in] emitter An emitter object. + * @param[out] error An error object. + */ + +YAML_DECLARE(void) +yaml_emitter_get_error(yaml_emitter_t *emitter, yaml_error_t *error); + /** * Set a string output. * * The emitter will write the output characters to the @a output buffer of the * size @a size. The emitter will set @a size_written to the number of written * bytes. If the buffer is smaller than required, the emitter produces the - * YAML_WRITE_ERROR error. + * @c YAML_WRITE_ERROR error. * * @param[in,out] emitter An emitter object. - * @param[in] output An output buffer. - * @param[in] size The buffer size. - * @param[in] size_written The pointer to save the number of written + * @param[in] buffer An output buffer. + * @param[in] length The pointer to save the number of written * bytes. + * @param[in] capacity The buffer size. */ YAML_DECLARE(void) -yaml_emitter_set_output_string(yaml_emitter_t *emitter, - unsigned char *output, size_t size, size_t *size_written); +yaml_emitter_set_string_writer(yaml_emitter_t *emitter, + unsigned char *buffer, size_t *length, size_t capacity); /** * Set a file output. @@ -1812,20 +1524,52 @@ yaml_emitter_set_output_string(yaml_emitter_t *emitter, */ YAML_DECLARE(void) -yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file); +yaml_emitter_set_file_writer(yaml_emitter_t *emitter, FILE *file); /** * Set a generic output handler. * * @param[in,out] emitter An emitter object. - * @param[in] handler A write handler. + * @param[in] writer A write handler. * @param[in] data Any application data for passing to the write * handler. */ YAML_DECLARE(void) -yaml_emitter_set_output(yaml_emitter_t *emitter, - yaml_write_handler_t *handler, void *data); +yaml_emitter_set_writer(yaml_emitter_t *emitter, + yaml_writer_t *writer, void *data); + +#if 0 + +/** + * Set the standard resolve handler. + * + * The standard resolver recognize the following scalar kinds: !!null, !!bool, + * !!str, !!int and !!float. + * + * @param[in,out] emitter An emitter object. + */ + +YAML_DECLARE(void) +yaml_emitter_set_standard_resolver(yaml_emitter_t *emitter); + +/** + * Set the resolve handler. + * + * The standard resolver recognize the following scalar kinds: !!null, !!bool, + * !!str, !!int and !!float. + * + * @param[in,out] emitter An emitter object. + * @param[in] resolver A resolve handler. + * @param[in] data Any application data for passing to the resolve + * handler. + */ + +YAML_DECLARE(void) +yaml_emitter_set_resolver(yaml_emitter_t *emitter, + yaml_resolver_t *resolver, void *data); + +#endif /** * Set the output encoding. @@ -1841,12 +1585,12 @@ yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding); * Set if the output should be in the "canonical" format as in the YAML * specification. * - * @param[in,out] emitter An emitter object. - * @param[in] canonical If the output is canonical. + * @param[in,out] emitter An emitter object. + * @param[in] is_canonical If the output is canonical. */ YAML_DECLARE(void) -yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical); +yaml_emitter_set_canonical(yaml_emitter_t *emitter, int is_canonical); /** * Set the intendation increment. @@ -1872,11 +1616,11 @@ yaml_emitter_set_width(yaml_emitter_t *emitter, int width); * Set if unescaped non-ASCII characters are allowed. * * @param[in,out] emitter An emitter object. - * @param[in] unicode If unescaped Unicode characters are allowed. + * @param[in] is_unicode If unescaped Unicode characters are allowed. */ YAML_DECLARE(void) -yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode); +yaml_emitter_set_unicode(yaml_emitter_t *emitter, int is_unicode); /** * Set the preferred line break. @@ -1905,10 +1649,13 @@ yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break); YAML_DECLARE(int) yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event); +#if 0 + /** * Start a YAML stream. * - * This function should be used before yaml_emitter_dump() is called. + * This function should be used before the first @c yaml_emitter_dump() is + * called. * * @param[in,out] emitter An emitter object. * @@ -1921,7 +1668,8 @@ yaml_emitter_open(yaml_emitter_t *emitter); /** * Finish a YAML stream. * - * This function should be used after yaml_emitter_dump() is called. + * This function should be used after the last @c yaml_emitter_dump() is + * called. * * @param[in,out] emitter An emitter object. * @@ -1934,10 +1682,10 @@ yaml_emitter_close(yaml_emitter_t *emitter); /** * Emit a YAML document. * - * The documen object may be generated using the yaml_parser_load() function - * or the yaml_document_initialize() function. The emitter takes the - * responsibility for the document object and destoys its content after - * it is emitted. The document object is destroyedeven if the function fails. + * The document object may be generated using the @c yaml_parser_load() + * function or the @c yaml_document_initialize() function. The emitter takes + * the responsibility for the document object and destoys its content after + * it is emitted. The document object is destroyed even if the function fails. * * @param[in,out] emitter An emitter object. * @param[in,out] document A document object. @@ -1948,8 +1696,10 @@ yaml_emitter_close(yaml_emitter_t *emitter); YAML_DECLARE(int) yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document); +#endif + /** - * Flush the accumulated characters to the output. + * Flush the accumulated characters to the output stream. * * @param[in,out] emitter An emitter object. * diff --git a/src/api.c b/src/api.c index 02e7b14..1fefb72 100644 --- a/src/api.c +++ b/src/api.c @@ -71,41 +71,39 @@ yaml_strdup(const yaml_char_t *str) */ YAML_DECLARE(int) -yaml_string_extend(yaml_char_t **start, - yaml_char_t **pointer, yaml_char_t **end) +yaml_string_extend(yaml_char_t **buffer, size_t *capacity) { - yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2); + yaml_char_t *new_buffer = yaml_realloc(*buffer, (*capacity)*2); - if (!new_start) return 0; + if (!new_buffer) return 0; - memset(new_start + (*end - *start), 0, *end - *start); + memset(new_buffer + *capacity, 0, *capacity); - *pointer = new_start + (*pointer - *start); - *end = new_start + (*end - *start)*2; - *start = new_start; + *buffer = new_buffer; + *capacity *= 2; return 1; } /* - * Append a string B to a string A. + * Append an adjunct string to a base string. */ YAML_DECLARE(int) yaml_string_join( - yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end, - yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end) + yaml_char_t **base_buffer, size_t *base_pointer, size_t *base_capacity, + yaml_char_t *adj_buffer, size_t adj_pointer, size_t adj_capacity) { - if (*b_start == *b_pointer) + if (!adj_pointer) return 1; - while (*a_end - *a_pointer <= *b_pointer - *b_start) { - if (!yaml_string_extend(a_start, a_pointer, a_end)) + while (*base_capacity - *base_pointer <= adj_pointer) { + if (!yaml_string_extend(base_buffer, base_capacity)) return 0; } - memcpy(*a_pointer, *b_start, *b_pointer - *b_start); - *a_pointer += *b_pointer - *b_start; + memcpy(*base_buffer+*base_pointer, adj_buffer, adj_pointer); + *base_pointer += adj_pointer; return 1; } @@ -115,15 +113,14 @@ yaml_string_join( */ YAML_DECLARE(int) -yaml_stack_extend(void **start, void **top, void **end) +yaml_stack_extend(void **list, size_t size, size_t *length, size_t *capacity) { - void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2); + void *new_list = yaml_realloc(*list, (*capacity)*size*2); - if (!new_start) return 0; + if (!new_list) return 0; - *top = (char *)new_start + ((char *)*top - (char *)*start); - *end = (char *)new_start + ((char *)*end - (char *)*start)*2; - *start = new_start; + *list = new_list; + *capacity *= 2; return 1; } @@ -133,30 +130,29 @@ yaml_stack_extend(void **start, void **top, void **end) */ YAML_DECLARE(int) -yaml_queue_extend(void **start, void **head, void **tail, void **end) +yaml_queue_extend(void **list, size_t size, + size_t *head, size_t *tail, size_t *capacity) { /* Check if we need to resize the queue. */ - if (*start == *head && *tail == *end) { - void *new_start = yaml_realloc(*start, - ((char *)*end - (char *)*start)*2); + if (*head == 0 && *tail == *capacity) { + void *new_list = yaml_realloc(*list, (*capacity)*size*2); - if (!new_start) return 0; + if (!new_list) return 0; - *head = (char *)new_start + ((char *)*head - (char *)*start); - *tail = (char *)new_start + ((char *)*tail - (char *)*start); - *end = (char *)new_start + ((char *)*end - (char *)*start)*2; - *start = new_start; + *list = new_list; + *capacity *= 2; } /* Check if we need to move the queue at the beginning of the buffer. */ - if (*tail == *end) { + if (*tail == *capacity) { if (*head != *tail) { - memmove(*start, *head, (char *)*tail - (char *)*head); + memmove((char *)*list, (char *)*list + (*head)*size, + (*tail-*head)*size); } - *tail = (char *)*tail - (char *)*head + (char *)*start; - *head = *start; + *tail -= *head; + *head = 0; } return 1; @@ -167,43 +163,38 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end) * Create a new parser object. */ -YAML_DECLARE(int) -yaml_parser_initialize(yaml_parser_t *parser) +YAML_DECLARE(yaml_parser_t *) +yaml_parser_new(void) { - assert(parser); /* Non-NULL parser object expected. */ + yaml_parser_t *parser = yaml_malloc(sizeof(yaml_parser_t)); + + if (!parser) + return NULL; memset(parser, 0, sizeof(yaml_parser_t)); - if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE)) + if (!BUFFER_INIT(parser, parser->raw_input, RAW_INPUT_BUFFER_CAPACITY)) goto error; - if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE)) + if (!BUFFER_INIT(parser, parser->input, INPUT_BUFFER_CAPACITY)) goto error; - if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE)) + if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_CAPACITY)) goto error; - if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE)) + if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_CAPACITY)) goto error; - if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE)) + if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_CAPACITY)) goto error; - if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE)) + if (!STACK_INIT(parser, parser->states, INITIAL_STACK_CAPACITY)) goto error; - if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE)) + if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_CAPACITY)) goto error; - if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE)) + if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_CAPACITY)) goto error; - return 1; + return parser; error: + yaml_parser_delete(parser); - BUFFER_DEL(parser, parser->raw_buffer); - BUFFER_DEL(parser, parser->buffer); - QUEUE_DEL(parser, parser->tokens); - STACK_DEL(parser, parser->indents); - STACK_DEL(parser, parser->simple_keys); - STACK_DEL(parser, parser->states); - STACK_DEL(parser, parser->marks); - STACK_DEL(parser, parser->tag_directives); - - return 0; + return NULL; } /* @@ -215,10 +206,10 @@ yaml_parser_delete(yaml_parser_t *parser) { assert(parser); /* Non-NULL parser object expected. */ - BUFFER_DEL(parser, parser->raw_buffer); - BUFFER_DEL(parser, parser->buffer); + BUFFER_DEL(parser, parser->raw_input); + BUFFER_DEL(parser, parser->input); while (!QUEUE_EMPTY(parser, parser->tokens)) { - yaml_token_delete(&DEQUEUE(parser, parser->tokens)); + yaml_token_destroy(&DEQUEUE(parser, parser->tokens)); } QUEUE_DEL(parser, parser->tokens); STACK_DEL(parser, parser->indents); @@ -233,46 +224,58 @@ yaml_parser_delete(yaml_parser_t *parser) STACK_DEL(parser, parser->tag_directives); memset(parser, 0, sizeof(yaml_parser_t)); + yaml_free(parser); } /* - * String read handler. + * 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_read_handler(void *data, unsigned char *buffer, size_t size, - size_t *size_read) +yaml_string_reader(void *untyped_data, unsigned char *buffer, size_t capacity, + size_t *length) { - yaml_parser_t *parser = data; + yaml_standard_reader_data_t *data = untyped_data; - if (parser->input.string.current == parser->input.string.end) { - *size_read = 0; + if (data->string.pointer == data->string.capacity) { + *length = 0; return 1; } - if (size > (size_t)(parser->input.string.end - - parser->input.string.current)) { - size = parser->input.string.end - parser->input.string.current; + if (capacity > (size_t)(data->string.capacity - data->string.pointer)) { + capacity = data->string.capacity - data->string.pointer; } - memcpy(buffer, parser->input.string.current, size); - parser->input.string.current += size; - *size_read = size; + memcpy(buffer, data->string.buffer + data->string.pointer, capacity); + data->string.pointer += capacity; + *length = capacity; return 1; } /* - * File read handler. + * Standard file read handler. */ static int -yaml_file_read_handler(void *data, unsigned char *buffer, size_t size, - size_t *size_read) +yaml_file_reader(void *untyped_data, unsigned char *buffer, size_t capacity, + size_t *length) { - yaml_parser_t *parser = data; + yaml_standard_reader_data_t *data = untyped_data; - *size_read = fread(buffer, 1, size, parser->input.file); - return !ferror(parser->input.file); + *length = fread(buffer, 1, capacity, data->file); + return !ferror(data->file); } /* @@ -280,19 +283,19 @@ yaml_file_read_handler(void *data, unsigned char *buffer, size_t size, */ YAML_DECLARE(void) -yaml_parser_set_input_string(yaml_parser_t *parser, - const unsigned char *input, size_t size) +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->read_handler); /* You can set the source only once. */ - assert(input); /* Non-NULL input string expected. */ + assert(!parser->reader); /* You can set the input handler only once. */ + assert(buffer); /* Non-NULL input string expected. */ - parser->read_handler = yaml_string_read_handler; - parser->read_handler_data = parser; + parser->reader = yaml_string_reader; + parser->reader_data = &(parser->standard_reader_data); - parser->input.string.start = input; - parser->input.string.current = input; - parser->input.string.end = input+size; + parser->standard_reader_data.string.buffer = (unsigned char *)buffer; + parser->standard_reader_data.string.pointer = 0; + parser->standard_reader_data.string.capacity = length; } /* @@ -300,16 +303,16 @@ yaml_parser_set_input_string(yaml_parser_t *parser, */ YAML_DECLARE(void) -yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file) +yaml_parser_set_file_reader(yaml_parser_t *parser, FILE *file) { assert(parser); /* Non-NULL parser object expected. */ - assert(!parser->read_handler); /* You can set the source only once. */ + assert(!parser->reader); /* You can set the input handler only once. */ assert(file); /* Non-NULL file object expected. */ - parser->read_handler = yaml_file_read_handler; - parser->read_handler_data = parser; + parser->reader = yaml_file_reader; + parser->reader_data = &(parser->standard_reader_data); - parser->input.file = file; + parser->standard_reader_data.file = file; } /* @@ -317,15 +320,15 @@ yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file) */ YAML_DECLARE(void) -yaml_parser_set_input(yaml_parser_t *parser, - yaml_read_handler_t *handler, void *data) +yaml_parser_set_reader(yaml_parser_t *parser, + yaml_reader_t *reader, void *data) { assert(parser); /* Non-NULL parser object expected. */ - assert(!parser->read_handler); /* You can set the source only once. */ - assert(handler); /* Non-NULL read handler expected. */ + assert(!parser->reader); /* You can set the input handler only once. */ + assert(reader); /* Non-NULL read handler expected. */ - parser->read_handler = handler; - parser->read_handler_data = data; + parser->reader = reader; + parser->reader_data = data; } /* @@ -336,7 +339,7 @@ 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. */ + assert(!parser->encoding); /* Encoding is already set or detected. */ parser->encoding = encoding; } @@ -345,37 +348,34 @@ yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding) * Create a new emitter object. */ -YAML_DECLARE(int) -yaml_emitter_initialize(yaml_emitter_t *emitter) +YAML_DECLARE(yaml_emitter_t *) +yaml_emitter_new(void) { - assert(emitter); /* Non-NULL emitter object expected. */ + yaml_emitter_t *emitter = yaml_malloc(sizeof(yaml_emitter_t)); + + if (!emitter) + return NULL; memset(emitter, 0, sizeof(yaml_emitter_t)); - if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE)) + if (!BUFFER_INIT(emitter, emitter->output, OUTPUT_BUFFER_CAPACITY)) goto error; - if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE)) + if (!BUFFER_INIT(emitter, emitter->raw_output, RAW_OUTPUT_BUFFER_CAPACITY)) goto error; - if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE)) + if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_CAPACITY)) goto error; - if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE)) + if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_CAPACITY)) goto error; - if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE)) + if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_CAPACITY)) goto error; - if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE)) + if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_CAPACITY)) goto error; - return 1; + return emitter; error: + yaml_emitter_delete(emitter); - BUFFER_DEL(emitter, emitter->buffer); - BUFFER_DEL(emitter, emitter->raw_buffer); - STACK_DEL(emitter, emitter->states); - QUEUE_DEL(emitter, emitter->events); - STACK_DEL(emitter, emitter->indents); - STACK_DEL(emitter, emitter->tag_directives); - - return 0; + return NULL; } /* @@ -387,8 +387,8 @@ yaml_emitter_delete(yaml_emitter_t *emitter) { assert(emitter); /* Non-NULL emitter object expected. */ - BUFFER_DEL(emitter, emitter->buffer); - BUFFER_DEL(emitter, emitter->raw_buffer); + BUFFER_DEL(emitter, emitter->output); + BUFFER_DEL(emitter, emitter->raw_output); STACK_DEL(emitter, emitter->states); while (!QUEUE_EMPTY(emitter, emitter->events)) { yaml_event_delete(&DEQUEUE(emitter, emitter->events)); @@ -404,6 +404,19 @@ yaml_emitter_delete(yaml_emitter_t *emitter) 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; } /* @@ -411,25 +424,21 @@ yaml_emitter_delete(yaml_emitter_t *emitter) */ static int -yaml_string_write_handler(void *data, unsigned char *buffer, size_t size) +yaml_string_writer(void *untyped_data, unsigned char *buffer, size_t length) { - yaml_emitter_t *emitter = data; - - if (emitter->output.string.size + *emitter->output.string.size_written - < size) { - memcpy(emitter->output.string.buffer - + *emitter->output.string.size_written, - buffer, - emitter->output.string.size - - *emitter->output.string.size_written); - *emitter->output.string.size_written = emitter->output.string.size; - return 0; + 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(emitter->output.string.buffer - + *emitter->output.string.size_written, buffer, size); - *emitter->output.string.size_written += size; - return 1; + memcpy(data->string.buffer + data->string.pointer, buffer, length); + data->string.pointer += length; + *data->length += length; + + return result; } /* @@ -437,31 +446,33 @@ yaml_string_write_handler(void *data, unsigned char *buffer, size_t size) */ static int -yaml_file_write_handler(void *data, unsigned char *buffer, size_t size) +yaml_file_writer(void *untyped_data, unsigned char *buffer, size_t length) { - yaml_emitter_t *emitter = data; + yaml_standard_writer_data_t *data = untyped_data; - return (fwrite(buffer, 1, size, emitter->output.file) == size); + return (fwrite(buffer, 1, length, data->file) == length); } /* * Set a string output. */ YAML_DECLARE(void) -yaml_emitter_set_output_string(yaml_emitter_t *emitter, - unsigned char *output, size_t size, size_t *size_written) +yaml_emitter_set_string_writer(yaml_emitter_t *emitter, + unsigned char *buffer, size_t *length, size_t capacity) { assert(emitter); /* Non-NULL emitter object expected. */ - assert(!emitter->write_handler); /* You can set the output only once. */ - assert(output); /* Non-NULL output string expected. */ + assert(!emitter->writer); /* You can set the output only once. */ + assert(buffer); /* Non-NULL output string expected. */ - emitter->write_handler = yaml_string_write_handler; - emitter->write_handler_data = emitter; + emitter->writer = yaml_string_writer; + emitter->writer_data = &(emitter->standard_writer_data); - emitter->output.string.buffer = output; - emitter->output.string.size = size; - emitter->output.string.size_written = size_written; - *size_written = 0; + 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; } /* @@ -469,16 +480,16 @@ yaml_emitter_set_output_string(yaml_emitter_t *emitter, */ YAML_DECLARE(void) -yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file) +yaml_emitter_set_file_writer(yaml_emitter_t *emitter, FILE *file) { assert(emitter); /* Non-NULL emitter object expected. */ - assert(!emitter->write_handler); /* You can set the output only once. */ + assert(!emitter->writer); /* You can set the output only once. */ assert(file); /* Non-NULL file object expected. */ - emitter->write_handler = yaml_file_write_handler; - emitter->write_handler_data = emitter; + emitter->writer = yaml_string_writer; + emitter->writer_data = &(emitter->standard_writer_data); - emitter->output.file = file; + emitter->standard_writer_data.file = file; } /* @@ -486,15 +497,15 @@ yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file) */ YAML_DECLARE(void) -yaml_emitter_set_output(yaml_emitter_t *emitter, - yaml_write_handler_t *handler, void *data) +yaml_emitter_set_writer(yaml_emitter_t *emitter, + yaml_writer_t *writer, void *data) { assert(emitter); /* Non-NULL emitter object expected. */ - assert(!emitter->write_handler); /* You can set the output only once. */ - assert(handler); /* Non-NULL handler object expected. */ + assert(!emitter->writer); /* You can set the output only once. */ + assert(writer); /* Non-NULL handler object expected. */ - emitter->write_handler = handler; - emitter->write_handler_data = data; + emitter->writer = writer; + emitter->writer_data = data; } /* @@ -515,11 +526,11 @@ yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding) */ YAML_DECLARE(void) -yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical) +yaml_emitter_set_canonical(yaml_emitter_t *emitter, int is_canonical) { assert(emitter); /* Non-NULL emitter object expected. */ - emitter->canonical = (canonical != 0); + emitter->is_canonical = (is_canonical != 0); } /* @@ -551,11 +562,11 @@ yaml_emitter_set_width(yaml_emitter_t *emitter, int width) */ YAML_DECLARE(void) -yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode) +yaml_emitter_set_unicode(yaml_emitter_t *emitter, int is_unicode) { assert(emitter); /* Non-NULL emitter object expected. */ - emitter->unicode = (unicode != 0); + emitter->is_unicode = (is_unicode != 0); } /* @@ -571,7 +582,24 @@ yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break) } /* - * Destroy a token object. + * Allocate a token object. + */ + +YAML_DECLARE(yaml_token_t *) +yaml_token_new(void) +{ + yaml_token_t *token = yaml_malloc(sizeof(yaml_token_t)); + + if (!token) + return NULL; + + memset(token, 0, sizeof(yaml_token_t)); + + return token; +} + +/* + * Deallocate a token object. */ YAML_DECLARE(void) @@ -579,6 +607,98 @@ yaml_token_delete(yaml_token_t *token) { assert(token); /* Non-NULL token object expected. */ + yaml_token_destroy(token); + yaml_free(token); +} + +/* + * Duplicate a token object. + */ + +YAML_DECLARE(int) +yaml_token_duplicate(yaml_token_t *token, yaml_token_t *model) +{ + assert(token); /* Non-NULL token object is expected. */ + assert(model); /* Non-NULL model token object is expected. */ + + 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) + { + case YAML_STREAM_START_TOKEN: + token->data.stream_start.encoding = + model->data.stream_start.encoding; + break; + + case YAML_VERSION_DIRECTIVE_TOKEN: + token->data.version_directive.major = + model->data.version_directive.major; + token->data.version_directive.minor = + model->data.version_directive.minor; + break; + + case YAML_TAG_DIRECTIVE_TOKEN: + if (!(token->data.tag_directive.handle = + yaml_strdup(model->data.tag_directive.handle))) + goto error; + if (!(token->data.tag_directive.prefix = + yaml_strdup(model->data.tag_directive.prefix))) + goto error; + break; + + case YAML_ALIAS_TOKEN: + if (!(token->data.alias.value = + yaml_strdup(model->data.alias.value))) + goto error; + break; + + case YAML_ANCHOR_TOKEN: + if (!(token->data.anchor.value = + yaml_strdup(model->data.anchor.value))) + goto error; + break; + + case YAML_TAG_TOKEN: + if (!(token->data.tag.handle = yaml_strdup(model->data.tag.handle))) + goto error; + if (!(token->data.tag.suffix = yaml_strdup(model->data.tag.suffix))) + goto error; + break; + + case YAML_SCALAR_TOKEN: + if (!(token->data.scalar.value = + yaml_malloc(model->data.scalar.length+1))) + goto error; + memcpy(token->data.scalar.value, model->data.scalar.value, + model->data.scalar.length+1); + token->data.scalar.length = model->data.scalar.length; + break; + + default: + break; + } + + return 1; + +error: + yaml_token_destroy(token); + + return 0; +} + +/* + * Destroy a token object. + */ + +YAML_DECLARE(void) +yaml_token_destroy(yaml_token_t *token) +{ + assert(token); /* Non-NULL token object expected. */ + switch (token->type) { case YAML_TAG_DIRECTIVE_TOKEN: @@ -617,18 +737,17 @@ yaml_token_delete(yaml_token_t *token) */ static int -yaml_check_utf8(yaml_char_t *start, size_t length) +yaml_valid_utf8(const yaml_char_t *buffer, size_t length) { - yaml_char_t *end = start+length; - yaml_char_t *pointer = start; + size_t pointer = 0; - while (pointer < end) { + while (pointer < length) { unsigned char octet; unsigned int width; unsigned int value; size_t k; - octet = pointer[0]; + octet = buffer[pointer]; width = (octet & 0x80) == 0x00 ? 1 : (octet & 0xE0) == 0xC0 ? 2 : (octet & 0xF0) == 0xE0 ? 3 : @@ -638,9 +757,9 @@ yaml_check_utf8(yaml_char_t *start, size_t length) (octet & 0xF0) == 0xE0 ? octet & 0x0F : (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; if (!width) return 0; - if (pointer+width > end) return 0; + if (pointer+width > length) return 0; for (k = 1; k < width; k ++) { - octet = pointer[k]; + octet = buffer[pointer+k]; if ((octet & 0xC0) != 0x80) return 0; value = (value << 6) + (octet & 0x3F); } @@ -655,12 +774,172 @@ yaml_check_utf8(yaml_char_t *start, size_t length) return 1; } +/* + * Allocate an event object. + */ + +YAML_DECLARE(yaml_event_t *) +yaml_event_new(void) +{ + yaml_event_t *event = yaml_malloc(sizeof(yaml_event_t)); + + if (!event) + return NULL; + + memset(event, 0, sizeof(yaml_event_t)); + + return event; +} + +/* + * Deallocate an event object. + */ + +YAML_DECLARE(void) +yaml_event_delete(yaml_event_t *event) +{ + assert(event); /* Non-NULL event object expected. */ + + yaml_event_destroy(event); + yaml_free(event); +} + +/* + * Duplicate an event object. + */ + +YAML_DECLARE(int) +yaml_event_duplicate(yaml_event_t *event, yaml_event_t *model) +{ + struct { + yaml_error_t error; + } self; + + assert(event); /* Non-NULL event object is expected. */ + assert(model); /* Non-NULL model event object is expected. */ + + 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) + { + case YAML_STREAM_START_EVENT: + event->data.stream_start.encoding = + model->data.stream_start.encoding; + break; + + case YAML_DOCUMENT_START_EVENT: + if (model->data.document_start.version_directive) { + if (!(event->data.document_start.version_directive = + yaml_malloc(sizeof(yaml_version_directive_t)))) + goto error; + *event->data.document_start.version_directive = + *model->data.document_start.version_directive; + } + if (model->data.document_start.tag_directives.length) { + yaml_tag_directive_t *tag_directives = + model->data.document_start.tag_directives.list; + if (!STACK_INIT(&self, event->data.document_start.tag_directives, + model->data.document_start.tag_directives.capacity)) + goto error; + while (event->data.document_start.tag_directives.length != + model->data.document_start.tag_directives.length) { + yaml_tag_directive_t value; + value.handle = yaml_strdup(tag_directives->handle); + value.prefix = yaml_strdup(tag_directives->prefix); + PUSH(&self, event->data.document_start.tag_directives, value); + if (!value.handle || !value.prefix) + goto error; + tag_directives ++; + } + } + event->data.document_start.is_implicit = + model->data.document_start.is_implicit; + break; + + case YAML_DOCUMENT_END_EVENT: + event->data.document_end.is_implicit = + model->data.document_end.is_implicit; + + case YAML_ALIAS_EVENT: + if (!(event->data.alias.anchor = + yaml_strdup(model->data.alias.anchor))) + goto error; + break; + + case YAML_SCALAR_EVENT: + if (model->data.scalar.anchor && + !(event->data.scalar.anchor = + yaml_strdup(model->data.scalar.anchor))) + goto error; + if (event->data.scalar.tag && + !(event->data.scalar.tag = + yaml_strdup(model->data.scalar.tag))) + goto error; + if (!(event->data.scalar.value = + yaml_malloc(model->data.scalar.length+1))) + goto error; + 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.style = model->data.scalar.style; + break; + + case YAML_SEQUENCE_START_EVENT: + if (model->data.sequence_start.anchor && + !(event->data.sequence_start.anchor = + yaml_strdup(model->data.sequence_start.anchor))) + goto error; + if (event->data.sequence_start.tag && + !(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.style = + model->data.sequence_start.style; + break; + + case YAML_MAPPING_START_EVENT: + if (model->data.mapping_start.anchor && + !(event->data.mapping_start.anchor = + yaml_strdup(model->data.mapping_start.anchor))) + goto error; + if (event->data.mapping_start.tag && + !(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.style = + model->data.mapping_start.style; + break; + + default: + break; + } + + return 1; + +error: + yaml_event_destroy(event); + + return 0; +} + /* * Create STREAM-START. */ YAML_DECLARE(int) -yaml_stream_start_event_initialize(yaml_event_t *event, +yaml_event_create_stream_start(yaml_event_t *event, yaml_encoding_t encoding) { yaml_mark_t mark = { 0, 0, 0 }; @@ -677,7 +956,7 @@ yaml_stream_start_event_initialize(yaml_event_t *event, */ YAML_DECLARE(int) -yaml_stream_end_event_initialize(yaml_event_t *event) +yaml_event_create_stream_end(yaml_event_t *event) { yaml_mark_t mark = { 0, 0, 0 }; @@ -693,76 +972,65 @@ yaml_stream_end_event_initialize(yaml_event_t *event) */ YAML_DECLARE(int) -yaml_document_start_event_initialize(yaml_event_t *event, - yaml_version_directive_t *version_directive, - yaml_tag_directive_t *tag_directives_start, - yaml_tag_directive_t *tag_directives_end, - int implicit) +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) { struct { - yaml_error_type_t error; - } context; + yaml_error_t error; + } self; yaml_mark_t mark = { 0, 0, 0 }; 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_tag_directive_t *list; + size_t length; + size_t capacity; + } tag_directives_copy = { NULL, 0, 0 }; assert(event); /* Non-NULL event object is expected. */ - assert((tag_directives_start && tag_directives_end) || - (tag_directives_start == tag_directives_end)); - /* Valid tag directives are expected. */ 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; + *version_directive_copy = *version_directive; } - if (tag_directives_start != tag_directives_end) { - yaml_tag_directive_t *tag_directive; - if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) + if (tag_directives && (tag_directives->handle || tag_directives->prefix)) { + if (!STACK_INIT(&self, tag_directives_copy, INITIAL_STACK_CAPACITY)) 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_check_utf8(tag_directive->handle, - strlen((char *)tag_directive->handle))) + while (tag_directives->handle || tag_directives->prefix) { + yaml_tag_directive_t value = *tag_directives; + assert(value.handle); + assert(value.prefix); + if (!yaml_valid_utf8(value.handle, strlen((char *)value.handle))) goto error; - if (!yaml_check_utf8(tag_directive->prefix, - strlen((char *)tag_directive->prefix))) + if (!yaml_valid_utf8(value.prefix, strlen((char *)value.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)) + 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; + if (!value.handle || !value.prefix) goto error; - value.handle = NULL; - value.prefix = NULL; } } DOCUMENT_START_EVENT_INIT(*event, version_directive_copy, - tag_directives_copy.start, tag_directives_copy.top, - implicit, mark, mark); + tag_directives_copy.list, tag_directives_copy.length, + tag_directives_copy.capacity, is_implicit, mark, mark); return 1; error: yaml_free(version_directive_copy); - while (!STACK_EMPTY(context, tag_directives_copy)) { - yaml_tag_directive_t value = POP(context, tag_directives_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(context, tag_directives_copy); - yaml_free(value.handle); - yaml_free(value.prefix); + STACK_DEL(&self, tag_directives_copy); return 0; } @@ -772,13 +1040,13 @@ error: */ YAML_DECLARE(int) -yaml_document_end_event_initialize(yaml_event_t *event, int implicit) +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. */ - DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark); + DOCUMENT_END_EVENT_INIT(*event, is_implicit, mark, mark); return 1; } @@ -788,7 +1056,7 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit) */ YAML_DECLARE(int) -yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) +yaml_event_create_alias(yaml_event_t *event, const yaml_char_t *anchor) { yaml_mark_t mark = { 0, 0, 0 }; yaml_char_t *anchor_copy = NULL; @@ -796,7 +1064,7 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) assert(event); /* Non-NULL event object is expected. */ assert(anchor); /* Non-NULL anchor is expected. */ - if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0; + if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) return 0; anchor_copy = yaml_strdup(anchor); if (!anchor_copy) @@ -812,10 +1080,10 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) */ YAML_DECLARE(int) -yaml_scalar_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, - yaml_char_t *value, int length, - int plain_implicit, int quoted_implicit, +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, yaml_scalar_style_t style) { yaml_mark_t mark = { 0, 0, 0 }; @@ -827,29 +1095,35 @@ yaml_scalar_event_initialize(yaml_event_t *event, assert(value); /* Non-NULL anchor is expected. */ if (anchor) { - if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) + goto error; anchor_copy = yaml_strdup(anchor); - if (!anchor_copy) goto error; + if (!anchor_copy) + goto error; } if (tag) { - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) + goto error; tag_copy = yaml_strdup(tag); - if (!tag_copy) goto error; + if (!tag_copy) + goto error; } if (length < 0) { length = strlen((char *)value); } - if (!yaml_check_utf8(value, length)) goto error; + if (!yaml_valid_utf8(value, length)) + goto error; value_copy = yaml_malloc(length+1); - if (!value_copy) goto error; + if (!value_copy) + goto error; memcpy(value_copy, value, length); value_copy[length] = '\0'; SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length, - plain_implicit, quoted_implicit, style, mark, mark); + is_plain_implicit, is_quoted_implicit, style, mark, mark); return 1; @@ -866,9 +1140,9 @@ error: */ YAML_DECLARE(int) -yaml_sequence_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, - yaml_sequence_style_t style) +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) { yaml_mark_t mark = { 0, 0, 0 }; yaml_char_t *anchor_copy = NULL; @@ -877,19 +1151,23 @@ yaml_sequence_start_event_initialize(yaml_event_t *event, assert(event); /* Non-NULL event object is expected. */ if (anchor) { - if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) + goto error; anchor_copy = yaml_strdup(anchor); - if (!anchor_copy) goto error; + if (!anchor_copy) + goto error; } if (tag) { - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) + goto error; tag_copy = yaml_strdup(tag); - if (!tag_copy) goto error; + if (!tag_copy) + goto error; } SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy, - implicit, style, mark, mark); + is_implicit, style, mark, mark); return 1; @@ -905,7 +1183,7 @@ error: */ YAML_DECLARE(int) -yaml_sequence_end_event_initialize(yaml_event_t *event) +yaml_event_create_sequence_end(yaml_event_t *event) { yaml_mark_t mark = { 0, 0, 0 }; @@ -921,9 +1199,9 @@ yaml_sequence_end_event_initialize(yaml_event_t *event) */ YAML_DECLARE(int) -yaml_mapping_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, - yaml_mapping_style_t style) +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) { yaml_mark_t mark = { 0, 0, 0 }; yaml_char_t *anchor_copy = NULL; @@ -932,19 +1210,23 @@ yaml_mapping_start_event_initialize(yaml_event_t *event, assert(event); /* Non-NULL event object is expected. */ if (anchor) { - if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + if (!yaml_valid_utf8(anchor, strlen((char *)anchor))) + goto error; anchor_copy = yaml_strdup(anchor); - if (!anchor_copy) goto error; + if (!anchor_copy) + goto error; } if (tag) { - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) + goto error; tag_copy = yaml_strdup(tag); - if (!tag_copy) goto error; + if (!tag_copy) + goto error; } MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy, - implicit, style, mark, mark); + is_implicit, style, mark, mark); return 1; @@ -960,7 +1242,7 @@ error: */ YAML_DECLARE(int) -yaml_mapping_end_event_initialize(yaml_event_t *event) +yaml_event_create_mapping_end(yaml_event_t *event) { yaml_mark_t mark = { 0, 0, 0 }; @@ -976,9 +1258,11 @@ yaml_mapping_end_event_initialize(yaml_event_t *event) */ YAML_DECLARE(void) -yaml_event_delete(yaml_event_t *event) +yaml_event_destroy(yaml_event_t *event) { - yaml_tag_directive_t *tag_directive; + struct { + yaml_error_t error; + } self; assert(event); /* Non-NULL event object expected. */ @@ -986,13 +1270,13 @@ yaml_event_delete(yaml_event_t *event) { case YAML_DOCUMENT_START_EVENT: yaml_free(event->data.document_start.version_directive); - for (tag_directive = event->data.document_start.tag_directives.start; - tag_directive != event->data.document_start.tag_directives.end; - tag_directive++) { - yaml_free(tag_directive->handle); - yaml_free(tag_directive->prefix); + 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); } - yaml_free(event->data.document_start.tag_directives.start); + STACK_DEL(&self, event->data.document_start.tag_directives); break; case YAML_ALIAS_EVENT: @@ -1022,6 +1306,8 @@ yaml_event_delete(yaml_event_t *event) memset(event, 0, sizeof(yaml_event_t)); } +#if 0 + /* * Create a document object. */ @@ -1072,10 +1358,10 @@ yaml_document_initialize(yaml_document_t *document, tag_directive != tag_directives_end; tag_directive ++) { assert(tag_directive->handle); assert(tag_directive->prefix); - if (!yaml_check_utf8(tag_directive->handle, + if (!yaml_valid_utf8(tag_directive->handle, strlen((char *)tag_directive->handle))) goto error; - if (!yaml_check_utf8(tag_directive->prefix, + if (!yaml_valid_utf8(tag_directive->prefix, strlen((char *)tag_directive->prefix))) goto error; value.handle = yaml_strdup(tag_directive->handle); @@ -1210,7 +1496,7 @@ yaml_document_add_scalar(yaml_document_t *document, tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG; } - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error; tag_copy = yaml_strdup(tag); if (!tag_copy) goto error; @@ -1218,7 +1504,7 @@ yaml_document_add_scalar(yaml_document_t *document, length = strlen((char *)value); } - if (!yaml_check_utf8(value, length)) goto error; + if (!yaml_valid_utf8(value, length)) goto error; value_copy = yaml_malloc(length+1); if (!value_copy) goto error; memcpy(value_copy, value, length); @@ -1262,7 +1548,7 @@ yaml_document_add_sequence(yaml_document_t *document, tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG; } - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error; tag_copy = yaml_strdup(tag); if (!tag_copy) goto error; @@ -1307,7 +1593,7 @@ yaml_document_add_mapping(yaml_document_t *document, tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG; } - if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + if (!yaml_valid_utf8(tag, strlen((char *)tag))) goto error; tag_copy = yaml_strdup(tag); if (!tag_copy) goto error; @@ -1385,4 +1671,5 @@ yaml_document_append_mapping_pair(yaml_document_t *document, return 1; } +#endif diff --git a/src/yaml_private.h b/src/yaml_private.h index 6320caf..8fe55f0 100644 --- a/src/yaml_private.h +++ b/src/yaml_private.h @@ -25,135 +25,221 @@ YAML_DECLARE(yaml_char_t *) yaml_strdup(const yaml_char_t *); /* - * 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. + * Error management. */ -YAML_DECLARE(int) -yaml_parser_fetch_more_tokens(yaml_parser_t *parser); +#define MEMORY_ERROR_INIT(error) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = YAML_MEMORY_ERROR, \ + 0) + +#define READING_ERROR_INIT(error,error_type,error_problem,error_offset,error_value) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = (error_type), \ + (error).data.reading.problem = (error_problem), \ + (error).data.reading.offset = (error_offset), \ + (error).data.reading.value = (error_value), \ + 0) + +#define LOADING_ERROR_INIT(error,error_type,error_problem,error_problem_mark) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = (error_type), \ + (error).data.loading.context = NULL, \ + (error).data.loading.context_mark.index = 0, \ + (error).data.loading.context_mark.line = 0, \ + (error).data.loading.context_mark.column = 0, \ + (error).data.loading.problem = (error_problem), \ + (error).data.loading.problem_mark = (error_problem_mark), \ + 0) + +#define LOADING_ERROR_WITH_CONTEXT_INIT(error,error_type,error_context,error_context_mark,error_problem,error_problem_mark) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = (error_type), \ + (error).data.loading.context = (error_context), \ + (error).data.loading.context_mark = (error_context_mark), \ + (error).data.loading.problem = (error_problem), \ + (error).data.loading.problem_mark = (error_problem_mark), \ + 0) + +#define WRITING_ERROR_INIT(error,error_type,error_problem,error_offset) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = (error_type), \ + (error).data.writing.problem = (error_problem), \ + (error).data.writing.offset = (error_offset), \ + 0) + +#define DUMPING_ERROR_INIT(error,error_type,error_problem) \ + (memset(&(error), 0, sizeof(error)), \ + (error).type = (error_type), \ + (error).type.dumping.problem = (error_problem), \ + 0) + +#define READER_ERROR_INIT(error,problem,offset) \ + READING_ERROR_INIT(error,YAML_READER_ERROR,problem,offset,-1) + +#define DECODER_ERROR_INIT(error,problem,offset,value) \ + READING_ERROR_INIT(error,YAML_DECODER_ERROR,problem,offset,value) + +#define SCANNER_ERROR_INIT(error,problem,problem_mark) \ + LOADING_ERROR_INIT(error,YAML_SCANNER_ERROR,problem,problem_mark) + +#define SCANNER_ERROR_WITH_CONTEXT_INIT(error,context,context_mark,problem,problem_mark) \ + LOADING_ERROR_WITH_CONTEXT_INIT(error,YAML_SCANNER_ERROR,context,context_mark,problem,problem_mark) + +#define PARSER_ERROR_INIT(error,problem,problem_mark) \ + LOADING_ERROR_INIT(error,YAML_PARSER_ERROR,problem,problem_mark) + +#define PARSER_ERROR_WITH_CONTEXT_INIT(error,context,context_mark,problem,problem_mark) \ + LOADING_ERROR_WITH_CONTEXT_INIT(error,YAML_PARSER_ERROR,context,context_mark,problem,problem_mark) + +#define COMPOSER_ERROR_INIT(error,problem,problem_mark) \ + LOADING_ERROR_INIT(error,YAML_COMPOSER_ERROR,problem,problem_mark) + +#define COMPOSER_ERROR_WITH_CONTEXT_INIT(error,context,context_mark,problem,problem_mark) \ + LOADING_ERROR_WITH_CONTEXT_INIT(error,YAML_COMPOSER_ERROR,context,context_mark,problem,problem_mark) + +#define WRITER_ERROR_INIT(error,problem,offset) \ + WRITING_ERROR_INIT(error,YAML_WRITER_ERROR,problem,offset) + +#define EMITTER_ERROR_INIT(error,context,problem) \ + DUMPING_ERROR_INIT(error,YAML_EMITTER_ERROR,problem) + +#define SERIALIZER_ERROR_INIT(error,context) \ + DUMPING_ERROR_INIT(error,YAML_SERIALIZER_ERROR,problem) /* * The size of the input raw buffer. */ -#define INPUT_RAW_BUFFER_SIZE 16384 +#define RAW_INPUT_BUFFER_CAPACITY 16384 /* * The size of the input buffer. * - * It should be possible to decode the whole raw buffer. + * The input buffer should be large enough to hold the content of the raw + * buffer after it is decoded. */ -#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3) +#define INPUT_BUFFER_CAPACITY (RAW_INPUT_BUFFER_CAPACITY*3) /* * The size of the output buffer. */ -#define OUTPUT_BUFFER_SIZE 16384 +#define OUTPUT_BUFFER_CAPACITY 16384 /* * The size of the output raw buffer. * - * It should be possible to encode the whole output buffer. + * The raw buffer should be able to hold the content of the output buffer + * after it is encoded. */ -#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2) +#define RAW_OUTPUT_BUFFER_CAPACITY (OUTPUT_BUFFER_CAPACITY*2+2) /* * The size of other stacks and queues. */ -#define INITIAL_STACK_SIZE 16 -#define INITIAL_QUEUE_SIZE 16 -#define INITIAL_STRING_SIZE 16 +#define INITIAL_STACK_CAPACITY 16 +#define INITIAL_QUEUE_CAPACITY 16 +#define INITIAL_STRING_CAPACITY 16 /* - * Buffer management. + * Input/output buffer management. */ -#define BUFFER_INIT(context,buffer,size) \ - (((buffer).start = yaml_malloc(size)) ? \ - ((buffer).last = (buffer).pointer = (buffer).start, \ - (buffer).end = (buffer).start+(size), \ +#define STORAGE_INIT(self,storage,storage_capacity) \ + (((storage).buffer = yaml_malloc(storage_capacity)) ? \ + ((storage).pointer = (storage).length = 0, \ + (buffer).capacity = (storage_capacity) \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define BUFFER_DEL(context,buffer) \ - (yaml_free((buffer).start), \ - (buffer).start = (buffer).pointer = (buffer).end = 0) +#define STORAGE_DEL(self,storage) \ + (yaml_free((storage).buffer), \ + (storage).pointer = (storage).length = (storage).capacity = 0) /* * String management. */ -typedef struct { - yaml_char_t *start; - yaml_char_t *end; - yaml_char_t *pointer; +typedef struct yaml_string_s { + yaml_char_t *buffer; + size_t pointer; + size_t capacity; } yaml_string_t; YAML_DECLARE(int) -yaml_string_extend(yaml_char_t **start, - yaml_char_t **pointer, yaml_char_t **end); +yaml_string_extend(yaml_char_t **buffer, size_t *capacity); YAML_DECLARE(int) yaml_string_join( - yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end, - yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end); + yaml_char_t **base_buffer, size_t *base_pointer, size_t *base_capacity, + yaml_char_t *adj_buffer, size_t adj_pointer, size_t adj_capacity); #define NULL_STRING { NULL, NULL, NULL } -#define STRING(string,length) { (string), (string)+(length), (string) } +#define STRING(string,capacity) { (string), 0, (capacity) } -#define STRING_INIT(context,string,size) \ - (((string).start = yaml_malloc(size)) ? \ - ((string).pointer = (string).start, \ - (string).end = (string).start+(size), \ - memset((string).start, 0, (size)), \ +#define STRING_INIT(self,string,string_capacity) \ + (((string).buffer = yaml_malloc(string_capacity)) ? \ + ((string).pointer = 0, \ + (string).capacity = (string_capacity), \ + memset((string).buffer, 0, (string_capacity)), \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define STRING_DEL(context,string) \ - (yaml_free((string).start), \ - (string).start = (string).pointer = (string).end = 0) - -#define STRING_EXTEND(context,string) \ - (((string).pointer+5 < (string).end) \ - || yaml_string_extend(&(string).start, \ - &(string).pointer, &(string).end)) - -#define CLEAR(context,string) \ - ((string).pointer = (string).start, \ - memset((string).start, 0, (string).end-(string).start)) - -#define JOIN(context,string_a,string_b) \ - ((yaml_string_join(&(string_a).start, &(string_a).pointer, \ - &(string_a).end, &(string_b).start, \ - &(string_b).pointer, &(string_b).end)) ? \ - ((string_b).pointer = (string_b).start, \ +#define STRING_DEL(self,string) \ + (yaml_free((string).buffer), \ + (string).buffer = NULL, \ + ((string).pointer = (string).capacity = 0)) + +#define STRING_EXTEND(self,string) \ + ((((string).pointer+5 < (string).capacity) \ + || yaml_string_extend(&(string).buffer, &(string).capacity)) ? \ + 1 : \ + ((self)->error.type = YAML_MEMORY_ERROR, \ + 0)) + +#define CLEAR(self,string) \ + ((string).pointer = 0, \ + memset((string).buffer, 0, (string).capacity)) + +#define JOIN(self,base_string,adj_string) \ + ((yaml_string_join(&(base_string).buffer, &(base_string).pointer, \ + &(base_string).capacity, (adj_string).buffer, \ + (adj_string).pointer, (adj_string).capacity)) ? \ + ((adj_string).pointer = 0, \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) /* * String check operations. */ +/* + * Get the octet at the specified position. + */ + +#define OCTET_AT(string,offset) \ + ((string).buffer[(string).pointer+(offset)]) + +/* + * Get the current offset. + */ + +#define OCTET(string) OCTET_AT((string),0) + /* * Check the octet at the specified position. */ #define CHECK_AT(string,octet,offset) \ - ((string).pointer[offset] == (yaml_char_t)(octet)) + (OCTET_AT((string),(offset)) == (yaml_char_t)(octet)) /* * Check the current octet in the buffer. @@ -167,14 +253,14 @@ yaml_string_join( */ #define IS_ALPHA_AT(string,offset) \ - (((string).pointer[offset] >= (yaml_char_t) '0' && \ - (string).pointer[offset] <= (yaml_char_t) '9') || \ - ((string).pointer[offset] >= (yaml_char_t) 'A' && \ - (string).pointer[offset] <= (yaml_char_t) 'Z') || \ - ((string).pointer[offset] >= (yaml_char_t) 'a' && \ - (string).pointer[offset] <= (yaml_char_t) 'z') || \ - (string).pointer[offset] == '_' || \ - (string).pointer[offset] == '-') + ((OCTET_AT((string),(offset)) >= (yaml_char_t) '0' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) '9') || \ + (OCTET_AT((string),(offset)) >= (yaml_char_t) 'A' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'Z') || \ + (OCTET_AT((string),(offset)) >= (yaml_char_t) 'a' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'z') || \ + OCTET_AT((string),(offset)) == '_' || \ + OCTET_AT((string),(offset)) == '-') #define IS_ALPHA(string) IS_ALPHA_AT((string),0) @@ -183,8 +269,8 @@ yaml_string_join( */ #define IS_DIGIT_AT(string,offset) \ - (((string).pointer[offset] >= (yaml_char_t) '0' && \ - (string).pointer[offset] <= (yaml_char_t) '9')) + ((OCTET_AT((string),(offset)) >= (yaml_char_t) '0' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) '9')) #define IS_DIGIT(string) IS_DIGIT_AT((string),0) @@ -193,7 +279,7 @@ yaml_string_join( */ #define AS_DIGIT_AT(string,offset) \ - ((string).pointer[offset] - (yaml_char_t) '0') + (OCTET_AT((string),(offset)) - (yaml_char_t) '0') #define AS_DIGIT(string) AS_DIGIT_AT((string),0) @@ -202,12 +288,12 @@ yaml_string_join( */ #define IS_HEX_AT(string,offset) \ - (((string).pointer[offset] >= (yaml_char_t) '0' && \ - (string).pointer[offset] <= (yaml_char_t) '9') || \ - ((string).pointer[offset] >= (yaml_char_t) 'A' && \ - (string).pointer[offset] <= (yaml_char_t) 'F') || \ - ((string).pointer[offset] >= (yaml_char_t) 'a' && \ - (string).pointer[offset] <= (yaml_char_t) 'f')) + ((OCTET_AT((string),(offset)) >= (yaml_char_t) '0' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) '9') || \ + (OCTET_AT((string),(offset)) >= (yaml_char_t) 'A' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'F') || \ + (OCTET_AT((string),(offset)) >= (yaml_char_t) 'a' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'f')) #define IS_HEX(string) IS_HEX_AT((string),0) @@ -216,13 +302,13 @@ yaml_string_join( */ #define AS_HEX_AT(string,offset) \ - (((string).pointer[offset] >= (yaml_char_t) 'A' && \ - (string).pointer[offset] <= (yaml_char_t) 'F') ? \ - ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \ - ((string).pointer[offset] >= (yaml_char_t) 'a' && \ - (string).pointer[offset] <= (yaml_char_t) 'f') ? \ - ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \ - ((string).pointer[offset] - (yaml_char_t) '0')) + ((OCTET_AT((string),(offset)) >= (yaml_char_t) 'A' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'F') ? \ + (OCTET_AT((string),(offset)) - (yaml_char_t) 'A' + 10) : \ + (OCTET_AT((string),(offset)) >= (yaml_char_t) 'a' && \ + OCTET_AT((string),(offset)) <= (yaml_char_t) 'f') ? \ + (OCTET_AT((string),(offset)) - (yaml_char_t) 'a' + 10) : \ + (OCTET_AT((string),(offset)) - (yaml_char_t) '0')) #define AS_HEX(string) AS_HEX_AT((string),0) @@ -231,7 +317,7 @@ yaml_string_join( */ #define IS_ASCII_AT(string,offset) \ - ((string).pointer[offset] <= (yaml_char_t) '\x7F') + (OCTET_AT((string),(offset)) <= (yaml_char_t) '\x7F') #define IS_ASCII(string) IS_ASCII_AT((string),0) @@ -240,22 +326,22 @@ yaml_string_join( */ #define IS_PRINTABLE_AT(string,offset) \ - (((string).pointer[offset] == 0x0A) /* . == #x0A */ \ - || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \ - && (string).pointer[offset] <= 0x7E) \ - || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \ - && (string).pointer[offset+1] >= 0xA0) \ - || ((string).pointer[offset] > 0xC2 \ - && (string).pointer[offset] < 0xED) \ - || ((string).pointer[offset] == 0xED \ - && (string).pointer[offset+1] < 0xA0) \ - || ((string).pointer[offset] == 0xEE) \ - || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \ - && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \ - && (string).pointer[offset+2] == 0xBF) \ - && !((string).pointer[offset+1] == 0xBF \ - && ((string).pointer[offset+2] == 0xBE \ - || (string).pointer[offset+2] == 0xBF)))) + ((OCTET_AT((string),(offset)) == 0x0A) /* . == #x0A */ \ + || (OCTET_AT((string),(offset)) >= 0x20 /* #x20 <= . <= #x7E */ \ + && OCTET_AT((string),(offset)) <= 0x7E) \ + || (OCTET_AT((string),(offset)) == 0xC2 /* #0xA0 <= . <= #xD7FF */ \ + && OCTET_AT((string),(offset)+1) >= 0xA0) \ + || (OCTET_AT((string),(offset)) > 0xC2 \ + && OCTET_AT((string),(offset)) < 0xED) \ + || (OCTET_AT((string),(offset)) == 0xED \ + && OCTET_AT((string),(offset)+1) < 0xA0) \ + || (OCTET_AT((string),(offset)) == 0xEE) \ + || (OCTET_AT((string),(offset)) == 0xEF /* #xE000 <= . <= #xFFFD */ \ + && !(OCTET_AT((string),(offset)+1) == 0xBB /* && . != #xFEFF */ \ + && OCTET_AT((string),(offset)+2) == 0xBF) \ + && !(OCTET_AT((string),(offset)+1) == 0xBF \ + && (OCTET_AT((string),(offset)+2) == 0xBE \ + || OCTET_AT((string),(offset)+2) == 0xBF)))) #define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0) @@ -358,10 +444,10 @@ yaml_string_join( */ #define WIDTH_AT(string,offset) \ - (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \ - ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \ - ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \ - ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0) + ((OCTET_AT((string),(offset)) & 0x80) == 0x00 ? 1 : \ + (OCTET_AT((string),(offset)) & 0xE0) == 0xC0 ? 2 : \ + (OCTET_AT((string),(offset)) & 0xF0) == 0xE0 ? 3 : \ + (OCTET_AT((string),(offset)) & 0xF8) == 0xF0 ? 4 : 0) #define WIDTH(string) WIDTH_AT((string),0) @@ -371,100 +457,112 @@ yaml_string_join( #define MOVE(string) ((string).pointer += WIDTH((string))) +/* + * Copy a single octet and bump the pointers. + */ + +#define COPY_OCTET(string_a,string_b) \ + ((string_a).buffer[(string_a).pointer++] \ + = (string_b).buffer[(string_b).pointer++]) + /* * Copy a character and move the pointers of both strings. */ #define COPY(string_a,string_b) \ - ((*(string_b).pointer & 0x80) == 0x00 ? \ - (*((string_a).pointer++) = *((string_b).pointer++)) : \ - (*(string_b).pointer & 0xE0) == 0xC0 ? \ - (*((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++)) : \ - (*(string_b).pointer & 0xF0) == 0xE0 ? \ - (*((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++)) : \ - (*(string_b).pointer & 0xF8) == 0xF0 ? \ - (*((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++), \ - *((string_a).pointer++) = *((string_b).pointer++)) : 0) + ((OCTET(string_b) & 0x80) == 0x00 ? \ + COPY_OCTET((string_a),(string_b)) : \ + (OCTET(string_b) & 0xE0) == 0xC0 ? \ + (COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b))) : \ + (OCTET(string_b) & 0xF0) == 0xE0 ? \ + (COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b))) : \ + (OCTET(string_b) & 0xF8) == 0xF0 ? \ + (COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b)), \ + COPY_OCTET((string_a),(string_b))) : 0) \ /* * Stack and queue management. */ YAML_DECLARE(int) -yaml_stack_extend(void **start, void **top, void **end); +yaml_stack_extend(void **list, size_t size, size_t *length, size_t *capacity); YAML_DECLARE(int) -yaml_queue_extend(void **start, void **head, void **tail, void **end); +yaml_queue_extend(void **list, size_t size, + size_t *head, size_t *tail, size_t *capacity); -#define STACK_INIT(context,stack,size) \ - (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \ - ((stack).top = (stack).start, \ - (stack).end = (stack).start+(size), \ +#define STACK_INIT(self,stack,stack_capacity) \ + (((stack).list = yaml_malloc((stack_capacity)*sizeof(*(stack).list))) ? \ + ((stack).length = 0, \ + (stack).capacity = (stack_capacity), \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define STACK_DEL(context,stack) \ - (yaml_free((stack).start), \ - (stack).start = (stack).top = (stack).end = 0) +#define STACK_DEL(self,stack) \ + (yaml_free((stack).list), \ + (stack).list = NULL, \ + (stack).length = (stack).capacity = 0) -#define STACK_EMPTY(context,stack) \ - ((stack).start == (stack).top) +#define STACK_EMPTY(self,stack) \ + ((stack).length == 0) -#define PUSH(context,stack,value) \ - (((stack).top != (stack).end \ - || yaml_stack_extend((void **)&(stack).start, \ - (void **)&(stack).top, (void **)&(stack).end)) ? \ - (*((stack).top++) = value, \ +#define PUSH(self,stack,value) \ + (((stack).length < (stack).capacity \ + || yaml_stack_extend((void **)&(stack).list, sizeof(*(stack).list), \ + &(stack).length, &(stack).capacity)) ? \ + ((stack).list[(stack).length++] = (value), \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define POP(context,stack) \ - (*(--(stack).top)) +#define POP(self,stack) \ + ((stack).list[--(stack).length]) -#define QUEUE_INIT(context,queue,size) \ - (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \ - ((queue).head = (queue).tail = (queue).start, \ - (queue).end = (queue).start+(size), \ +#define QUEUE_INIT(self,queue,queue_capacity) \ + (((queue).list = yaml_malloc((queue_capacity)*sizeof(*(queue).list))) ? \ + ((queue).head = (queue).tail = 0, \ + (queue).capacity = (queue_capacity), \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define QUEUE_DEL(context,queue) \ - (yaml_free((queue).start), \ - (queue).start = (queue).head = (queue).tail = (queue).end = 0) +#define QUEUE_DEL(self,queue) \ + (yaml_free((queue).list), \ + (queue).list = NULL, \ + (queue).head = (queue).tail = (queue).capacity = 0) -#define QUEUE_EMPTY(context,queue) \ +#define QUEUE_EMPTY(self,queue) \ ((queue).head == (queue).tail) -#define ENQUEUE(context,queue,value) \ - (((queue).tail != (queue).end \ - || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \ - (void **)&(queue).tail, (void **)&(queue).end)) ? \ - (*((queue).tail++) = value, \ +#define ENQUEUE(self,queue,value) \ + (((queue).tail != (queue).capacity \ + || yaml_queue_extend((void **)&(queue).list, sizeof(*(queue).list), \ + &(queue).head, &(queue).tail, &(queue).capacity)) ? \ + ((queue).list[(queue).tail++] = (value), \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) -#define DEQUEUE(context,queue) \ - (*((queue).head++)) - -#define QUEUE_INSERT(context,queue,index,value) \ - (((queue).tail != (queue).end \ - || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \ - (void **)&(queue).tail, (void **)&(queue).end)) ? \ - (memmove((queue).head+(index)+1,(queue).head+(index), \ - ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \ - *((queue).head+(index)) = value, \ +#define DEQUEUE(self,queue) \ + ((queue).list[(queue).head++]) + +#define QUEUE_INSERT(self,queue,index,value) \ + (((queue).tail != (queue).capacity \ + || yaml_queue_extend((void **)&(queue).list, sizeof(*(queue).list), \ + &(queue).head, &(queue).tail, &(queue).capacity)) ? \ + (memmove((queue).list+(queue).head+(index)+1, \ + (queue).list+(queue).head+(index), \ + ((queue).tail-(queue).head-(index))*sizeof(*(queue).list)), \ + (queue).list[(queue).head+(index)] = (value), \ (queue).tail++, \ 1) : \ - ((context)->error = YAML_MEMORY_ERROR, \ + ((self)->error.type = YAML_MEMORY_ERROR, \ 0)) /* @@ -531,49 +629,52 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end); (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark))) #define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \ - event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \ + event_tag_directives_list,event_tag_directives_length, \ + event_tag_directives_capacity,event_is_implicit,start_mark,end_mark) \ (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \ (event).data.document_start.version_directive = (event_version_directive), \ - (event).data.document_start.tag_directives.start = (event_tag_directives_start), \ - (event).data.document_start.tag_directives.end = (event_tag_directives_end), \ - (event).data.document_start.implicit = (event_implicit)) + (event).data.document_start.tag_directives.list = (event_tag_directives_list), \ + (event).data.document_start.tag_directives.length = (event_tag_directives_length), \ + (event).data.document_start.tag_directives.capacity = (event_tag_directives_capacity), \ + (event).data.document_start.is_implicit = (event_is_implicit)) -#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \ +#define DOCUMENT_END_EVENT_INIT(event,event_is_implicit,start_mark,end_mark) \ (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \ - (event).data.document_end.implicit = (event_implicit)) + (event).data.document_end.is_implicit = (event_is_implicit)) #define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \ (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \ (event).data.alias.anchor = (event_anchor)) -#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \ - event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \ +#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value, \ + event_length,event_is_plain_implicit,event_is_quoted_implicit, \ + event_style,start_mark,end_mark) \ (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \ (event).data.scalar.anchor = (event_anchor), \ (event).data.scalar.tag = (event_tag), \ (event).data.scalar.value = (event_value), \ (event).data.scalar.length = (event_length), \ - (event).data.scalar.plain_implicit = (event_plain_implicit), \ - (event).data.scalar.quoted_implicit = (event_quoted_implicit), \ + (event).data.scalar.is_plain_implicit = (event_is_plain_implicit), \ + (event).data.scalar.is_quoted_implicit = (event_is_quoted_implicit), \ (event).data.scalar.style = (event_style)) #define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \ - event_implicit,event_style,start_mark,end_mark) \ + event_is_implicit,event_style,start_mark,end_mark) \ (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \ (event).data.sequence_start.anchor = (event_anchor), \ (event).data.sequence_start.tag = (event_tag), \ - (event).data.sequence_start.implicit = (event_implicit), \ + (event).data.sequence_start.is_implicit = (event_is_implicit), \ (event).data.sequence_start.style = (event_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,event_anchor,event_tag, \ - event_implicit,event_style,start_mark,end_mark) \ + event_is_implicit,event_style,start_mark,end_mark) \ (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \ (event).data.mapping_start.anchor = (event_anchor), \ (event).data.mapping_start.tag = (event_tag), \ - (event).data.mapping_start.implicit = (event_implicit), \ + (event).data.mapping_start.is_implicit = (event_is_implicit), \ (event).data.mapping_start.style = (event_style)) #define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \ @@ -633,3 +734,503 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end); (node).data.mapping.pairs.top = (node_pairs_start), \ (node).data.mapping.style = (node_style)) +/* + * This structure holds information about a potential simple key. + */ + +typedef struct yaml_simple_key_s { + /* Is a simple key possible? */ + int is_possible; + /* Is a simple key required? */ + int is_required; + /* The number of the token. */ + size_t token_number; + /* The position mark. */ + yaml_mark_t mark; +} yaml_simple_key_t; + +/* + * The states of the parser. + */ + +typedef enum yaml_parser_state_e { + /* Expect STREAM-START. */ + YAML_PARSE_STREAM_START_STATE, + /* Expect the beginning of an implicit document. */ + YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, + /* Expect DOCUMENT-START. */ + YAML_PARSE_DOCUMENT_START_STATE, + /* Expect the content of a document. */ + YAML_PARSE_DOCUMENT_CONTENT_STATE, + /* Expect DOCUMENT-END. */ + YAML_PARSE_DOCUMENT_END_STATE, + /* Expect a block node. */ + YAML_PARSE_BLOCK_NODE_STATE, + /* Expect a block node or indentless sequence. */ + YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE, + /* Expect a flow node. */ + YAML_PARSE_FLOW_NODE_STATE, + /* Expect the first entry of a block sequence. */ + YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, + /* Expect an entry of a block sequence. */ + YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, + /* Expect an entry of an indentless sequence. */ + YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, + /* Expect the first key of a block mapping. */ + YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, + /* Expect a block mapping key. */ + YAML_PARSE_BLOCK_MAPPING_KEY_STATE, + /* Expect a block mapping value. */ + YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, + /* Expect the first entry of a flow sequence. */ + YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, + /* Expect an entry of a flow sequence. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, + /* Expect a key of an ordered mapping. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE, + /* Expect a value of an ordered mapping. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, + /* Expect the and of an ordered mapping entry. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE, + /* Expect the first key of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, + /* Expect a key of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_KEY_STATE, + /* Expect a value of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_VALUE_STATE, + /* Expect an empty value of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, + /* Expect nothing. */ + YAML_PARSE_END_STATE +} yaml_parser_state_t; + +/* + * This structure holds aliases data. + */ + +typedef struct yaml_alias_data_s { + /* The anchor. */ + yaml_char_t *anchor; + /* The node id. */ + int index; + /* The anchor mark. */ + yaml_mark_t mark; +} yaml_alias_data_t; + +/* + * The structure that holds data used by the file and string readers. + */ + +typedef union yaml_standard_reader_data_u { + /* String input data. */ + yaml_string_t string; + /* File input data. */ + FILE *file; +} yaml_standard_reader_data_t; + +/* + * The internal parser structure. + */ + +struct yaml_parser_s { + + /* + * Error stuff. + */ + + yaml_error_t error; + + /* + * Reader stuff. + */ + + /* The read handler. */ + yaml_reader_t *reader; + + /* The application data to be passed to the reader. */ + void *reader_data; + + /* Standard (string or file) input data. */ + yaml_standard_reader_data_t standard_reader_data; + + /* EOF flag. */ + int is_eof; + + /* The working buffer. */ + struct { + yaml_char_t *buffer; + size_t pointer; + size_t length; + size_t capacity; + } input; + + /* The number of unread characters in the buffer. */ + size_t unread; + + /* The raw buffer. */ + struct { + unsigned char *buffer; + size_t pointer; + size_t length; + size_t capacity; + } raw_input; + + /* The input encoding. */ + yaml_encoding_t encoding; + + /* The offset of the current position (in bytes). */ + size_t offset; + + /* The mark of the current position. */ + yaml_mark_t mark; + + /* + * Scanner stuff. + */ + + /* Have we started to scan the input stream? */ + int is_stream_start_produced; + + /* Have we reached the end of the input stream? */ + int is_stream_end_produced; + + /* The number of unclosed '[' and '{' indicators. */ + int flow_level; + + /* The tokens queue. */ + struct { + yaml_token_t *list; + size_t head; + size_t tail; + size_t capacity; + } tokens; + + /* The number of tokens fetched from the queue. */ + size_t tokens_parsed; + + /* Does the tokens queue contain a token ready for dequeueing. */ + int is_token_available; + + /* The indentation levels stack. */ + struct { + int *list; + size_t length; + size_t capacity; + } indents; + + /* The current indentation level. */ + int indent; + + /* May a simple key occur at the current position? */ + int is_simple_key_allowed; + + /* The stack of simple keys. */ + struct { + yaml_simple_key_t *list; + size_t length; + size_t capacity; + } simple_keys; + + /* + * Parser stuff. + */ + + /* The parser states stack. */ + struct { + yaml_parser_state_t *list; + size_t length; + size_t capacity; + } states; + + /* The current parser state. */ + yaml_parser_state_t state; + + /* The stack of marks. */ + struct { + yaml_mark_t *list; + size_t length; + size_t capacity; + } marks; + + /* The list of TAG directives. */ + struct { + yaml_tag_directive_t *list; + size_t length; + size_t capacity; + } tag_directives; + + /* + * Dumper stuff. + */ + + /* The resolve handler. */ + yaml_resolver_t *resolver; + + /* The application data to be passed to the resolver. */ + void *resolver_data; + + /* The alias data. */ + struct { + yaml_alias_data_t *list; + size_t length; + size_t capacity; + } aliases; + + /* The currently parsed document. */ + yaml_document_t *document; + +}; + +/* + * The emitter states. + */ + +typedef enum yaml_emitter_state_e { + /** Expect STREAM-START. */ + YAML_EMIT_STREAM_START_STATE, + /** Expect the first DOCUMENT-START or STREAM-END. */ + YAML_EMIT_FIRST_DOCUMENT_START_STATE, + /** Expect DOCUMENT-START or STREAM-END. */ + YAML_EMIT_DOCUMENT_START_STATE, + /** Expect the content of a document. */ + YAML_EMIT_DOCUMENT_CONTENT_STATE, + /** Expect DOCUMENT-END. */ + YAML_EMIT_DOCUMENT_END_STATE, + /** Expect the first item of a flow sequence. */ + YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, + /** Expect an item of a flow sequence. */ + YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, + /** Expect the first key of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, + /** Expect a key of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_KEY_STATE, + /** 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. */ + YAML_EMIT_FLOW_MAPPING_VALUE_STATE, + /** Expect the first item of a block sequence. */ + YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, + /** Expect an item of a block sequence. */ + YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, + /** Expect the first key of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, + /** Expect the key of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_KEY_STATE, + /** 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. */ + YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, + /** Expect nothing. */ + YAML_EMIT_END_STATE +} yaml_emitter_state_t; + +/* + * The structure that holds data used by the file and string readers. + */ + +typedef union yaml_standard_writer_data_u { + /* String output data. */ + yaml_string_t string; + size_t *length; + /* File output data. */ + FILE *file; +} yaml_standard_writer_data_t; + +/* + * The internals emitter structure. + */ + +struct yaml_emitter_s { + + /* + * Error stuff. + */ + + yaml_error_t error; + + /* + * Writer stuff. + */ + + /* Write handler. */ + yaml_writer_t *writer; + + /* A pointer for passing to the white handler. */ + void *writer_data; + + /* Standard (string or file) output data. */ + yaml_standard_writer_data_t standard_writer_data; + + /* The working buffer. */ + struct { + yaml_char_t *buffer; + size_t pointer; + size_t length; + size_t capacity; + } output; + + /* The raw buffer. */ + struct { + yaml_char_t *buffer; + size_t pointer; + size_t length; + size_t capacity; + } raw_output; + + /* The stream encoding. */ + yaml_encoding_t encoding; + + /* + * Emitter stuff. + */ + + /* If the output is in the canonical style? */ + int is_canonical; + /* The number of indentation spaces. */ + int best_indent; + /* The preferred width of the output lines. */ + int best_width; + /* Allow unescaped non-ASCII characters? */ + int is_unicode; + /* The preferred line break. */ + yaml_break_t line_break; + + /* The stack of states. */ + struct { + yaml_emitter_state_t *list; + size_t length; + size_t capacity; + } states; + + /* The current emitter state. */ + yaml_emitter_state_t state; + + /* The event queue. */ + struct { + yaml_event_t *list; + size_t head; + size_t tail; + size_t capacity; + } events; + + /* The stack of indentation levels. */ + struct { + int *list; + size_t length; + size_t capacity; + } indents; + + /* The list of tag directives. */ + struct { + yaml_tag_directive_t *list; + size_t length; + size_t capacity; + } tag_directives; + + /* The current indentation level. */ + int indent; + + /* The current flow level. */ + int flow_level; + + /* Is it the document root context? */ + int is_root_context; + /* Is it a sequence context? */ + int is_sequence_context; + /* Is it a mapping context? */ + int is_mapping_context; + /* Is it a simple mapping key context? */ + int is_simple_key_context; + + /* The current line. */ + int line; + /* The current column. */ + int column; + /* If the last character was a whitespace? */ + int whitespace; + /* If the last character was an indentation character (' ', '-', '?', ':')? */ + int indention; + + /* Anchor analysis. */ + struct { + /* The anchor value. */ + yaml_char_t *anchor; + /* The anchor length. */ + size_t anchor_length; + /* Is it an alias? */ + int is_alias; + } anchor_data; + + /* Tag analysis. */ + struct { + /* The tag handle. */ + yaml_char_t *handle; + /* The tag handle length. */ + size_t handle_length; + /* The tag suffix. */ + yaml_char_t *suffix; + /* The tag suffix length. */ + size_t suffix_length; + } tag_data; + + /* Scalar analysis. */ + struct { + /* The scalar value. */ + yaml_char_t *value; + /* The scalar length. */ + size_t length; + /* Does the scalar contain line breaks? */ + int is_multiline; + /* Can the scalar be expessed in the flow plain style? */ + int is_flow_plain_allowed; + /* Can the scalar be expressed in the block plain style? */ + int is_block_plain_allowed; + /* Can the scalar be expressed in the single quoted style? */ + int is_single_quoted_allowed; + /* Can the scalar be expressed in the literal or folded styles? */ + int is_block_allowed; + /* The output style. */ + yaml_scalar_style_t style; + } scalar_data; + + /* + * Dumper stuff. + */ + + /* If the stream was already opened? */ + int is_opened; + /* If the stream was already closed? */ + int is_closed; + + /* The information associated with the document nodes. */ + struct { + /* The number of references. */ + size_t references; + /* The anchor id. */ + int anchor; + /* If the node has been emitted? */ + int is_serialized; + } *anchors; + + /* The last assigned anchor id. */ + int last_anchor_id; + + /* The currently emitted document. */ + 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); + -- cgit v1.2.1