Marshal base 60 floats quoted for YAML 1.1 compat. Closes #34.
diff --git a/decode_test.go b/decode_test.go index a290645..46c94d4 100644 --- a/decode_test.go +++ b/decode_test.go
@@ -377,6 +377,12 @@ "a: <foo>", map[string]string{"a": "<foo>"}, }, + + // Base 60 floats are obsolete and unsupported. + { + "a: 1:1\n", + map[string]string{"a": "1:1"}, + }, } type inlineB struct {
diff --git a/encode.go b/encode.go index 1d928b0..9f0c699 100644 --- a/encode.go +++ b/encode.go
@@ -2,8 +2,10 @@ import ( "reflect" + "regexp" "sort" "strconv" + "strings" "time" ) @@ -167,10 +169,32 @@ e.emit() } +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base64re.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base64re = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + func (e *encoder) stringv(tag string, in reflect.Value) { var style yaml_scalar_style_t s := in.String() - if rtag, _ := resolve("", s); rtag != "!!str" { + if rtag, _ := resolve("", s); rtag != "!!str" || isBase60(s) { style = yaml_DOUBLE_QUOTED_SCALAR_STYLE } else { style = yaml_PLAIN_SCALAR_STYLE
diff --git a/encode_test.go b/encode_test.go index 83dc490..b9319db 100644 --- a/encode_test.go +++ b/encode_test.go
@@ -220,11 +220,18 @@ "a: 3s\n", }, - // Issue #24. + // Issue #24: bug in map merging logic. { map[string]string{"a": "<foo>"}, "a: <foo>\n", }, + + // Issue #34: marshal unsupported base 60 floats quoted for compatibility + // with old YAML 1.1 parsers. + { + map[string]string{"a": "1:1"}, + "a: \"1:1\"\n", + }, } func (s *S) TestMarshal(c *C) {