diff --git a/tomltree_write.go b/tomltree_write.go index 4aaf491..836a8de 100644 --- a/tomltree_write.go +++ b/tomltree_write.go @@ -13,33 +13,34 @@ import ( // encodes a string to a TOML-compliant string value func encodeTomlString(value string) string { - result := "" + var b bytes.Buffer + for _, rr := range value { switch rr { case '\b': - result += "\\b" + b.WriteString(`\b`) case '\t': - result += "\\t" + b.WriteString(`\t`) case '\n': - result += "\\n" + b.WriteString(`\n`) case '\f': - result += "\\f" + b.WriteString(`\f`) case '\r': - result += "\\r" + b.WriteString(`\r`) case '"': - result += "\\\"" + b.WriteString(`\"`) case '\\': - result += "\\\\" + b.WriteString(`\\`) default: intRr := uint16(rr) if intRr < 0x001F { - result += fmt.Sprintf("\\u%0.4X", intRr) + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) } else { - result += string(rr) + b.WriteRune(rr) } } } - return result + return b.String() } func tomlValueStringRepresentation(v interface{}) (string, error) { @@ -111,7 +112,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) ( return bytesCount, err } - kvRepr := fmt.Sprintf("%s%s = %s\n", indent, k, repr) + kvRepr := indent + k + " = " + repr + "\n" writtenBytesCount, err := w.Write([]byte(kvRepr)) bytesCount += int64(writtenBytesCount) if err != nil { @@ -130,7 +131,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) ( switch node := v.(type) { // node has to be of those two types given how keys are sorted above case *Tree: - tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey) + tableName := "\n" + indent + "[" + combinedKey + "]\n" writtenBytesCount, err := w.Write([]byte(tableName)) bytesCount += int64(writtenBytesCount) if err != nil { @@ -142,7 +143,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) ( } case []*Tree: for _, subTree := range node { - tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey) + tableArrayName := "\n" + indent + "[[" + combinedKey + "]]\n" writtenBytesCount, err := w.Write([]byte(tableArrayName)) bytesCount += int64(writtenBytesCount) if err != nil { diff --git a/tomltree_write_test.go b/tomltree_write_test.go index 371434e..53e7aa9 100644 --- a/tomltree_write_test.go +++ b/tomltree_write_test.go @@ -293,3 +293,51 @@ func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) { treeMap := tree.ToMap() testMaps(t, treeMap, expected) } + +func BenchmarkTreeToTomlString(b *testing.B) { + toml, err := Load(sampleHard) + if err != nil { + b.Fatal("Unexpected error:", err) + } + + for i := 0; i < b.N; i++ { + _, err := toml.ToTomlString() + if err != nil { + b.Fatal(err) + } + } +} + +var sampleHard = `# Test file for TOML +# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate +# This part you'll really hate + +[the] +test_string = "You'll hate me after this - #" # " Annoying, isn't it? + + [the.hard] + test_array = [ "] ", " # "] # ] There you go, parse this! + test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ] + # You didn't think it'd as easy as chucking out the last #, did you? + another_test_string = " Same thing, but with a string #" + harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too" + # Things will get harder + + [the.hard."bit#"] + "what?" = "You don't think some user won't do that?" + multi_line_array = [ + "]", + # ] Oh yes I did + ] + +# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test + +#[error] if you didn't catch this, your parser is broken +#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment" like this +#array = [ +# "This might most likely happen in multiline arrays", +# Like here, +# "or here, +# and here" +# ] End of array comment, forgot the # +#number = 3.14 pi <--again forgot the # `