]> andersk Git - libyaml.git/blobdiff - src/emitter.c
Don't emit document-end marker at the end of stream
[libyaml.git] / src / emitter.c
index b8d3dc9712f19cf949c89b8b28542b8125ff52de..274449577f24b50788b4194f83dd65e600bb2d59 100644 (file)
 
 #define WRITE_BREAK(emitter,string)                                             \
     (FLUSH(emitter)                                                             \
-     && (COPY(emitter->buffer,string),                                          \
-         emitter->column = 0,                                                   \
-         emitter->line ++,                                                      \
-         1))
+     && (CHECK(string,'\n') ?                                                   \
+         (PUT_BREAK(emitter),                                                   \
+          string.pointer ++,                                                    \
+          1) :                                                                  \
+         (COPY(emitter->buffer,string),                                         \
+          emitter->column = 0,                                                  \
+          emitter->line ++,                                                     \
+          1)))
 
 /*
  * API functions.
@@ -230,7 +234,7 @@ yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
 
 static int
 yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
-        yaml_char_t *value, size_t length);
+        yaml_char_t *value, size_t length, int need_whitespace);
 
 static int
 yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
@@ -244,6 +248,10 @@ 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_block_scalar_hints(yaml_emitter_t *emitter,
+        yaml_string_t string);
+
 static int
 yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length);
@@ -282,7 +290,7 @@ yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
             return 0;
         if (!yaml_emitter_state_machine(emitter, emitter->events.head))
             return 0;
-        DEQUEUE(emitter, emitter->events);
+        yaml_event_delete(&DEQUEUE(emitter, emitter->events));
     }
 
     return 1;
@@ -509,7 +517,7 @@ yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
         if (emitter->best_width < 0) {
             emitter->best_width = INT_MAX;
         }
-        
+
         if (!emitter->line_break) {
             emitter->line_break = YAML_LN_BREAK;
         }
@@ -579,6 +587,17 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
             implicit = 0;
         }
 
+        if ((event->data.document_start.version_directive ||
+                    (event->data.document_start.tag_directives.start
+                     != event->data.document_start.tag_directives.end)) &&
+                emitter->open_ended)
+        {
+            if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
+                return 0;
+            if (!yaml_emitter_write_indent(emitter))
+                return 0;
+        }
+
         if (event->data.document_start.version_directive) {
             implicit = 0;
             if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0))
@@ -588,7 +607,7 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
             if (!yaml_emitter_write_indent(emitter))
                 return 0;
         }
-        
+
         if (event->data.document_start.tag_directives.start
                 != event->data.document_start.tag_directives.end) {
             implicit = 0;
@@ -601,7 +620,7 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
                             strlen((char *)tag_directive->handle)))
                     return 0;
                 if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix,
-                            strlen((char *)tag_directive->prefix)))
+                            strlen((char *)tag_directive->prefix), 1))
                     return 0;
                 if (!yaml_emitter_write_indent(emitter))
                     return 0;
@@ -630,6 +649,7 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
 
     else if (event->type == YAML_STREAM_END_EVENT)
     {
+
         if (!yaml_emitter_flush(emitter))
             return 0;
 
@@ -679,6 +699,13 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
 
         emitter->state = YAML_EMIT_DOCUMENT_START_STATE;
 
+        while (!STACK_EMPTY(emitter, emitter->tag_directives)) {
+            yaml_tag_directive_t tag_directive = POP(emitter,
+                    emitter->tag_directives);
+            yaml_free(tag_directive.handle);
+            yaml_free(tag_directive.prefix);
+        }
+
         return 1;
     }
 
@@ -687,6 +714,7 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
 }
 
 /*
+ *
  * Expect a flow item node.
  */
 
@@ -720,11 +748,16 @@ yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
         return 1;
     }
 
+    if (!first) {
+        if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
+            return 0;
+    }
+
     if (emitter->canonical || emitter->column > emitter->best_width) {
         if (!yaml_emitter_write_indent(emitter))
             return 0;
     }
-    if (PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
+    if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
         return 0;
 
     return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
@@ -962,7 +995,7 @@ yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
  */
 
 static int
-yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event)
+yaml_emitter_emit_alias(yaml_emitter_t *emitter, SHIM(yaml_event_t *event))
 {
     if (!yaml_emitter_process_anchor(emitter))
         return 0;
@@ -1047,7 +1080,7 @@ yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event)
  */
 
 static int
