Rename TomlTree to Tree (#159)

Avoid stutter.

Fixes #55
This commit is contained in:
Thomas Pelletier
2017-05-10 17:53:23 -07:00
committed by GitHub
parent 23f644976a
commit 685a1f1cb7
20 changed files with 170 additions and 170 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ This library supports TOML version
Go-toml provides the following features for using data parsed from TOML documents: Go-toml provides the following features for using data parsed from TOML documents:
* Load TOML documents from files and string data * Load TOML documents from files and string data
* Easily navigate TOML structure using TomlTree * Easily navigate TOML structure using Tree
* Line & column position data for all parsed elements * Line & column position data for all parsed elements
* [Query support similar to JSON-Path](query/) * [Query support similar to JSON-Path](query/)
* Syntax errors contain line and column numbers * Syntax errors contain line and column numbers
@@ -61,7 +61,7 @@ if err != nil {
password := config.Get("postgres.password").(string) password := config.Get("postgres.password").(string)
// or using an intermediate object // or using an intermediate object
configTree := config.Get("postgres").(*toml.TomlTree) configTree := config.Get("postgres").(*toml.Tree)
user = configTree.Get("user").(string) user = configTree.Get("user").(string)
password = configTree.Get("password").(string) password = configTree.Get("password").(string)
fmt.Println("User is ", user, ". Password is ", password) fmt.Println("User is ", user, ". Password is ", password)
+3 -3
View File
@@ -41,16 +41,16 @@ func translate(tomlData interface{}) interface{} {
typed[k] = translate(v) typed[k] = translate(v)
} }
return typed return typed
case *toml.TomlTree: case *toml.Tree:
return translate(*orig) return translate(*orig)
case toml.TomlTree: case toml.Tree:
keys := orig.Keys() keys := orig.Keys()
typed := make(map[string]interface{}, len(keys)) typed := make(map[string]interface{}, len(keys))
for _, k := range keys { for _, k := range keys {
typed[k] = translate(orig.GetPath([]string{k})) typed[k] = translate(orig.GetPath([]string{k}))
} }
return typed return typed
case []*toml.TomlTree: case []*toml.Tree:
typed := make([]map[string]interface{}, len(orig)) typed := make([]map[string]interface{}, len(orig))
for i, v := range orig { for i, v := range orig {
typed[i] = translate(v).(map[string]interface{}) typed[i] = translate(v).(map[string]interface{})
+1 -1
View File
@@ -57,7 +57,7 @@ func reader(r io.Reader) (string, error) {
return mapToJSON(tree) return mapToJSON(tree)
} }
func mapToJSON(tree *toml.TomlTree) (string, error) { func mapToJSON(tree *toml.Tree) (string, error) {
treeMap := tree.ToMap() treeMap := tree.ToMap()
bytes, err := json.MarshalIndent(treeMap, "", " ") bytes, err := json.MarshalIndent(treeMap, "", " ")
if err != nil { if err != nil {
+5 -5
View File
@@ -13,14 +13,14 @@
// // load TOML data stored in a string // // load TOML data stored in a string
// tree, err := toml.Load(stringContainingTomlData) // tree, err := toml.Load(stringContainingTomlData)
// //
// Either way, the result is a TomlTree object that can be used to navigate the // Either way, the result is a Tree object that can be used to navigate the
// structure and data within the original document. // structure and data within the original document.
// //
// //
// Getting data from the TomlTree // Getting data from the Tree
// //
// After parsing TOML data with Load() or LoadFile(), use the Has() and Get() // After parsing TOML data with Load() or LoadFile(), use the Has() and Get()
// methods on the returned TomlTree, to find your way through the document data. // methods on the returned Tree, to find your way through the document data.
// //
// if tree.Has("foo") { // if tree.Has("foo") {
// fmt.Println("foo is:", tree.Get("foo")) // fmt.Println("foo is:", tree.Get("foo"))
@@ -50,11 +50,11 @@
// tree.GetPath([]string{"foo","bar","baz"}) // tree.GetPath([]string{"foo","bar","baz"})
// //
// Note that this is distinct from the heavyweight query syntax supported by // Note that this is distinct from the heavyweight query syntax supported by
// TomlTree.Query() and the Query() struct (see below). // Tree.Query() and the Query() struct (see below).
// //
// Position Support // Position Support
// //
// Each element within the TomlTree is stored with position metadata, which is // Each element within the Tree is stored with position metadata, which is
// invaluable for providing semantic feedback to a user. This helps in // invaluable for providing semantic feedback to a user. This helps in
// situations where the TOML file parses correctly, but contains data that is // situations where the TOML file parses correctly, but contains data that is
// not correct for the application. In such cases, an error message can be // not correct for the application. In such cases, an error message can be
+1 -1
View File
@@ -17,7 +17,7 @@ func Example_comprehensiveExample() {
password := config.Get("postgres.password").(string) password := config.Get("postgres.password").(string)
// or using an intermediate object // or using an intermediate object
configTree := config.Get("postgres").(*TomlTree) configTree := config.Get("postgres").(*Tree)
user = configTree.Get("user").(string) user = configTree.Get("user").(string)
password = configTree.Get("password").(string) password = configTree.Get("password").(string)
fmt.Println("User is ", user, ". Password is ", password) fmt.Println("User is ", user, ". Password is ", password)
+18 -18
View File
@@ -10,14 +10,14 @@ import (
) )
/* /*
TomlTree structural types and corresponding marshal types Tree structural types and corresponding marshal types
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*TomlTree (*)struct, (*)map[string]interface{} *Tree (*)struct, (*)map[string]interface{}
[]*TomlTree (*)[](*)struct, (*)[](*)map[string]interface{} []*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{}) []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
interface{} (*)primitive interface{} (*)primitive
TomlTree primitive types and corresponding marshal types Tree primitive types and corresponding marshal types
----------------------------------------------------------- -----------------------------------------------------------
uint64 uint, uint8-uint64, pointers to same uint64 uint, uint8-uint64, pointers to same
int64 int, int8-uint64, pointers to same int64 int, int8-uint64, pointers to same
@@ -36,7 +36,7 @@ type tomlOpts struct {
var timeType = reflect.TypeOf(time.Time{}) var timeType = reflect.TypeOf(time.Time{})
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
// Check if the given marshall type maps to a TomlTree primitive // Check if the given marshall type maps to a Tree primitive
func isPrimitive(mtype reflect.Type) bool { func isPrimitive(mtype reflect.Type) bool {
switch mtype.Kind() { switch mtype.Kind() {
case reflect.Ptr: case reflect.Ptr:
@@ -58,7 +58,7 @@ func isPrimitive(mtype reflect.Type) bool {
} }
} }
// Check if the given marshall type maps to a TomlTree slice // Check if the given marshall type maps to a Tree slice
func isTreeSlice(mtype reflect.Type) bool { func isTreeSlice(mtype reflect.Type) bool {
switch mtype.Kind() { switch mtype.Kind() {
case reflect.Slice: case reflect.Slice:
@@ -68,7 +68,7 @@ func isTreeSlice(mtype reflect.Type) bool {
} }
} }
// Check if the given marshall type maps to a non-TomlTree slice // Check if the given marshall type maps to a non-Tree slice
func isOtherSlice(mtype reflect.Type) bool { func isOtherSlice(mtype reflect.Type) bool {
switch mtype.Kind() { switch mtype.Kind() {
case reflect.Ptr: case reflect.Ptr:
@@ -80,7 +80,7 @@ func isOtherSlice(mtype reflect.Type) bool {
} }
} }
// Check if the given marshall type maps to a TomlTree // Check if the given marshall type maps to a Tree
func isTree(mtype reflect.Type) bool { func isTree(mtype reflect.Type) bool {
switch mtype.Kind() { switch mtype.Kind() {
case reflect.Map: case reflect.Map:
@@ -134,11 +134,11 @@ func Marshal(v interface{}) ([]byte, error) {
} }
// Convert given marshal struct or map value to toml tree // Convert given marshal struct or map value to toml tree
func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) { func valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
if mtype.Kind() == reflect.Ptr { if mtype.Kind() == reflect.Ptr {
return valueToTree(mtype.Elem(), mval.Elem()) return valueToTree(mtype.Elem(), mval.Elem())
} }
tval := newTomlTree() tval := newTree()
switch mtype.Kind() { switch mtype.Kind() {
case reflect.Struct: case reflect.Struct:
for i := 0; i < mtype.NumField(); i++ { for i := 0; i < mtype.NumField(); i++ {
@@ -166,8 +166,8 @@ func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
} }
// Convert given marshal slice to slice of Toml trees // Convert given marshal slice to slice of Toml trees
func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*TomlTree, error) { func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
tval := make([]*TomlTree, mval.Len(), mval.Len()) tval := make([]*Tree, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ { for i := 0; i < mval.Len(); i++ {
val, err := valueToTree(mtype.Elem(), mval.Index(i)) val, err := valueToTree(mtype.Elem(), mval.Index(i))
if err != nil { if err != nil {
@@ -225,10 +225,10 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
} }
} }
// Unmarshal attempts to unmarshal the TomlTree into a Go struct pointed by v. // Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for // Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
// sub-structs, and only definite types can be unmarshaled. // sub-structs, and only definite types can be unmarshaled.
func (t *TomlTree) Unmarshal(v interface{}) error { func (t *Tree) Unmarshal(v interface{}) error {
mtype := reflect.TypeOf(v) mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct { if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
return errors.New("Only a pointer to struct can be unmarshaled from TOML") return errors.New("Only a pointer to struct can be unmarshaled from TOML")
@@ -256,7 +256,7 @@ func Unmarshal(data []byte, v interface{}) error {
} }
// Convert toml tree to marshal struct or map, using marshal type // Convert toml tree to marshal struct or map, using marshal type
func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) { func valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr { if mtype.Kind() == reflect.Ptr {
return unwrapPointer(mtype, tval) return unwrapPointer(mtype, tval)
} }
@@ -295,7 +295,7 @@ func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
} }
// Convert toml value to marshal struct/map slice, using marshal type // Convert toml value to marshal struct/map slice, using marshal type
func valueFromTreeSlice(mtype reflect.Type, tval []*TomlTree) (reflect.Value, error) { func valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
mval := reflect.MakeSlice(mtype, len(tval), len(tval)) mval := reflect.MakeSlice(mtype, len(tval), len(tval))
for i := 0; i < len(tval); i++ { for i := 0; i < len(tval); i++ {
val, err := valueFromTree(mtype.Elem(), tval[i]) val, err := valueFromTree(mtype.Elem(), tval[i])
@@ -327,9 +327,9 @@ func valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error)
} }
switch { switch {
case isTree(mtype): case isTree(mtype):
return valueFromTree(mtype, tval.(*TomlTree)) return valueFromTree(mtype, tval.(*Tree))
case isTreeSlice(mtype): case isTreeSlice(mtype):
return valueFromTreeSlice(mtype, tval.([]*TomlTree)) return valueFromTreeSlice(mtype, tval.([]*Tree))
case isOtherSlice(mtype): case isOtherSlice(mtype):
return valueFromOtherSlice(mtype, tval.([]interface{})) return valueFromOtherSlice(mtype, tval.([]interface{}))
default: default:
+1 -1
View File
@@ -181,7 +181,7 @@ func TestDocPartialUnmarshal(t *testing.T) {
result := testDocSubs{} result := testDocSubs{}
tree, _ := LoadFile("marshal_test.toml") tree, _ := LoadFile("marshal_test.toml")
subTree := tree.Get("subdoc").(*TomlTree) subTree := tree.Get("subdoc").(*Tree)
err := subTree.Unmarshal(&result) err := subTree.Unmarshal(&result)
expected := docData.Subdocs expected := docData.Subdocs
if err != nil { if err != nil {
+19 -19
View File
@@ -14,7 +14,7 @@ import (
type tomlParser struct { type tomlParser struct {
flow chan token flow chan token
tree *TomlTree tree *Tree
tokensBuffer []token tokensBuffer []token
currentTable []string currentTable []string
seenTableKeys []string seenTableKeys []string
@@ -106,18 +106,18 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
} }
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
destTree := p.tree.GetPath(keys) destTree := p.tree.GetPath(keys)
var array []*TomlTree var array []*Tree
if destTree == nil { if destTree == nil {
array = make([]*TomlTree, 0) array = make([]*Tree, 0)
} else if target, ok := destTree.([]*TomlTree); ok && target != nil { } else if target, ok := destTree.([]*Tree); ok && target != nil {
array = destTree.([]*TomlTree) array = destTree.([]*Tree)
} else { } else {
p.raiseError(key, "key %s is already assigned and not of type table array", key) p.raiseError(key, "key %s is already assigned and not of type table array", key)
} }
p.currentTable = keys p.currentTable = keys
// add a new tree to the end of the table array // add a new tree to the end of the table array
newTree := newTomlTree() newTree := newTree()
newTree.position = startToken.Position newTree.position = startToken.Position
array = append(array, newTree) array = append(array, newTree)
p.tree.SetPath(p.currentTable, array) p.tree.SetPath(p.currentTable, array)
@@ -183,11 +183,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
} }
// find the table to assign, looking out for arrays of tables // find the table to assign, looking out for arrays of tables
var targetNode *TomlTree var targetNode *Tree
switch node := p.tree.GetPath(tableKey).(type) { switch node := p.tree.GetPath(tableKey).(type) {
case []*TomlTree: case []*Tree:
targetNode = node[len(node)-1] targetNode = node[len(node)-1]
case *TomlTree: case *Tree:
targetNode = node targetNode = node
default: default:
p.raiseError(key, "Unknown table type for path: %s", p.raiseError(key, "Unknown table type for path: %s",
@@ -212,7 +212,7 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
var toInsert interface{} var toInsert interface{}
switch value.(type) { switch value.(type) {
case *TomlTree, []*TomlTree: case *Tree, []*Tree:
toInsert = value toInsert = value
default: default:
toInsert = &tomlValue{value, key.Position} toInsert = &tomlValue{value, key.Position}
@@ -289,8 +289,8 @@ func tokenIsComma(t *token) bool {
return t != nil && t.typ == tokenComma return t != nil && t.typ == tokenComma
} }
func (p *tomlParser) parseInlineTable() *TomlTree { func (p *tomlParser) parseInlineTable() *Tree {
tree := newTomlTree() tree := newTree()
var previous *token var previous *token
Loop: Loop:
for { for {
@@ -360,22 +360,22 @@ func (p *tomlParser) parseArray() interface{} {
p.getToken() p.getToken()
} }
} }
// An array of TomlTrees is actually an array of inline // An array of Trees is actually an array of inline
// tables, which is a shorthand for a table array. If the // tables, which is a shorthand for a table array. If the
// array was not converted from []interface{} to []*TomlTree, // array was not converted from []interface{} to []*Tree,
// the two notations would not be equivalent. // the two notations would not be equivalent.
if arrayType == reflect.TypeOf(newTomlTree()) { if arrayType == reflect.TypeOf(newTree()) {
tomlArray := make([]*TomlTree, len(array)) tomlArray := make([]*Tree, len(array))
for i, v := range array { for i, v := range array {
tomlArray[i] = v.(*TomlTree) tomlArray[i] = v.(*Tree)
} }
return tomlArray return tomlArray
} }
return array return array
} }
func parseToml(flow chan token) *TomlTree { func parseToml(flow chan token) *Tree {
result := newTomlTree() result := newTree()
result.position = Position{1, 1} result.position = Position{1, 1}
parser := &tomlParser{ parser := &tomlParser{
flow: flow, flow: flow,
+5 -5
View File
@@ -9,7 +9,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
) )
func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref map[string]interface{}) { func assertSubTree(t *testing.T, path []string, tree *Tree, err error, ref map[string]interface{}) {
if err != nil { if err != nil {
t.Error("Non-nil error:", err.Error()) t.Error("Non-nil error:", err.Error())
return return
@@ -20,12 +20,12 @@ func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref m
// NOTE: directly access key instead of resolve by path // NOTE: directly access key instead of resolve by path
// NOTE: see TestSpecialKV // NOTE: see TestSpecialKV
switch node := tree.GetPath([]string{k}).(type) { switch node := tree.GetPath([]string{k}).(type) {
case []*TomlTree: case []*Tree:
t.Log("\tcomparing key", nextPath, "by array iteration") t.Log("\tcomparing key", nextPath, "by array iteration")
for idx, item := range node { for idx, item := range node {
assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx]) assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx])
} }
case *TomlTree: case *Tree:
t.Log("\tcomparing key", nextPath, "by subtree assestion") t.Log("\tcomparing key", nextPath, "by subtree assestion")
assertSubTree(t, nextPath, node, err, v.(map[string]interface{})) assertSubTree(t, nextPath, node, err, v.(map[string]interface{}))
default: default:
@@ -37,14 +37,14 @@ func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref m
} }
} }
func assertTree(t *testing.T, tree *TomlTree, err error, ref map[string]interface{}) { func assertTree(t *testing.T, tree *Tree, err error, ref map[string]interface{}) {
t.Log("Asserting tree:\n", spew.Sdump(tree)) t.Log("Asserting tree:\n", spew.Sdump(tree))
assertSubTree(t, []string{}, tree, err, ref) assertSubTree(t, []string{}, tree, err, ref)
t.Log("Finished tree assertion.") t.Log("Finished tree assertion.")
} }
func TestCreateSubTree(t *testing.T) { func TestCreateSubTree(t *testing.T) {
tree := newTomlTree() tree := newTree()
tree.createSubTree([]string{"a", "b", "c"}, Position{}) tree.createSubTree([]string{"a", "b", "c"}, Position{})
tree.Set("a.b.c", 42) tree.Set("a.b.c", 42)
if tree.Get("a.b.c") != 42 { if tree.Get("a.b.c") != 42 {
+3 -3
View File
@@ -112,7 +112,7 @@
// There are several filters provided with the library: // There are several filters provided with the library:
// //
// tree // tree
// Allows nodes of type TomlTree. // Allows nodes of type Tree.
// int // int
// Allows nodes of type int64. // Allows nodes of type int64.
// float // float
@@ -138,7 +138,7 @@
// //
// Compiled Queries // Compiled Queries
// //
// Queries may be executed directly on a TomlTree object, or compiled ahead // Queries may be executed directly on a Tree object, or compiled ahead
// of time and executed discretely. The former is more convienent, but has the // of time and executed discretely. The former is more convienent, but has the
// penalty of having to recompile the query expression each time. // penalty of having to recompile the query expression each time.
// //
@@ -163,7 +163,7 @@
// //
// // define the filter, and assign it to the query // // define the filter, and assign it to the query
// query.SetFilter("bazOnly", func(node interface{}) bool{ // query.SetFilter("bazOnly", func(node interface{}) bool{
// if tree, ok := node.(*TomlTree); ok { // if tree, ok := node.(*Tree); ok {
// return tree.Has("baz") // return tree.Has("baz")
// } // }
// return false // reject all other node types // return false // reject all other node types
+12 -12
View File
@@ -42,7 +42,7 @@ func newMatchKeyFn(name string) *matchKeyFn {
} }
func (f *matchKeyFn) call(node interface{}, ctx *queryContext) { func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
if array, ok := node.([]*toml.TomlTree); ok { if array, ok := node.([]*toml.Tree); ok {
for _, tree := range array { for _, tree := range array {
item := tree.Get(f.Name) item := tree.Get(f.Name)
if item != nil { if item != nil {
@@ -50,7 +50,7 @@ func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
f.next.call(item, ctx) f.next.call(item, ctx)
} }
} }
} else if tree, ok := node.(*toml.TomlTree); ok { } else if tree, ok := node.(*toml.Tree); ok {
item := tree.Get(f.Name) item := tree.Get(f.Name)
if item != nil { if item != nil {
ctx.lastPosition = tree.GetPosition(f.Name) ctx.lastPosition = tree.GetPosition(f.Name)
@@ -72,7 +72,7 @@ func newMatchIndexFn(idx int) *matchIndexFn {
func (f *matchIndexFn) call(node interface{}, ctx *queryContext) { func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
if arr, ok := node.([]interface{}); ok { if arr, ok := node.([]interface{}); ok {
if f.Idx < len(arr) && f.Idx >= 0 { if f.Idx < len(arr) && f.Idx >= 0 {
if treesArray, ok := node.([]*toml.TomlTree); ok { if treesArray, ok := node.([]*toml.Tree); ok {
if len(treesArray) > 0 { if len(treesArray) > 0 {
ctx.lastPosition = treesArray[0].Position() ctx.lastPosition = treesArray[0].Position()
} }
@@ -107,7 +107,7 @@ func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
} }
// loop and gather // loop and gather
for idx := realStart; idx < realEnd; idx += f.Step { for idx := realStart; idx < realEnd; idx += f.Step {
if treesArray, ok := node.([]*toml.TomlTree); ok { if treesArray, ok := node.([]*toml.Tree); ok {
if len(treesArray) > 0 { if len(treesArray) > 0 {
ctx.lastPosition = treesArray[0].Position() ctx.lastPosition = treesArray[0].Position()
} }
@@ -127,7 +127,7 @@ func newMatchAnyFn() *matchAnyFn {
} }
func (f *matchAnyFn) call(node interface{}, ctx *queryContext) { func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
if tree, ok := node.(*toml.TomlTree); ok { if tree, ok := node.(*toml.Tree); ok {
for _, k := range tree.Keys() { for _, k := range tree.Keys() {
v := tree.Get(k) v := tree.Get(k)
ctx.lastPosition = tree.GetPosition(k) ctx.lastPosition = tree.GetPosition(k)
@@ -164,17 +164,17 @@ func newMatchRecursiveFn() *matchRecursiveFn {
func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) { func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
originalPosition := ctx.lastPosition originalPosition := ctx.lastPosition
if tree, ok := node.(*toml.TomlTree); ok { if tree, ok := node.(*toml.Tree); ok {
var visit func(tree *toml.TomlTree) var visit func(tree *toml.Tree)
visit = func(tree *toml.TomlTree) { visit = func(tree *toml.Tree) {
for _, k := range tree.Keys() { for _, k := range tree.Keys() {
v := tree.Get(k) v := tree.Get(k)
ctx.lastPosition = tree.GetPosition(k) ctx.lastPosition = tree.GetPosition(k)
f.next.call(v, ctx) f.next.call(v, ctx)
switch node := v.(type) { switch node := v.(type) {
case *toml.TomlTree: case *toml.Tree:
visit(node) visit(node)
case []*toml.TomlTree: case []*toml.Tree:
for _, subtree := range node { for _, subtree := range node {
visit(subtree) visit(subtree)
} }
@@ -205,7 +205,7 @@ func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
f.Pos.String(), f.Name)) f.Pos.String(), f.Name))
} }
switch castNode := node.(type) { switch castNode := node.(type) {
case *toml.TomlTree: case *toml.Tree:
for _, k := range castNode.Keys() { for _, k := range castNode.Keys() {
v := castNode.Get(k) v := castNode.Get(k)
if fn(v) { if fn(v) {
@@ -213,7 +213,7 @@ func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
f.next.call(v, ctx) f.next.call(v, ctx)
} }
} }
case []*toml.TomlTree: case []*toml.Tree:
for _, v := range castNode { for _, v := range castNode {
if fn(v) { if fn(v) {
if len(castNode) > 0 { if len(castNode) > 0 {
+1 -1
View File
@@ -36,7 +36,7 @@ func valueString(root interface{}) string {
} }
sort.Strings(items) sort.Strings(items)
result = "[" + strings.Join(items, ", ") + "]" result = "[" + strings.Join(items, ", ") + "]"
case *toml.TomlTree: case *toml.Tree:
// workaround for unreliable map key ordering // workaround for unreliable map key ordering
items := []string{} items := []string{}
for _, k := range node.Keys() { for _, k := range node.Keys() {
+6 -6
View File
@@ -53,7 +53,7 @@ type queryContext struct {
type pathFn interface { type pathFn interface {
setNext(next pathFn) setNext(next pathFn)
// it is the caller's responsibility to set the ctx.lastPosition before invoking call() // it is the caller's responsibility to set the ctx.lastPosition before invoking call()
// node can be one of: *toml.TomlTree, []*toml.TomlTree, or a scalar // node can be one of: *toml.Tree, []*toml.Tree, or a scalar
call(node interface{}, ctx *queryContext) call(node interface{}, ctx *queryContext)
} }
@@ -84,13 +84,13 @@ func (q *Query) appendPath(next pathFn) {
} }
// Compile compiles a TOML path expression. The returned Query can be used // Compile compiles a TOML path expression. The returned Query can be used
// to match elements within a TomlTree and its descendants. See Execute. // to match elements within a Tree and its descendants. See Execute.
func Compile(path string) (*Query, error) { func Compile(path string) (*Query, error) {
return parseQuery(lexQuery(path)) return parseQuery(lexQuery(path))
} }
// Execute executes a query against a TomlTree, and returns the result of the query. // Execute executes a query against a Tree, and returns the result of the query.
func (q *Query) Execute(tree *toml.TomlTree) *Result { func (q *Query) Execute(tree *toml.Tree) *Result {
result := &Result{ result := &Result{
items: []interface{}{}, items: []interface{}{},
positions: []toml.Position{}, positions: []toml.Position{},
@@ -109,7 +109,7 @@ func (q *Query) Execute(tree *toml.TomlTree) *Result {
} }
// CompileAndExecute is a shorthand for Compile(path) followed by Execute(tree). // CompileAndExecute is a shorthand for Compile(path) followed by Execute(tree).
func CompileAndExecute(path string, tree *toml.TomlTree) (*Result, error) { func CompileAndExecute(path string, tree *toml.Tree) (*Result, error) {
query, err := Compile(path) query, err := Compile(path)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -132,7 +132,7 @@ func (q *Query) SetFilter(name string, fn NodeFilterFn) {
var defaultFilterFunctions = map[string]NodeFilterFn{ var defaultFilterFunctions = map[string]NodeFilterFn{
"tree": func(node interface{}) bool { "tree": func(node interface{}) bool {
_, ok := node.(*toml.TomlTree) _, ok := node.(*toml.Tree)
return ok return ok
}, },
"int": func(node interface{}) bool { "int": func(node interface{}) bool {
+4 -4
View File
@@ -99,13 +99,13 @@ func ExampleNodeFilterFn_filterExample() {
// define the filter, and assign it to the query // define the filter, and assign it to the query
query.SetFilter("bazOnly", func(node interface{}) bool { query.SetFilter("bazOnly", func(node interface{}) bool {
if tree, ok := node.(*toml.TomlTree); ok { if tree, ok := node.(*toml.Tree); ok {
return tree.Has("baz") return tree.Has("baz")
} }
return false // reject all other node types return false // reject all other node types
}) })
// results contain only the 'struct_two' TomlTree // results contain only the 'struct_two' Tree
query.Execute(tree) query.Execute(tree)
} }
@@ -147,8 +147,8 @@ func TestTomlQuery(t *testing.T) {
t.Errorf("Expected resultset of 1, got %d instead: %v", len(values), values) t.Errorf("Expected resultset of 1, got %d instead: %v", len(values), values)
} }
if tt, ok := values[0].(*toml.TomlTree); !ok { if tt, ok := values[0].(*toml.Tree); !ok {
t.Errorf("Expected type of TomlTree: %T", values[0]) t.Errorf("Expected type of Tree: %T", values[0])
} else if tt.Get("a") != int64(1) { } else if tt.Get("a") != int64(1) {
t.Errorf("Expected 'a' with a value 1: %v", tt.Get("a")) t.Errorf("Expected 'a' with a value 1: %v", tt.Get("a"))
} else if tt.Get("b") != int64(2) { } else if tt.Get("b") != int64(2) {
+42 -42
View File
@@ -14,35 +14,35 @@ type tomlValue struct {
position Position position Position
} }
// TomlTree is the result of the parsing of a TOML file. // Tree is the result of the parsing of a TOML file.
type TomlTree struct { type Tree struct {
values map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
position Position position Position
} }
func newTomlTree() *TomlTree { func newTree() *Tree {
return &TomlTree{ return &Tree{
values: make(map[string]interface{}), values: make(map[string]interface{}),
position: Position{}, position: Position{},
} }
} }
// TreeFromMap initializes a new TomlTree object using the given map. // TreeFromMap initializes a new Tree object using the given map.
func TreeFromMap(m map[string]interface{}) (*TomlTree, error) { func TreeFromMap(m map[string]interface{}) (*Tree, error) {
result, err := toTree(m) result, err := toTree(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*TomlTree), nil return result.(*Tree), nil
} }
// Position returns the position of the tree. // Position returns the position of the tree.
func (t *TomlTree) Position() Position { func (t *Tree) Position() Position {
return t.position return t.position
} }
// Has returns a boolean indicating if the given key exists. // Has returns a boolean indicating if the given key exists.
func (t *TomlTree) Has(key string) bool { func (t *Tree) Has(key string) bool {
if key == "" { if key == "" {
return false return false
} }
@@ -50,13 +50,13 @@ func (t *TomlTree) Has(key string) bool {
} }
// HasPath returns true if the given path of keys exists, false otherwise. // HasPath returns true if the given path of keys exists, false otherwise.
func (t *TomlTree) HasPath(keys []string) bool { func (t *Tree) HasPath(keys []string) bool {
return t.GetPath(keys) != nil return t.GetPath(keys) != nil
} }
// Keys returns the keys of the toplevel tree. // Keys returns the keys of the toplevel tree.
// Warning: this is a costly operation. // Warning: this is a costly operation.
func (t *TomlTree) Keys() []string { func (t *Tree) Keys() []string {
keys := make([]string, len(t.values)) keys := make([]string, len(t.values))
i := 0 i := 0
for k := range t.values { for k := range t.values {
@@ -66,11 +66,11 @@ func (t *TomlTree) Keys() []string {
return keys return keys
} }
// Get the value at key in the TomlTree. // Get the value at key in the Tree.
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Returns nil if the path does not exist in the tree. // Returns nil if the path does not exist in the tree.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) Get(key string) interface{} { func (t *Tree) Get(key string) interface{} {
if key == "" { if key == "" {
return t return t
} }
@@ -83,7 +83,7 @@ func (t *TomlTree) Get(key string) interface{} {
// GetPath returns the element in the tree indicated by 'keys'. // GetPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPath(keys []string) interface{} { func (t *Tree) GetPath(keys []string) interface{} {
if len(keys) == 0 { if len(keys) == 0 {
return t return t
} }
@@ -94,9 +94,9 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
return nil return nil
} }
switch node := value.(type) { switch node := value.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return nil return nil
@@ -116,7 +116,7 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
} }
// GetPosition returns the position of the given key. // GetPosition returns the position of the given key.
func (t *TomlTree) GetPosition(key string) Position { func (t *Tree) GetPosition(key string) Position {
if key == "" { if key == "" {
return t.position return t.position
} }
@@ -125,7 +125,7 @@ func (t *TomlTree) GetPosition(key string) Position {
// GetPositionPath returns the element in the tree indicated by 'keys'. // GetPositionPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned. // If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPositionPath(keys []string) Position { func (t *Tree) GetPositionPath(keys []string) Position {
if len(keys) == 0 { if len(keys) == 0 {
return t.position return t.position
} }
@@ -136,9 +136,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
return Position{0, 0} return Position{0, 0}
} }
switch node := value.(type) { switch node := value.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return Position{0, 0} return Position{0, 0}
@@ -152,9 +152,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
switch node := subtree.values[keys[len(keys)-1]].(type) { switch node := subtree.values[keys[len(keys)-1]].(type) {
case *tomlValue: case *tomlValue:
return node.position return node.position
case *TomlTree: case *Tree:
return node.position return node.position
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
return Position{0, 0} return Position{0, 0}
@@ -166,7 +166,7 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
} }
// GetDefault works like Get but with a default value // GetDefault works like Get but with a default value
func (t *TomlTree) GetDefault(key string, def interface{}) interface{} { func (t *Tree) GetDefault(key string, def interface{}) interface{} {
val := t.Get(key) val := t.Get(key)
if val == nil { if val == nil {
return def return def
@@ -177,29 +177,29 @@ func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
// Set an element in the tree. // Set an element in the tree.
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Creates all necessary intermediate trees, if needed. // Creates all necessary intermediate trees, if needed.
func (t *TomlTree) Set(key string, value interface{}) { func (t *Tree) Set(key string, value interface{}) {
t.SetPath(strings.Split(key, "."), value) t.SetPath(strings.Split(key, "."), value)
} }
// SetPath sets an element in the tree. // SetPath sets an element in the tree.
// Keys is an array of path elements (e.g. {"a","b","c"}). // Keys is an array of path elements (e.g. {"a","b","c"}).
// Creates all necessary intermediate trees, if needed. // Creates all necessary intermediate trees, if needed.
func (t *TomlTree) SetPath(keys []string, value interface{}) { func (t *Tree) SetPath(keys []string, value interface{}) {
subtree := t subtree := t
for _, intermediateKey := range keys[:len(keys)-1] { for _, intermediateKey := range keys[:len(keys)-1] {
nextTree, exists := subtree.values[intermediateKey] nextTree, exists := subtree.values[intermediateKey]
if !exists { if !exists {
nextTree = newTomlTree() nextTree = newTree()
subtree.values[intermediateKey] = nextTree // add new element here subtree.values[intermediateKey] = nextTree // add new element here
} }
switch node := nextTree.(type) { switch node := nextTree.(type) {
case *TomlTree: case *Tree:
subtree = node subtree = node
case []*TomlTree: case []*Tree:
// go to most recent element // go to most recent element
if len(node) == 0 { if len(node) == 0 {
// create element if it does not exist // create element if it does not exist
subtree.values[intermediateKey] = append(node, newTomlTree()) subtree.values[intermediateKey] = append(node, newTree())
} }
subtree = node[len(node)-1] subtree = node[len(node)-1]
} }
@@ -208,9 +208,9 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
var toInsert interface{} var toInsert interface{}
switch value.(type) { switch value.(type) {
case *TomlTree: case *Tree:
toInsert = value toInsert = value
case []*TomlTree: case []*Tree:
toInsert = value toInsert = value
case *tomlValue: case *tomlValue:
toInsert = value toInsert = value
@@ -228,21 +228,21 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
// and tree[a][b][c] // and tree[a][b][c]
// //
// Returns nil on success, error object on failure // Returns nil on success, error object on failure
func (t *TomlTree) createSubTree(keys []string, pos Position) error { func (t *Tree) createSubTree(keys []string, pos Position) error {
subtree := t subtree := t
for _, intermediateKey := range keys { for _, intermediateKey := range keys {
nextTree, exists := subtree.values[intermediateKey] nextTree, exists := subtree.values[intermediateKey]
if !exists { if !exists {
tree := newTomlTree() tree := newTree()
tree.position = pos tree.position = pos
subtree.values[intermediateKey] = tree subtree.values[intermediateKey] = tree
nextTree = tree nextTree = tree
} }
switch node := nextTree.(type) { switch node := nextTree.(type) {
case []*TomlTree: case []*Tree:
subtree = node[len(node)-1] subtree = node[len(node)-1]
case *TomlTree: case *Tree:
subtree = node subtree = node
default: default:
return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
@@ -252,8 +252,8 @@ func (t *TomlTree) createSubTree(keys []string, pos Position) error {
return nil return nil
} }
// LoadReader creates a TomlTree from any io.Reader. // LoadReader creates a Tree from any io.Reader.
func LoadReader(reader io.Reader) (tree *TomlTree, err error) { func LoadReader(reader io.Reader) (tree *Tree, err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok { if _, ok := r.(runtime.Error); ok {
@@ -266,13 +266,13 @@ func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
return return
} }
// Load creates a TomlTree from a string. // Load creates a Tree from a string.
func Load(content string) (tree *TomlTree, err error) { func Load(content string) (tree *Tree, err error) {
return LoadReader(strings.NewReader(content)) return LoadReader(strings.NewReader(content))
} }
// LoadFile creates a TomlTree from a file. // LoadFile creates a Tree from a file.
func LoadFile(path string) (tree *TomlTree, err error) { func LoadFile(path string) (tree *Tree, err error) {
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err
+2 -2
View File
@@ -70,12 +70,12 @@ func TestTomlHasPath(t *testing.T) {
} }
func TestTomlGetPath(t *testing.T) { func TestTomlGetPath(t *testing.T) {
node := newTomlTree() node := newTree()
//TODO: set other node data //TODO: set other node data
for idx, item := range []struct { for idx, item := range []struct {
Path []string Path []string
Expected *TomlTree Expected *Tree
}{ }{
{ // empty path test { // empty path test
[]string{}, []string{},
+5 -5
View File
@@ -51,7 +51,7 @@ func simpleValueCoercion(object interface{}) (interface{}, error) {
case fmt.Stringer: case fmt.Stringer:
return original.String(), nil return original.String(), nil
default: default:
return nil, fmt.Errorf("cannot convert type %T to TomlTree", object) return nil, fmt.Errorf("cannot convert type %T to Tree", object)
} }
} }
@@ -59,7 +59,7 @@ func sliceToTree(object interface{}) (interface{}, error) {
// arrays are a bit tricky, since they can represent either a // arrays are a bit tricky, since they can represent either a
// collection of simple values, which is represented by one // collection of simple values, which is represented by one
// *tomlValue, or an array of tables, which is represented by an // *tomlValue, or an array of tables, which is represented by an
// array of *TomlTree. // array of *Tree.
// holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
value := reflect.ValueOf(object) value := reflect.ValueOf(object)
@@ -70,14 +70,14 @@ func sliceToTree(object interface{}) (interface{}, error) {
} }
if insideType.Kind() == reflect.Map { if insideType.Kind() == reflect.Map {
// this is considered as an array of tables // this is considered as an array of tables
tablesArray := make([]*TomlTree, 0, length) tablesArray := make([]*Tree, 0, length)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
table := value.Index(i) table := value.Index(i)
tree, err := toTree(table.Interface()) tree, err := toTree(table.Interface())
if err != nil { if err != nil {
return nil, err return nil, err
} }
tablesArray = append(tablesArray, tree.(*TomlTree)) tablesArray = append(tablesArray, tree.(*Tree))
} }
return tablesArray, nil return tablesArray, nil
} }
@@ -120,7 +120,7 @@ func toTree(object interface{}) (interface{}, error) {
} }
values[key.String()] = newValue values[key.String()] = newValue
} }
return &TomlTree{values, Position{}}, nil return &Tree{values, Position{}}, nil
} }
if value.Kind() == reflect.Array || value.Kind() == reflect.Slice { if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
+12 -12
View File
@@ -1,9 +1,9 @@
package toml package toml
import ( import (
"strconv"
"testing" "testing"
"time" "time"
"strconv"
) )
type customString string type customString string
@@ -16,11 +16,11 @@ func (s stringer) String() string {
func validate(t *testing.T, path string, object interface{}) { func validate(t *testing.T, path string, object interface{}) {
switch o := object.(type) { switch o := object.(type) {
case *TomlTree: case *Tree:
for key, tree := range o.values { for key, tree := range o.values {
validate(t, path+"."+key, tree) validate(t, path+"."+key, tree)
} }
case []*TomlTree: case []*Tree:
for index, tree := range o { for index, tree := range o {
validate(t, path+"."+strconv.Itoa(index), tree) validate(t, path+"."+strconv.Itoa(index), tree)
} }
@@ -37,11 +37,11 @@ func validate(t *testing.T, path string, object interface{}) {
t.Logf("validation ok %s as %T", path, object) t.Logf("validation ok %s as %T", path, object)
} }
func validateTree(t *testing.T, tree *TomlTree) { func validateTree(t *testing.T, tree *Tree) {
validate(t, "", tree) validate(t, "", tree)
} }
func TestTomlTreeCreateToTree(t *testing.T) { func TestTreeCreateToTree(t *testing.T) {
data := map[string]interface{}{ data := map[string]interface{}{
"a_string": "bar", "a_string": "bar",
"an_int": 42, "an_int": 42,
@@ -72,15 +72,15 @@ func TestTomlTreeCreateToTree(t *testing.T) {
validateTree(t, tree) validateTree(t, tree)
} }
func TestTomlTreeCreateToTreeInvalidLeafType(t *testing.T) { func TestTreeCreateToTreeInvalidLeafType(t *testing.T) {
_, err := TreeFromMap(map[string]interface{}{"foo": t}) _, err := TreeFromMap(map[string]interface{}{"foo": t})
expected := "cannot convert type *testing.T to TomlTree" expected := "cannot convert type *testing.T to Tree"
if err.Error() != expected { if err.Error() != expected {
t.Fatalf("expected error %s, got %s", expected, err.Error()) t.Fatalf("expected error %s, got %s", expected, err.Error())
} }
} }
func TestTomlTreeCreateToTreeInvalidMapKeyType(t *testing.T) { func TestTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
_, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}}) _, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}})
expected := "map key needs to be a string, not int (int)" expected := "map key needs to be a string, not int (int)"
if err.Error() != expected { if err.Error() != expected {
@@ -88,17 +88,17 @@ func TestTomlTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
} }
} }
func TestTomlTreeCreateToTreeInvalidArrayMemberType(t *testing.T) { func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) {
_, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}}) _, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}})
expected := "cannot convert type *testing.T to TomlTree" expected := "cannot convert type *testing.T to Tree"
if err.Error() != expected { if err.Error() != expected {
t.Fatalf("expected error %s, got %s", expected, err.Error()) t.Fatalf("expected error %s, got %s", expected, err.Error())
} }
} }
func TestTomlTreeCreateToTreeInvalidTableGroupType(t *testing.T) { func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) {
_, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}}) _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}})
expected := "cannot convert type *testing.T to TomlTree" expected := "cannot convert type *testing.T to Tree"
if err.Error() != expected { if err.Error() != expected {
t.Fatalf("expected error %s, got %s", expected, err.Error()) t.Fatalf("expected error %s, got %s", expected, err.Error())
} }
+12 -12
View File
@@ -4,11 +4,11 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"reflect"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"reflect"
) )
// encodes a string to a TOML-compliant string value // encodes a string to a TOML-compliant string value
@@ -83,14 +83,14 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
return "", fmt.Errorf("unsupported value type %T: %v", v, v) return "", fmt.Errorf("unsupported value type %T: %v", v, v)
} }
func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) { func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
simpleValuesKeys := make([]string, 0) simpleValuesKeys := make([]string, 0)
complexValuesKeys := make([]string, 0) complexValuesKeys := make([]string, 0)
for k := range t.values { for k := range t.values {
v := t.values[k] v := t.values[k]
switch v.(type) { switch v.(type) {
case *TomlTree, []*TomlTree: case *Tree, []*Tree:
complexValuesKeys = append(complexValuesKeys, k) complexValuesKeys = append(complexValuesKeys, k)
default: default:
simpleValuesKeys = append(simpleValuesKeys, k) simpleValuesKeys = append(simpleValuesKeys, k)
@@ -129,7 +129,7 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
switch node := v.(type) { switch node := v.(type) {
// node has to be of those two types given how keys are sorted above // node has to be of those two types given how keys are sorted above
case *TomlTree: case *Tree:
tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey) tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
writtenBytesCount, err := w.Write([]byte(tableName)) writtenBytesCount, err := w.Write([]byte(tableName))
bytesCount += int64(writtenBytesCount) bytesCount += int64(writtenBytesCount)
@@ -140,7 +140,7 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
} }
case []*TomlTree: case []*Tree:
for _, subTree := range node { for _, subTree := range node {
if len(subTree.values) > 0 { if len(subTree.values) > 0 {
tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey) tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
@@ -162,16 +162,16 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
return bytesCount, nil return bytesCount, nil
} }
// WriteTo encode the TomlTree as Toml and writes it to the writer w. // WriteTo encode the Tree as Toml and writes it to the writer w.
// Returns the number of bytes written in case of success, or an error if anything happened. // Returns the number of bytes written in case of success, or an error if anything happened.
func (t *TomlTree) WriteTo(w io.Writer) (int64, error) { func (t *Tree) WriteTo(w io.Writer) (int64, error) {
return t.writeTo(w, "", "", 0) return t.writeTo(w, "", "", 0)
} }
// ToTomlString generates a human-readable representation of the current tree. // ToTomlString generates a human-readable representation of the current tree.
// Output spans multiple lines, and is suitable for ingest by a TOML parser. // 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. // If the conversion cannot be performed, ToString returns a non-nil error.
func (t *TomlTree) ToTomlString() (string, error) { func (t *Tree) ToTomlString() (string, error) {
var buf bytes.Buffer var buf bytes.Buffer
_, err := t.WriteTo(&buf) _, err := t.WriteTo(&buf)
if err != nil { if err != nil {
@@ -182,7 +182,7 @@ func (t *TomlTree) ToTomlString() (string, error) {
// String generates a human-readable representation of the current tree. // String generates a human-readable representation of the current tree.
// Alias of ToString. Present to implement the fmt.Stringer interface. // Alias of ToString. Present to implement the fmt.Stringer interface.
func (t *TomlTree) String() string { func (t *Tree) String() string {
result, _ := t.ToTomlString() result, _ := t.ToTomlString()
return result return result
} }
@@ -196,18 +196,18 @@ func (t *TomlTree) String() string {
// * time.Time // * time.Time
// * map[string]interface{} (where interface{} is any of this list) // * map[string]interface{} (where interface{} is any of this list)
// * []interface{} (where interface{} is any of this list) // * []interface{} (where interface{} is any of this list)
func (t *TomlTree) ToMap() map[string]interface{} { func (t *Tree) ToMap() map[string]interface{} {
result := map[string]interface{}{} result := map[string]interface{}{}
for k, v := range t.values { for k, v := range t.values {
switch node := v.(type) { switch node := v.(type) {
case []*TomlTree: case []*Tree:
var array []interface{} var array []interface{}
for _, item := range node { for _, item := range node {
array = append(array, item.ToMap()) array = append(array, item.ToMap())
} }
result[k] = array result[k] = array
case *TomlTree: case *Tree:
result[k] = node.ToMap() result[k] = node.ToMap()
case *tomlValue: case *tomlValue:
result[k] = node.value result[k] = node.value
+16 -16
View File
@@ -40,7 +40,7 @@ func assertErrorString(t *testing.T, expected string, err error) {
} }
} }
func TestTomlTreeWriteToTomlString(t *testing.T) { func TestTreeWriteToTomlString(t *testing.T) {
toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" } toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
points = { x = 1, y = 2 }`) points = { x = 1, y = 2 }`)
@@ -63,7 +63,7 @@ points = { x = 1, y = 2 }`)
}) })
} }
func TestTomlTreeWriteToTomlStringSimple(t *testing.T) { func TestTreeWriteToTomlStringSimple(t *testing.T) {
tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n") tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n")
if err != nil { if err != nil {
t.Errorf("Test failed to parse: %v", err) t.Errorf("Test failed to parse: %v", err)
@@ -79,7 +79,7 @@ func TestTomlTreeWriteToTomlStringSimple(t *testing.T) {
} }
} }
func TestTomlTreeWriteToTomlStringKeysOrders(t *testing.T) { func TestTreeWriteToTomlStringKeysOrders(t *testing.T) {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
tree, _ := Load(` tree, _ := Load(`
foobar = true foobar = true
@@ -119,7 +119,7 @@ func testMaps(t *testing.T, actual, expected map[string]interface{}) {
} }
} }
func TestTomlTreeWriteToMapSimple(t *testing.T) { func TestTreeWriteToMapSimple(t *testing.T) {
tree, _ := Load("a = 42\nb = 17") tree, _ := Load("a = 42\nb = 17")
expected := map[string]interface{}{ expected := map[string]interface{}{
@@ -130,32 +130,32 @@ func TestTomlTreeWriteToMapSimple(t *testing.T) {
testMaps(t, tree.ToMap(), expected) testMaps(t, tree.ToMap(), expected)
} }
func TestTomlTreeWriteToInvalidTreeSimpleValue(t *testing.T) { func TestTreeWriteToInvalidTreeSimpleValue(t *testing.T) {
tree := TomlTree{values: map[string]interface{}{"foo": int8(1)}} tree := Tree{values: map[string]interface{}{"foo": int8(1)}}
_, err := tree.ToTomlString() _, err := tree.ToTomlString()
assertErrorString(t, "invalid value type at foo: int8", err) assertErrorString(t, "invalid value type at foo: int8", err)
} }
func TestTomlTreeWriteToInvalidTreeTomlValue(t *testing.T) { func TestTreeWriteToInvalidTreeTomlValue(t *testing.T) {
tree := TomlTree{values: map[string]interface{}{"foo": &tomlValue{int8(1), Position{}}}} tree := Tree{values: map[string]interface{}{"foo": &tomlValue{int8(1), Position{}}}}
_, err := tree.ToTomlString() _, err := tree.ToTomlString()
assertErrorString(t, "unsupported value type int8: 1", err) assertErrorString(t, "unsupported value type int8: 1", err)
} }
func TestTomlTreeWriteToInvalidTreeTomlValueArray(t *testing.T) { func TestTreeWriteToInvalidTreeTomlValueArray(t *testing.T) {
tree := TomlTree{values: map[string]interface{}{"foo": &tomlValue{[]interface{}{int8(1)}, Position{}}}} tree := Tree{values: map[string]interface{}{"foo": &tomlValue{[]interface{}{int8(1)}, Position{}}}}
_, err := tree.ToTomlString() _, err := tree.ToTomlString()
assertErrorString(t, "unsupported value type int8: 1", err) assertErrorString(t, "unsupported value type int8: 1", err)
} }
func TestTomlTreeWriteToFailingWriterInSimpleValue(t *testing.T) { func TestTreeWriteToFailingWriterInSimpleValue(t *testing.T) {
toml, _ := Load(`a = 2`) toml, _ := Load(`a = 2`)
writer := failingWriter{failAt: 0, written: 0} writer := failingWriter{failAt: 0, written: 0}
_, err := toml.WriteTo(writer) _, err := toml.WriteTo(writer)
assertErrorString(t, "failingWriter failed after writting 0 bytes", err) assertErrorString(t, "failingWriter failed after writting 0 bytes", err)
} }
func TestTomlTreeWriteToFailingWriterInTable(t *testing.T) { func TestTreeWriteToFailingWriterInTable(t *testing.T) {
toml, _ := Load(` toml, _ := Load(`
[b] [b]
a = 2`) a = 2`)
@@ -168,7 +168,7 @@ a = 2`)
assertErrorString(t, "failingWriter failed after writting 13 bytes", err) assertErrorString(t, "failingWriter failed after writting 13 bytes", err)
} }
func TestTomlTreeWriteToFailingWriterInArray(t *testing.T) { func TestTreeWriteToFailingWriterInArray(t *testing.T) {
toml, _ := Load(` toml, _ := Load(`
[[b]] [[b]]
a = 2`) a = 2`)
@@ -181,7 +181,7 @@ a = 2`)
assertErrorString(t, "failingWriter failed after writting 15 bytes", err) assertErrorString(t, "failingWriter failed after writting 15 bytes", err)
} }
func TestTomlTreeWriteToMapExampleFile(t *testing.T) { func TestTreeWriteToMapExampleFile(t *testing.T) {
tree, _ := LoadFile("example.toml") tree, _ := LoadFile("example.toml")
expected := map[string]interface{}{ expected := map[string]interface{}{
"title": "TOML Example", "title": "TOML Example",
@@ -217,7 +217,7 @@ func TestTomlTreeWriteToMapExampleFile(t *testing.T) {
testMaps(t, tree.ToMap(), expected) testMaps(t, tree.ToMap(), expected)
} }
func TestTomlTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) { func TestTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
tree, _ := Load(` tree, _ := Load(`
[[menu.main]] [[menu.main]]
a = "menu 1" a = "menu 1"
@@ -238,7 +238,7 @@ func TestTomlTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
testMaps(t, treeMap, expected) testMaps(t, treeMap, expected)
} }
func TestTomlTreeWriteToMapWithArrayOfInlineTables(t *testing.T) { func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) {
tree, _ := Load(` tree, _ := Load(`
[params] [params]
language_tabs = [ language_tabs = [