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

     1  package kmgYaml
     2  
     3  import (
     4  	"bytes"
     5  )
     6  
     7  // Check if a %YAML directive is valid.
     8  func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
     9  	if version_directive.major != 1 || version_directive.minor != 1 {
    10  		return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
    11  	}
    12  	return true
    13  }
    14  
    15  // Check if a %TAG directive is valid.
    16  func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
    17  	handle := tag_directive.handle
    18  	prefix := tag_directive.prefix
    19  	if len(handle) == 0 {
    20  		return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
    21  	}
    22  	if handle[0] != '!' {
    23  		return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
    24  	}
    25  	if handle[len(handle)-1] != '!' {
    26  		return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
    27  	}
    28  	for i := 1; i < len(handle)-1; i += width(handle[i]) {
    29  		if !is_alpha(handle, i) {
    30  			return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
    31  		}
    32  	}
    33  	if len(prefix) == 0 {
    34  		return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
    35  	}
    36  	return true
    37  }
    38  
    39  // Check if an anchor is valid.
    40  func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
    41  	if len(anchor) == 0 {
    42  		problem := "anchor value must not be empty"
    43  		if alias {
    44  			problem = "alias value must not be empty"
    45  		}
    46  		return yaml_emitter_set_emitter_error(emitter, problem)
    47  	}
    48  	for i := 0; i < len(anchor); i += width(anchor[i]) {
    49  		if !is_alpha(anchor, i) {
    50  			problem := "anchor value must contain alphanumerical characters only"
    51  			if alias {
    52  				problem = "alias value must contain alphanumerical characters only"
    53  			}
    54  			return yaml_emitter_set_emitter_error(emitter, problem)
    55  		}
    56  	}
    57  	emitter.anchor_data.anchor = anchor
    58  	emitter.anchor_data.alias = alias
    59  	return true
    60  }
    61  
    62  // Check if a tag is valid.
    63  func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
    64  	if len(tag) == 0 {
    65  		return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
    66  	}
    67  	for i := 0; i < len(emitter.tag_directives); i++ {
    68  		tag_directive := &emitter.tag_directives[i]
    69  		if bytes.HasPrefix(tag, tag_directive.prefix) {
    70  			emitter.tag_data.handle = tag_directive.handle
    71  			emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
    72  		}
    73  		return true
    74  	}
    75  	emitter.tag_data.suffix = tag
    76  	return true
    77  }
    78  
    79  // Check if a scalar is valid.
    80  func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
    81  	var (
    82  		block_indicators   = false
    83  		flow_indicators    = false
    84  		line_breaks        = false
    85  		special_characters = false
    86  
    87  		leading_space  = false
    88  		leading_break  = false
    89  		trailing_space = false
    90  		trailing_break = false
    91  		break_space    = false
    92  		space_break    = false
    93  
    94  		preceeded_by_whitespace = false
    95  		followed_by_whitespace  = false
    96  		previous_space          = false
    97  		previous_break          = false
    98  	)
    99  
   100  	emitter.scalar_data.value = value
   101  
   102  	if len(value) == 0 {
   103  		emitter.scalar_data.multiline = false
   104  		emitter.scalar_data.flow_plain_allowed = false
   105  		emitter.scalar_data.block_plain_allowed = true
   106  		emitter.scalar_data.single_quoted_allowed = true
   107  		emitter.scalar_data.block_allowed = false
   108  		return true
   109  	}
   110  
   111  	if (value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.') {
   112  		block_indicators = true
   113  		flow_indicators = true
   114  	}
   115  
   116  	preceeded_by_whitespace = true
   117  	for i, w := 0, 0; i < len(value); i += w {
   118  		w = width(value[i]) //bug origin width(value[0])
   119  		followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
   120  
   121  		if i == 0 {
   122  			switch value[i] {
   123  			case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
   124  				flow_indicators = true
   125  				block_indicators = true
   126  			case '?', ':':
   127  				flow_indicators = true
   128  				if followed_by_whitespace {
   129  					block_indicators = true
   130  				}
   131  			case '-':
   132  				if followed_by_whitespace {
   133  					flow_indicators = true
   134  					block_indicators = true
   135  				}
   136  			}
   137  		} else {
   138  			switch value[i] {
   139  			case ',', '?', '[', ']', '{', '}':
   140  				flow_indicators = true
   141  			case ':':
   142  				flow_indicators = true
   143  				if followed_by_whitespace {
   144  					block_indicators = true
   145  				}
   146  			case '#':
   147  				if preceeded_by_whitespace {
   148  					flow_indicators = true
   149  					block_indicators = true
   150  				}
   151  			}
   152  		}
   153  
   154  		if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
   155  			special_characters = true
   156  		}
   157  		if is_space(value, i) {
   158  			if i == 0 {
   159  				leading_space = true
   160  			}
   161  			if i+width(value[i]) == len(value) {
   162  				trailing_space = true
   163  			}
   164  			if previous_break {
   165  				break_space = true
   166  			}
   167  			previous_space = true
   168  			previous_break = false
   169  		} else if is_break(value, i) {
   170  			line_breaks = true
   171  			if i == 0 {
   172  				leading_break = true
   173  			}
   174  			if i+width(value[i]) == len(value) {
   175  				trailing_break = true
   176  			}
   177  			if previous_space {
   178  				space_break = true
   179  			}
   180  			previous_space = false
   181  			previous_break = true
   182  		} else {
   183  			previous_space = false
   184  			previous_break = false
   185  		}
   186  
   187  		// [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
   188  		preceeded_by_whitespace = is_blankz(value, i)
   189  	}
   190  
   191  	emitter.scalar_data.multiline = line_breaks
   192  	emitter.scalar_data.flow_plain_allowed = true
   193  	emitter.scalar_data.block_plain_allowed = true
   194  	emitter.scalar_data.single_quoted_allowed = true
   195  	emitter.scalar_data.block_allowed = true
   196  
   197  	if leading_space || leading_break || trailing_space || trailing_break {
   198  		emitter.scalar_data.flow_plain_allowed = false
   199  		emitter.scalar_data.block_plain_allowed = false
   200  	}
   201  	if trailing_space {
   202  		emitter.scalar_data.block_allowed = false
   203  	}
   204  	if break_space {
   205  		emitter.scalar_data.flow_plain_allowed = false
   206  		emitter.scalar_data.block_plain_allowed = false
   207  		emitter.scalar_data.single_quoted_allowed = false
   208  	}
   209  	if space_break || special_characters {
   210  		emitter.scalar_data.flow_plain_allowed = false
   211  		emitter.scalar_data.block_plain_allowed = false
   212  		emitter.scalar_data.single_quoted_allowed = false
   213  		emitter.scalar_data.block_allowed = false
   214  	}
   215  	if line_breaks {
   216  		emitter.scalar_data.flow_plain_allowed = false
   217  		emitter.scalar_data.block_plain_allowed = false
   218  	}
   219  	if flow_indicators {
   220  		emitter.scalar_data.flow_plain_allowed = false
   221  	}
   222  	if block_indicators {
   223  		emitter.scalar_data.block_plain_allowed = false
   224  	}
   225  	return true
   226  }
   227  
   228  // Check if the event data is valid.
   229  func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
   230  
   231  	emitter.anchor_data.anchor = nil
   232  	emitter.tag_data.handle = nil
   233  	emitter.tag_data.suffix = nil
   234  	emitter.scalar_data.value = nil
   235  
   236  	switch event.typ {
   237  	case yaml_ALIAS_EVENT:
   238  		if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
   239  			return false
   240  		}
   241  
   242  	case yaml_SCALAR_EVENT:
   243  		if len(event.anchor) > 0 {
   244  			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
   245  				return false
   246  			}
   247  		}
   248  		if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
   249  			if !yaml_emitter_analyze_tag(emitter, event.tag) {
   250  				return false
   251  			}
   252  		}
   253  		if !yaml_emitter_analyze_scalar(emitter, event.value) {
   254  			return false
   255  		}
   256  
   257  	case yaml_SEQUENCE_START_EVENT:
   258  		if len(event.anchor) > 0 {
   259  			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
   260  				return false
   261  			}
   262  		}
   263  		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
   264  			if !yaml_emitter_analyze_tag(emitter, event.tag) {
   265  				return false
   266  			}
   267  		}
   268  
   269  	case yaml_MAPPING_START_EVENT:
   270  		if len(event.anchor) > 0 {
   271  			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
   272  				return false
   273  			}
   274  		}
   275  		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
   276  			if !yaml_emitter_analyze_tag(emitter, event.tag) {
   277  				return false
   278  			}
   279  		}
   280  	}
   281  	return true
   282  }