-yaml_emitter_check_empty_document(yaml_emitter_t *emitter)
+yaml_emitter_check_empty_document(SHIM(yaml_emitter_t *emitter))
 {
     return 0;
 }
@@ -1114,7 +1147,7 @@ yaml_emitter_check_simple_key(yaml_emitter_t *emitter)
             break;
 
         case YAML_MAPPING_START_EVENT:
-            if (!yaml_emitter_check_empty_sequence(emitter))
+            if (!yaml_emitter_check_empty_mapping(emitter))
                 return 0;
             length += emitter->anchor_data.anchor_length
                 + emitter->tag_data.handle_length
@@ -1139,6 +1172,13 @@ static int
 yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
 {
     yaml_scalar_style_t style = event->data.scalar.style;
+    int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
+
+    if (no_tag && !event->data.scalar.plain_implicit
+            && !event->data.scalar.quoted_implicit) {
+        return yaml_emitter_set_emitter_error(emitter,
+                "neither tag nor implicit flags are specified");
+    }
 
     if (style == YAML_ANY_SCALAR_STYLE)
         style = YAML_PLAIN_SCALAR_STYLE;
@@ -1157,8 +1197,7 @@ yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
         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)
+        if (no_tag && !event->data.scalar.plain_implicit)
             style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
     }
 
@@ -1170,23 +1209,16 @@ yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
 
     if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE)
     {
-        if (!emitter->scalar_data.block_allowed)
+        if (!emitter->scalar_data.block_allowed
+                || emitter->flow_level || emitter->simple_key_context)
             style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
     }
 
-    if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
+    if (no_tag && !event->data.scalar.quoted_implicit
+            && style != YAML_PLAIN_SCALAR_STYLE)
     {
-        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->tag_data.handle = (yaml_char_t *)"!";
+        emitter->tag_data.handle_length = 1;
     }
 
     emitter->scalar_data.style = style;
@@ -1229,7 +1261,7 @@ yaml_emitter_process_tag(yaml_emitter_t *emitter)
             return 0;
         if (emitter->tag_data.suffix) {
             if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
-                        emitter->tag_data.suffix_length))
+                        emitter->tag_data.suffix_length, 0))
                 return 0;
         }
     }
@@ -1238,7 +1270,7 @@ yaml_emitter_process_tag(yaml_emitter_t *emitter)
         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))
+                    emitter->tag_data.suffix_length, 0))
             return 0;
         if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0))
             return 0;
