Multiline Marshal tag (#221)

The new multiline tag works just like the existing 'commented' tag (i.e.
`multiline:"true"`), and tells go-toml to marshal the value as a
multi-line string. The tag currently has no impact on any non-string
fields.
This commit is contained in:
Alan Murtagh
2018-03-06 12:43:58 +10:00
committed by Thomas Pelletier
parent 66540cf1fc
commit c01d1270ff
3 changed files with 117 additions and 4 deletions
+48 -2
View File
@@ -12,7 +12,41 @@ import (
"time"
)
// encodes a string to a TOML-compliant string value
// Encodes a string to a TOML-compliant multi-line string value
// This function is a clone of the existing encodeTomlString function, except that whitespace characters
// are preserved. Quotation marks and backslashes are also not escaped.
func encodeMultilineTomlString(value string) string {
var b bytes.Buffer
for _, rr := range value {
switch rr {
case '\b':
b.WriteString(`\b`)
case '\t':
b.WriteString("\t")
case '\n':
b.WriteString("\n")
case '\f':
b.WriteString(`\f`)
case '\r':
b.WriteString("\r")
case '"':
b.WriteString(`"`)
case '\\':
b.WriteString(`\`)
default:
intRr := uint16(rr)
if intRr < 0x001F {
b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
} else {
b.WriteRune(rr)
}
}
}
return b.String()
}
// Encodes a string to a TOML-compliant string value
func encodeTomlString(value string) string {
var b bytes.Buffer
@@ -45,6 +79,15 @@ func encodeTomlString(value string) string {
}
func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
// this interface check is added to dereference the change made in the writeTo function.
// That change was made to allow this function to see formatting options.
tv, ok := v.(*tomlValue)
if ok {
v = tv.value
} else {
tv = &tomlValue{}
}
switch value := v.(type) {
case uint64:
return strconv.FormatUint(value, 10), nil
@@ -58,6 +101,9 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
}
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
case string:
if tv.multiline {
return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil
}
return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
b, _ := v.([]byte)
@@ -130,7 +176,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, a
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
}
repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine)
repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine)
if err != nil {
return bytesCount, err
}