github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/encoding/kmgYaml/yaml_emitter.go (about)

     1  package kmgYaml
     2  
     3  import (
     4  	"bytes"
     5  )
     6  
     7  // Set an emitter error and return false.
     8  func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
     9  	emitter.error = yaml_EMITTER_ERROR
    10  	emitter.problem = problem
    11  	return false
    12  }
    13  
    14  // Check if we need to accumulate more events before emitting.
    15  //
    16  // We accumulate extra
    17  //  - 1 event for DOCUMENT-START
    18  //  - 2 events for SEQUENCE-START
    19  //  - 3 events for MAPPING-START
    20  //
    21  func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
    22  	if emitter.events_head == len(emitter.events) {
    23  		return true
    24  	}
    25  	var accumulate int
    26  	switch emitter.events[emitter.events_head].typ {
    27  	case yaml_DOCUMENT_START_EVENT:
    28  		accumulate = 1
    29  		break
    30  	case yaml_SEQUENCE_START_EVENT:
    31  		accumulate = 2
    32  		break
    33  	case yaml_MAPPING_START_EVENT:
    34  		accumulate = 3
    35  		break
    36  	default:
    37  		return false
    38  	}
    39  	if len(emitter.events)-emitter.events_head > accumulate {
    40  		return false
    41  	}
    42  	var level int
    43  	for i := emitter.events_head; i < len(emitter.events); i++ {
    44  		switch emitter.events[i].typ {
    45  		case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
    46  			level++
    47  		case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
    48  			level--
    49  		}
    50  		if level == 0 {
    51  			return false
    52  		}
    53  	}
    54  	return true
    55  }
    56  
    57  // Append a directive to the directives stack.
    58  func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
    59  	for i := 0; i < len(emitter.tag_directives); i++ {
    60  		if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
    61  			if allow_duplicates {
    62  				return true
    63  			}
    64  			return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
    65  		}
    66  	}
    67  
    68  	// [Go] Do we actually need to copy this given garbage collection
    69  	// and the lack of deallocating destructors?
    70  	tag_copy := yaml_tag_directive_t{
    71  		handle: make([]byte, len(value.handle)),
    72  		prefix: make([]byte, len(value.prefix)),
    73  	}
    74  	copy(tag_copy.handle, value.handle)
    75  	copy(tag_copy.prefix, value.prefix)
    76  	emitter.tag_directives = append(emitter.tag_directives, tag_copy)
    77  	return true
    78  }
    79  
    80  // Increase the indentation level.
    81  func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
    82  	emitter.indents = append(emitter.indents, emitter.indent)
    83  	if emitter.indent < 0 {
    84  		if flow {
    85  			emitter.indent = emitter.best_indent
    86  		} else {
    87  			emitter.indent = 0
    88  		}
    89  	} else if !indentless {
    90  		emitter.indent += emitter.best_indent
    91  	}
    92  	return true
    93  }
    94  
    95  // State dispatcher.
    96  func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
    97  	switch emitter.state {
    98  	default:
    99  	case yaml_EMIT_STREAM_START_STATE:
   100  		return yaml_emitter_emit_stream_start(emitter, event)
   101  
   102  	case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
   103  		return yaml_emitter_emit_document_start(emitter, event, true)
   104  
   105  	case yaml_EMIT_DOCUMENT_START_STATE:
   106  		return yaml_emitter_emit_document_start(emitter, event, false)
   107  
   108  	case yaml_EMIT_DOCUMENT_CONTENT_STATE:
   109  		return yaml_emitter_emit_document_content(emitter, event)
   110  
   111  	case yaml_EMIT_DOCUMENT_END_STATE:
   112  		return yaml_emitter_emit_document_end(emitter, event)
   113  
   114  	case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
   115  		return yaml_emitter_emit_flow_sequence_item(emitter, event, true)
   116  
   117  	case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
   118  		return yaml_emitter_emit_flow_sequence_item(emitter, event, false)
   119  
   120  	case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
   121  		return yaml_emitter_emit_flow_mapping_key(emitter, event, true)
   122  
   123  	case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
   124  		return yaml_emitter_emit_flow_mapping_key(emitter, event, false)
   125  
   126  	case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
   127  		return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
   128  
   129  	case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
   130  		return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
   131  
   132  	case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
   133  		return yaml_emitter_emit_block_sequence_item(emitter, event, true)
   134  
   135  	case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
   136  		return yaml_emitter_emit_block_sequence_item(emitter, event, false)
   137  
   138  	case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
   139  		return yaml_emitter_emit_block_mapping_key(emitter, event, true)
   140  
   141  	case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
   142  		return yaml_emitter_emit_block_mapping_key(emitter, event, false)
   143  
   144  	case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
   145  		return yaml_emitter_emit_block_mapping_value(emitter, event, true)
   146  
   147  	case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
   148  		return yaml_emitter_emit_block_mapping_value(emitter, event, false)
   149  
   150  	case yaml_EMIT_END_STATE:
   151  		return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
   152  	}
   153  	panic("invalid emitter state")
   154  }
   155  
   156  // Determine an acceptable scalar style.
   157  func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
   158  
   159  	no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
   160  	if no_tag && !event.implicit && !event.quoted_implicit {
   161  		return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
   162  	}
   163  
   164  	style := event.scalar_style()
   165  	if style == yaml_ANY_SCALAR_STYLE {
   166  		style = yaml_PLAIN_SCALAR_STYLE
   167  	}
   168  	if emitter.canonical {
   169  		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
   170  	}
   171  	if emitter.simple_key_context && emitter.scalar_data.multiline {
   172  		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
   173  	}
   174  
   175  	if style == yaml_PLAIN_SCALAR_STYLE {
   176  		if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed {
   177  			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
   178  		}
   179  		if emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
   180  			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
   181  		}
   182  		if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
   183  			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
   184  		}
   185  		if no_tag && !event.implicit {
   186  			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
   187  		}
   188  	}
   189  	if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
   190  		if !emitter.scalar_data.single_quoted_allowed {
   191  			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
   192  		}
   193  	}
   194  	if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
   195  		if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
   196  			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
   197  		}
   198  	}
   199  
   200  	if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
   201  		emitter.tag_data.handle = []byte{'!'}
   202  	}
   203  	emitter.scalar_data.style = style
   204  	return true
   205  }