@@ -1310,10 +1342,15 @@ 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));
+    yaml_string_t handle;
+    yaml_string_t prefix;
+    size_t handle_length;
+    size_t prefix_length;
+
+    handle_length = strlen((char *)tag_directive.handle);
+    prefix_length = strlen((char *)tag_directive.prefix);
+    STRING_ASSIGN(handle, tag_directive.handle, handle_length);
+    STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length);
 
     if (handle.start == handle.end) {
         return yaml_emitter_set_emitter_error(emitter,
@@ -1332,7 +1369,7 @@ yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
 
     handle.pointer ++;
 
-    while (handle.pointer != handle.end-1) {
+    while (handle.pointer < handle.end-1) {
         if (!IS_ALPHA(handle)) {
             return yaml_emitter_set_emitter_error(emitter,
                     "tag handle must contain alphanumerical characters only");
@@ -1356,7 +1393,11 @@ 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));
+    size_t anchor_length;
+    yaml_string_t string;
+
+    anchor_length = strlen((char *)anchor);
+    STRING_ASSIGN(string, anchor, anchor_length);
 
     if (string.start == string.end) {
         return yaml_emitter_set_emitter_error(emitter, alias ?
@@ -1372,6 +1413,12 @@ yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
         }
         MOVE(string);
     }
+
+    emitter->anchor_data.anchor = string.start;
+    emitter->anchor_data.anchor_length = string.end - string.start;
+    emitter->anchor_data.alias = alias;
+
+    return 1;
 }
 
 /*
@@ -1382,18 +1429,22 @@ static int
 yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
         yaml_char_t *tag)
 {
-    yaml_string_t string = STRING(tag, strlen((char *)tag));
+    size_t tag_length;
+    yaml_string_t string;
     yaml_tag_directive_t *tag_directive;
 
+    tag_length = strlen((char *)tag);
+    STRING_ASSIGN(string, tag, tag_length);
+
     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 ++) {
+            tag_directive != emitter->tag_directives.top; tag_directive ++) {
         size_t prefix_length = strlen((char *)tag_directive->prefix);
-        if (prefix_length < (string.end - string.start)
+        if (prefix_length < (size_t)(string.end - string.start)
                 && strncmp((char *)tag_directive->prefix, (char *)string.start,
                     prefix_length) == 0)
         {
@@ -1421,28 +1472,26 @@ static int
 yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length)
 {
-    yaml_string_t string = STRING(value, length);
+    yaml_string_t string;
 
     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;
+    int leading_space = 0;
+    int leading_break = 0;
+    int trailing_space = 0;
+    int trailing_break = 0;
+    int break_space = 0;
+    int space_break = 0;
+
+    int preceded_by_whitespace = 0;
+    int followed_by_whitespace = 0;
+    int previous_space = 0;
+    int previous_break = 0;
+
+    STRING_ASSIGN(string, value, length);
 
     emitter->scalar_data.value = value;
     emitter->scalar_data.length = length;
@@ -1468,8 +1517,8 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
         flow_indicators = 1;
     }
 
-    preceeded_by_space = 1;
-    followed_by_space = IS_BLANKZ_AT(string, WIDTH(string));
+    preceded_by_whitespace = 1;
+    followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
 
     while (string.pointer != string.end)
     {
@@ -1489,12 +1538,12 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
 
             if (CHECK(string, '?') || CHECK(string, ':')) {
                 flow_indicators = 1;
-                if (followed_by_space) {
+                if (followed_by_whitespace) {
                     block_indicators = 1;
                 }
             }
 
-            if (CHECK(string, '-') && followed_by_space) {
+            if (CHECK(string, '-') && followed_by_whitespace) {
                 flow_indicators = 1;
                 block_indicators = 1;
             }
@@ -1509,12 +1558,12 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
 
             if (CHECK(string, ':')) {
                 flow_indicators = 1;
-                if (followed_by_space) {
+                if (followed_by_whitespace) {
                     block_indicators = 1;
                 }
             }
 
-            if (CHECK(string, '#') && preceeded_by_space) {
+            if (CHECK(string, '#') && preceded_by_whitespace) {
                 flow_indicators = 1;
                 block_indicators = 1;
             }
@@ -1531,57 +1580,42 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
 
         if (IS_SPACE(string))
         {
-            spaces = 1;
             if (string.start == string.pointer) {
-                leading = 1;
+                leading_space = 1;
+            }
+            if (string.pointer+WIDTH(string) == string.end) {
+                trailing_space = 1;
             }
+            if (previous_break) {
+                break_space = 1;
+            }
+            previous_space = 1;
+            previous_break = 0;
         }
-
         else if (IS_BREAK(string))
         {
-            if (spaces) {
-                mixed = 1;
-            }
-            breaks = 1;
             if (string.start == string.pointer) {
-                leading = 1;
+                leading_break = 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;
-                }
+            if (string.pointer+WIDTH(string) == string.end) {
+                trailing_break = 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;
-                }
+            if (previous_space) {
+                space_break = 1;
             }
-            spaces = breaks = mixed = leading = 0;
+            previous_space = 0;
+            previous_break = 1;
+        }
+        else
+        {
+            previous_space = 0;
+            previous_break = 0;
         }
 
-        preceeded_by_space = IS_BLANKZ(string);
+        preceded_by_whitespace = IS_BLANKZ(string);
         MOVE(string);
         if (string.pointer != string.end) {
-            followed_by_space = IS_BLANKZ_AT(string, WIDTH(string));
+            followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
         }
     }
 
@@ -1592,24 +1626,22 @@ yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
     emitter->scalar_data.single_quoted_allowed = 1;
     emitter->scalar_data.block_allowed = 1;
 
-    if (leading_spaces || leading_breaks || trailing_spaces) {
+    if (leading_space || leading_break || trailing_space || trailing_break) {
         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 (trailing_space) {
+        emitter->scalar_data.block_allowed = 0;
     }
 
-    if (inline_breaks_spaces) {
+    if (break_space) {
         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) {
+    if (space_break || special_characters) {
         emitter->scalar_data.flow_plain_allowed = 0;
         emitter->scalar_data.block_plain_allowed = 0;
         emitter->scalar_data.single_quoted_allowed = 0;
@@ -1748,7 +1780,11 @@ 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));
+    size_t indicator_length;
+    yaml_string_t string;
+
+    indicator_length = strlen(indicator);
+    STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length);
 
     if (need_whitespace && !emitter->whitespace) {
         if (!PUT(emitter, ' ')) return 0;
@@ -1760,6 +1796,7 @@ yaml_emitter_write_indicator(yaml_emitter_t *emitter,
 
     emitter->whitespace = is_whitespace;
     emitter->indention = (emitter->indention && is_indention);
+    emitter->open_ended = 0;
 
     return 1;
 }
@@ -1768,7 +1805,8 @@ static int
 yaml_emitter_write_anchor(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length)
 {
-    yaml_string_t string = STRING(value, length);
+    yaml_string_t string;
+    STRING_ASSIGN(string, value, length);
 
     while (string.pointer != string.end) {
         if (!WRITE(emitter, string)) return 0;
@@ -1784,7 +1822,12 @@ 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);
+    yaml_string_t string;
+    STRING_ASSIGN(string, value, length);
+
+    if (!emitter->whitespace) {
+        if (!PUT(emitter, ' ')) return 0;
+    }
 
     while (string.pointer != string.end) {
         if (!WRITE(emitter, string)) return 0;
@@ -1798,43 +1841,481 @@ yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
 
 static int
 yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
-        yaml_char_t *value, size_t length)
+        yaml_char_t *value, size_t length,
+        int need_whitespace)
 {
-    return 0;
+    yaml_string_t string;
+    STRING_ASSIGN(string, value, length);
+
+    if (need_whitespace && !emitter->whitespace) {
+        if (!PUT(emitter, ' ')) return 0;
+    }
+
+    while (string.pointer != string.end) {
+        if (IS_ALPHA(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, '\'') || CHECK(string, '(')
+                || CHECK(string, ')') || CHECK(string, '[')
+                || CHECK(string, ']')) {
+            if (!WRITE(emitter, string)) return 0;
+        }
+        else {
+            int width = WIDTH(string);
+            unsigned int value;
+            while (width --) {
+                value = *(string.pointer++);
+                if (!PUT(emitter, '%')) return 0;
+                if (!PUT(emitter, (value >> 4)
+                            + ((value >> 4) < 10 ? '0' : 'A' - 10)))
+                    return 0;
+                if (!PUT(emitter, (value & 0x0F)
+                            + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
+                    return 0;
+            }
+        }
+    }
+
+    emitter->whitespace = 0;
+    emitter->indention = 0;
+
+    return 1;
 }
 
 static int
 yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length, int allow_breaks)
 {
-    return 0;
+    yaml_string_t string;
+    int spaces = 0;
+    int breaks = 0;
+
+    STRING_ASSIGN(string, value, length);
+
+    if (!emitter->whitespace) {
+        if (!PUT(emitter, ' ')) return 0;
+    }
+
+    while (string.pointer != string.end)
+    {
+        if (IS_SPACE(string))
+        {
+            if (allow_breaks && !spaces
+                    && emitter->column > emitter->best_width
+                    && !IS_SPACE_AT(string, 1)) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+                MOVE(string);
+            }
+            else {
+                if (!WRITE(emitter, string)) return 0;
+            }
+            spaces = 1;
+        }
+        else if (IS_BREAK(string))
+        {
+            if (!breaks && CHECK(string, '\n')) {
+                if (!PUT_BREAK(emitter)) return 0;
+            }
+            if (!WRITE_BREAK(emitter, string)) return 0;
+            emitter->indention = 1;
+            breaks = 1;
+        }
+        else
+        {
+            if (breaks) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+            }
+            if (!WRITE(emitter, string)) return 0;
+            emitter->indention = 0;
+            spaces = 0;
+            breaks = 0;
+        }
+    }
+
+    emitter->whitespace = 0;
+    emitter->indention = 0;
+    if (emitter->root_context)
+    {
+        emitter->open_ended = 1;
+    }
+
+    return 1;
 }
 
 static int
 yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length, int allow_breaks)
 {
-    return 0;
+    yaml_string_t string;
+    int spaces = 0;
+    int breaks = 0;
+
+    STRING_ASSIGN(string, value, length);
+
+    if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
+        return 0;
+
+    while (string.pointer != string.end)
+    {
+        if (IS_SPACE(string))
+        {
+            if (allow_breaks && !spaces
+                    && emitter->column > emitter->best_width
+                    && string.pointer != string.start
+                    && string.pointer != string.end - 1
+                    && !IS_SPACE_AT(string, 1)) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+                MOVE(string);
+            }
+            else {
+                if (!WRITE(emitter, string)) return 0;
+            }
+            spaces = 1;
+        }
+        else if (IS_BREAK(string))
+        {
+            if (!breaks && CHECK(string, '\n')) {
+                if (!PUT_BREAK(emitter)) return 0;
+            }
+            if (!WRITE_BREAK(emitter, string)) return 0;
+            emitter->indention = 1;
+            breaks = 1;
+        }
+        else
+        {
+            if (breaks) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+            }
+            if (CHECK(string, '\'')) {
+                if (!PUT(emitter, '\'')) return 0;
+            }
+            if (!WRITE(emitter, string)) return 0;
+            emitter->indention = 0;
+            spaces = 0;
+            breaks = 0;
+        }
+    }
+
+    if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
+        return 0;
+
+    emitter->whitespace = 0;
+    emitter->indention = 0;
+
+    return 1;
 }
 
 static int
 yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length, int allow_breaks)
 {
-    return 0;
+    yaml_string_t string;
+    int spaces = 0;
+
+    STRING_ASSIGN(string, value, length);
+
+    if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
+        return 0;
+
+    while (string.pointer != string.end)
+    {
+        if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
+                || IS_BOM(string) || IS_BREAK(string)
+                || CHECK(string, '"') || CHECK(string, '\\'))
+        {
+            unsigned char octet;
+            unsigned int width;
+            unsigned int value;
+            int k;
+
+            octet = string.pointer[0];
+            width = (octet & 0x80) == 0x00 ? 1 :
+                    (octet & 0xE0) == 0xC0 ? 2 :
+                    (octet & 0xF0) == 0xE0 ? 3 :
+                    (octet & 0xF8) == 0xF0 ? 4 : 0;
+            value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+                    (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+                    (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+                    (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+            for (k = 1; k < (int)width; k ++) {
+                octet = string.pointer[k];
+                value = (value << 6) + (octet & 0x3F);
+            }
+            string.pointer += width;
+
+            if (!PUT(emitter, '\\')) return 0;
+
+            switch (value)
+            {
+                case 0x00:
+                    if (!PUT(emitter, '0')) return 0;
+                    break;
+
+                case 0x07:
+                    if (!PUT(emitter, 'a')) return 0;
+                    break;
+
+                case 0x08:
+                    if (!PUT(emitter, 'b')) return 0;
+                    break;
+
+                case 0x09:
+                    if (!PUT(emitter, 't')) return 0;
+                    break;
+
+                case 0x0A:
+                    if (!PUT(emitter, 'n')) return 0;
+                    break;
+
+                case 0x0B:
+                    if (!PUT(emitter, 'v')) return 0;
+                    break;
+
+                case 0x0C:
+                    if (!PUT(emitter, 'f')) return 0;
+                    break;
+
+                case 0x0D:
+                    if (!PUT(emitter, 'r')) return 0;
+                    break;
+
+                case 0x1B:
+                    if (!PUT(emitter, 'e')) return 0;
+                    break;
+
+                case 0x22:
+                    if (!PUT(emitter, '\"')) return 0;
+                    break;
+
+                case 0x5C:
+                    if (!PUT(emitter, '\\')) return 0;
+                    break;
+
+                case 0x85:
+                    if (!PUT(emitter, 'N')) return 0;
+                    break;
+
+                case 0xA0:
+                    if (!PUT(emitter, '_')) return 0;
+                    break;
+
+                case 0x2028:
+                    if (!PUT(emitter, 'L')) return 0;
+                    break;
+
+                case 0x2029:
+                    if (!PUT(emitter, 'P')) return 0;
+                    break;
+
+                default:
+                    if (value <= 0xFF) {
+                        if (!PUT(emitter, 'x')) return 0;
+                        width = 2;
+                    }
+                    else if (value <= 0xFFFF) {
+                        if (!PUT(emitter, 'u')) return 0;
+                        width = 4;
+                    }
+                    else {
+                        if (!PUT(emitter, 'U')) return 0;
+                        width = 8;
+                    }
+                    for (k = (width-1)*4; k >= 0; k -= 4) {
+                        int digit = (value >> k) & 0x0F;
+                        if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
+                            return 0;
+                    }
+            }
+            spaces = 0;
+        }
+        else if (IS_SPACE(string))
+        {
+            if (allow_breaks && !spaces
+                    && emitter->column > emitter->best_width
+                    && string.pointer != string.start
+                    && string.pointer != string.end - 1) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+                if (IS_SPACE_AT(string, 1)) {
+                    if (!PUT(emitter, '\\')) return 0;
+                }
+                MOVE(string);
+            }
+            else {
+                if (!WRITE(emitter, string)) return 0;
+            }
+            spaces = 1;
+        }
+        else
+        {
+            if (!WRITE(emitter, string)) return 0;
+            spaces = 0;
+        }
+    }
+
+    if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
+        return 0;
+
+    emitter->whitespace = 0;
+    emitter->indention = 0;
+
+    return 1;
+}
+
+static int
+yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
+        yaml_string_t string)
+{
+    char indent_hint[2];
+    char *chomp_hint = NULL;
+
+    if (IS_SPACE(string) || IS_BREAK(string))
+    {
+        indent_hint[0] = '0' + (char)emitter->best_indent;
+        indent_hint[1] = '\0';
+        if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
+            return 0;
+    }
+
+    emitter->open_ended = 0;
+
+    string.pointer = string.end;
+    if (string.start == string.pointer)
+    {
+        chomp_hint = "-";
+    }
+    else
+    {
+        do {
+            string.pointer --;
+        } while ((*string.pointer & 0xC0) == 0x80);
+        if (!IS_BREAK(string))
+        {
+            chomp_hint = "-";
+        }
+        else if (string.start == string.pointer)
+        {
+            chomp_hint = "+";
+            emitter->open_ended = 1;
+        }
+        else
+        {
+            do {
+                string.pointer --;
+            } while ((*string.pointer & 0xC0) == 0x80);
+            if (IS_BREAK(string))
+            {
+                chomp_hint = "+";
+                emitter->open_ended = 1;
+            }
+        }
+    }
+
+    if (chomp_hint)
+    {
+        if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
+            return 0;
+    }
+
+    return 1;
 }
 
 static int
 yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length)
 {
-    return 0;
+    yaml_string_t string;
+    int breaks = 1;
+
+    STRING_ASSIGN(string, value, length);
+
+    if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
+        return 0;
+    if (!yaml_emitter_write_block_scalar_hints(emitter, string))
+        return 0;
+    if (!PUT_BREAK(emitter)) return 0;
+    emitter->indention = 1;
+    emitter->whitespace = 1;
+
+    while (string.pointer != string.end)
+    {
+        if (IS_BREAK(string))
+        {
+            if (!WRITE_BREAK(emitter, string)) return 0;
+            emitter->indention = 1;
+            breaks = 1;
+        }
+        else
+        {
+            if (breaks) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+            }
+            if (!WRITE(emitter, string)) return 0;
+            emitter->indention = 0;
+            breaks = 0;
+        }
+    }
+
+    return 1;
 }
 
 static int
 yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
         yaml_char_t *value, size_t length)
 {
-    return 0;
-}
+    yaml_string_t string;
+    int breaks = 1;
+    int leading_spaces = 1;
+
+    STRING_ASSIGN(string, value, length);
 
+    if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
+        return 0;
+    if (!yaml_emitter_write_block_scalar_hints(emitter, string))
+        return 0;
+    if (!PUT_BREAK(emitter)) return 0;
+    emitter->indention = 1;
+    emitter->whitespace = 1;
+
+    while (string.pointer != string.end)
+    {
+        if (IS_BREAK(string))
+        {
+            if (!breaks && !leading_spaces && CHECK(string, '\n')) {
+                int k = 0;
+                while (IS_BREAK_AT(string, k)) {
+                    k += WIDTH_AT(string, k);
+                }
+                if (!IS_BLANKZ_AT(string, k)) {
+                    if (!PUT_BREAK(emitter)) return 0;
+                }
+            }
+            if (!WRITE_BREAK(emitter, string)) return 0;
+            emitter->indention = 1;
+            breaks = 1;
+        }
+        else
+        {
+            if (breaks) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+                leading_spaces = IS_BLANK(string);
+            }
+            if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
+                    && emitter->column > emitter->best_width) {
+                if (!yaml_emitter_write_indent(emitter)) return 0;
+                MOVE(string);
+            }
+            else {
+                if (!WRITE(emitter, string)) return 0;
+            }
+            emitter->indention = 0;
+            breaks = 0;
+        }
+    }
+
+    return 1;
+}
This page took 0.0693 seconds and 4 git commands to generate.