X-Git-Url: http://andersk.mit.edu/gitweb/libyaml.git/blobdiff_plain/52fba2c6b357fefbc9ad2c099506e64618ef2ced..2a02dfd2625480af0f2b48664c46dab20ea799da:/include/yaml.h diff --git a/include/yaml.h b/include/yaml.h index f195bf4..47de95d 100644 --- a/include/yaml.h +++ b/include/yaml.h @@ -101,6 +101,15 @@ typedef enum { YAML_UTF16BE_ENCODING } yaml_encoding_t; +/** Line break types. */ + +typedef enum { + YAML_ANY_BREAK, + YAML_CR_BREAK, + YAML_LN_BREAK, + YAML_CRLN_BREAK +} yaml_break_t; + /** Many bad things could happen with the parser and emitter. */ typedef enum { YAML_NO_ERROR, @@ -147,7 +156,6 @@ typedef enum { YAML_FOLDED_SCALAR_STYLE } yaml_scalar_style_t; - /** Sequence styles. */ typedef enum { YAML_ANY_SEQUENCE_STYLE, @@ -162,6 +170,7 @@ typedef enum { YAML_BLOCK_MAPPING_STYLE, YAML_FLOW_MAPPING_STYLE +/* YAML_FLOW_SET_MAPPING_STYLE */ } yaml_mapping_style_t; /** @} */ @@ -173,6 +182,8 @@ typedef enum { /** Token types. */ typedef enum { + YAML_NO_TOKEN, + YAML_STREAM_START_TOKEN, YAML_STREAM_END_TOKEN, @@ -232,20 +243,16 @@ typedef struct { struct { /** The tag handle. */ yaml_char_t *handle; - /** The tag suffix. */ yaml_char_t *suffix; } tag; /** The scalar value (for @c YAML_SCALAR_TOKEN). */ struct { - /** The scalar value. */ yaml_char_t *value; - /** The length of the scalar value. */ size_t length; - /** The scalar style. */ yaml_scalar_style_t style; } scalar; @@ -254,7 +261,6 @@ typedef struct { struct { /** The major version number. */ int major; - /** The minor version number. */ int minor; } version_directive; @@ -263,181 +269,21 @@ typedef struct { struct { /** The tag handle. */ yaml_char_t *handle; - /** The tag prefix. */ yaml_char_t *prefix; } tag_directive; + } data; /** The beginning of the token. */ yaml_mark_t start_mark; - /** The end of the token. */ yaml_mark_t end_mark; } yaml_token_t; /** - * Create a new token without assigning any data. - * - * This function can be used for constructing indicator tokens: - * @c YAML_DOCUMENT_START, @c YAML_DOCUMENT_END, - * @c YAML_BLOCK_SEQUENCE_START_TOKEN, @c YAML_BLOCK_MAPPING_START_TOKEN, - * @c YAML_BLOCK_END_TOKEN, - * @c YAML_FLOW_SEQUENCE_START_TOKEN, @c YAML_FLOW_SEQUENCE_END_TOKEN, - * @c YAML_FLOW_MAPPING_START_TOKEN, @c YAML_FLOW_MAPPING_END_TOKEN, - * @c YAML_BLOCK_ENTRY_TOKEN, @c YAML_FLOW_ENTRY_TOKEN, - * @c YAML_KEY_TOKEN, @c YAML_VALUE_TOKEN. - * - * @param[in] type The token type. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_token_new(yaml_token_type_t type, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_STREAM_START_TOKEN token with the specified encoding. - * - * @param[in] encoding The stream encoding. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_stream_start_token_new(yaml_encoding_t encoding, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_STREAM_END_TOKEN token. - * - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_stream_end_token_new(yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_VERSION_DIRECTIVE_TOKEN token with the specified - * version numbers. - * - * @param[in] major The major version number. - * @param[in] minor The minor version number. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_version_directive_token_new(int major, int minor, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_TAG_DIRECTIVE_TOKEN token with the specified tag - * handle and prefix. - * - * Note that the @a handle and the @a prefix pointers will be freed by - * the token descructor. - * - * @param[in] handle The tag handle. - * @param[in] prefix The tag prefix. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_tag_directive_token_new(yaml_char_t *handle, yaml_char_t *prefix, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_ALIAS_TOKEN token with the specified anchor. - * - * Note that the @a anchor pointer will be freed by the token descructor. - * - * @param[in] anchor The anchor. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_alias_token_new(yaml_char_t *anchor, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_ANCHOR_TOKEN token with the specified anchor. - * - * Note that the @a anchor pointer will be freed by the token descructor. - * - * @param[in] anchor The anchor. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_anchor_token_new(yaml_char_t *anchor, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_TAG_TOKEN token with the specified tag handle and - * suffix. - * - * Note that the @a handle and the @a suffix pointers will be freed by - * the token descructor. - * - * @param[in] handle The tag handle. - * @param[in] suffix The tag suffix. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_tag_token_new(yaml_char_t *handle, yaml_char_t *suffix, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Create a new @c YAML_SCALAR_TOKEN token with the specified scalar value, - * length, and style. - * - * Note that the scalar value may contain the @c NUL character, therefore - * the value length is also required. The scalar value always ends with - * @c NUL. - * - * Note that the @a value pointer will be freed by the token descructor. - * - * @param[in] value The scalar value. - * @param[in] length The value length. - * @param[in] style The scalar style. - * @param[in] start_mark The beginning of the token. - * @param[in] end_mark The end of the token. - * - * @returns A new token object, or @c NULL on error. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_scalar_token_new(yaml_char_t *value, size_t length, - yaml_scalar_style_t style, - yaml_mark_t start_mark, yaml_mark_t end_mark); - -/** - * Destroy a token object. + * Free any memory allocated for a token object. * * @param[in] token A token object. */ @@ -454,6 +300,8 @@ yaml_token_delete(yaml_token_t *token); /** Event types. */ typedef enum { + YAML_NO_EVENT, + YAML_STREAM_START_EVENT, YAML_STREAM_END_EVENT, @@ -489,8 +337,15 @@ typedef struct { struct { /** The version directive. */ yaml_version_directive_t *version_directive; + /** The list of tag directives. */ - yaml_tag_directive_t **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; + } tag_directives; + /** Is the document indicator implicit? */ int implicit; } document_start; @@ -553,167 +408,177 @@ typedef struct { /** The beginning of the token. */ yaml_mark_t start_mark; - /** The end of the token. */ yaml_mark_t end_mark; + } yaml_event_t; /** - * Create a new @c YAML_STREAM_START_EVENT event. + * Create the STREAM-START event. * + * @param[in] event An empty event object. * @param[in] encoding The stream encoding. - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_stream_start_event_new(yaml_encoding_t encoding, - yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_stream_start_event_initialize(yaml_event_t *event, + yaml_encoding_t encoding); /** - * Create a new @c YAML_STREAM_END_TOKEN event. + * Create the STREAM-END event. * - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. + * @param[in] event An empty event object. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_stream_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_stream_end_event_initialize(yaml_event_t *event); /** - * Create a new @c YAML_DOCUMENT_START_EVENT event. + * Create the DOCUMENT-START event. * - * @param[in] version_directive The version directive or @c NULL. - * @param[in] tag_directives A list of tag directives or @c NULL. - * @param[in] implicit Is the document indicator present? - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. + * The @a implicit argument is considered as a stylistic parameter and may be + * ignored by the emitter. * - * @returns A new event object, or @c NULL on error. + * @param[in] 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. + * + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_document_start_event_new(yaml_version_directive_t *version_directive, - yaml_tag_directive_t **tag_directives, int implicit, - yaml_mark_t start_mark, yaml_mark_t end_mark); +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); /** - * Create a new @c YAML_DOCUMENT_END_EVENT event. + * Create the DOCUMENT-END event. * - * @param[in] implicit Is the document end indicator present? - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. + * The @a implicit argument is considered as a stylistic parameter and may be + * ignored by the emitter. * - * @returns A new event object, or @c NULL on error. + * @param[in] event An empty event object. + * @param[in] implicit If the document end indicator is implicit. + * + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_document_end_event_new(int implicit, - yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_document_end_event_initialize(yaml_event_t *event, int implicit); /** - * Create a new @c YAML_ALIAS_EVENT event. + * Create an ALIAS event. * + * @param[in] event An empty event object. * @param[in] anchor The anchor value. - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_alias_event_new(yaml_char_t *anchor, - yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor); /** - * Create a new @c YAML_SCALAR_EVENT event. + * Create a SCALAR event. + * + * The @a style argument may be ignored by the emitter. * - * @param[in] anchor The anchor value or @c NULL. - * @param[in] tag The tag value or @c NULL. + * Either the @a tag attribute or one of the @a plain_implicit and + * @a quoted_implicit flags must be set. + * + * @param[in] 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 Is the tag optional for the plain style? - * @param[in] quoted_implicit Is the tag optional for any non-plain style? + * @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[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_scalar_event_new(yaml_char_t *anchor, yaml_char_t *tag, - yaml_char_t *value, size_t length, +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_scalar_style_t style, - yaml_mark_t start_mark, yaml_mark_t end_mark); + yaml_scalar_style_t style); /** - * Create a new @c YAML_SEQUENCE_START_EVENT event. + * Create a SEQUENCE-START event. + * + * The @a style argument may be ignored by the emitter. * - * @param[in] anchor The anchor value or @c NULL. - * @param[in] tag The tag value or @c NULL. - * @param[in] implicit Is the tag optional? + * Either the @a tag attribute or the @a implicit flag must be set. + * + * @param[in] 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] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_sequence_start_event_new(yaml_char_t *anchor, yaml_char_t *tag, - int implicit, yaml_sequence_style_t style, - yaml_mark_t start_mark, yaml_mark_t end_mark); +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); /** - * Create a new @c YAML_SEQUENCE_END_EVENT event. + * Create a SEQUENCE-END event. * - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. + * @param[in] event An empty event object. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_sequence_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_sequence_end_event_initialize(yaml_event_t *event); /** - * Create a new @c YAML_MAPPING_START_EVENT event. + * Create a MAPPING-START event. + * + * The @a style argument may be ignored by the emitter. * - * @param[in] anchor The anchor value or @c NULL. - * @param[in] tag The tag value or @c NULL. - * @param[in] implicit Is the tag optional? + * Either the @a tag attribute or the @a implicit flag must be set. + * + * @param[in] 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] style The mapping style. - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_mapping_start_event_new(yaml_char_t *anchor, yaml_char_t *tag, - int implicit, yaml_mapping_style_t style, - yaml_mark_t start_mark, yaml_mark_t end_mark); +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); /** - * Create a new @c YAML_MAPPING_END_EVENT event. + * Create a MAPPING-END event. * - * @param[in] start_mark The beginning of the event. - * @param[in] end_mark The end of the event. + * @param[in] event An empty event object. * - * @returns A new event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_mapping_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark); +YAML_DECLARE(int) +yaml_mapping_end_event_initialize(yaml_event_t *event); /** - * Destroy an event object. + * Free any memory allocated for an event object. * * @param[in] event An event object. */ @@ -743,48 +608,26 @@ yaml_event_delete(yaml_event_t *event); * * @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 length to @c 0 and return @c 1. + * @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); -/** - * This structure holds a string input specified by - * @c yaml_parser_set_input_string. - */ - -typedef struct { - /** The string start pointer. */ - unsigned char *start; - - /** The string end pointer. */ - unsigned char *end; - - /** The string current position. */ - unsigned char *current; -} yaml_string_input_t; - /** * This structure holds information about a potential simple key. */ typedef struct { + /** 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 index. */ - size_t index; - - /** The position line. */ - size_t line; - - /** The position column. */ - size_t column; - /** The position mark. */ yaml_mark_t mark; } yaml_simple_key_t; @@ -793,7 +636,6 @@ typedef struct { * The states of the parser. */ typedef enum { - YAML_PARSE_END_STATE, YAML_PARSE_STREAM_START_STATE, YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, YAML_PARSE_DOCUMENT_START_STATE, @@ -816,7 +658,8 @@ typedef enum { YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, YAML_PARSE_FLOW_MAPPING_KEY_STATE, YAML_PARSE_FLOW_MAPPING_VALUE_STATE, - YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE + YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, + YAML_PARSE_END_STATE } yaml_parser_state_t; /** @@ -835,22 +678,16 @@ typedef struct { /** 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; @@ -869,29 +706,51 @@ typedef struct { /** 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. */ + unsigned char *start; + /** The string end pointer. */ + unsigned char *end; + /** The string current position. */ + unsigned char *current; + } string; + + /** File input data. */ + FILE *file; + } input; + /** EOF flag */ int eof; - /** The pointer to the beginning of the working buffer. */ - yaml_char_t *buffer; - - /** The pointer to the end of the working buffer. */ - yaml_char_t *buffer_end; - - /** The pointer to the current character in the working buffer. */ - yaml_char_t *pointer; - - /** The number of unread characters in the working buffer. */ + /** 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 pointer to the beginning of the raw buffer. */ - unsigned char *raw_buffer; - - /** The pointer to the current character in the raw buffer. */ - unsigned char *raw_pointer; - - /** The number of unread bytes in the raw buffer. */ - size_t raw_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; @@ -899,17 +758,8 @@ typedef struct { /** The offset of the current position (in bytes). */ size_t offset; - /** The index of the current position (in characters). */ - size_t index; - - /** The line of the current position (starting from @c 0). */ - size_t line; - - /** The column of the current position (starting from @c 0). */ - size_t column; - - /* String input structure. */ - yaml_string_input_t string_input; + /** The mark of the current position. */ + yaml_mark_t mark; /** * @} @@ -929,29 +779,33 @@ typedef struct { /** The number of unclosed '[' and '{' indicators. */ int flow_level; - /** The tokens queue, which contains the current produced tokens. */ - yaml_token_t **tokens; - - /** The size of the tokens queue. */ - size_t tokens_size; - - /** The head of the tokens queue. */ - size_t tokens_head; - - /** The tail of the tokens queue. */ - size_t tokens_tail; - - /** The number of tokens fetched from the tokens queue. */ + /** 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; - /** The stack of indentation levels. */ - int *indents; - - /** The size of the indents stack. */ - size_t indents_size; + /* Does the tokens queue contain a token ready for dequeueing. */ + int token_available; - /** The number of items in the indents stack. */ - size_t indents_length; + /** 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; @@ -959,11 +813,15 @@ typedef struct { /** May a simple key occur at the current position? */ int simple_key_allowed; - /** The stack of potential simple keys. */ - yaml_simple_key_t **simple_keys; - - /** The size of the simple keys stack. */ - size_t simple_keys_size; + /** 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; /** * @} @@ -975,40 +833,37 @@ typedef struct { */ /** The parser states stack. */ - yaml_parser_state_t *states; - - /** The size of the parser states stack. */ - size_t states_size; - - /** The number of items in the parser states stack. */ - size_t states_length; + 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. */ - yaml_mark_t *marks; - - /** The size of the marks stack. */ - size_t marks_size; - - /** The number of items in the marks stack. */ - size_t marks_length; - - /** The current event. */ - yaml_event_t *current_event; - - /** The YAML version directive. */ - yaml_version_directive_t *version_directive; + 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. */ - yaml_tag_directive_t **tag_directives; - - /** The size of the TAG directives list. */ - size_t tag_directives_size; - - /** The number of items in the TAG directives list. */ - size_t tag_directives_length; + 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; /** * @} @@ -1017,16 +872,18 @@ typedef struct { } yaml_parser_t; /** - * Create a new parser. + * Initialize a parser. * * This function creates a new parser object. An application is responsible * for destroying the object using the @c yaml_parser_delete function. * - * @returns A new parser object; @c NULL on error. + * @param[in] parser An empty parser object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_parser_t *) -yaml_parser_new(void); +YAML_DECLARE(int) +yaml_parser_initialize(yaml_parser_t *parser); /** * Destroy a parser. @@ -1053,7 +910,6 @@ YAML_DECLARE(void) yaml_parser_set_input_string(yaml_parser_t *parser, unsigned char *input, size_t size); - /** * Set a file input. * @@ -1090,141 +946,468 @@ YAML_DECLARE(void) yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding); /** - * Get the next token. + * Scan the input stream and produce the next token. + * + * Call the function subsequently to produce a sequence of tokens corresponding + * to the input stream. The initial token has the type + * @c YAML_STREAM_START_TOKEN while the ending token has the type + * @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. * - * The token is removed from the internal token queue and the application is - * responsible for destroing the token object. + * An application must not alternate the calls of @c yaml_parser_scan with the + * calls of @c yaml_parser_parse. Doing this will break the parser. * * @param[in] parser A parser object. + * @param[in] token An empty token object. * - * @returns A token object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_token_t *) -yaml_parser_get_token(yaml_parser_t *parser); +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); /** - * Peek the next token. + * Parse the input stream and produce the next parsing event. + * + * Call the function subsequently to produce a sequence of events corresponding + * to the input stream. The initial event has the type + * @c YAML_STREAM_START_EVENT while the ending event has the type + * @c YAML_STREAM_END_EVENT. + * + * An application is responsible for freeing any buffers associated with the + * produced event object using the @c yaml_event_delete function. * - * The token is not removed from the internal token queue and will be returned - * again on a subsequent call of @c yaml_parser_get_token or - * @c yaml_parser_peek_token. The application should not destroy the token - * object. + * An application must not alternate the calls of @c yaml_parser_scan with the + * calls of @c yaml_parser_parse. Doing this will break the parser. * * @param[in] parser A parser object. + * @param[in] event An empty event object. * - * @returns A token object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_token_t *) -yaml_parser_peek_token(yaml_parser_t *parser); +YAML_DECLARE(int) +yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); + +/** @} */ /** - * Get the next event. + * @defgroup emitter Emitter Definitions + * @{ + */ + +/** + * The prototype of a write handler. * - * The application is responsible for destroing the event object. + * 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] parser A parser object. + * @param[in] data A pointer to an application data specified by + * @c yaml_emitter_set_write_handler. + * @param[out] buffer The buffer with bytes to be written. + * @param[in] size The size of the buffer. * - * @returns An event object, or @c NULL on error. + * @returns On success, the handler should return @c 1. If the handler failed, + * the returned value should be @c 0. */ -YAML_DECLARE(yaml_event_t *) -yaml_parser_get_event(yaml_parser_t *parser); +typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size); + +/** The emitter states. */ +typedef enum { + YAML_EMIT_STREAM_START_STATE, + YAML_EMIT_FIRST_DOCUMENT_START_STATE, + YAML_EMIT_DOCUMENT_START_STATE, + YAML_EMIT_DOCUMENT_CONTENT_STATE, + YAML_EMIT_DOCUMENT_END_STATE, + YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, + YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, + YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, + YAML_EMIT_FLOW_MAPPING_KEY_STATE, + YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, + YAML_EMIT_FLOW_MAPPING_VALUE_STATE, + YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, + YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, + YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, + YAML_EMIT_BLOCK_MAPPING_KEY_STATE, + YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, + YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, + YAML_EMIT_END_STATE +} yaml_emitter_state_t; /** - * Peek the next event. + * The emitter structure. * - * The event will be returned again on a subsequent call of - * @c yaml_parser_get_event or @c yaml_parser_peek_event. The application - * should not destroy the event object. + * All members are internal. Manage the structure using the @c yaml_emitter_ + * family of functions. + */ + +typedef struct { + + /** + * @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; + + /** + * @} + */ + +} yaml_emitter_t; + +/** + * Initialize an emitter. * - * @param[in] parser A parser object. + * This function creates a new emitter object. An application is responsible + * for destroying the object using the @c yaml_emitter_delete function. + * + * @param[in] emitter An empty parser object. * - * @returns An event object, or @c NULL on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ -YAML_DECLARE(yaml_event_t *) -yaml_parser_peek_event(yaml_parser_t *parser); +YAML_DECLARE(int) +yaml_emitter_initialize(yaml_emitter_t *emitter); -/** @} */ +/** + * Destroy an emitter. + * + * @param[in] emitter An emitter object. + */ -/* -typedef struct { -} yaml_emitter_t; -*/ +YAML_DECLARE(void) +yaml_emitter_delete(yaml_emitter_t *emitter); /** - * @defgroup internal Internal Definitions - * @{ + * 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. + * + * @param[in] 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 bytes. */ +YAML_DECLARE(void) +yaml_emitter_set_output_string(yaml_emitter_t *emitter, + unsigned char *output, size_t size, size_t *size_written); + /** - * Allocate a dynamic memory block. + * Set a file output. * - * @param[in] size Size of a memory block, \c 0 is valid. + * @a file should be a file object open for writing. The application is + * responsible for closing the @a file. * - * @returns @c yaml_malloc returns a pointer to a newly allocated memory block, - * or @c NULL if it failed. + * @param[in] emitter An emitter object. + * @param[in] file An open file. */ -YAML_DECLARE(void *) -yaml_malloc(size_t size); +YAML_DECLARE(void) +yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file); /** - * Reallocate a dynamic memory block. + * Set a generic output handler. * - * @param[in] ptr A pointer to an existing memory block, \c NULL is - * valid. - * @param[in] size A size of a new block, \c 0 is valid. + * @param[in] emitter An emitter object. + * @param[in] handler 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); + +/** + * Set the output encoding. * - * @returns @c yaml_realloc returns a pointer to a reallocated memory block, - * or @c NULL if it failed. + * @param[in] emitter An emitter object. + * @param[in] encoding The output encoding. */ -YAML_DECLARE(void *) -yaml_realloc(void *ptr, size_t size); +YAML_DECLARE(void) +yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding); /** - * Free a dynamic memory block. + * Set if the output should be in the "canonical" format as in the YAML + * specification. * - * @param[in] ptr A pointer to an existing memory block, \c NULL is - * valid. + * @param[in] emitter An emitter object. + * @param[in] canonical If the output is canonical. */ YAML_DECLARE(void) -yaml_free(void *ptr); +yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical); -/** The initial size for various buffers. */ +/** + * Set the intendation increment. + * + * @param[in] emitter An emitter object. + * @param[in] indent The indentation increment (1 < . < 10). + */ -#define YAML_DEFAULT_SIZE 16 +YAML_DECLARE(void) +yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent); -/** The size of the raw buffer. */ +/** + * Set the preferred line width. @c -1 means unlimited. + * + * @param[in] emitter An emitter object. + * @param[in] width The preferred line width. + */ -#define YAML_RAW_BUFFER_SIZE 16384 +YAML_DECLARE(void) +yaml_emitter_set_width(yaml_emitter_t *emitter, int width); /** - * The size of the buffer. + * Set if unescaped non-ASCII characters are allowed. * - * We allocate enough space for decoding the whole raw buffer. + * @param[in] emitter An emitter object. + * @param[in] unicode If unescaped Unicode characters are allowed. */ -#define YAML_BUFFER_SIZE (YAML_RAW_BUFFER_SIZE*3) +YAML_DECLARE(void) +yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode); /** - * Ensure that the buffer contains at least @a length characters. + * Set the preferred line break. * - * @param[in] parser A parser object. - * @param[in] length The number of characters in the buffer. + * @param[in] emitter An emitter object. + * @param[in] line_break The preferred line break. + */ + +YAML_DECLARE(void) +yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break); + +/** + * Emit an event. + * + * The event object may be generated using the @c yaml_parser_parse function. + * The emitter takes the responsibility for the event object and destroys its + * content after it is emitted. The event object is destroyed even if the + * function fails. + * + * @param[in] emitter An emitter object. + * @param[in] event An event object. * - * @returns @c 1 on success, @c 0 on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) -yaml_parser_update_buffer(yaml_parser_t *parser, size_t length); +yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event); -/** @} */ +/** + * Flush the accumulated characters to the output. + * + * @param[in] emitter An emitter object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_flush(yaml_emitter_t *emitter); +/** @} */ #ifdef __cplusplus }