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 }