From 14e898dae1b62bfc87043fdf9c902942fa834673 Mon Sep 17 00:00:00 2001 From: xi Date: Fri, 28 Jul 2006 20:09:34 +0000 Subject: Implement everything except tag and scalar writers. git-svn-id: http://svn.pyyaml.org/libyaml/trunk@214 18f92427-320e-0410-9341-c67f048884a3 --- include/yaml.h | 42 +++ src/emitter.c | 1044 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/scanner.c | 515 +++++++++----------------- src/writer.c | 3 + src/yaml_private.h | 249 +++++++++++++ 5 files changed, 1469 insertions(+), 384 deletions(-) diff --git a/include/yaml.h b/include/yaml.h index 6284068..0408a67 100644 --- a/include/yaml.h +++ b/include/yaml.h @@ -1203,6 +1203,48 @@ typedef struct { /** 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; + /** * @} */ diff --git a/src/emitter.c b/src/emitter.c index 41ed3fc..b8d3dc9 100644 --- a/src/emitter.c +++ b/src/emitter.c @@ -1,6 +1,62 @@ #include "yaml_private.h" +/* + * Flush the buffer if needed. + */ + +#define FLUSH(emitter) \ + ((emitter->buffer.pointer+5 < emitter->buffer.end) \ + || yaml_emitter_flush(emitter)) + +/* + * Put a character to the output buffer. + */ + +#define PUT(emitter,value) \ + (FLUSH(emitter) \ + && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \ + emitter->column ++, \ + 1)) + +/* + * Put a line break to the output buffer. + */ + +#define PUT_BREAK(emitter) \ + (FLUSH(emitter) \ + && ((emitter->line_break == YAML_CR_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \ + emitter->line_break == YAML_LN_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \ + emitter->line_break == YAML_CRLN_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \ + *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \ + emitter->column = 0, \ + emitter->line ++, \ + 1)) + +/* + * Copy a character from a string into buffer. + */ + +#define WRITE(emitter,string) \ + (FLUSH(emitter) \ + && (COPY(emitter->buffer,string), \ + emitter->column ++, \ + 1)) + +/* + * Copy a line break character from a string into buffer. + */ + +#define WRITE_BREAK(emitter,string) \ + (FLUSH(emitter) \ + && (COPY(emitter->buffer,string), \ + emitter->column = 0, \ + emitter->line ++, \ + 1)) + /* * API functions. */ @@ -105,39 +161,57 @@ yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter); static int yaml_emitter_check_simple_key(yaml_emitter_t *emitter); +static int +yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event); + /* * Processors. */ static int -yaml_emitter_process_anchor(yaml_emitter_t *emitter, - yaml_char_t *anchor, int alias); +yaml_emitter_process_anchor(yaml_emitter_t *emitter); static int -yaml_emitter_process_tag(yaml_emitter_t *emitter, - yaml_char_t *tag); +yaml_emitter_process_tag(yaml_emitter_t *emitter); static int -yaml_emitter_process_scalar(yaml_emitter_t *emitter, - yaml_char_t *value, size_t length, - int plain_implicit, int quoted_implicit, - yaml_scalar_style_t style); +yaml_emitter_process_scalar(yaml_emitter_t *emitter); /* - * Writers. + * Analyzers. */ static int -yaml_emitter_write_bom(yaml_emitter_t *emitter); - -static int -yaml_emitter_write_version_directive(yaml_emitter_t *emitter, +yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter, yaml_version_directive_t version_directive); static int -yaml_emitter_write_tag_directive(yaml_emitter_t *emitter, +yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter, yaml_tag_directive_t tag_directive); +static int +yaml_emitter_analyze_anchor(yaml_emitter_t *emitter, + yaml_char_t *anchor, int alias); + +static int +yaml_emitter_analyze_tag(yaml_emitter_t *emitter, + yaml_char_t *tag); + +static int +yaml_emitter_analyze_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_analyze_event(yaml_emitter_t *emitter, + yaml_event_t *event); + +/* + * Writers. + */ + +static int +yaml_emitter_write_bom(yaml_emitter_t *emitter); + static int yaml_emitter_write_indent(yaml_emitter_t *emitter); @@ -146,6 +220,38 @@ yaml_emitter_write_indicator(yaml_emitter_t *emitter, char *indicator, int need_whitespace, int is_whitespace, int is_indention); +static int +yaml_emitter_write_anchor(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_tag_handle(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_tag_content(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + /* * Set an emitter error and return 0. */ @@ -172,9 +278,10 @@ yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event) } while (!yaml_emitter_need_more_events(emitter)) { - if (!yaml_emitter_state_machine(emitter, emitter->events.head)) { + if (!yaml_emitter_analyze_event(emitter, emitter->events.head)) + return 0; + if (!yaml_emitter_state_machine(emitter, emitter->events.head)) return 0; - } DEQUEUE(emitter, emitter->events); } @@ -428,6 +535,10 @@ yaml_emitter_emit_stream_start(yaml_emitter_t *emitter, "expected STREAM-START"); } +/* + * Expect DOCUMENT-START or STREAM-END. + */ + static int yaml_emitter_emit_document_start(yaml_emitter_t *emitter, yaml_event_t *event, int first) @@ -443,16 +554,16 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, int implicit; if (event->data.document_start.version_directive) { - if (event->data.document_start.version_directive->major != 1 - || event->data.document_start.version_directive-> minor != 1) { - return yaml_emitter_set_emitter_error(emitter, - "incompatible %YAML directive"); - } + if (!yaml_emitter_analyze_version_directive(emitter, + *event->data.document_start.version_directive)) + return 0; } for (tag_directive = event->data.document_start.tag_directives.start; tag_directive != event->data.document_start.tag_directives.end; tag_directive ++) { + if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive)) + return 0; if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0)) return 0; } @@ -470,8 +581,11 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, if (event->data.document_start.version_directive) { implicit = 0; - if (!yaml_emitter_write_version_directive(emitter, - *event->data.document_start.version_directive)) + if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) return 0; } @@ -481,7 +595,15 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, for (tag_directive = event->data.document_start.tag_directives.start; tag_directive != event->data.document_start.tag_directives.end; tag_directive ++) { - if (!yaml_emitter_write_tag_directive(emitter, *tag_directive)) + if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle, + strlen((char *)tag_directive->handle))) + return 0; + if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix, + strlen((char *)tag_directive->prefix))) + return 0; + if (!yaml_emitter_write_indent(emitter)) return 0; } } @@ -520,6 +642,10 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, "expected DOCUMENT-START or STREAM-END"); } +/* + * Expect the root node. + */ + static int yaml_emitter_emit_document_content(yaml_emitter_t *emitter, yaml_event_t *event) @@ -530,6 +656,10 @@ yaml_emitter_emit_document_content(yaml_emitter_t *emitter, return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0); } +/* + * Expect DOCUMENT-END. + */ + static int yaml_emitter_emit_document_end(yaml_emitter_t *emitter, yaml_event_t *event) @@ -556,6 +686,10 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter, "expected DOCUMENT-END"); } +/* + * Expect a flow item node. + */ + static int yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter, yaml_event_t *event, int first) @@ -596,6 +730,10 @@ yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter, return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0); } +/* + * Expect a flow key node. + */ + static int yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter, yaml_event_t *event, int first) @@ -655,6 +793,10 @@ yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter, } } +/* + * Expect a flow value node. + */ + static int yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter, yaml_event_t *event, int simple) @@ -676,6 +818,10 @@ yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter, return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); } +/* + * Expect a block item node. + */ + static int yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter, yaml_event_t *event, int first) @@ -706,6 +852,10 @@ yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter, return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0); } +/* + * Expect a block key node. + */ + static int yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter, yaml_event_t *event, int first) @@ -747,6 +897,10 @@ yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter, } } +/* + * Expect a block value node. + */ + static int yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter, yaml_event_t *event, int simple) @@ -768,6 +922,10 @@ yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter, return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); } +/* + * Expect a node. + */ + static int yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event, int root, int sequence, int mapping, int simple_key) @@ -799,30 +957,36 @@ yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event, return 0; } +/* + * Expect ALIAS. + */ + static int yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event) { - if (!yaml_emitter_process_anchor(emitter, event->data.alias.anchor, 1)) + if (!yaml_emitter_process_anchor(emitter)) return 0; emitter->state = POP(emitter, emitter->states); return 1; } +/* + * Expect SCALAR. + */ + static int yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event) { - if (!yaml_emitter_process_anchor(emitter, event->data.scalar.anchor, 0)) + if (!yaml_emitter_select_scalar_style(emitter, event)) return 0; - if (!yaml_emitter_process_tag(emitter, event->data.scalar.tag)) + if (!yaml_emitter_process_anchor(emitter)) + return 0; + if (!yaml_emitter_process_tag(emitter)) return 0; if (!yaml_emitter_increase_indent(emitter, 1, 0)) return 0; - if (!yaml_emitter_process_scalar(emitter, - event->data.scalar.value, event->data.scalar.length, - event->data.scalar.plain_implicit, - event->data.scalar.quoted_implicit, - event->data.scalar.style)) + if (!yaml_emitter_process_scalar(emitter)) return 0; emitter->indent = POP(emitter, emitter->indents); emitter->state = POP(emitter, emitter->states); @@ -830,14 +994,16 @@ yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event) return 1; } +/* + * Expect SEQUENCE-START. + */ + static int yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event) { - if (!yaml_emitter_process_anchor(emitter, - event->data.sequence_start.anchor, 0)) + if (!yaml_emitter_process_anchor(emitter)) return 0; - if (!yaml_emitter_process_tag(emitter, - event->data.sequence_start.tag)) + if (!yaml_emitter_process_tag(emitter)) return 0; if (emitter->flow_level || emitter->canonical @@ -852,14 +1018,16 @@ yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event) return 1; } +/* + * Expect MAPPING-START. + */ + static int yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event) { - if (!yaml_emitter_process_anchor(emitter, - event->data.mapping_start.anchor, 0)) + if (!yaml_emitter_process_anchor(emitter)) return 0; - if (!yaml_emitter_process_tag(emitter, - event->data.mapping_start.tag)) + if (!yaml_emitter_process_tag(emitter)) return 0; if (emitter->flow_level || emitter->canonical @@ -874,3 +1042,799 @@ yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event) return 1; } +/* + * Check if the document content is an empty scalar. + */ + +static int +yaml_emitter_check_empty_document(yaml_emitter_t *emitter) +{ + return 0; +} + +/* + * Check if the next events represent an empty sequence. + */ + +static int +yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter) +{ + if (emitter->events.tail - emitter->events.head < 2) + return 0; + + return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT + && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT); +} + +/* + * Check if the next events represent an empty mapping. + */ + +static int +yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter) +{ + if (emitter->events.tail - emitter->events.head < 2) + return 0; + + return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT + && emitter->events.head[1].type == YAML_MAPPING_END_EVENT); +} + +/* + * Check if the next node can be expressed as a simple key. + */ + +static int +yaml_emitter_check_simple_key(yaml_emitter_t *emitter) +{ + yaml_event_t *event = emitter->events.head; + size_t length = 0; + + switch (event->type) + { + case YAML_ALIAS_EVENT: + length += emitter->anchor_data.anchor_length; + break; + + case YAML_SCALAR_EVENT: + if (emitter->scalar_data.multiline) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length + + emitter->scalar_data.length; + break; + + case YAML_SEQUENCE_START_EVENT: + if (!yaml_emitter_check_empty_sequence(emitter)) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length; + break; + + case YAML_MAPPING_START_EVENT: + if (!yaml_emitter_check_empty_sequence(emitter)) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length; + break; + + default: + return 0; + } + + if (length > 128) + return 0; + + return 1; +} + +/* + * Determine an acceptable scalar style. + */ + +static int +yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event) +{ + yaml_scalar_style_t style = event->data.scalar.style; + + if (style == YAML_ANY_SCALAR_STYLE) + style = YAML_PLAIN_SCALAR_STYLE; + + if (emitter->canonical) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + + if (emitter->simple_key_context && emitter->scalar_data.multiline) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + + if (style == YAML_PLAIN_SCALAR_STYLE) + { + if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed) + || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed)) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + if (!emitter->scalar_data.length + && (emitter->flow_level || emitter->simple_key_context)) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + if (!event->data.scalar.plain_implicit + && !emitter->tag_data.handle && !emitter->tag_data.suffix) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + } + + if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE) + { + if (!emitter->scalar_data.single_quoted_allowed) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + } + + if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE) + { + if (!emitter->scalar_data.block_allowed) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + } + + if (!emitter->tag_data.handle && !emitter->tag_data.suffix) + { + if (!event->data.scalar.plain_implicit + && !event->data.scalar.quoted_implicit) { + return yaml_emitter_set_emitter_error(emitter, + "neither tag nor implicit flags are specified"); + } + + if (event->data.scalar.plain_implicit + && style != YAML_PLAIN_SCALAR_STYLE) { + emitter->tag_data.handle = (yaml_char_t *)"!"; + emitter->tag_data.handle_length = 1; + } + } + + emitter->scalar_data.style = style; + + return 1; +} + +/* + * Write an achor. + */ + +static int +yaml_emitter_process_anchor(yaml_emitter_t *emitter) +{ + if (!emitter->anchor_data.anchor) + return 1; + + if (!yaml_emitter_write_indicator(emitter, + (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0)) + return 0; + + return yaml_emitter_write_anchor(emitter, + emitter->anchor_data.anchor, emitter->anchor_data.anchor_length); +} + +/* + * Write a tag. + */ + +static int +yaml_emitter_process_tag(yaml_emitter_t *emitter) +{ + if (!emitter->tag_data.handle && !emitter->tag_data.suffix) + return 1; + + if (emitter->tag_data.handle) + { + if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle, + emitter->tag_data.handle_length)) + return 0; + if (emitter->tag_data.suffix) { + if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix, + emitter->tag_data.suffix_length)) + return 0; + } + } + else + { + if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix, + emitter->tag_data.suffix_length)) + return 0; + if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0)) + return 0; + } + + return 1; +} + +/* + * Write a scalar. + */ + +static int +yaml_emitter_process_scalar(yaml_emitter_t *emitter) +{ + switch (emitter->scalar_data.style) + { + case YAML_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length); + + case YAML_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length); + + default: + assert(1); /* Impossible. */ + } + + return 0; +} + +/* + * Check if a %YAML directive is valid. + */ + +static int +yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter, + yaml_version_directive_t version_directive) +{ + if (version_directive.major != 1 || version_directive.minor != 1) { + return yaml_emitter_set_emitter_error(emitter, + "incompatible %YAML directive"); + } + + return 1; +} + +/* + * Check if a %TAG directive is valid. + */ + +static int +yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter, + yaml_tag_directive_t tag_directive) +{ + yaml_string_t handle = STRING(tag_directive.handle, + strlen((char *)tag_directive.handle)); + yaml_string_t prefix = STRING(tag_directive.prefix, + strlen((char *)tag_directive.prefix)); + + if (handle.start == handle.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must not be empty"); + } + + if (handle.start[0] != '!') { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must start with '!'"); + } + + if (handle.end[-1] != '!') { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must end with '!'"); + } + + handle.pointer ++; + + while (handle.pointer != handle.end-1) { + if (!IS_ALPHA(handle)) { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must contain alphanumerical characters only"); + } + MOVE(handle); + } + + if (prefix.start == prefix.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag prefix must not be empty"); + } + + return 1; +} + +/* + * Check if an anchor is valid. + */ + +static int +yaml_emitter_analyze_anchor(yaml_emitter_t *emitter, + yaml_char_t *anchor, int alias) +{ + yaml_string_t string = STRING(anchor, strlen((char *)anchor)); + + if (string.start == string.end) { + return yaml_emitter_set_emitter_error(emitter, alias ? + "alias value must not be empty" : + "anchor value must not be empty"); + } + + while (string.pointer != string.end) { + if (!IS_ALPHA(string)) { + return yaml_emitter_set_emitter_error(emitter, alias ? + "alias value must contain alphanumerical characters only" : + "anchor value must contain alphanumerical characters only"); + } + MOVE(string); + } +} + +/* + * Check if a tag is valid. + */ + +static int +yaml_emitter_analyze_tag(yaml_emitter_t *emitter, + yaml_char_t *tag) +{ + yaml_string_t string = STRING(tag, strlen((char *)tag)); + yaml_tag_directive_t *tag_directive; + + if (string.start == string.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag value must not be empty"); + } + + for (tag_directive = emitter->tag_directives.start; + tag_directive != emitter->tag_directives.end; tag_directive ++) { + size_t prefix_length = strlen((char *)tag_directive->prefix); + if (prefix_length < (string.end - string.start) + && strncmp((char *)tag_directive->prefix, (char *)string.start, + prefix_length) == 0) + { + emitter->tag_data.handle = tag_directive->handle; + emitter->tag_data.handle_length = + strlen((char *)tag_directive->handle); + emitter->tag_data.suffix = string.start + prefix_length; + emitter->tag_data.suffix_length = + (string.end - string.start) - prefix_length; + return 1; + } + } + + emitter->tag_data.suffix = string.start; + emitter->tag_data.suffix_length = string.end - string.start; + + return 1; +} + +/* + * Check if a scalar is valid. + */ + +static int +yaml_emitter_analyze_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string = STRING(value, length); + + int block_indicators = 0; + int flow_indicators = 0; + int line_breaks = 0; + int special_characters = 0; + + int inline_spaces = 0; + int inline_breaks = 0; + int leading_spaces = 0; + int leading_breaks = 0; + int trailing_spaces = 0; + int trailing_breaks = 0; + int inline_breaks_spaces = 0; + int mixed_breaks_spaces = 0; + + int preceeded_by_space = 0; + int followed_by_space = 0; + int spaces = 0; + int breaks = 0; + int mixed = 0; + int leading = 0; + + emitter->scalar_data.value = value; + emitter->scalar_data.length = length; + + if (string.start == string.end) + { + emitter->scalar_data.multiline = 0; + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 1; + emitter->scalar_data.single_quoted_allowed = 1; + emitter->scalar_data.block_allowed = 0; + + return 1; + } + + if ((CHECK_AT(string, '-', 0) + && CHECK_AT(string, '-', 1) + && CHECK_AT(string, '-', 2)) + || (CHECK_AT(string, '.', 0) + && CHECK_AT(string, '.', 1) + && CHECK_AT(string, '.', 2))) { + block_indicators = 1; + flow_indicators = 1; + } + + preceeded_by_space = 1; + followed_by_space = IS_BLANKZ_AT(string, WIDTH(string)); + + while (string.pointer != string.end) + { + if (string.start == string.pointer) + { + if (CHECK(string, '#') || CHECK(string, ',') + || CHECK(string, '[') || CHECK(string, ']') + || CHECK(string, '{') || CHECK(string, '}') + || CHECK(string, '&') || CHECK(string, '*') + || CHECK(string, '!') || CHECK(string, '|') + || CHECK(string, '>') || CHECK(string, '\'') + || CHECK(string, '"') || CHECK(string, '%') + || CHECK(string, '@') || CHECK(string, '`')) { + flow_indicators = 1; + block_indicators = 1; + } + + if (CHECK(string, '?') || CHECK(string, ':')) { + flow_indicators = 1; + if (followed_by_space) { + block_indicators = 1; + } + } + + if (CHECK(string, '-') && followed_by_space) { + flow_indicators = 1; + block_indicators = 1; + } + } + else + { + if (CHECK(string, ',') || CHECK(string, '?') + || CHECK(string, '[') || CHECK(string, ']') + || CHECK(string, '{') || CHECK(string, '}')) { + flow_indicators = 1; + } + + if (CHECK(string, ':')) { + flow_indicators = 1; + if (followed_by_space) { + block_indicators = 1; + } + } + + if (CHECK(string, '#') && preceeded_by_space) { + flow_indicators = 1; + block_indicators = 1; + } + } + + if (!IS_PRINTABLE(string) + || (!IS_ASCII(string) && !emitter->unicode)) { + special_characters = 1; + } + + if (IS_BREAK(string)) { + line_breaks = 1; + } + + if (IS_SPACE(string)) + { + spaces = 1; + if (string.start == string.pointer) { + leading = 1; + } + } + + else if (IS_BREAK(string)) + { + if (spaces) { + mixed = 1; + } + breaks = 1; + if (string.start == string.pointer) { + leading = 1; + } + } + + else if (spaces || breaks) + { + if (leading) { + if (spaces && breaks) { + mixed_breaks_spaces = 1; + } + else if (spaces) { + leading_spaces = 1; + } + else if (breaks) { + leading_breaks = 1; + } + } + else { + if (mixed) { + mixed_breaks_spaces = 1; + } + else if (spaces && breaks) { + inline_breaks_spaces = 1; + } + else if (spaces) { + inline_spaces = 1; + } + else if (breaks) { + inline_breaks = 1; + } + } + spaces = breaks = mixed = leading = 0; + } + + preceeded_by_space = IS_BLANKZ(string); + MOVE(string); + if (string.pointer != string.end) { + followed_by_space = IS_BLANKZ_AT(string, WIDTH(string)); + } + } + + emitter->scalar_data.multiline = line_breaks; + + emitter->scalar_data.flow_plain_allowed = 1; + emitter->scalar_data.block_plain_allowed = 1; + emitter->scalar_data.single_quoted_allowed = 1; + emitter->scalar_data.block_allowed = 1; + + if (leading_spaces || leading_breaks || trailing_spaces) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + emitter->scalar_data.block_allowed = 0; + } + + if (trailing_breaks) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + } + + if (inline_breaks_spaces) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + emitter->scalar_data.single_quoted_allowed = 0; + } + + if (mixed_breaks_spaces || special_characters) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + emitter->scalar_data.single_quoted_allowed = 0; + emitter->scalar_data.block_allowed = 0; + } + + if (line_breaks) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + } + + if (flow_indicators) { + emitter->scalar_data.flow_plain_allowed = 0; + } + + if (block_indicators) { + emitter->scalar_data.block_plain_allowed = 0; + } + + return 1; +} + +/* + * Check if the event data is valid. + */ + +static int +yaml_emitter_analyze_event(yaml_emitter_t *emitter, + yaml_event_t *event) +{ + emitter->anchor_data.anchor = NULL; + emitter->anchor_data.anchor_length = 0; + emitter->tag_data.handle = NULL; + emitter->tag_data.handle_length = 0; + emitter->tag_data.suffix = NULL; + emitter->tag_data.suffix_length = 0; + emitter->scalar_data.value = NULL; + emitter->scalar_data.length = 0; + + switch (event->type) + { + case YAML_ALIAS_EVENT: + if (!yaml_emitter_analyze_anchor(emitter, + event->data.alias.anchor, 1)) + return 0; + return 1; + + case YAML_SCALAR_EVENT: + if (event->data.scalar.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.scalar.anchor, 0)) + return 0; + } + if (event->data.scalar.tag && (emitter->canonical || + (!event->data.scalar.plain_implicit + && !event->data.scalar.quoted_implicit))) { + if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag)) + return 0; + } + if (!yaml_emitter_analyze_scalar(emitter, + event->data.scalar.value, event->data.scalar.length)) + return 0; + return 1; + + case YAML_SEQUENCE_START_EVENT: + if (event->data.sequence_start.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.sequence_start.anchor, 0)) + return 0; + } + if (event->data.sequence_start.tag && (emitter->canonical || + !event->data.sequence_start.implicit)) { + if (!yaml_emitter_analyze_tag(emitter, + event->data.sequence_start.tag)) + return 0; + } + return 1; + + case YAML_MAPPING_START_EVENT: + if (event->data.mapping_start.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.mapping_start.anchor, 0)) + return 0; + } + if (event->data.mapping_start.tag && (emitter->canonical || + !event->data.mapping_start.implicit)) { + if (!yaml_emitter_analyze_tag(emitter, + event->data.mapping_start.tag)) + return 0; + } + return 1; + + default: + return 1; + } +} + +/* + * Write the BOM character. + */ + +static int +yaml_emitter_write_bom(yaml_emitter_t *emitter) +{ + if (!FLUSH(emitter)) return 0; + + *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF'; + *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB'; + *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF'; + + return 1; +} + +static int +yaml_emitter_write_indent(yaml_emitter_t *emitter) +{ + int indent = (emitter->indent >= 0) ? emitter->indent : 0; + + if (!emitter->indention || emitter->column > indent + || (emitter->column == indent && !emitter->whitespace)) { + if (!PUT_BREAK(emitter)) return 0; + } + + while (emitter->column < indent) { + if (!PUT(emitter, ' ')) return 0; + } + + emitter->whitespace = 1; + emitter->indention = 1; + + return 1; +} + +static int +yaml_emitter_write_indicator(yaml_emitter_t *emitter, + char *indicator, int need_whitespace, + int is_whitespace, int is_indention) +{ + yaml_string_t string = STRING((yaml_char_t *)indicator, strlen(indicator)); + + if (need_whitespace && !emitter->whitespace) { + if (!PUT(emitter, ' ')) return 0; + } + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = is_whitespace; + emitter->indention = (emitter->indention && is_indention); + + return 1; +} + +static int +yaml_emitter_write_anchor(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string = STRING(value, length); + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_tag_handle(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string = STRING(value, length); + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_tag_content(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + return 0; +} + +static int +yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + return 0; +} + +static int +yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + return 0; +} + +static int +yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + return 0; +} + +static int +yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + return 0; +} + +static int +yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + return 0; +} + diff --git a/src/scanner.c b/src/scanner.c index 4265763..1414401 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -487,190 +487,6 @@ ? 1 \ : yaml_parser_update_buffer(parser, (length))) -/* - * Check the octet at the specified position. - */ - -#define CHECK_AT(parser,octet,offset) \ - (parser->buffer.pointer[offset] == (yaml_char_t)(octet)) - -/* - * Check the current octet in the buffer. - */ - -#define CHECK(parser,octet) CHECK_AT(parser,(octet),0) - -/* - * Check if the character at the specified position is an alphabetical - * character, a digit, '_', or '-'. - */ - -#define IS_ALPHA_AT(parser,offset) \ - ((parser->buffer.pointer[offset] >= (yaml_char_t) '0' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) '9') || \ - (parser->buffer.pointer[offset] >= (yaml_char_t) 'A' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'Z') || \ - (parser->buffer.pointer[offset] >= (yaml_char_t) 'a' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'z') || \ - parser->buffer.pointer[offset] == '_' || \ - parser->buffer.pointer[offset] == '-') - -#define IS_ALPHA(parser) IS_ALPHA_AT(parser,0) - -/* - * Check if the character at the specified position is a digit. - */ - -#define IS_DIGIT_AT(parser,offset) \ - ((parser->buffer.pointer[offset] >= (yaml_char_t) '0' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) '9')) - -#define IS_DIGIT(parser) IS_DIGIT_AT(parser,0) - -/* - * Get the value of a digit. - */ - -#define AS_DIGIT_AT(parser,offset) \ - (parser->buffer.pointer[offset] - (yaml_char_t) '0') - -#define AS_DIGIT(parser) AS_DIGIT_AT(parser,0) - -/* - * Check if the character at the specified position is a hex-digit. - */ - -#define IS_HEX_AT(parser,offset) \ - ((parser->buffer.pointer[offset] >= (yaml_char_t) '0' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) '9') || \ - (parser->buffer.pointer[offset] >= (yaml_char_t) 'A' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'F') || \ - (parser->buffer.pointer[offset] >= (yaml_char_t) 'a' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'f')) - -#define IS_HEX(parser) IS_HEX_AT(parser,0) - -/* - * Get the value of a hex-digit. - */ - -#define AS_HEX_AT(parser,offset) \ - ((parser->buffer.pointer[offset] >= (yaml_char_t) 'A' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'F') ? \ - (parser->buffer.pointer[offset] - (yaml_char_t) 'A' + 10) : \ - (parser->buffer.pointer[offset] >= (yaml_char_t) 'a' && \ - parser->buffer.pointer[offset] <= (yaml_char_t) 'f') ? \ - (parser->buffer.pointer[offset] - (yaml_char_t) 'a' + 10) : \ - (parser->buffer.pointer[offset] - (yaml_char_t) '0')) - -#define AS_HEX(parser) AS_HEX_AT(parser,0) - -/* - * Check if the character at the specified position is NUL. - */ - -#define IS_Z_AT(parser,offset) CHECK_AT(parser,'\0',(offset)) - -#define IS_Z(parser) IS_Z_AT(parser,0) - -/* - * Check if the character at the specified position is BOM. - */ - -#define IS_BOM_AT(parser,offset) \ - (CHECK_AT(parser,'\xEF',(offset)) \ - && CHECK_AT(parser,'\xBB',(offset)+1) \ - && CHECK_AT(parser,'\xBF',(offset)+1)) /* BOM (#xFEFF) */ - -#define IS_BOM(parser) IS_BOM_AT(parser,0) - -/* - * Check if the character at the specified position is space. - */ - -#define IS_SPACE_AT(parser,offset) CHECK_AT(parser,' ',(offset)) - -#define IS_SPACE(parser) IS_SPACE_AT(parser,0) - -/* - * Check if the character at the specified position is tab. - */ - -#define IS_TAB_AT(parser,offset) CHECK_AT(parser,'\t',(offset)) - -#define IS_TAB(parser) IS_TAB_AT(parser,0) - -/* - * Check if the character at the specified position is blank (space or tab). - */ - -#define IS_BLANK_AT(parser,offset) \ - (IS_SPACE_AT(parser,(offset)) || IS_TAB_AT(parser,(offset))) - -#define IS_BLANK(parser) IS_BLANK_AT(parser,0) - -/* - * Check if the character at the specified position is a line break. - */ - -#define IS_BREAK_AT(parser,offset) \ - (CHECK_AT(parser,'\r',(offset)) /* CR (#xD)*/ \ - || CHECK_AT(parser,'\n',(offset)) /* LF (#xA) */ \ - || (CHECK_AT(parser,'\xC2',(offset)) \ - && CHECK_AT(parser,'\x85',(offset)+1)) /* NEL (#x85) */ \ - || (CHECK_AT(parser,'\xE2',(offset)) \ - && CHECK_AT(parser,'\x80',(offset)+1) \ - && CHECK_AT(parser,'\xA8',(offset)+2)) /* LS (#x2028) */ \ - || (CHECK_AT(parser,'\xE2',(offset)) \ - && CHECK_AT(parser,'\x80',(offset)+1) \ - && CHECK_AT(parser,'\xA9',(offset)+2))) /* PS (#x2029) */ - -#define IS_BREAK(parser) IS_BREAK_AT(parser,0) - -#define IS_CRLF_AT(parser,offset) \ - (CHECK_AT(parser,'\r',(offset)) && CHECK_AT(parser,'\n',(offset)+1)) - -#define IS_CRLF(parser) IS_CRLF_AT(parser,0) - -/* - * Check if the character is a line break or NUL. - */ - -#define IS_BREAKZ_AT(parser,offset) \ - (IS_BREAK_AT(parser,(offset)) || IS_Z_AT(parser,(offset))) - -#define IS_BREAKZ(parser) IS_BREAKZ_AT(parser,0) - -/* - * Check if the character is a line break, space, or NUL. - */ - -#define IS_SPACEZ_AT(parser,offset) \ - (IS_SPACE_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset))) - -#define IS_SPACEZ(parser) IS_SPACEZ_AT(parser,0) - -/* - * Check if the character is a line break, space, tab, or NUL. - */ - -#define IS_BLANKZ_AT(parser,offset) \ - (IS_BLANK_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset))) - -#define IS_BLANKZ(parser) IS_BLANKZ_AT(parser,0) - -/* - * Determine the width of the character. - */ - -#define WIDTH_AT(parser,offset) \ - ((parser->buffer.pointer[offset] & 0x80) == 0x00 ? 1 : \ - (parser->buffer.pointer[offset] & 0xE0) == 0xC0 ? 2 : \ - (parser->buffer.pointer[offset] & 0xF0) == 0xE0 ? 3 : \ - (parser->buffer.pointer[offset] & 0xF8) == 0xF0 ? 4 : 0) - -#define WIDTH(parser) WIDTH_AT(parser,0) - /* * Advance the buffer pointer. */ @@ -679,21 +495,21 @@ (parser->mark.index ++, \ parser->mark.column ++, \ parser->unread --, \ - parser->buffer.pointer += WIDTH(parser)) + parser->buffer.pointer += WIDTH(parser->buffer)) #define SKIP_LINE(parser) \ - (IS_CRLF(parser) ? \ + (IS_CRLF(parser->buffer) ? \ (parser->mark.index += 2, \ parser->mark.column = 0, \ parser->mark.line ++, \ parser->unread -= 2, \ parser->buffer.pointer += 2) : \ - IS_BREAK(parser) ? \ + IS_BREAK(parser->buffer) ? \ (parser->mark.index ++, \ parser->mark.column = 0, \ parser->mark.line ++, \ parser->unread --, \ - parser->buffer.pointer += WIDTH(parser)) : 0) + parser->buffer.pointer += WIDTH(parser->buffer)) : 0) /* * Copy a character to a string buffer and advance pointers. @@ -701,20 +517,7 @@ #define READ(parser,string) \ (STRING_EXTEND(parser,string) ? \ - (((*parser->buffer.pointer & 0x80) == 0x00 ? \ - (*((string).pointer++) = *(parser->buffer.pointer++)) : \ - (*parser->buffer.pointer & 0xE0) == 0xC0 ? \ - (*((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++)) : \ - (*parser->buffer.pointer & 0xF0) == 0xE0 ? \ - (*((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++)) : \ - (*parser->buffer.pointer & 0xF8) == 0xF0 ? \ - (*((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++), \ - *((string).pointer++) = *(parser->buffer.pointer++)) : 0), \ + (COPY(string,parser->buffer), \ parser->mark.index ++, \ parser->mark.column ++, \ parser->unread --, \ @@ -726,31 +529,34 @@ #define READ_LINE(parser,string) \ (STRING_EXTEND(parser,string) ? \ - (((CHECK_AT(parser,'\r',0) && CHECK_AT(parser,'\n',1)) ? /* CR LF -> LF */ \ + (((CHECK_AT(parser->buffer,'\r',0) \ + && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ parser->buffer.pointer += 2, \ parser->mark.index += 2, \ parser->mark.column = 0, \ parser->mark.line ++, \ parser->unread -= 2) : \ - (CHECK_AT(parser,'\r',0) || CHECK_AT(parser,'\n',0)) ? /* CR|LF -> LF */ \ + (CHECK_AT(parser->buffer,'\r',0) \ + || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ parser->buffer.pointer ++, \ parser->mark.index ++, \ parser->mark.column = 0, \ parser->mark.line ++, \ parser->unread --) : \ - (CHECK_AT(parser,'\xC2',0) && CHECK_AT(parser,'\x85',1)) ? /* NEL -> LF */ \ + (CHECK_AT(parser->buffer,'\xC2',0) \ + && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ parser->buffer.pointer += 2, \ parser->mark.index ++, \ parser->mark.column = 0, \ parser->mark.line ++, \ parser->unread --) : \ - (CHECK_AT(parser,'\xE2',0) && \ - CHECK_AT(parser,'\x80',1) && \ - (CHECK_AT(parser,'\xA8',2) || \ - CHECK_AT(parser,'\xA9',2))) ? /* LS|PS -> LS|PS */ \ + (CHECK_AT(parser->buffer,'\xE2',0) && \ + CHECK_AT(parser->buffer,'\x80',1) && \ + (CHECK_AT(parser->buffer,'\xA8',2) || \ + CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \ (*((string).pointer++) = *(parser->buffer.pointer++), \ *((string).pointer++) = *(parser->buffer.pointer++), \ *((string).pointer++) = *(parser->buffer.pointer++), \ @@ -1088,111 +894,113 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) /* Is it the end of the stream? */ - if (IS_Z(parser)) + if (IS_Z(parser->buffer)) return yaml_parser_fetch_stream_end(parser); /* Is it a directive? */ - if (parser->mark.column == 0 && CHECK(parser, '%')) + if (parser->mark.column == 0 && CHECK(parser->buffer, '%')) return yaml_parser_fetch_directive(parser); /* Is it the document start indicator? */ if (parser->mark.column == 0 - && CHECK_AT(parser, '-', 0) - && CHECK_AT(parser, '-', 1) - && CHECK_AT(parser, '-', 2) - && IS_BLANKZ_AT(parser, 3)) + && CHECK_AT(parser->buffer, '-', 0) + && CHECK_AT(parser->buffer, '-', 1) + && CHECK_AT(parser->buffer, '-', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_START_TOKEN); /* Is it the document end indicator? */ if (parser->mark.column == 0 - && CHECK_AT(parser, '.', 0) - && CHECK_AT(parser, '.', 1) - && CHECK_AT(parser, '.', 2) - && IS_BLANKZ_AT(parser, 3)) + && CHECK_AT(parser->buffer, '.', 0) + && CHECK_AT(parser->buffer, '.', 1) + && CHECK_AT(parser->buffer, '.', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_END_TOKEN); /* Is it the flow sequence start indicator? */ - if (CHECK(parser, '[')) + if (CHECK(parser->buffer, '[')) return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_SEQUENCE_START_TOKEN); /* Is it the flow mapping start indicator? */ - if (CHECK(parser, '{')) + if (CHECK(parser->buffer, '{')) return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_MAPPING_START_TOKEN); /* Is it the flow sequence end indicator? */ - if (CHECK(parser, ']')) + if (CHECK(parser->buffer, ']')) return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_SEQUENCE_END_TOKEN); /* Is it the flow mapping end indicator? */ - if (CHECK(parser, '}')) + if (CHECK(parser->buffer, '}')) return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_MAPPING_END_TOKEN); /* Is it the flow entry indicator? */ - if (CHECK(parser, ',')) + if (CHECK(parser->buffer, ',')) return yaml_parser_fetch_flow_entry(parser); /* Is it the block entry indicator? */ - if (CHECK(parser, '-') && IS_BLANKZ_AT(parser, 1)) + if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1)) return yaml_parser_fetch_block_entry(parser); /* Is it the key indicator? */ - if (CHECK(parser, '?') && (parser->flow_level || IS_BLANKZ_AT(parser, 1))) + if (CHECK(parser->buffer, '?') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_key(parser); /* Is it the value indicator? */ - if (CHECK(parser, ':') && (parser->flow_level || IS_BLANKZ_AT(parser, 1))) + if (CHECK(parser->buffer, ':') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_value(parser); /* Is it an alias? */ - if (CHECK(parser, '*')) + if (CHECK(parser->buffer, '*')) return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN); /* Is it an anchor? */ - if (CHECK(parser, '&')) + if (CHECK(parser->buffer, '&')) return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN); /* Is it a tag? */ - if (CHECK(parser, '!')) + if (CHECK(parser->buffer, '!')) return yaml_parser_fetch_tag(parser); /* Is it a literal scalar? */ - if (CHECK(parser, '|') && !parser->flow_level) + if (CHECK(parser->buffer, '|') && !parser->flow_level) return yaml_parser_fetch_block_scalar(parser, 1); /* Is it a folded scalar? */ - if (CHECK(parser, '>') && !parser->flow_level) + if (CHECK(parser->buffer, '>') && !parser->flow_level) return yaml_parser_fetch_block_scalar(parser, 0); /* Is it a single-quoted scalar? */ - if (CHECK(parser, '\'')) + if (CHECK(parser->buffer, '\'')) return yaml_parser_fetch_flow_scalar(parser, 1); /* Is it a double-quoted scalar? */ - if (CHECK(parser, '"')) + if (CHECK(parser->buffer, '"')) return yaml_parser_fetch_flow_scalar(parser, 0); /* @@ -1214,16 +1022,20 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) * The last rule is more restrictive than the specification requires. */ - if (!(IS_BLANKZ(parser) || CHECK(parser, '-') || CHECK(parser, '?') - || CHECK(parser, ':') || CHECK(parser, ',') || CHECK(parser, '[') - || CHECK(parser, ']') || CHECK(parser, '{') || CHECK(parser, '}') - || CHECK(parser, '#') || CHECK(parser, '&') || CHECK(parser, '*') - || CHECK(parser, '!') || CHECK(parser, '|') || CHECK(parser, '>') - || CHECK(parser, '\'') || CHECK(parser, '"') || CHECK(parser, '%') - || CHECK(parser, '@') || CHECK(parser, '`')) || - (CHECK(parser, '-') && !IS_BLANK_AT(parser, 1)) || + if (!(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '-') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}') || CHECK(parser->buffer, '#') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '*') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '|') + || CHECK(parser->buffer, '>') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '"') || CHECK(parser->buffer, '%') + || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '`')) || + (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) || (!parser->flow_level && - (CHECK(parser, '?') || CHECK(parser, ':')) && !IS_BLANKZ_AT(parser, 1))) + (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':')) + && !IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_plain_scalar(parser); /* @@ -2101,7 +1913,7 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) if (!CACHE(parser, 1)) return 0; - if (parser->mark.column == 0 && IS_BOM(parser)) + if (parser->mark.column == 0 && IS_BOM(parser->buffer)) SKIP(parser); /* @@ -2116,17 +1928,17 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) if (!CACHE(parser, 1)) return 0; - while (CHECK(parser,' ') || + while (CHECK(parser->buffer,' ') || ((parser->flow_level || !parser->simple_key_allowed) && - CHECK(parser, '\t'))) { + CHECK(parser->buffer, '\t'))) { SKIP(parser); if (!CACHE(parser, 1)) return 0; } /* Eat a comment until a line break. */ - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) return 0; } @@ -2134,7 +1946,7 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) /* If it is a line break, eat it. */ - if (IS_BREAK(parser)) + if (IS_BREAK(parser->buffer)) { if (!CACHE(parser, 2)) return 0; SKIP_LINE(parser); @@ -2234,13 +2046,13 @@ yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser)) { + while (IS_BLANK(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } @@ -2248,7 +2060,7 @@ yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) /* Check if we are at the end of the line. */ - if (!IS_BREAKZ(parser)) { + if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a directive", start_mark, "did not found expected comment or line break"); goto error; @@ -2256,7 +2068,7 @@ yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) /* Eat a line break. */ - if (IS_BREAK(parser)) { + if (IS_BREAK(parser->buffer)) { if (!CACHE(parser, 2)) goto error; SKIP_LINE(parser); } @@ -2294,7 +2106,7 @@ yaml_parser_scan_directive_name(yaml_parser_t *parser, if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) + while (IS_ALPHA(parser->buffer)) { if (!READ(parser, string)) goto error; if (!CACHE(parser, 1)) goto error; @@ -2310,7 +2122,7 @@ yaml_parser_scan_directive_name(yaml_parser_t *parser, /* Check for an blank character after the name. */ - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a directive", start_mark, "found unexpected non-alphabetical character"); goto error; @@ -2341,7 +2153,7 @@ yaml_parser_scan_version_directive_value(yaml_parser_t *parser, if (!CACHE(parser, 1)) return 0; - while (IS_BLANK(parser)) { + while (IS_BLANK(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) return 0; } @@ -2353,7 +2165,7 @@ yaml_parser_scan_version_directive_value(yaml_parser_t *parser, /* Eat '.'. */ - if (!CHECK(parser, '.')) { + if (!CHECK(parser->buffer, '.')) { return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", start_mark, "did not find expected digit or '.' character"); } @@ -2391,7 +2203,7 @@ yaml_parser_scan_version_directive_number(yaml_parser_t *parser, if (!CACHE(parser, 1)) return 0; - while (IS_DIGIT(parser)) + while (IS_DIGIT(parser->buffer)) { /* Check if the number is too long. */ @@ -2400,7 +2212,7 @@ yaml_parser_scan_version_directive_number(yaml_parser_t *parser, start_mark, "found extremely long version number"); } - value = value*10 + AS_DIGIT(parser); + value = value*10 + AS_DIGIT(parser->buffer); SKIP(parser); @@ -2438,7 +2250,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser)) { + while (IS_BLANK(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } @@ -2452,7 +2264,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, if (!CACHE(parser, 1)) goto error; - if (!IS_BLANK(parser)) { + if (!IS_BLANK(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", start_mark, "did not find expected whitespace"); goto error; @@ -2460,7 +2272,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Eat whitespaces. */ - while (IS_BLANK(parser)) { + while (IS_BLANK(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } @@ -2474,7 +2286,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, if (!CACHE(parser, 1)) goto error; - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", start_mark, "did not find expected whitespace or line break"); goto error; @@ -2511,7 +2323,7 @@ yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) { + while (IS_ALPHA(parser->buffer)) { if (!READ(parser, string)) goto error; if (!CACHE(parser, 1)) goto error; length ++; @@ -2526,9 +2338,11 @@ yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, * '?', ':', ',', ']', '}', '%', '@', '`'. */ - if (!length || !(IS_BLANKZ(parser) || CHECK(parser, '?') || CHECK(parser, ':') || - CHECK(parser, ',') || CHECK(parser, ']') || CHECK(parser, '}') || - CHECK(parser, '%') || CHECK(parser, '@') || CHECK(parser, '`'))) { + if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}') + || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '`'))) { yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ? "while scanning an anchor" : "while scanning an alias", start_mark, "did not find expected alphabetic or numeric character"); @@ -2568,7 +2382,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 2)) goto error; - if (CHECK_AT(parser, '<', 1)) + if (CHECK_AT(parser->buffer, '<', 1)) { /* Set the handle to '' */ @@ -2588,7 +2402,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) /* Check for '>' and eat it. */ - if (!CHECK(parser, '>')) { + if (!CHECK(parser->buffer, '>')) { yaml_parser_set_scanner_error(parser, "while scanning a tag", start_mark, "did not find the expected '>'"); goto error; @@ -2646,7 +2460,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 1)) goto error; - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a tag", start_mark, "did not found expected whitespace or line break"); goto error; @@ -2682,7 +2496,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, if (!CACHE(parser, 1)) goto error; - if (!CHECK(parser, '!')) { + if (!CHECK(parser->buffer, '!')) { yaml_parser_set_scanner_error(parser, directive ? "while scanning a tag directive" : "while scanning a tag", start_mark, "did not find expected '!'"); @@ -2697,7 +2511,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) + while (IS_ALPHA(parser->buffer)) { if (!READ(parser, string)) goto error; if (!CACHE(parser, 1)) goto error; @@ -2705,7 +2519,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, /* Check if the trailing character is '!' and copy it. */ - if (CHECK(parser, '!')) + if (CHECK(parser->buffer, '!')) { if (!READ(parser, string)) goto error; } @@ -2778,17 +2592,21 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, * '%'. */ - while (IS_ALPHA(parser) || CHECK(parser, ';') || CHECK(parser, '/') || - CHECK(parser, '?') || CHECK(parser, ':') || CHECK(parser, '@') || - CHECK(parser, '&') || CHECK(parser, '=') || CHECK(parser, '+') || - CHECK(parser, '$') || CHECK(parser, ',') || CHECK(parser, '.') || - CHECK(parser, '!') || CHECK(parser, '~') || CHECK(parser, '*') || - CHECK(parser, '\'') || CHECK(parser, '(') || CHECK(parser, ')') || - CHECK(parser, '[') || CHECK(parser, ']') || CHECK(parser, '%')) + while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';') + || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=') + || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~') + || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')') + || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') + || CHECK(parser->buffer, '%')) { /* Check if it is a URI-escape sequence. */ - if (CHECK(parser, '%')) { + if (CHECK(parser->buffer, '%')) { if (!yaml_parser_scan_uri_escapes(parser, directive, start_mark, &string)) goto error; } @@ -2841,7 +2659,9 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, if (!CACHE(parser, 3)) return 0; - if (!(CHECK(parser, '%') && IS_HEX_AT(parser, 1) && IS_HEX_AT(parser, 2))) { + if (!(CHECK(parser->buffer, '%') + && IS_HEX_AT(parser->buffer, 1) + && IS_HEX_AT(parser->buffer, 2))) { return yaml_parser_set_scanner_error(parser, directive ? "while parsing a %TAG directive" : "while parsing a tag", start_mark, "did not find URI escaped octet"); @@ -2849,7 +2669,7 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, /* Get the octet. */ - octet = (AS_HEX_AT(parser, 1) << 4) + AS_HEX_AT(parser, 2); + octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2); /* If it is the leading octet, determine the length of the UTF-8 sequence. */ @@ -2923,11 +2743,11 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check for a chomping indicator. */ - if (CHECK(parser, '+') || CHECK(parser, '-')) + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) { /* Set the chomping method and eat the indicator. */ - chomping = CHECK(parser, '+') ? +1 : -1; + chomping = CHECK(parser->buffer, '+') ? +1 : -1; SKIP(parser); @@ -2935,11 +2755,11 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - if (IS_DIGIT(parser)) + if (IS_DIGIT(parser->buffer)) { /* Check that the intendation is greater than 0. */ - if (CHECK(parser, '0')) { + if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found an intendation indicator equal to 0"); goto error; @@ -2947,7 +2767,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Get the intendation level and eat the indicator. */ - increment = AS_DIGIT(parser); + increment = AS_DIGIT(parser->buffer); SKIP(parser); } @@ -2955,22 +2775,22 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Do the same as above, but in the opposite order. */ - else if (IS_DIGIT(parser)) + else if (IS_DIGIT(parser->buffer)) { - if (CHECK(parser, '0')) { + if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found an intendation indicator equal to 0"); goto error; } - increment = AS_DIGIT(parser); + increment = AS_DIGIT(parser->buffer); SKIP(parser); if (!CACHE(parser, 1)) goto error; - if (CHECK(parser, '+') || CHECK(parser, '-')) { - chomping = CHECK(parser, '+') ? +1 : -1; + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) { + chomping = CHECK(parser->buffer, '+') ? +1 : -1; SKIP(parser); } @@ -2980,13 +2800,13 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser)) { + while (IS_BLANK(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) goto error; } @@ -2994,7 +2814,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check if we are at the end of the line. */ - if (!IS_BREAKZ(parser)) { + if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "did not found expected comment or line break"); goto error; @@ -3002,7 +2822,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Eat a line break. */ - if (IS_BREAK(parser)) { + if (IS_BREAK(parser->buffer)) { if (!CACHE(parser, 2)) goto error; SKIP_LINE(parser); } @@ -3024,7 +2844,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - while (parser->mark.column == indent && !IS_Z(parser)) + while (parser->mark.column == indent && !IS_Z(parser->buffer)) { /* * We are at the beginning of a non-empty line. @@ -3032,7 +2852,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Is it a trailing whitespace? */ - trailing_blank = IS_BLANK(parser); + trailing_blank = IS_BLANK(parser->buffer); /* Check if we need to fold the leading line break. */ @@ -3060,11 +2880,11 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Is it a leading whitespace? */ - leading_blank = IS_BLANK(parser); + leading_blank = IS_BLANK(parser->buffer); /* Consume the current line. */ - while (!IS_BREAKZ(parser)) { + while (!IS_BREAKZ(parser->buffer)) { if (!READ(parser, string)) goto error; if (!CACHE(parser, 1)) goto error; } @@ -3131,7 +2951,8 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, if (!CACHE(parser, 1)) return 0; - while ((!*indent || parser->mark.column < *indent) && IS_SPACE(parser)) { + while ((!*indent || parser->mark.column < *indent) + && IS_SPACE(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) return 0; } @@ -3141,14 +2962,15 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, /* Check for a tab character messing the intendation. */ - if ((!*indent || parser->mark.column < *indent) && IS_TAB(parser)) { + if ((!*indent || parser->mark.column < *indent) + && IS_TAB(parser->buffer)) { return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found a tab character where an intendation space is expected"); } /* Have we found a non-empty line? */ - if (!IS_BREAK(parser)) break; + if (!IS_BREAK(parser->buffer)) break; /* Consume the line break. */ @@ -3206,13 +3028,13 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 4)) goto error; if (parser->mark.column == 0 && - ((CHECK_AT(parser, '-', 0) && - CHECK_AT(parser, '-', 1) && - CHECK_AT(parser, '-', 2)) || - (CHECK_AT(parser, '.', 0) && - CHECK_AT(parser, '.', 1) && - CHECK_AT(parser, '.', 2))) && - IS_BLANKZ_AT(parser, 3)) + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) { yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", start_mark, "found unexpected document indicator"); @@ -3221,7 +3043,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check for EOF. */ - if (IS_Z(parser)) { + if (IS_Z(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", start_mark, "found unexpected end of stream"); goto error; @@ -3233,11 +3055,12 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, leading_blanks = 0; - while (!IS_BLANKZ(parser)) + while (!IS_BLANKZ(parser->buffer)) { /* Check for an escaped single quote. */ - if (single && CHECK_AT(parser, '\'', 0) && CHECK_AT(parser, '\'', 1)) + if (single && CHECK_AT(parser->buffer, '\'', 0) + && CHECK_AT(parser->buffer, '\'', 1)) { if (!STRING_EXTEND(parser, string)) goto error; *(string.pointer++) = '\''; @@ -3247,14 +3070,15 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check for the right quote. */ - else if (CHECK(parser, single ? '\'' : '"')) + else if (CHECK(parser->buffer, single ? '\'' : '"')) { break; } /* Check for an escaped line break. */ - else if (!single && CHECK(parser, '\\') && IS_BREAK_AT(parser, 1)) + else if (!single && CHECK(parser->buffer, '\\') + && IS_BREAK_AT(parser->buffer, 1)) { if (!CACHE(parser, 3)) goto error; SKIP(parser); @@ -3265,7 +3089,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check for an escape sequence. */ - else if (!single && CHECK(parser, '\\')) + else if (!single && CHECK(parser->buffer, '\\')) { int code_length = 0; @@ -3383,12 +3207,12 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, code_length)) goto error; for (k = 0; k < code_length; k ++) { - if (!IS_HEX_AT(parser, k)) { + if (!IS_HEX_AT(parser->buffer, k)) { yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", start_mark, "did not find expected hexdecimal number"); goto error; } - value = (value << 4) + AS_HEX_AT(parser, k); + value = (value << 4) + AS_HEX_AT(parser->buffer, k); } /* Check the value and write the character. */ @@ -3438,16 +3262,16 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check if we are at the end of the scalar. */ - if (CHECK(parser, single ? '\'' : '"')) + if (CHECK(parser->buffer, single ? '\'' : '"')) break; /* Consume blank characters. */ if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser) || IS_BREAK(parser)) + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) { - if (IS_BLANK(parser)) + if (IS_BLANK(parser->buffer)) { /* Consume a space or a tab character. */ @@ -3568,26 +3392,28 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 4)) goto error; if (parser->mark.column == 0 && - ((CHECK_AT(parser, '-', 0) && - CHECK_AT(parser, '-', 1) && - CHECK_AT(parser, '-', 2)) || - (CHECK_AT(parser, '.', 0) && - CHECK_AT(parser, '.', 1) && - CHECK_AT(parser, '.', 2))) && - IS_BLANKZ_AT(parser, 3)) break; + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) break; /* Check for a comment. */ - if (CHECK(parser, '#')) + if (CHECK(parser->buffer, '#')) break; /* Consume non-blank characters. */ - while (!IS_BLANKZ(parser)) + while (!IS_BLANKZ(parser->buffer)) { /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */ - if (parser->flow_level && CHECK(parser, ':') && !IS_BLANKZ_AT(parser, 1)) { + if (parser->flow_level + && CHECK(parser->buffer, ':') + && !IS_BLANKZ_AT(parser->buffer, 1)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found unexpected ':'"); goto error; @@ -3595,12 +3421,12 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) /* Check for indicators that may end a plain scalar. */ - if ((CHECK(parser, ':') && IS_BLANKZ_AT(parser, 1)) || - (parser->flow_level && - (CHECK(parser, ',') || CHECK(parser, ':') || - CHECK(parser, '?') || CHECK(parser, '[') || - CHECK(parser, ']') || CHECK(parser, '{') || - CHECK(parser, '}')))) + if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1)) + || (parser->flow_level && + (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}')))) break; /* Check if we need to join whitespaces and breaks. */ @@ -3649,20 +3475,21 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) /* Is it the end? */ - if (!(IS_BLANK(parser) || IS_BREAK(parser))) + if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))) break; /* Consume blank characters. */ if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser) || IS_BREAK(parser)) + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) { - if (IS_BLANK(parser)) + if (IS_BLANK(parser->buffer)) { /* Check for tab character that abuse intendation. */ - if (leading_blanks && parser->mark.column < indent && IS_TAB(parser)) { + if (leading_blanks && parser->mark.column < indent + && IS_TAB(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found a tab character that violate intendation"); goto error; diff --git a/src/writer.c b/src/writer.c index 2131372..ec0e477 100644 --- a/src/writer.c +++ b/src/writer.c @@ -37,6 +37,9 @@ yaml_emitter_flush(yaml_emitter_t *emitter) assert(emitter->write_handler); /* Write handler must be set. */ assert(emitter->encoding); /* Output encoding must be set. */ + emitter->buffer.last = emitter->buffer.pointer; + emitter->buffer.pointer = emitter->buffer.start; + /* Check if the buffer is empty. */ if (emitter->buffer.start == emitter->buffer.last) { diff --git a/src/yaml_private.h b/src/yaml_private.h index efd1d43..08a0232 100644 --- a/src/yaml_private.h +++ b/src/yaml_private.h @@ -111,6 +111,8 @@ yaml_string_join( #define NULL_STRING { NULL, NULL, NULL } +#define STRING(string,length) { (string), (string)+(length), (string) } + #define STRING_INIT(context,string,size) \ (((string).start = yaml_malloc(size)) ? \ ((string).pointer = (string).start, \ @@ -142,6 +144,253 @@ yaml_string_join( ((context)->error = YAML_MEMORY_ERROR, \ 0)) +/* + * String check operations. + */ + +/* + * Check the octet at the specified position. + */ + +#define CHECK_AT(string,octet,offset) \ + ((string).pointer[offset] == (yaml_char_t)(octet)) + +/* + * Check the current octet in the buffer. + */ + +#define CHECK(string,octet) CHECK_AT((string),(octet),0) + +/* + * Check if the character at the specified position is an alphabetical + * character, a digit, '_', or '-'. + */ + +#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] == '-') + +#define IS_ALPHA(string) IS_ALPHA_AT((string),0) + +/* + * Check if the character at the specified position is a digit. + */ + +#define IS_DIGIT_AT(string,offset) \ + (((string).pointer[offset] >= (yaml_char_t) '0' && \ + (string).pointer[offset] <= (yaml_char_t) '9')) + +#define IS_DIGIT(string) IS_DIGIT_AT((string),0) + +/* + * Get the value of a digit. + */ + +#define AS_DIGIT_AT(string,offset) \ + ((string).pointer[offset] - (yaml_char_t) '0') + +#define AS_DIGIT(string) AS_DIGIT_AT((string),0) + +/* + * Check if the character at the specified position is a hex-digit. + */ + +#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')) + +#define IS_HEX(string) IS_HEX_AT((string),0) + +/* + * Get the value of a hex-digit. + */ + +#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')) + +#define AS_HEX(string) AS_HEX_AT((string),0) + +/* + * Check if the character is ASCII. + */ + +#define IS_ASCII_AT(string,offset) \ + ((string).pointer[offset] <= (yaml_char_t) '\x7F') + +#define IS_ASCII(string) IS_ASCII_AT((string),0) + +/* + * Check if the character can be printed unescaped. + */ + +#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)))) + +#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0) + +/* + * Check if the character at the specified position is NUL. + */ + +#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset)) + +#define IS_Z(string) IS_Z_AT((string),0) + +/* + * Check if the character at the specified position is BOM. + */ + +#define IS_BOM_AT(string,offset) \ + (CHECK_AT((string),'\xEF',(offset)) \ + && CHECK_AT((string),'\xBB',(offset)+1) \ + && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */ + +#define IS_BOM(string) IS_BOM_AT(string,0) + +/* + * Check if the character at the specified position is space. + */ + +#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset)) + +#define IS_SPACE(string) IS_SPACE_AT((string),0) + +/* + * Check if the character at the specified position is tab. + */ + +#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset)) + +#define IS_TAB(string) IS_TAB_AT((string),0) + +/* + * Check if the character at the specified position is blank (space or tab). + */ + +#define IS_BLANK_AT(string,offset) \ + (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset))) + +#define IS_BLANK(string) IS_BLANK_AT((string),0) + +/* + * Check if the character at the specified position is a line break. + */ + +#define IS_BREAK_AT(string,offset) \ + (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \ + || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \ + || (CHECK_AT((string),'\xC2',(offset)) \ + && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \ + || (CHECK_AT((string),'\xE2',(offset)) \ + && CHECK_AT((string),'\x80',(offset)+1) \ + && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \ + || (CHECK_AT((string),'\xE2',(offset)) \ + && CHECK_AT((string),'\x80',(offset)+1) \ + && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */ + +#define IS_BREAK(string) IS_BREAK_AT((string),0) + +#define IS_CRLF_AT(string,offset) \ + (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1)) + +#define IS_CRLF(string) IS_CRLF_AT((string),0) + +/* + * Check if the character is a line break or NUL. + */ + +#define IS_BREAKZ_AT(string,offset) \ + (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset))) + +#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0) + +/* + * Check if the character is a line break, space, or NUL. + */ + +#define IS_SPACEZ_AT(string,offset) \ + (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset))) + +#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0) + +/* + * Check if the character is a line break, space, tab, or NUL. + */ + +#define IS_BLANKZ_AT(string,offset) \ + (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset))) + +#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0) + +/* + * Determine the width of the character. + */ + +#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) + +#define WIDTH(string) WIDTH_AT((string),0) + +/* + * Move the string pointer to the next character. + */ + +#define MOVE(string) ((string).pointer += WIDTH((string))) + +/* + * 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) + /* * Stack and queue management. */ -- cgit v1.2.1