Commits

Kirill Simonov committed 8e0a8f4

Implement everything except tag and scalar writers.

Comments (0)

Files changed (5)

     /** 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;
+
     /**
      * @}
      */
 #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.
  */
 
 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_emitter_process_anchor(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_process_tag(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_process_scalar(yaml_emitter_t *emitter);
+
+/*
+ * Analyzers.
+ */
+
+static int
+yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
+        yaml_version_directive_t version_directive);
+
+static int
+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_process_tag(yaml_emitter_t *emitter,
+yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
         yaml_char_t *tag);
 
 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_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.
 yaml_emitter_write_bom(yaml_emitter_t *emitter);
 
 static int
-yaml_emitter_write_version_directive(yaml_emitter_t *emitter,
-        yaml_version_directive_t version_directive);
-
-static int
-yaml_emitter_write_tag_directive(yaml_emitter_t *emitter,
-        yaml_tag_directive_t tag_directive);
-
-static int
 yaml_emitter_write_indent(yaml_emitter_t *emitter);
 
 static int
         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.
  */
     }
 
     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);
     }
 
             "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)
         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;
         }
 
         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;
         }
         
             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;
             }
         }
             "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)
     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)
             "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)
     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)
     }
 }
 
+/*
+ * Expect a flow value node.
+ */
+
 static int
 yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
         yaml_event_t *event, int simple)
     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)
     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)
     }
 }
 
+/*
+ * Expect a block value node.
+ */
+
 static int
 yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
         yaml_event_t *event, int simple)
     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)
     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);
     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
     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
     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;
+}
+
         : 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.
  */
 
      (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.
 
 #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 --,                                                    \
 
 #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++),                      \
 
     /* 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);
 
     /*
      * 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);
 
     /*
 
         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);
 
         /*
 
         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;
             }
 
         /* 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);
 
     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;
         }
 
     /* 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;
 
     /* Eat a line break. */
 
-    if (IS_BREAK(parser)) {
+    if (IS_BREAK(parser->buffer)) {
         if (!CACHE(parser, 2)) goto error;
         SKIP_LINE(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;
 
     /* 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;
 
     if (!CACHE(parser, 1)) return 0;
 
-    while (IS_BLANK(parser)) {
+    while (IS_BLANK(parser->buffer)) {
         SKIP(parser);
         if (!CACHE(parser, 1)) return 0;
     }
 
     /* 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");
     }
 
     if (!CACHE(parser, 1)) return 0;
 
-    while (IS_DIGIT(parser))
+    while (IS_DIGIT(parser->buffer))
     {
         /* Check if the number is too long. */
 
                     start_mark, "found extremely long version number");
         }
 
-        value = value*10 + AS_DIGIT(parser);
+        value = value*10 + AS_DIGIT(parser->buffer);
 
         SKIP(parser);
 
 
     if (!CACHE(parser, 1)) goto error;
 
-    while (IS_BLANK(parser)) {
+    while (IS_BLANK(parser->buffer)) {
         SKIP(parser);
         if (!CACHE(parser, 1)) goto error;
     }
 
     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;
 
     /* Eat whitespaces. */
 
-    while (IS_BLANK(parser)) {
+    while (IS_BLANK(parser->buffer)) {
         SKIP(parser);
         if (!CACHE(parser, 1)) goto error;
     }
 
     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;
 
     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 ++;
      *      '?', ':', ',', ']', '}', '%', '@', '`'.
      */
 
-    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");
 
     if (!CACHE(parser, 2)) goto error;
 
-    if (CHECK_AT(parser, '<', 1))
+    if (CHECK_AT(parser->buffer, '<', 1))
     {
         /* Set the handle to '' */
 
 
         /* 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;
 
     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;
 
     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 '!'");
 
     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;
 
     /* Check if the trailing character is '!' and copy it. */
 
-    if (CHECK(parser, '!'))
+    if (CHECK(parser->buffer, '!'))
     {
         if (!READ(parser, string)) goto error;
     }
      *      '%'.
      */
 
-    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;
         }
 
         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");
 
         /* 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. */
 
 
     /* 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);
 
 
         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;
 
             /* Get the intendation level and eat the indicator. */
 
-            increment = AS_DIGIT(parser);
+            increment = AS_DIGIT(parser->buffer);
 
             SKIP(parser);
         }
 
     /* 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);
         }
 
     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;
         }
 
     /* 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;
 
     /* Eat a line break. */
 
-    if (IS_BREAK(parser)) {
+    if (IS_BREAK(parser->buffer)) {
         if (!CACHE(parser, 2)) goto error;
         SKIP_LINE(parser);
     }
 
     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.
 
         /* 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. */
 
 
         /* 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;
         }
 
         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;
         }
 
         /* 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. */
 
         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))