summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pelletier/go-toml/tomltree_write.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2020-08-10 00:29:54 +0200
committerGitHub <noreply@github.com>2020-08-10 00:29:54 +0200
commit4e50fd864921c556988c919269448efdb90fa961 (patch)
treea3625f03f8de3c4f3841364000a4ea3aa42c1533 /vendor/github.com/pelletier/go-toml/tomltree_write.go
parentdfdffa0027334e55ce213fc6eb62206dbf48baf6 (diff)
downloadmatterbridge-msglm-4e50fd864921c556988c919269448efdb90fa961.tar.gz
matterbridge-msglm-4e50fd864921c556988c919269448efdb90fa961.tar.bz2
matterbridge-msglm-4e50fd864921c556988c919269448efdb90fa961.zip
Use mattermost v5 module (#1192)
Diffstat (limited to 'vendor/github.com/pelletier/go-toml/tomltree_write.go')
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_write.go322
1 files changed, 235 insertions, 87 deletions
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go
index e4049e29..16c19867 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_write.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"math"
+ "math/big"
"reflect"
"sort"
"strconv"
@@ -12,12 +13,25 @@ import (
"time"
)
+type valueComplexity int
+
+const (
+ valueSimple valueComplexity = iota + 1
+ valueComplex
+)
+
+type sortNode struct {
+ key string
+ complexity valueComplexity
+}
+
// 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 {
+func encodeMultilineTomlString(value string, commented string) string {
var b bytes.Buffer
+ b.WriteString(commented)
for _, rr := range value {
switch rr {
case '\b':
@@ -25,7 +39,7 @@ func encodeMultilineTomlString(value string) string {
case '\t':
b.WriteString("\t")
case '\n':
- b.WriteString("\n")
+ b.WriteString("\n" + commented)
case '\f':
b.WriteString(`\f`)
case '\r':
@@ -78,7 +92,7 @@ func encodeTomlString(value string) string {
return b.String()
}
-func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
+func tomlValueStringRepresentation(v interface{}, commented string, 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)
@@ -94,20 +108,28 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
case int64:
return strconv.FormatInt(value, 10), nil
case float64:
- // Ensure a round float does contain a decimal point. Otherwise feeding
- // the output back to the parser would convert to an integer.
+ // Default bit length is full 64
+ bits := 64
+ // Float panics if nan is used
+ if !math.IsNaN(value) {
+ // if 32 bit accuracy is enough to exactly show, use 32
+ _, acc := big.NewFloat(value).Float32()
+ if acc == big.Exact {
+ bits = 32
+ }
+ }
if math.Trunc(value) == value {
- return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil
+ return strings.ToLower(strconv.FormatFloat(value, 'f', 1, bits)), nil
}
- return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
+ return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil
case string:
if tv.multiline {
- return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil
+ return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil
}
return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
b, _ := v.([]byte)
- return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine)
+ return tomlValueStringRepresentation(string(b), commented, indent, arraysOneElementPerLine)
case bool:
if value {
return "true", nil
@@ -115,6 +137,12 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
return "false", nil
case time.Time:
return value.Format(time.RFC3339), nil
+ case LocalDate:
+ return value.String(), nil
+ case LocalDateTime:
+ return value.String(), nil
+ case LocalTime:
+ return value.String(), nil
case nil:
return "", nil
}
@@ -125,7 +153,7 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
var values []string
for i := 0; i < rv.Len(); i++ {
item := rv.Index(i).Interface()
- itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine)
+ itemRepr, err := tomlValueStringRepresentation(item, commented, indent, arraysOneElementPerLine)
if err != nil {
return "", err
}
@@ -139,12 +167,12 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
for _, value := range values {
stringBuffer.WriteString(valueIndent)
- stringBuffer.WriteString(value)
+ stringBuffer.WriteString(commented + value)
stringBuffer.WriteString(`,`)
stringBuffer.WriteString("\n")
}
- stringBuffer.WriteString(indent + "]")
+ stringBuffer.WriteString(indent + commented + "]")
return stringBuffer.String(), nil
}
@@ -153,117 +181,238 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
}
-func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
- simpleValuesKeys := make([]string, 0)
- complexValuesKeys := make([]string, 0)
+func getTreeArrayLine(trees []*Tree) (line int) {
+ // get lowest line number that is not 0
+ for _, tv := range trees {
+ if tv.position.Line < line || line == 0 {
+ line = tv.position.Line
+ }
+ }
+ return
+}
+
+func sortByLines(t *Tree) (vals []sortNode) {
+ var (
+ line int
+ lines []int
+ tv *Tree
+ tom *tomlValue
+ node sortNode
+ )
+ vals = make([]sortNode, 0)
+ m := make(map[int]sortNode)
for k := range t.values {
v := t.values[k]
switch v.(type) {
- case *Tree, []*Tree:
- complexValuesKeys = append(complexValuesKeys, k)
+ case *Tree:
+ tv = v.(*Tree)
+ line = tv.position.Line
+ node = sortNode{key: k, complexity: valueComplex}
+ case []*Tree:
+ line = getTreeArrayLine(v.([]*Tree))
+ node = sortNode{key: k, complexity: valueComplex}
default:
- simpleValuesKeys = append(simpleValuesKeys, k)
+ tom = v.(*tomlValue)
+ line = tom.position.Line
+ node = sortNode{key: k, complexity: valueSimple}
}
+ lines = append(lines, line)
+ vals = append(vals, node)
+ m[line] = node
}
+ sort.Ints(lines)
- sort.Strings(simpleValuesKeys)
- sort.Strings(complexValuesKeys)
+ for i, line := range lines {
+ vals[i] = m[line]
+ }
- for _, k := range simpleValuesKeys {
- v, ok := t.values[k].(*tomlValue)
- if !ok {
- return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
- }
+ return vals
+}
- repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine)
- if err != nil {
- return bytesCount, err
- }
+func sortAlphabetical(t *Tree) (vals []sortNode) {
+ var (
+ node sortNode
+ simpVals []string
+ compVals []string
+ )
+ vals = make([]sortNode, 0)
+ m := make(map[string]sortNode)
- if v.comment != "" {
- comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1)
- start := "# "
- if strings.HasPrefix(comment, "#") {
- start = ""
- }
- writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n")
- bytesCount += int64(writtenBytesCountComment)
- if errc != nil {
- return bytesCount, errc
- }
+ for k := range t.values {
+ v := t.values[k]
+ switch v.(type) {
+ case *Tree, []*Tree:
+ node = sortNode{key: k, complexity: valueComplex}
+ compVals = append(compVals, node.key)
+ default:
+ node = sortNode{key: k, complexity: valueSimple}
+ simpVals = append(simpVals, node.key)
}
+ vals = append(vals, node)
+ m[node.key] = node
+ }
- var commented string
- if v.commented {
- commented = "# "
- }
- writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n")
- bytesCount += int64(writtenBytesCount)
- if err != nil {
- return bytesCount, err
- }
+ // Simples first to match previous implementation
+ sort.Strings(simpVals)
+ i := 0
+ for _, key := range simpVals {
+ vals[i] = m[key]
+ i++
}
- for _, k := range complexValuesKeys {
- v := t.values[k]
+ sort.Strings(compVals)
+ for _, key := range compVals {
+ vals[i] = m[key]
+ i++
+ }
- combinedKey := k
- if keyspace != "" {
- combinedKey = keyspace + "." + combinedKey
- }
- var commented string
- if t.commented {
- commented = "# "
- }
+ return vals
+}
- switch node := v.(type) {
- // node has to be of those two types given how keys are sorted above
- case *Tree:
- tv, ok := t.values[k].(*Tree)
+func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
+ return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, false)
+}
+
+func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder, parentCommented bool) (int64, error) {
+ var orderedVals []sortNode
+
+ switch ord {
+ case OrderPreserve:
+ orderedVals = sortByLines(t)
+ default:
+ orderedVals = sortAlphabetical(t)
+ }
+
+ for _, node := range orderedVals {
+ switch node.complexity {
+ case valueComplex:
+ k := node.key
+ v := t.values[k]
+
+ combinedKey := k
+ if keyspace != "" {
+ combinedKey = keyspace + "." + combinedKey
+ }
+
+ switch node := v.(type) {
+ // node has to be of those two types given how keys are sorted above
+ case *Tree:
+ tv, ok := t.values[k].(*Tree)
+ if !ok {
+ return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
+ }
+ if tv.comment != "" {
+ comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1)
+ start := "# "
+ if strings.HasPrefix(comment, "#") {
+ start = ""
+ }
+ writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment)
+ bytesCount += int64(writtenBytesCountComment)
+ if errc != nil {
+ return bytesCount, errc
+ }
+ }
+
+ var commented string
+ if parentCommented || t.commented || tv.commented {
+ commented = "# "
+ }
+ writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
+ bytesCount += int64(writtenBytesCount)
+ if err != nil {
+ return bytesCount, err
+ }
+ bytesCount, err = node.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord, parentCommented || t.commented || tv.commented)
+ if err != nil {
+ return bytesCount, err
+ }
+ case []*Tree:
+ for _, subTree := range node {
+ var commented string
+ if parentCommented || t.commented || subTree.commented {
+ commented = "# "
+ }
+ writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n")
+ bytesCount += int64(writtenBytesCount)
+ if err != nil {
+ return bytesCount, err
+ }
+
+ bytesCount, err = subTree.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord, parentCommented || t.commented || subTree.commented)
+ if err != nil {
+ return bytesCount, err
+ }
+ }
+ }
+ default: // Simple
+ k := node.key
+ v, ok := t.values[k].(*tomlValue)
if !ok {
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
}
- if tv.comment != "" {
- comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1)
+
+ var commented string
+ if parentCommented || t.commented || v.commented {
+ commented = "# "
+ }
+ repr, err := tomlValueStringRepresentation(v, commented, indent, arraysOneElementPerLine)
+ if err != nil {
+ return bytesCount, err
+ }
+
+ if v.comment != "" {
+ comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1)
start := "# "
if strings.HasPrefix(comment, "#") {
start = ""
}
- writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment)
+ writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n")
bytesCount += int64(writtenBytesCountComment)
if errc != nil {
return bytesCount, errc
}
}
- writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
+
+ quotedKey := quoteKeyIfNeeded(k)
+ writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n")
bytesCount += int64(writtenBytesCount)
if err != nil {
return bytesCount, err
}
- bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
- if err != nil {
- return bytesCount, err
- }
- case []*Tree:
- for _, subTree := range node {
- writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n")
- bytesCount += int64(writtenBytesCount)
- if err != nil {
- return bytesCount, err
- }
-
- bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
- if err != nil {
- return bytesCount, err
- }
- }
}
}
return bytesCount, nil
}
+// quote a key if it does not fit the bare key format (A-Za-z0-9_-)
+// quoted keys use the same rules as strings
+func quoteKeyIfNeeded(k string) string {
+ // when encoding a map with the 'quoteMapKeys' option enabled, the tree will contain
+ // keys that have already been quoted.
+ // not an ideal situation, but good enough of a stop gap.
+ if len(k) >= 2 && k[0] == '"' && k[len(k)-1] == '"' {
+ return k
+ }
+ isBare := true
+ for _, r := range k {
+ if !isValidBareChar(r) {
+ isBare = false
+ break
+ }
+ }
+ if isBare {
+ return k
+ }
+ return quoteKey(k)
+}
+
+func quoteKey(k string) string {
+ return "\"" + encodeTomlString(k) + "\""
+}
+
func writeStrings(w io.Writer, s ...string) (int, error) {
var n int
for i := range s {
@@ -286,12 +435,11 @@ func (t *Tree) WriteTo(w io.Writer) (int64, error) {
// Output spans multiple lines, and is suitable for ingest by a TOML parser.
// If the conversion cannot be performed, ToString returns a non-nil error.
func (t *Tree) ToTomlString() (string, error) {
- var buf bytes.Buffer
- _, err := t.WriteTo(&buf)
+ b, err := t.Marshal()
if err != nil {
return "", err
}
- return buf.String(), nil
+ return string(b), nil
}
// String generates a human-readable representation of the current tree.