package yaml
import (
"bytes"
"fmt"
)
func flush(emitter *yaml_emitter_t ) bool {
if emitter .buffer_pos +5 >= len (emitter .buffer ) {
return yaml_emitter_flush (emitter )
}
return true
}
func put(emitter *yaml_emitter_t , value byte ) bool {
if emitter .buffer_pos +5 >= len (emitter .buffer ) && !yaml_emitter_flush (emitter ) {
return false
}
emitter .buffer [emitter .buffer_pos ] = value
emitter .buffer_pos ++
emitter .column ++
return true
}
func put_break(emitter *yaml_emitter_t ) bool {
if emitter .buffer_pos +5 >= len (emitter .buffer ) && !yaml_emitter_flush (emitter ) {
return false
}
switch emitter .line_break {
case yaml_CR_BREAK :
emitter .buffer [emitter .buffer_pos ] = '\r'
emitter .buffer_pos += 1
case yaml_LN_BREAK :
emitter .buffer [emitter .buffer_pos ] = '\n'
emitter .buffer_pos += 1
case yaml_CRLN_BREAK :
emitter .buffer [emitter .buffer_pos +0 ] = '\r'
emitter .buffer [emitter .buffer_pos +1 ] = '\n'
emitter .buffer_pos += 2
default :
panic ("unknown line break setting" )
}
if emitter .column == 0 {
emitter .space_above = true
}
emitter .column = 0
emitter .line ++
emitter .indention = true
return true
}
func write(emitter *yaml_emitter_t , s []byte , i *int ) bool {
if emitter .buffer_pos +5 >= len (emitter .buffer ) && !yaml_emitter_flush (emitter ) {
return false
}
p := emitter .buffer_pos
w := width (s [*i ])
switch w {
case 4 :
emitter .buffer [p +3 ] = s [*i +3 ]
fallthrough
case 3 :
emitter .buffer [p +2 ] = s [*i +2 ]
fallthrough
case 2 :
emitter .buffer [p +1 ] = s [*i +1 ]
fallthrough
case 1 :
emitter .buffer [p +0 ] = s [*i +0 ]
default :
panic ("unknown character width" )
}
emitter .column ++
emitter .buffer_pos += w
*i += w
return true
}
func write_all(emitter *yaml_emitter_t , s []byte ) bool {
for i := 0 ; i < len (s ); {
if !write (emitter , s , &i ) {
return false
}
}
return true
}
func write_break(emitter *yaml_emitter_t , s []byte , i *int ) bool {
if s [*i ] == '\n' {
if !put_break (emitter ) {
return false
}
*i ++
} else {
if !write (emitter , s , i ) {
return false
}
if emitter .column == 0 {
emitter .space_above = true
}
emitter .column = 0
emitter .line ++
emitter .indention = true
}
return true
}
func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t , problem string ) bool {
emitter .error = yaml_EMITTER_ERROR
emitter .problem = problem
return false
}
func yaml_emitter_emit(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
emitter .events = append (emitter .events , *event )
for !yaml_emitter_need_more_events (emitter ) {
event := &emitter .events [emitter .events_head ]
if !yaml_emitter_analyze_event (emitter , event ) {
return false
}
if !yaml_emitter_state_machine (emitter , event ) {
return false
}
yaml_event_delete (event )
emitter .events_head ++
}
return true
}
func yaml_emitter_need_more_events(emitter *yaml_emitter_t ) bool {
if emitter .events_head == len (emitter .events ) {
return true
}
var accumulate int
switch emitter .events [emitter .events_head ].typ {
case yaml_DOCUMENT_START_EVENT :
accumulate = 1
break
case yaml_SEQUENCE_START_EVENT :
accumulate = 2
break
case yaml_MAPPING_START_EVENT :
accumulate = 3
break
default :
return false
}
if len (emitter .events )-emitter .events_head > accumulate {
return false
}
var level int
for i := emitter .events_head ; i < len (emitter .events ); i ++ {
switch emitter .events [i ].typ {
case yaml_STREAM_START_EVENT , yaml_DOCUMENT_START_EVENT , yaml_SEQUENCE_START_EVENT , yaml_MAPPING_START_EVENT :
level ++
case yaml_STREAM_END_EVENT , yaml_DOCUMENT_END_EVENT , yaml_SEQUENCE_END_EVENT , yaml_MAPPING_END_EVENT :
level --
}
if level == 0 {
return false
}
}
return true
}
func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t , value *yaml_tag_directive_t , allow_duplicates bool ) bool {
for i := 0 ; i < len (emitter .tag_directives ); i ++ {
if bytes .Equal (value .handle , emitter .tag_directives [i ].handle ) {
if allow_duplicates {
return true
}
return yaml_emitter_set_emitter_error (emitter , "duplicate %TAG directive" )
}
}
tag_copy := yaml_tag_directive_t {
handle : make ([]byte , len (value .handle )),
prefix : make ([]byte , len (value .prefix )),
}
copy (tag_copy .handle , value .handle )
copy (tag_copy .prefix , value .prefix )
emitter .tag_directives = append (emitter .tag_directives , tag_copy )
return true
}
func yaml_emitter_increase_indent(emitter *yaml_emitter_t , flow , indentless bool ) bool {
emitter .indents = append (emitter .indents , emitter .indent )
if emitter .indent < 0 {
if flow {
emitter .indent = emitter .best_indent
} else {
emitter .indent = 0
}
} else if !indentless {
if emitter .states [len (emitter .states )-1 ] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
emitter .indent += 2
} else {
emitter .indent = emitter .best_indent *((emitter .indent +emitter .best_indent )/emitter .best_indent )
}
}
return true
}
func yaml_emitter_state_machine(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
switch emitter .state {
default :
case yaml_EMIT_STREAM_START_STATE :
return yaml_emitter_emit_stream_start (emitter , event )
case yaml_EMIT_FIRST_DOCUMENT_START_STATE :
return yaml_emitter_emit_document_start (emitter , event , true )
case yaml_EMIT_DOCUMENT_START_STATE :
return yaml_emitter_emit_document_start (emitter , event , false )
case yaml_EMIT_DOCUMENT_CONTENT_STATE :
return yaml_emitter_emit_document_content (emitter , event )
case yaml_EMIT_DOCUMENT_END_STATE :
return yaml_emitter_emit_document_end (emitter , event )
case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE :
return yaml_emitter_emit_flow_sequence_item (emitter , event , true , false )
case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE :
return yaml_emitter_emit_flow_sequence_item (emitter , event , false , true )
case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE :
return yaml_emitter_emit_flow_sequence_item (emitter , event , false , false )
case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE :
return yaml_emitter_emit_flow_mapping_key (emitter , event , true , false )
case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE :
return yaml_emitter_emit_flow_mapping_key (emitter , event , false , true )
case yaml_EMIT_FLOW_MAPPING_KEY_STATE :
return yaml_emitter_emit_flow_mapping_key (emitter , event , false , false )
case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE :
return yaml_emitter_emit_flow_mapping_value (emitter , event , true )
case yaml_EMIT_FLOW_MAPPING_VALUE_STATE :
return yaml_emitter_emit_flow_mapping_value (emitter , event , false )
case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE :
return yaml_emitter_emit_block_sequence_item (emitter , event , true )
case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE :
return yaml_emitter_emit_block_sequence_item (emitter , event , false )
case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE :
return yaml_emitter_emit_block_mapping_key (emitter , event , true )
case yaml_EMIT_BLOCK_MAPPING_KEY_STATE :
return yaml_emitter_emit_block_mapping_key (emitter , event , false )
case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE :
return yaml_emitter_emit_block_mapping_value (emitter , event , true )
case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE :
return yaml_emitter_emit_block_mapping_value (emitter , event , false )
case yaml_EMIT_END_STATE :
return yaml_emitter_set_emitter_error (emitter , "expected nothing after STREAM-END" )
}
panic ("invalid emitter state" )
}
func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if event .typ != yaml_STREAM_START_EVENT {
return yaml_emitter_set_emitter_error (emitter , "expected STREAM-START" )
}
if emitter .encoding == yaml_ANY_ENCODING {
emitter .encoding = event .encoding
if emitter .encoding == yaml_ANY_ENCODING {
emitter .encoding = yaml_UTF8_ENCODING
}
}
if emitter .best_indent < 2 || emitter .best_indent > 9 {
emitter .best_indent = 2
}
if emitter .best_width >= 0 && emitter .best_width <= emitter .best_indent *2 {
emitter .best_width = 80
}
if emitter .best_width < 0 {
emitter .best_width = 1 <<31 - 1
}
if emitter .line_break == yaml_ANY_BREAK {
emitter .line_break = yaml_LN_BREAK
}
emitter .indent = -1
emitter .line = 0
emitter .column = 0
emitter .whitespace = true
emitter .indention = true
emitter .space_above = true
emitter .foot_indent = -1
if emitter .encoding != yaml_UTF8_ENCODING {
if !yaml_emitter_write_bom (emitter ) {
return false
}
}
emitter .state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
return true
}
func yaml_emitter_emit_document_start(emitter *yaml_emitter_t , event *yaml_event_t , first bool ) bool {
if event .typ == yaml_DOCUMENT_START_EVENT {
if event .version_directive != nil {
if !yaml_emitter_analyze_version_directive (emitter , event .version_directive ) {
return false
}
}
for i := 0 ; i < len (event .tag_directives ); i ++ {
tag_directive := &event .tag_directives [i ]
if !yaml_emitter_analyze_tag_directive (emitter , tag_directive ) {
return false
}
if !yaml_emitter_append_tag_directive (emitter , tag_directive , false ) {
return false
}
}
for i := 0 ; i < len (default_tag_directives ); i ++ {
tag_directive := &default_tag_directives [i ]
if !yaml_emitter_append_tag_directive (emitter , tag_directive , true ) {
return false
}
}
implicit := event .implicit
if !first || emitter .canonical {
implicit = false
}
if emitter .open_ended && (event .version_directive != nil || len (event .tag_directives ) > 0 ) {
if !yaml_emitter_write_indicator (emitter , []byte ("..." ), true , false , false ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if event .version_directive != nil {
implicit = false
if !yaml_emitter_write_indicator (emitter , []byte ("%YAML" ), true , false , false ) {
return false
}
if !yaml_emitter_write_indicator (emitter , []byte ("1.1" ), true , false , false ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if len (event .tag_directives ) > 0 {
implicit = false
for i := 0 ; i < len (event .tag_directives ); i ++ {
tag_directive := &event .tag_directives [i ]
if !yaml_emitter_write_indicator (emitter , []byte ("%TAG" ), true , false , false ) {
return false
}
if !yaml_emitter_write_tag_handle (emitter , tag_directive .handle ) {
return false
}
if !yaml_emitter_write_tag_content (emitter , tag_directive .prefix , true ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
}
if yaml_emitter_check_empty_document (emitter ) {
implicit = false
}
if !implicit {
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_indicator (emitter , []byte ("---" ), true , false , false ) {
return false
}
if emitter .canonical || true {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
}
if len (emitter .head_comment ) > 0 {
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if !put_break (emitter ) {
return false
}
}
emitter .state = yaml_EMIT_DOCUMENT_CONTENT_STATE
return true
}
if event .typ == yaml_STREAM_END_EVENT {
if emitter .open_ended {
if !yaml_emitter_write_indicator (emitter , []byte ("..." ), true , false , false ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !yaml_emitter_flush (emitter ) {
return false
}
emitter .state = yaml_EMIT_END_STATE
return true
}
return yaml_emitter_set_emitter_error (emitter , "expected DOCUMENT-START or STREAM-END" )
}
func yaml_emitter_emit_document_content(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
emitter .states = append (emitter .states , yaml_EMIT_DOCUMENT_END_STATE )
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if !yaml_emitter_emit_node (emitter , event , true , false , false , false ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
return true
}
func yaml_emitter_emit_document_end(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if event .typ != yaml_DOCUMENT_END_EVENT {
return yaml_emitter_set_emitter_error (emitter , "expected DOCUMENT-END" )
}
emitter .foot_indent = 0
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
emitter .foot_indent = -1
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !event .implicit {
if !yaml_emitter_write_indicator (emitter , []byte ("..." ), true , false , false ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !yaml_emitter_flush (emitter ) {
return false
}
emitter .state = yaml_EMIT_DOCUMENT_START_STATE
emitter .tag_directives = emitter .tag_directives [:0 ]
return true
}
func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t , event *yaml_event_t , first , trail bool ) bool {
if first {
if !yaml_emitter_write_indicator (emitter , []byte {'[' }, true , true , false ) {
return false
}
if !yaml_emitter_increase_indent (emitter , true , false ) {
return false
}
emitter .flow_level ++
}
if event .typ == yaml_SEQUENCE_END_EVENT {
if emitter .canonical && !first && !trail {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
emitter .flow_level --
emitter .indent = emitter .indents [len (emitter .indents )-1 ]
emitter .indents = emitter .indents [:len (emitter .indents )-1 ]
if emitter .column == 0 || emitter .canonical && !first {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !yaml_emitter_write_indicator (emitter , []byte {']' }, false , false , false ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
if !first && !trail {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if emitter .column == 0 {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if emitter .canonical || emitter .column > emitter .best_width {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if len (emitter .line_comment )+len (emitter .foot_comment )+len (emitter .tail_comment ) > 0 {
emitter .states = append (emitter .states , yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE )
} else {
emitter .states = append (emitter .states , yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE )
}
if !yaml_emitter_emit_node (emitter , event , false , true , false , false ) {
return false
}
if len (emitter .line_comment )+len (emitter .foot_comment )+len (emitter .tail_comment ) > 0 {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
return true
}
func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t , event *yaml_event_t , first , trail bool ) bool {
if first {
if !yaml_emitter_write_indicator (emitter , []byte {'{' }, true , true , false ) {
return false
}
if !yaml_emitter_increase_indent (emitter , true , false ) {
return false
}
emitter .flow_level ++
}
if event .typ == yaml_MAPPING_END_EVENT {
if (emitter .canonical || len (emitter .head_comment )+len (emitter .foot_comment )+len (emitter .tail_comment ) > 0 ) && !first && !trail {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
emitter .flow_level --
emitter .indent = emitter .indents [len (emitter .indents )-1 ]
emitter .indents = emitter .indents [:len (emitter .indents )-1 ]
if emitter .canonical && !first {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !yaml_emitter_write_indicator (emitter , []byte {'}' }, false , false , false ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
if !first && !trail {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if emitter .column == 0 {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if emitter .canonical || emitter .column > emitter .best_width {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !emitter .canonical && yaml_emitter_check_simple_key (emitter ) {
emitter .states = append (emitter .states , yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE )
return yaml_emitter_emit_node (emitter , event , false , false , true , true )
}
if !yaml_emitter_write_indicator (emitter , []byte {'?' }, true , false , false ) {
return false
}
emitter .states = append (emitter .states , yaml_EMIT_FLOW_MAPPING_VALUE_STATE )
return yaml_emitter_emit_node (emitter , event , false , false , true , false )
}
func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t , event *yaml_event_t , simple bool ) bool {
if simple {
if !yaml_emitter_write_indicator (emitter , []byte {':' }, false , false , false ) {
return false
}
} else {
if emitter .canonical || emitter .column > emitter .best_width {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !yaml_emitter_write_indicator (emitter , []byte {':' }, true , false , false ) {
return false
}
}
if len (emitter .line_comment )+len (emitter .foot_comment )+len (emitter .tail_comment ) > 0 {
emitter .states = append (emitter .states , yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE )
} else {
emitter .states = append (emitter .states , yaml_EMIT_FLOW_MAPPING_KEY_STATE )
}
if !yaml_emitter_emit_node (emitter , event , false , false , true , false ) {
return false
}
if len (emitter .line_comment )+len (emitter .foot_comment )+len (emitter .tail_comment ) > 0 {
if !yaml_emitter_write_indicator (emitter , []byte {',' }, false , false , false ) {
return false
}
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
return true
}
func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t , event *yaml_event_t , first bool ) bool {
if first {
if !yaml_emitter_increase_indent (emitter , false , false ) {
return false
}
}
if event .typ == yaml_SEQUENCE_END_EVENT {
emitter .indent = emitter .indents [len (emitter .indents )-1 ]
emitter .indents = emitter .indents [:len (emitter .indents )-1 ]
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_indicator (emitter , []byte {'-' }, true , false , true ) {
return false
}
emitter .states = append (emitter .states , yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE )
if !yaml_emitter_emit_node (emitter , event , false , true , false , false ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
return true
}
func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t , event *yaml_event_t , first bool ) bool {
if first {
if !yaml_emitter_increase_indent (emitter , false , false ) {
return false
}
}
if !yaml_emitter_process_head_comment (emitter ) {
return false
}
if event .typ == yaml_MAPPING_END_EVENT {
emitter .indent = emitter .indents [len (emitter .indents )-1 ]
emitter .indents = emitter .indents [:len (emitter .indents )-1 ]
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
if len (emitter .line_comment ) > 0 {
emitter .key_line_comment = emitter .line_comment
emitter .line_comment = nil
}
if yaml_emitter_check_simple_key (emitter ) {
emitter .states = append (emitter .states , yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE )
return yaml_emitter_emit_node (emitter , event , false , false , true , true )
}
if !yaml_emitter_write_indicator (emitter , []byte {'?' }, true , false , true ) {
return false
}
emitter .states = append (emitter .states , yaml_EMIT_BLOCK_MAPPING_VALUE_STATE )
return yaml_emitter_emit_node (emitter , event , false , false , true , false )
}
func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t , event *yaml_event_t , simple bool ) bool {
if simple {
if !yaml_emitter_write_indicator (emitter , []byte {':' }, false , false , false ) {
return false
}
} else {
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_indicator (emitter , []byte {':' }, true , false , true ) {
return false
}
}
if len (emitter .key_line_comment ) > 0 {
if event .typ == yaml_SCALAR_EVENT {
if len (emitter .line_comment ) == 0 {
emitter .line_comment = emitter .key_line_comment
emitter .key_line_comment = nil
}
} else if event .sequence_style () != yaml_FLOW_SEQUENCE_STYLE && (event .typ == yaml_MAPPING_START_EVENT || event .typ == yaml_SEQUENCE_START_EVENT ) {
emitter .line_comment , emitter .key_line_comment = emitter .key_line_comment , emitter .line_comment
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
emitter .line_comment , emitter .key_line_comment = emitter .key_line_comment , emitter .line_comment
}
}
emitter .states = append (emitter .states , yaml_EMIT_BLOCK_MAPPING_KEY_STATE )
if !yaml_emitter_emit_node (emitter , event , false , false , true , false ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
if !yaml_emitter_process_foot_comment (emitter ) {
return false
}
return true
}
func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
return event .typ == yaml_SCALAR_EVENT && event .implicit && !emitter .canonical && len (emitter .scalar_data .value ) == 0
}
func yaml_emitter_emit_node(emitter *yaml_emitter_t , event *yaml_event_t ,
root bool , sequence bool , mapping bool , simple_key bool ) bool {
emitter .root_context = root
emitter .sequence_context = sequence
emitter .mapping_context = mapping
emitter .simple_key_context = simple_key
switch event .typ {
case yaml_ALIAS_EVENT :
return yaml_emitter_emit_alias (emitter , event )
case yaml_SCALAR_EVENT :
return yaml_emitter_emit_scalar (emitter , event )
case yaml_SEQUENCE_START_EVENT :
return yaml_emitter_emit_sequence_start (emitter , event )
case yaml_MAPPING_START_EVENT :
return yaml_emitter_emit_mapping_start (emitter , event )
default :
return yaml_emitter_set_emitter_error (emitter ,
fmt .Sprintf ("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v" , event .typ ))
}
}
func yaml_emitter_emit_alias(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if !yaml_emitter_process_anchor (emitter ) {
return false
}
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
func yaml_emitter_emit_scalar(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if !yaml_emitter_select_scalar_style (emitter , event ) {
return false
}
if !yaml_emitter_process_anchor (emitter ) {
return false
}
if !yaml_emitter_process_tag (emitter ) {
return false
}
if !yaml_emitter_increase_indent (emitter , true , false ) {
return false
}
if !yaml_emitter_process_scalar (emitter ) {
return false
}
emitter .indent = emitter .indents [len (emitter .indents )-1 ]
emitter .indents = emitter .indents [:len (emitter .indents )-1 ]
emitter .state = emitter .states [len (emitter .states )-1 ]
emitter .states = emitter .states [:len (emitter .states )-1 ]
return true
}
func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if !yaml_emitter_process_anchor (emitter ) {
return false
}
if !yaml_emitter_process_tag (emitter ) {
return false
}
if emitter .flow_level > 0 || emitter .canonical || event .sequence_style () == yaml_FLOW_SEQUENCE_STYLE ||
yaml_emitter_check_empty_sequence (emitter ) {
emitter .state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
} else {
emitter .state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
}
return true
}
func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
if !yaml_emitter_process_anchor (emitter ) {
return false
}
if !yaml_emitter_process_tag (emitter ) {
return false
}
if emitter .flow_level > 0 || emitter .canonical || event .mapping_style () == yaml_FLOW_MAPPING_STYLE ||
yaml_emitter_check_empty_mapping (emitter ) {
emitter .state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
} else {
emitter .state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
}
return true
}
func yaml_emitter_check_empty_document(emitter *yaml_emitter_t ) bool {
return false
}
func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t ) bool {
if len (emitter .events )-emitter .events_head < 2 {
return false
}
return emitter .events [emitter .events_head ].typ == yaml_SEQUENCE_START_EVENT &&
emitter .events [emitter .events_head +1 ].typ == yaml_SEQUENCE_END_EVENT
}
func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t ) bool {
if len (emitter .events )-emitter .events_head < 2 {
return false
}
return emitter .events [emitter .events_head ].typ == yaml_MAPPING_START_EVENT &&
emitter .events [emitter .events_head +1 ].typ == yaml_MAPPING_END_EVENT
}
func yaml_emitter_check_simple_key(emitter *yaml_emitter_t ) bool {
length := 0
switch emitter .events [emitter .events_head ].typ {
case yaml_ALIAS_EVENT :
length += len (emitter .anchor_data .anchor )
case yaml_SCALAR_EVENT :
if emitter .scalar_data .multiline {
return false
}
length += len (emitter .anchor_data .anchor ) +
len (emitter .tag_data .handle ) +
len (emitter .tag_data .suffix ) +
len (emitter .scalar_data .value )
case yaml_SEQUENCE_START_EVENT :
if !yaml_emitter_check_empty_sequence (emitter ) {
return false
}
length += len (emitter .anchor_data .anchor ) +
len (emitter .tag_data .handle ) +
len (emitter .tag_data .suffix )
case yaml_MAPPING_START_EVENT :
if !yaml_emitter_check_empty_mapping (emitter ) {
return false
}
length += len (emitter .anchor_data .anchor ) +
len (emitter .tag_data .handle ) +
len (emitter .tag_data .suffix )
default :
return false
}
return length <= 128
}
func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
no_tag := len (emitter .tag_data .handle ) == 0 && len (emitter .tag_data .suffix ) == 0
if no_tag && !event .implicit && !event .quoted_implicit {
return yaml_emitter_set_emitter_error (emitter , "neither tag nor implicit flags are specified" )
}
style := event .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 > 0 && !emitter .scalar_data .flow_plain_allowed ||
emitter .flow_level == 0 && !emitter .scalar_data .block_plain_allowed {
style = yaml_SINGLE_QUOTED_SCALAR_STYLE
}
if len (emitter .scalar_data .value ) == 0 && (emitter .flow_level > 0 || emitter .simple_key_context ) {
style = yaml_SINGLE_QUOTED_SCALAR_STYLE
}
if no_tag && !event .implicit {
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 || emitter .flow_level > 0 || emitter .simple_key_context {
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
}
}
if no_tag && !event .quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
emitter .tag_data .handle = []byte {'!' }
}
emitter .scalar_data .style = style
return true
}
func yaml_emitter_process_anchor(emitter *yaml_emitter_t ) bool {
if emitter .anchor_data .anchor == nil {
return true
}
c := []byte {'&' }
if emitter .anchor_data .alias {
c [0 ] = '*'
}
if !yaml_emitter_write_indicator (emitter , c , true , false , false ) {
return false
}
return yaml_emitter_write_anchor (emitter , emitter .anchor_data .anchor )
}
func yaml_emitter_process_tag(emitter *yaml_emitter_t ) bool {
if len (emitter .tag_data .handle ) == 0 && len (emitter .tag_data .suffix ) == 0 {
return true
}
if len (emitter .tag_data .handle ) > 0 {
if !yaml_emitter_write_tag_handle (emitter , emitter .tag_data .handle ) {
return false
}
if len (emitter .tag_data .suffix ) > 0 {
if !yaml_emitter_write_tag_content (emitter , emitter .tag_data .suffix , false ) {
return false
}
}
} else {
if !yaml_emitter_write_indicator (emitter , []byte ("!<" ), true , false , false ) {
return false
}
if !yaml_emitter_write_tag_content (emitter , emitter .tag_data .suffix , false ) {
return false
}
if !yaml_emitter_write_indicator (emitter , []byte {'>' }, false , false , false ) {
return false
}
}
return true
}
func yaml_emitter_process_scalar(emitter *yaml_emitter_t ) bool {
switch emitter .scalar_data .style {
case yaml_PLAIN_SCALAR_STYLE :
return yaml_emitter_write_plain_scalar (emitter , emitter .scalar_data .value , !emitter .simple_key_context )
case yaml_SINGLE_QUOTED_SCALAR_STYLE :
return yaml_emitter_write_single_quoted_scalar (emitter , emitter .scalar_data .value , !emitter .simple_key_context )
case yaml_DOUBLE_QUOTED_SCALAR_STYLE :
return yaml_emitter_write_double_quoted_scalar (emitter , emitter .scalar_data .value , !emitter .simple_key_context )
case yaml_LITERAL_SCALAR_STYLE :
return yaml_emitter_write_literal_scalar (emitter , emitter .scalar_data .value )
case yaml_FOLDED_SCALAR_STYLE :
return yaml_emitter_write_folded_scalar (emitter , emitter .scalar_data .value )
}
panic ("unknown scalar style" )
}
func yaml_emitter_process_head_comment(emitter *yaml_emitter_t ) bool {
if len (emitter .tail_comment ) > 0 {
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_comment (emitter , emitter .tail_comment ) {
return false
}
emitter .tail_comment = emitter .tail_comment [:0 ]
emitter .foot_indent = emitter .indent
if emitter .foot_indent < 0 {
emitter .foot_indent = 0
}
}
if len (emitter .head_comment ) == 0 {
return true
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_comment (emitter , emitter .head_comment ) {
return false
}
emitter .head_comment = emitter .head_comment [:0 ]
return true
}
func yaml_emitter_process_line_comment(emitter *yaml_emitter_t ) bool {
if len (emitter .line_comment ) == 0 {
return true
}
if !emitter .whitespace {
if !put (emitter , ' ' ) {
return false
}
}
if !yaml_emitter_write_comment (emitter , emitter .line_comment ) {
return false
}
emitter .line_comment = emitter .line_comment [:0 ]
return true
}
func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t ) bool {
if len (emitter .foot_comment ) == 0 {
return true
}
if !yaml_emitter_write_indent (emitter ) {
return false
}
if !yaml_emitter_write_comment (emitter , emitter .foot_comment ) {
return false
}
emitter .foot_comment = emitter .foot_comment [:0 ]
emitter .foot_indent = emitter .indent
if emitter .foot_indent < 0 {
emitter .foot_indent = 0
}
return true
}
func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t , version_directive *yaml_version_directive_t ) bool {
if version_directive .major != 1 || version_directive .minor != 1 {
return yaml_emitter_set_emitter_error (emitter , "incompatible %YAML directive" )
}
return true
}
func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t , tag_directive *yaml_tag_directive_t ) bool {
handle := tag_directive .handle
prefix := tag_directive .prefix
if len (handle ) == 0 {
return yaml_emitter_set_emitter_error (emitter , "tag handle must not be empty" )
}
if handle [0 ] != '!' {
return yaml_emitter_set_emitter_error (emitter , "tag handle must start with '!'" )
}
if handle [len (handle )-1 ] != '!' {
return yaml_emitter_set_emitter_error (emitter , "tag handle must end with '!'" )
}
for i := 1 ; i < len (handle )-1 ; i += width (handle [i ]) {
if !is_alpha (handle , i ) {
return yaml_emitter_set_emitter_error (emitter , "tag handle must contain alphanumerical characters only" )
}
}
if len (prefix ) == 0 {
return yaml_emitter_set_emitter_error (emitter , "tag prefix must not be empty" )
}
return true
}
func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t , anchor []byte , alias bool ) bool {
if len (anchor ) == 0 {
problem := "anchor value must not be empty"
if alias {
problem = "alias value must not be empty"
}
return yaml_emitter_set_emitter_error (emitter , problem )
}
for i := 0 ; i < len (anchor ); i += width (anchor [i ]) {
if !is_alpha (anchor , i ) {
problem := "anchor value must contain alphanumerical characters only"
if alias {
problem = "alias value must contain alphanumerical characters only"
}
return yaml_emitter_set_emitter_error (emitter , problem )
}
}
emitter .anchor_data .anchor = anchor
emitter .anchor_data .alias = alias
return true
}
func yaml_emitter_analyze_tag(emitter *yaml_emitter_t , tag []byte ) bool {
if len (tag ) == 0 {
return yaml_emitter_set_emitter_error (emitter , "tag value must not be empty" )
}
for i := 0 ; i < len (emitter .tag_directives ); i ++ {
tag_directive := &emitter .tag_directives [i ]
if bytes .HasPrefix (tag , tag_directive .prefix ) {
emitter .tag_data .handle = tag_directive .handle
emitter .tag_data .suffix = tag [len (tag_directive .prefix ):]
return true
}
}
emitter .tag_data .suffix = tag
return true
}
func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t , value []byte ) bool {
var (
block_indicators = false
flow_indicators = false
line_breaks = false
special_characters = false
tab_characters = false
leading_space = false
leading_break = false
trailing_space = false
trailing_break = false
break_space = false
space_break = false
preceded_by_whitespace = false
followed_by_whitespace = false
previous_space = false
previous_break = false
)
emitter .scalar_data .value = value
if len (value ) == 0 {
emitter .scalar_data .multiline = false
emitter .scalar_data .flow_plain_allowed = false
emitter .scalar_data .block_plain_allowed = true
emitter .scalar_data .single_quoted_allowed = true
emitter .scalar_data .block_allowed = false
return true
}
if len (value ) >= 3 && ((value [0 ] == '-' && value [1 ] == '-' && value [2 ] == '-' ) || (value [0 ] == '.' && value [1 ] == '.' && value [2 ] == '.' )) {
block_indicators = true
flow_indicators = true
}
preceded_by_whitespace = true
for i , w := 0 , 0 ; i < len (value ); i += w {
w = width (value [i ])
followed_by_whitespace = i +w >= len (value ) || is_blank (value , i +w )
if i == 0 {
switch value [i ] {
case '#' , ',' , '[' , ']' , '{' , '}' , '&' , '*' , '!' , '|' , '>' , '\'' , '"' , '%' , '@' , '`' :
flow_indicators = true
block_indicators = true
case '?' , ':' :
flow_indicators = true
if followed_by_whitespace {
block_indicators = true
}
case '-' :
if followed_by_whitespace {
flow_indicators = true
block_indicators = true
}
}
} else {
switch value [i ] {
case ',' , '?' , '[' , ']' , '{' , '}' :
flow_indicators = true
case ':' :
flow_indicators = true
if followed_by_whitespace {
block_indicators = true
}
case '#' :
if preceded_by_whitespace {
flow_indicators = true
block_indicators = true
}
}
}
if value [i ] == '\t' {
tab_characters = true
} else if !is_printable (value , i ) || !is_ascii (value , i ) && !emitter .unicode {
special_characters = true
}
if is_space (value , i ) {
if i == 0 {
leading_space = true
}
if i +width (value [i ]) == len (value ) {
trailing_space = true
}
if previous_break {
break_space = true
}
previous_space = true
previous_break = false
} else if is_break (value , i ) {
line_breaks = true
if i == 0 {
leading_break = true
}
if i +width (value [i ]) == len (value ) {
trailing_break = true
}
if previous_space {
space_break = true
}
previous_space = false
previous_break = true
} else {
previous_space = false
previous_break = false
}
preceded_by_whitespace = is_blankz (value , i )
}
emitter .scalar_data .multiline = line_breaks
emitter .scalar_data .flow_plain_allowed = true
emitter .scalar_data .block_plain_allowed = true
emitter .scalar_data .single_quoted_allowed = true
emitter .scalar_data .block_allowed = true
if leading_space || leading_break || trailing_space || trailing_break {
emitter .scalar_data .flow_plain_allowed = false
emitter .scalar_data .block_plain_allowed = false
}
if trailing_space {
emitter .scalar_data .block_allowed = false
}
if break_space {
emitter .scalar_data .flow_plain_allowed = false
emitter .scalar_data .block_plain_allowed = false
emitter .scalar_data .single_quoted_allowed = false
}
if space_break || tab_characters || special_characters {
emitter .scalar_data .flow_plain_allowed = false
emitter .scalar_data .block_plain_allowed = false
emitter .scalar_data .single_quoted_allowed = false
}
if space_break || special_characters {
emitter .scalar_data .block_allowed = false
}
if line_breaks {
emitter .scalar_data .flow_plain_allowed = false
emitter .scalar_data .block_plain_allowed = false
}
if flow_indicators {
emitter .scalar_data .flow_plain_allowed = false
}
if block_indicators {
emitter .scalar_data .block_plain_allowed = false
}
return true
}
func yaml_emitter_analyze_event(emitter *yaml_emitter_t , event *yaml_event_t ) bool {
emitter .anchor_data .anchor = nil
emitter .tag_data .handle = nil
emitter .tag_data .suffix = nil
emitter .scalar_data .value = nil
if len (event .head_comment ) > 0 {
emitter .head_comment = event .head_comment
}
if len (event .line_comment ) > 0 {
emitter .line_comment = event .line_comment
}
if len (event .foot_comment ) > 0 {
emitter .foot_comment = event .foot_comment
}
if len (event .tail_comment ) > 0 {
emitter .tail_comment = event .tail_comment
}
switch event .typ {
case yaml_ALIAS_EVENT :
if !yaml_emitter_analyze_anchor (emitter , event .anchor , true ) {
return false
}
case yaml_SCALAR_EVENT :
if len (event .anchor ) > 0 {
if !yaml_emitter_analyze_anchor (emitter , event .anchor , false ) {
return false
}
}
if len (event .tag ) > 0 && (emitter .canonical || (!event .implicit && !event .quoted_implicit )) {
if !yaml_emitter_analyze_tag (emitter , event .tag ) {
return false
}
}
if !yaml_emitter_analyze_scalar (emitter , event .value ) {
return false
}
case yaml_SEQUENCE_START_EVENT :
if len (event .anchor ) > 0 {
if !yaml_emitter_analyze_anchor (emitter , event .anchor , false ) {
return false
}
}
if len (event .tag ) > 0 && (emitter .canonical || !event .implicit ) {
if !yaml_emitter_analyze_tag (emitter , event .tag ) {
return false
}
}
case yaml_MAPPING_START_EVENT :
if len (event .anchor ) > 0 {
if !yaml_emitter_analyze_anchor (emitter , event .anchor , false ) {
return false
}
}
if len (event .tag ) > 0 && (emitter .canonical || !event .implicit ) {
if !yaml_emitter_analyze_tag (emitter , event .tag ) {
return false
}
}
}
return true
}
func yaml_emitter_write_bom(emitter *yaml_emitter_t ) bool {
if !flush (emitter ) {
return false
}
pos := emitter .buffer_pos
emitter .buffer [pos +0 ] = '\xEF'
emitter .buffer [pos +1 ] = '\xBB'
emitter .buffer [pos +2 ] = '\xBF'
emitter .buffer_pos += 3
return true
}
func yaml_emitter_write_indent(emitter *yaml_emitter_t ) bool {
indent := emitter .indent
if indent < 0 {
indent = 0
}
if !emitter .indention || emitter .column > indent || (emitter .column == indent && !emitter .whitespace ) {
if !put_break (emitter ) {
return false
}
}
if emitter .foot_indent == indent {
if !put_break (emitter ) {
return false
}
}
for emitter .column < indent {
if !put (emitter , ' ' ) {
return false
}
}
emitter .whitespace = true
emitter .space_above = false
emitter .foot_indent = -1
return true
}
func yaml_emitter_write_indicator(emitter *yaml_emitter_t , indicator []byte , need_whitespace , is_whitespace , is_indention bool ) bool {
if need_whitespace && !emitter .whitespace {
if !put (emitter , ' ' ) {
return false
}
}
if !write_all (emitter , indicator ) {
return false
}
emitter .whitespace = is_whitespace
emitter .indention = (emitter .indention && is_indention )
emitter .open_ended = false
return true
}
func yaml_emitter_write_anchor(emitter *yaml_emitter_t , value []byte ) bool {
if !write_all (emitter , value ) {
return false
}
emitter .whitespace = false
emitter .indention = false
return true
}
func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t , value []byte ) bool {
if !emitter .whitespace {
if !put (emitter , ' ' ) {
return false
}
}
if !write_all (emitter , value ) {
return false
}
emitter .whitespace = false
emitter .indention = false
return true
}
func yaml_emitter_write_tag_content(emitter *yaml_emitter_t , value []byte , need_whitespace bool ) bool {
if need_whitespace && !emitter .whitespace {
if !put (emitter , ' ' ) {
return false
}
}
for i := 0 ; i < len (value ); {
var must_write bool
switch value [i ] {
case ';' , '/' , '?' , ':' , '@' , '&' , '=' , '+' , '$' , ',' , '_' , '.' , '~' , '*' , '\'' , '(' , ')' , '[' , ']' :
must_write = true
default :
must_write = is_alpha (value , i )
}
if must_write {
if !write (emitter , value , &i ) {
return false
}
} else {
w := width (value [i ])
for k := 0 ; k < w ; k ++ {
octet := value [i ]
i ++
if !put (emitter , '%' ) {
return false
}
c := octet >> 4
if c < 10 {
c += '0'
} else {
c += 'A' - 10
}
if !put (emitter , c ) {
return false
}
c = octet & 0x0f
if c < 10 {
c += '0'
} else {
c += 'A' - 10
}
if !put (emitter , c ) {
return false
}
}
}
}
emitter .whitespace = false
emitter .indention = false
return true
}
func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t , value []byte , allow_breaks bool ) bool {
if len (value ) > 0 && !emitter .whitespace {
if !put (emitter , ' ' ) {
return false
}
}
spaces := false
breaks := false
for i := 0 ; i < len (value ); {
if is_space (value , i ) {
if allow_breaks && !spaces && emitter .column > emitter .best_width && !is_space (value , i +1 ) {
if !yaml_emitter_write_indent (emitter ) {
return false
}
i += width (value [i ])
} else {
if !write (emitter , value , &i ) {
return false
}
}
spaces = true
} else if is_break (value , i ) {
if !breaks && value [i ] == '\n' {
if !put_break (emitter ) {
return false
}
}
if !write_break (emitter , value , &i ) {
return false
}
breaks = true
} else {
if breaks {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !write (emitter , value , &i ) {
return false
}
emitter .indention = false
spaces = false
breaks = false
}
}
if len (value ) > 0 {
emitter .whitespace = false
}
emitter .indention = false
if emitter .root_context {
emitter .open_ended = true
}
return true
}
func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t , value []byte , allow_breaks bool ) bool {
if !yaml_emitter_write_indicator (emitter , []byte {'\'' }, true , false , false ) {
return false
}
spaces := false
breaks := false
for i := 0 ; i < len (value ); {
if is_space (value , i ) {
if allow_breaks && !spaces && emitter .column > emitter .best_width && i > 0 && i < len (value )-1 && !is_space (value , i +1 ) {
if !yaml_emitter_write_indent (emitter ) {
return false
}
i += width (value [i ])
} else {
if !write (emitter , value , &i ) {
return false
}
}
spaces = true
} else if is_break (value , i ) {
if !breaks && value [i ] == '\n' {
if !put_break (emitter ) {
return false
}
}
if !write_break (emitter , value , &i ) {
return false
}
breaks = true
} else {
if breaks {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if value [i ] == '\'' {
if !put (emitter , '\'' ) {
return false
}
}
if !write (emitter , value , &i ) {
return false
}
emitter .indention = false
spaces = false
breaks = false
}
}
if !yaml_emitter_write_indicator (emitter , []byte {'\'' }, false , false , false ) {
return false
}
emitter .whitespace = false
emitter .indention = false
return true
}
func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t , value []byte , allow_breaks bool ) bool {
spaces := false
if !yaml_emitter_write_indicator (emitter , []byte {'"' }, true , false , false ) {
return false
}
for i := 0 ; i < len (value ); {
if !is_printable (value , i ) || (!emitter .unicode && !is_ascii (value , i )) ||
is_bom (value , i ) || is_break (value , i ) ||
value [i ] == '"' || value [i ] == '\\' {
octet := value [i ]
var w int
var v rune
switch {
case octet &0x80 == 0x00 :
w , v = 1 , rune (octet &0x7F )
case octet &0xE0 == 0xC0 :
w , v = 2 , rune (octet &0x1F )
case octet &0xF0 == 0xE0 :
w , v = 3 , rune (octet &0x0F )
case octet &0xF8 == 0xF0 :
w , v = 4 , rune (octet &0x07 )
}
for k := 1 ; k < w ; k ++ {
octet = value [i +k ]
v = (v << 6 ) + (rune (octet ) & 0x3F )
}
i += w
if !put (emitter , '\\' ) {
return false
}
var ok bool
switch v {
case 0x00 :
ok = put (emitter , '0' )
case 0x07 :
ok = put (emitter , 'a' )
case 0x08 :
ok = put (emitter , 'b' )
case 0x09 :
ok = put (emitter , 't' )
case 0x0A :
ok = put (emitter , 'n' )
case 0x0b :
ok = put (emitter , 'v' )
case 0x0c :
ok = put (emitter , 'f' )
case 0x0d :
ok = put (emitter , 'r' )
case 0x1b :
ok = put (emitter , 'e' )
case 0x22 :
ok = put (emitter , '"' )
case 0x5c :
ok = put (emitter , '\\' )
case 0x85 :
ok = put (emitter , 'N' )
case 0xA0 :
ok = put (emitter , '_' )
case 0x2028 :
ok = put (emitter , 'L' )
case 0x2029 :
ok = put (emitter , 'P' )
default :
if v <= 0xFF {
ok = put (emitter , 'x' )
w = 2
} else if v <= 0xFFFF {
ok = put (emitter , 'u' )
w = 4
} else {
ok = put (emitter , 'U' )
w = 8
}
for k := (w - 1 ) * 4 ; ok && k >= 0 ; k -= 4 {
digit := byte ((v >> uint (k )) & 0x0F )
if digit < 10 {
ok = put (emitter , digit +'0' )
} else {
ok = put (emitter , digit +'A' -10 )
}
}
}
if !ok {
return false
}
spaces = false
} else if is_space (value , i ) {
if allow_breaks && !spaces && emitter .column > emitter .best_width && i > 0 && i < len (value )-1 {
if !yaml_emitter_write_indent (emitter ) {
return false
}
if is_space (value , i +1 ) {
if !put (emitter , '\\' ) {
return false
}
}
i += width (value [i ])
} else if !write (emitter , value , &i ) {
return false
}
spaces = true
} else {
if !write (emitter , value , &i ) {
return false
}
spaces = false
}
}
if !yaml_emitter_write_indicator (emitter , []byte {'"' }, false , false , false ) {
return false
}
emitter .whitespace = false
emitter .indention = false
return true
}
func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t , value []byte ) bool {
if is_space (value , 0 ) || is_break (value , 0 ) {
indent_hint := []byte {'0' + byte (emitter .best_indent )}
if !yaml_emitter_write_indicator (emitter , indent_hint , false , false , false ) {
return false
}
}
emitter .open_ended = false
var chomp_hint [1 ]byte
if len (value ) == 0 {
chomp_hint [0 ] = '-'
} else {
i := len (value ) - 1
for value [i ]&0xC0 == 0x80 {
i --
}
if !is_break (value , i ) {
chomp_hint [0 ] = '-'
} else if i == 0 {
chomp_hint [0 ] = '+'
emitter .open_ended = true
} else {
i --
for value [i ]&0xC0 == 0x80 {
i --
}
if is_break (value , i ) {
chomp_hint [0 ] = '+'
emitter .open_ended = true
}
}
}
if chomp_hint [0 ] != 0 {
if !yaml_emitter_write_indicator (emitter , chomp_hint [:], false , false , false ) {
return false
}
}
return true
}
func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t , value []byte ) bool {
if !yaml_emitter_write_indicator (emitter , []byte {'|' }, true , false , false ) {
return false
}
if !yaml_emitter_write_block_scalar_hints (emitter , value ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
emitter .whitespace = true
breaks := true
for i := 0 ; i < len (value ); {
if is_break (value , i ) {
if !write_break (emitter , value , &i ) {
return false
}
breaks = true
} else {
if breaks {
if !yaml_emitter_write_indent (emitter ) {
return false
}
}
if !write (emitter , value , &i ) {
return false
}
emitter .indention = false
breaks = false
}
}
return true
}
func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t , value []byte ) bool {
if !yaml_emitter_write_indicator (emitter , []byte {'>' }, true , false , false ) {
return false
}
if !yaml_emitter_write_block_scalar_hints (emitter , value ) {
return false
}
if !yaml_emitter_process_line_comment (emitter ) {
return false
}
emitter .whitespace = true
breaks := true
leading_spaces := true
for i := 0 ; i < len (value ); {
if is_break (value , i ) {
if !breaks && !leading_spaces && value [i ] == '\n' {
k := 0
for is_break (value , k ) {
k += width (value [k ])
}
if !is_blankz (value , k ) {
if !put_break (emitter ) {
return false
}
}
}
if !write_break (emitter , value , &i ) {
return false
}
breaks = true
} else {
if breaks {
if !yaml_emitter_write_indent (emitter ) {
return false
}
leading_spaces = is_blank (value , i )
}
if !breaks && is_space (value , i ) && !is_space (value , i +1 ) && emitter .column > emitter .best_width {
if !yaml_emitter_write_indent (emitter ) {
return false
}
i += width (value [i ])
} else {
if !write (emitter , value , &i ) {
return false
}
}
emitter .indention = false
breaks = false
}
}
return true
}
func yaml_emitter_write_comment(emitter *yaml_emitter_t , comment []byte ) bool {
breaks := false
pound := false
for i := 0 ; i < len (comment ); {
if is_break (comment , i ) {
if !write_break (emitter , comment , &i ) {
return false
}
breaks = true
pound = false
} else {
if breaks && !yaml_emitter_write_indent (emitter ) {
return false
}
if !pound {
if comment [i ] != '#' && (!put (emitter , '#' ) || !put (emitter , ' ' )) {
return false
}
pound = true
}
if !write (emitter , comment , &i ) {
return false
}
emitter .indention = false
breaks = false
}
}
if !breaks && !put_break (emitter ) {
return false
}
emitter .whitespace = true
return true
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .