X-Git-Url: http://andersk.mit.edu/gitweb/libyaml.git/blobdiff_plain/e35af832e9765e72b3ee3e337b2bfb958e3c5962..e01343456d08b6d2bfd53ced4fadb1529399bc96:/src/emitter.c diff --git a/src/emitter.c b/src/emitter.c index b8d3dc9..c4b56a2 100644 --- a/src/emitter.c +++ b/src/emitter.c @@ -52,10 +52,14 @@ #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; @@ -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)) @@ -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,14 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, else if (event->type == YAML_STREAM_END_EVENT) { + if (emitter->open_ended) + { + if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!yaml_emitter_flush(emitter)) return 0; @@ -679,6 +706,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 +721,7 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter, } /* + * * Expect a flow item node. */ @@ -720,11 +755,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); @@ -1114,7 +1154,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 +1179,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 +1204,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 +1216,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 +1268,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 +1277,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 +1349,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 +1376,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 +1400,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 +1420,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 +1436,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 +1479,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 preceeded_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 +1524,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)); + preceeded_by_whitespace = 1; + followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string)); while (string.pointer != string.end) { @@ -1489,12 +1545,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 +1565,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, '#') && preceeded_by_whitespace) { flow_indicators = 1; block_indicators = 1; } @@ -1531,57 +1587,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); + preceeded_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 +1633,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 +1787,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 +1803,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 +1812,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 +1829,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 +1848,482 @@ 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; }