Make values come before tables in ToString output (#111)

If no order on the key is enforced in ToString, the following tree:

foo = 1
bar = "baz"
foobar = true
[qux]
  foo = 1
  bar = "baz"

may come out as:

bar = "baz"
foobar = true
[qux]
  foo = 1
  bar = "baz"
foo = 1

which is incorrect, since putting that back to the parser would panic
because of a duplicated key (qux.foo). Those changes make sure that
leaf values come before tables in the ToString output.
diff --git a/tomltree_conversions.go b/tomltree_conversions.go
index bf9321b..08efebc 100644
--- a/tomltree_conversions.go
+++ b/tomltree_conversions.go
@@ -94,55 +94,64 @@
 // Recursive support function for ToString()
 // Outputs a tree, using the provided keyspace to prefix group names
 func (t *TomlTree) toToml(indent, keyspace string) string {
-	result := ""
+	resultChunks := []string{}
 	for k, v := range t.values {
 		// figure out the keyspace
 		combinedKey := k
 		if keyspace != "" {
 			combinedKey = keyspace + "." + combinedKey
 		}
+		resultChunk := ""
 		// output based on type
 		switch node := v.(type) {
 		case []*TomlTree:
 			for _, item := range node {
 				if len(item.Keys()) > 0 {
-					result += fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
+					resultChunk += fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
 				}
-				result += item.toToml(indent+"  ", combinedKey)
+				resultChunk += item.toToml(indent+"  ", combinedKey)
 			}
+			resultChunks = append(resultChunks, resultChunk)
 		case *TomlTree:
 			if len(node.Keys()) > 0 {
-				result += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
+				resultChunk += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
 			}
-			result += node.toToml(indent+"  ", combinedKey)
+			resultChunk += node.toToml(indent+"  ", combinedKey)
+			resultChunks = append(resultChunks, resultChunk)
 		case map[string]interface{}:
 			sub := TreeFromMap(node)
 
 			if len(sub.Keys()) > 0 {
-				result += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
+				resultChunk += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
 			}
-			result += sub.toToml(indent+"  ", combinedKey)
+			resultChunk += sub.toToml(indent+"  ", combinedKey)
+			resultChunks = append(resultChunks, resultChunk)
 		case map[string]string:
 			sub := TreeFromMap(convertMapStringString(node))
 
 			if len(sub.Keys()) > 0 {
-				result += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
+				resultChunk += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
 			}
-			result += sub.toToml(indent+"  ", combinedKey)
+			resultChunk += sub.toToml(indent+"  ", combinedKey)
+			resultChunks = append(resultChunks, resultChunk)
 		case map[interface{}]interface{}:
 			sub := TreeFromMap(convertMapInterfaceInterface(node))
 
 			if len(sub.Keys()) > 0 {
-				result += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
+				resultChunk += fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
 			}
-			result += sub.toToml(indent+"  ", combinedKey)
+			resultChunk += sub.toToml(indent+"  ", combinedKey)
+			resultChunks = append(resultChunks, resultChunk)
 		case *tomlValue:
-			result += fmt.Sprintf("%s%s = %s\n", indent, k, toTomlValue(node.value, 0))
+			resultChunk = fmt.Sprintf("%s%s = %s\n", indent, k, toTomlValue(node.value, 0))
+			resultChunks = append([]string{resultChunk}, resultChunks...)
 		default:
-			result += fmt.Sprintf("%s%s = %s\n", indent, k, toTomlValue(v, 0))
+			resultChunk = fmt.Sprintf("%s%s = %s\n", indent, k, toTomlValue(v, 0))
+			resultChunks = append([]string{resultChunk}, resultChunks...)
 		}
+
 	}
-	return result
+	return strings.Join(resultChunks, "")
 }
 
 func convertMapStringString(in map[string]string) map[string]interface{} {
diff --git a/tomltree_conversions_test.go b/tomltree_conversions_test.go
index 58dbf4e..4ad9009 100644
--- a/tomltree_conversions_test.go
+++ b/tomltree_conversions_test.go
@@ -4,6 +4,7 @@
 	"reflect"
 	"testing"
 	"time"
+	"strings"
 )
 
 func TestTomlTreeConversionToString(t *testing.T) {
@@ -28,6 +29,41 @@
 	})
 }
 
+func TestTomlTreeConversionToStringKeysOrders(t *testing.T) {
+	for i := 0; i < 100; i++ {
+		tree, _ := Load(`
+		foobar = true
+		bar = "baz"
+		foo = 1
+		[qux]
+		  foo = 1
+		  bar = "baz2"`)
+
+		stringRepr := tree.ToString()
+
+		t.Log("Intermediate string representation:")
+		t.Log(stringRepr)
+
+		r := strings.NewReader(stringRepr)
+		toml, err := LoadReader(r)
+
+
+		if err != nil {
+			t.Fatal("Unexpected error:", err)
+		}
+
+		assertTree(t, toml, err, map[string]interface{}{
+			"foobar": true,
+			"bar": "baz",
+			"foo": 1,
+			"qux": map[string]interface{}{
+				"foo": 1,
+				"bar": "baz2",
+			},
+		})
+	}
+}
+
 func testMaps(t *testing.T, actual, expected map[string]interface{}) {
 	if !reflect.DeepEqual(actual, expected) {
 		t.Fatal("trees aren't equal.\n", "Expected:\n", expected, "\nActual:\n", actual)