aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/pelletier
diff options
context:
space:
mode:
authorNiall Sheridan <nsheridan@gmail.com>2017-10-18 13:15:14 +0100
committerNiall Sheridan <niall@intercom.io>2017-10-18 13:25:46 +0100
commit7b320119ba532fd409ec7dade7ad02011c309599 (patch)
treea39860f35b55e6cc499f8f5bfa969138c5dd6b73 /vendor/github.com/pelletier
parent7c99874c7a3e7a89716f3ee0cdf696532e35ae35 (diff)
Update dependencies
Diffstat (limited to 'vendor/github.com/pelletier')
-rw-r--r--vendor/github.com/pelletier/go-toml/README.md85
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.json164
-rwxr-xr-xvendor/github.com/pelletier/go-toml/benchmark.sh32
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.toml244
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.yml121
-rwxr-xr-xvendor/github.com/pelletier/go-toml/clean.sh6
-rw-r--r--vendor/github.com/pelletier/go-toml/doc.go251
-rw-r--r--vendor/github.com/pelletier/go-toml/lexer.go88
-rw-r--r--vendor/github.com/pelletier/go-toml/marshal.go125
-rw-r--r--vendor/github.com/pelletier/go-toml/match.go234
-rw-r--r--vendor/github.com/pelletier/go-toml/parser.go72
-rw-r--r--vendor/github.com/pelletier/go-toml/query.go153
-rw-r--r--vendor/github.com/pelletier/go-toml/querylexer.go356
-rw-r--r--vendor/github.com/pelletier/go-toml/queryparser.go275
-rwxr-xr-xvendor/github.com/pelletier/go-toml/test.sh10
-rw-r--r--vendor/github.com/pelletier/go-toml/toml.go144
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_create.go31
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_write.go145
18 files changed, 971 insertions, 1565 deletions
diff --git a/vendor/github.com/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md
index b8137e0..2681690 100644
--- a/vendor/github.com/pelletier/go-toml/README.md
+++ b/vendor/github.com/pelletier/go-toml/README.md
@@ -16,65 +16,64 @@ This library supports TOML version
Go-toml provides the following features for using data parsed from TOML documents:
* Load TOML documents from files and string data
-* Easily navigate TOML structure using TomlTree
+* Easily navigate TOML structure using Tree
+* Mashaling and unmarshaling to and from data structures
* Line & column position data for all parsed elements
-* Query support similar to JSON-Path
+* [Query support similar to JSON-Path](query/)
* Syntax errors contain line and column numbers
-Go-toml is designed to help cover use-cases not covered by reflection-based TOML parsing:
+## Import
-* Semantic evaluation of parsed TOML
-* Informing a user of mistakes in the source document, after it has been parsed
-* Programatic handling of default values on a case-by-case basis
-* Using a TOML document as a flexible data-store
+```go
+import "github.com/pelletier/go-toml"
+```
-## Import
+## Usage example
- import "github.com/pelletier/go-toml"
+Read a TOML document:
-## Usage
+```go
+config, _ := toml.Load(`
+[postgres]
+user = "pelletier"
+password = "mypassword"`)
+// retrieve data directly
+user := config.Get("postgres.user").(string)
-### Example
+// or using an intermediate object
+postgresConfig := config.Get("postgres").(*toml.Tree)
+password := postgresConfig.Get("password").(string)
+```
+
+Or use Unmarshal:
-Say you have a TOML file that looks like this:
+```go
+type Postgres struct {
+ User string
+ Password string
+}
+type Config struct {
+ Postgres Postgres
+}
-```toml
+doc := []byte(`
[postgres]
user = "pelletier"
-password = "mypassword"
+password = "mypassword"`)
+
+config := Config{}
+toml.Unmarshal(doc, &config)
+fmt.Println("user=", config.Postgres.User)
```
-Read the username and password like this:
+Or use a query:
```go
-import (
- "fmt"
- "github.com/pelletier/go-toml"
-)
-
-config, err := toml.LoadFile("config.toml")
-if err != nil {
- fmt.Println("Error ", err.Error())
-} else {
- // retrieve data directly
- user := config.Get("postgres.user").(string)
- password := config.Get("postgres.password").(string)
-
- // or using an intermediate object
- configTree := config.Get("postgres").(*toml.TomlTree)
- user = configTree.Get("user").(string)
- password = configTree.Get("password").(string)
- fmt.Println("User is ", user, ". Password is ", password)
-
- // show where elements are in the file
- fmt.Println("User position: %v", configTree.GetPosition("user"))
- fmt.Println("Password position: %v", configTree.GetPosition("password"))
-
- // use a query to gather elements without walking the tree
- results, _ := config.Query("$..[user,password]")
- for ii, item := range results.Values() {
- fmt.Println("Query result %d: %v", ii, item)
- }
+// use a query to gather elements without walking the tree
+q, _ := query.Compile("$..[user,password]")
+results := q.Execute(config)
+for ii, item := range results.Values() {
+ fmt.Println("Query result %d: %v", ii, item)
}
```
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.json b/vendor/github.com/pelletier/go-toml/benchmark.json
new file mode 100644
index 0000000..86f99c6
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/benchmark.json
@@ -0,0 +1,164 @@
+{
+ "array": {
+ "key1": [
+ 1,
+ 2,
+ 3
+ ],
+ "key2": [
+ "red",
+ "yellow",
+ "green"
+ ],
+ "key3": [
+ [
+ 1,
+ 2
+ ],
+ [
+ 3,
+ 4,
+ 5
+ ]
+ ],
+ "key4": [
+ [
+ 1,
+ 2
+ ],
+ [
+ "a",
+ "b",
+ "c"
+ ]
+ ],
+ "key5": [
+ 1,
+ 2,
+ 3
+ ],
+ "key6": [
+ 1,
+ 2
+ ]
+ },
+ "boolean": {
+ "False": false,
+ "True": true
+ },
+ "datetime": {
+ "key1": "1979-05-27T07:32:00Z",
+ "key2": "1979-05-27T00:32:00-07:00",
+ "key3": "1979-05-27T00:32:00.999999-07:00"
+ },
+ "float": {
+ "both": {
+ "key": 6.626e-34
+ },
+ "exponent": {
+ "key1": 5e+22,
+ "key2": 1000000,
+ "key3": -0.02
+ },
+ "fractional": {
+ "key1": 1,
+ "key2": 3.1415,
+ "key3": -0.01
+ },
+ "underscores": {
+ "key1": 9224617.445991227,
+ "key2": 1e+100
+ }
+ },
+ "fruit": [{
+ "name": "apple",
+ "physical": {
+ "color": "red",
+ "shape": "round"
+ },
+ "variety": [{
+ "name": "red delicious"
+ },
+ {
+ "name": "granny smith"
+ }
+ ]
+ },
+ {
+ "name": "banana",
+ "variety": [{
+ "name": "plantain"
+ }]
+ }
+ ],
+ "integer": {
+ "key1": 99,
+ "key2": 42,
+ "key3": 0,
+ "key4": -17,
+ "underscores": {
+ "key1": 1000,
+ "key2": 5349221,
+ "key3": 12345
+ }
+ },
+ "products": [{
+ "name": "Hammer",
+ "sku": 738594937
+ },
+ {},
+ {
+ "color": "gray",
+ "name": "Nail",
+ "sku": 284758393
+ }
+ ],
+ "string": {
+ "basic": {
+ "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
+ },
+ "literal": {
+ "multiline": {
+ "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n",
+ "regex2": "I [dw]on't need \\d{2} apples"
+ },
+ "quoted": "Tom \"Dubs\" Preston-Werner",
+ "regex": "\u003c\\i\\c*\\s*\u003e",
+ "winpath": "C:\\Users\\nodejs\\templates",
+ "winpath2": "\\\\ServerX\\admin$\\system32\\"
+ },
+ "multiline": {
+ "continued": {
+ "key1": "The quick brown fox jumps over the lazy dog.",
+ "key2": "The quick brown fox jumps over the lazy dog.",
+ "key3": "The quick brown fox jumps over the lazy dog."
+ },
+ "key1": "One\nTwo",
+ "key2": "One\nTwo",
+ "key3": "One\nTwo"
+ }
+ },
+ "table": {
+ "inline": {
+ "name": {
+ "first": "Tom",
+ "last": "Preston-Werner"
+ },
+ "point": {
+ "x": 1,
+ "y": 2
+ }
+ },
+ "key": "value",
+ "subtable": {
+ "key": "another value"
+ }
+ },
+ "x": {
+ "y": {
+ "z": {
+ "w": {}
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh
new file mode 100755
index 0000000..8b8bb52
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/benchmark.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+reference_ref=${1:-master}
+reference_git=${2:-.}
+
+if ! `hash benchstat 2>/dev/null`; then
+ echo "Installing benchstat"
+ go get golang.org/x/perf/cmd/benchstat
+ go install golang.org/x/perf/cmd/benchstat
+fi
+
+tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX`
+ref_tempdir="${tempdir}/ref"
+ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt"
+local_benchmark="`pwd`/benchmark-local.txt"
+
+echo "=== ${reference_ref} (${ref_tempdir})"
+git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null
+pushd ${ref_tempdir} >/dev/null
+git checkout ${reference_ref} >/dev/null 2>/dev/null
+go test -bench=. -benchmem | tee ${ref_benchmark}
+popd >/dev/null
+
+echo ""
+echo "=== local"
+go test -bench=. -benchmem | tee ${local_benchmark}
+
+echo ""
+echo "=== diff"
+benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} \ No newline at end of file
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml
new file mode 100644
index 0000000..dfd77e0
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/benchmark.toml
@@ -0,0 +1,244 @@
+################################################################################
+## Comment
+
+# Speak your mind with the hash symbol. They go from the symbol to the end of
+# the line.
+
+
+################################################################################
+## Table
+
+# Tables (also known as hash tables or dictionaries) are collections of
+# key/value pairs. They appear in square brackets on a line by themselves.
+
+[table]
+
+key = "value" # Yeah, you can do this.
+
+# Nested tables are denoted by table names with dots in them. Name your tables
+# whatever crap you please, just don't use #, ., [ or ].
+
+[table.subtable]
+
+key = "another value"
+
+# You don't need to specify all the super-tables if you don't want to. TOML
+# knows how to do it for you.
+
+# [x] you
+# [x.y] don't
+# [x.y.z] need these
+[x.y.z.w] # for this to work
+
+
+################################################################################
+## Inline Table
+
+# Inline tables provide a more compact syntax for expressing tables. They are
+# especially useful for grouped data that can otherwise quickly become verbose.
+# Inline tables are enclosed in curly braces `{` and `}`. No newlines are
+# allowed between the curly braces unless they are valid within a value.
+
+[table.inline]
+
+name = { first = "Tom", last = "Preston-Werner" }
+point = { x = 1, y = 2 }
+
+
+################################################################################
+## String
+
+# There are four ways to express strings: basic, multi-line basic, literal, and
+# multi-line literal. All strings must contain only valid UTF-8 characters.
+
+[string.basic]
+
+basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+[string.multiline]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "One\nTwo"
+key2 = """One\nTwo"""
+key3 = """
+One
+Two"""
+
+[string.multiline.continued]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "The quick brown fox jumps over the lazy dog."
+
+key2 = """
+The quick brown \
+
+
+ fox jumps over \
+ the lazy dog."""
+
+key3 = """\
+ The quick brown \
+ fox jumps over \
+ the lazy dog.\
+ """
+
+[string.literal]
+
+# What you see is what you get.
+winpath = 'C:\Users\nodejs\templates'
+winpath2 = '\\ServerX\admin$\system32\'
+quoted = 'Tom "Dubs" Preston-Werner'
+regex = '<\i\c*\s*>'
+
+
+[string.literal.multiline]
+
+regex2 = '''I [dw]on't need \d{2} apples'''
+lines = '''
+The first newline is
+trimmed in raw strings.
+ All other whitespace
+ is preserved.
+'''
+
+
+################################################################################
+## Integer
+
+# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
+# Negative numbers are prefixed with a minus sign.
+
+[integer]
+
+key1 = +99
+key2 = 42
+key3 = 0
+key4 = -17
+
+[integer.underscores]
+
+# For large numbers, you may use underscores to enhance readability. Each
+# underscore must be surrounded by at least one digit.
+key1 = 1_000
+key2 = 5_349_221
+key3 = 1_2_3_4_5 # valid but inadvisable
+
+
+################################################################################
+## Float
+
+# A float consists of an integer part (which may be prefixed with a plus or
+# minus sign) followed by a fractional part and/or an exponent part.
+
+[float.fractional]
+
+key1 = +1.0
+key2 = 3.1415
+key3 = -0.01
+
+[float.exponent]
+
+key1 = 5e+22
+key2 = 1e6
+key3 = -2E-2
+
+[float.both]
+
+key = 6.626e-34
+
+[float.underscores]
+
+key1 = 9_224_617.445_991_228_313
+key2 = 1e1_00
+
+
+################################################################################
+## Boolean
+
+# Booleans are just the tokens you're used to. Always lowercase.
+
+[boolean]
+
+True = true
+False = false
+
+
+################################################################################
+## Datetime
+
+# Datetimes are RFC 3339 dates.
+
+[datetime]
+
+key1 = 1979-05-27T07:32:00Z
+key2 = 1979-05-27T00:32:00-07:00
+key3 = 1979-05-27T00:32:00.999999-07:00
+
+
+################################################################################
+## Array
+
+# Arrays are square brackets with other primitives inside. Whitespace is
+# ignored. Elements are separated by commas. Data types may not be mixed.
+
+[array]
+
+key1 = [ 1, 2, 3 ]
+key2 = [ "red", "yellow", "green" ]
+key3 = [ [ 1, 2 ], [3, 4, 5] ]
+#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
+
+# Arrays can also be multiline. So in addition to ignoring whitespace, arrays
+# also ignore newlines between the brackets. Terminating commas are ok before
+# the closing bracket.
+
+key5 = [
+ 1, 2, 3
+]
+key6 = [
+ 1,
+ 2, # this is ok
+]
+
+
+################################################################################
+## Array of Tables
+
+# These can be expressed by using a table name in double brackets. Each table
+# with the same double bracketed name will be an element in the array. The
+# tables are inserted in the order encountered.
+
+[[products]]
+
+name = "Hammer"
+sku = 738594937
+
+[[products]]
+
+[[products]]
+
+name = "Nail"
+sku = 284758393
+color = "gray"
+
+
+# You can create nested arrays of tables as well.
+
+[[fruit]]
+ name = "apple"
+
+ [fruit.physical]
+ color = "red"
+ shape = "round"
+
+ [[fruit.variety]]
+ name = "red delicious"
+
+ [[fruit.variety]]
+ name = "granny smith"
+
+[[fruit]]
+ name = "banana"
+
+ [[fruit.variety]]
+ name = "plantain"
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.yml b/vendor/github.com/pelletier/go-toml/benchmark.yml
new file mode 100644
index 0000000..0bd19f0
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/benchmark.yml
@@ -0,0 +1,121 @@
+---
+array:
+ key1:
+ - 1
+ - 2
+ - 3
+ key2:
+ - red
+ - yellow
+ - green
+ key3:
+ - - 1
+ - 2
+ - - 3
+ - 4
+ - 5
+ key4:
+ - - 1
+ - 2
+ - - a
+ - b
+ - c
+ key5:
+ - 1
+ - 2
+ - 3
+ key6:
+ - 1
+ - 2
+boolean:
+ 'False': false
+ 'True': true
+datetime:
+ key1: '1979-05-27T07:32:00Z'
+ key2: '1979-05-27T00:32:00-07:00'
+ key3: '1979-05-27T00:32:00.999999-07:00'
+float:
+ both:
+ key: 6.626e-34
+ exponent:
+ key1: 5.0e+22
+ key2: 1000000
+ key3: -0.02
+ fractional:
+ key1: 1
+ key2: 3.1415
+ key3: -0.01
+ underscores:
+ key1: 9224617.445991227
+ key2: 1.0e+100
+fruit:
+- name: apple
+ physical:
+ color: red
+ shape: round
+ variety:
+ - name: red delicious
+ - name: granny smith
+- name: banana
+ variety:
+ - name: plantain
+integer:
+ key1: 99
+ key2: 42
+ key3: 0
+ key4: -17
+ underscores:
+ key1: 1000
+ key2: 5349221
+ key3: 12345
+products:
+- name: Hammer
+ sku: 738594937
+- {}
+- color: gray
+ name: Nail
+ sku: 284758393
+string:
+ basic:
+ basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
+ literal:
+ multiline:
+ lines: |
+ The first newline is
+ trimmed in raw strings.
+ All other whitespace
+ is preserved.
+ regex2: I [dw]on't need \d{2} apples
+ quoted: Tom "Dubs" Preston-Werner
+ regex: "<\\i\\c*\\s*>"
+ winpath: C:\Users\nodejs\templates
+ winpath2: "\\\\ServerX\\admin$\\system32\\"
+ multiline:
+ continued:
+ key1: The quick brown fox jumps over the lazy dog.
+ key2: The quick brown fox jumps over the lazy dog.
+ key3: The quick brown fox jumps over the lazy dog.
+ key1: |-
+ One
+ Two
+ key2: |-
+ One
+ Two
+ key3: |-
+ One
+ Two
+table:
+ inline:
+ name:
+ first: Tom
+ last: Preston-Werner
+ point:
+ x: 1
+ y: 2
+ key: value
+ subtable:
+ key: another value
+x:
+ y:
+ z:
+ w: {}
diff --git a/vendor/github.com/pelletier/go-toml/clean.sh b/vendor/github.com/pelletier/go-toml/clean.sh
deleted file mode 100755
index 44d49d9..0000000
--- a/vendor/github.com/pelletier/go-toml/clean.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-# fail out of the script if anything here fails
-set -e
-
-# clear out stuff generated by test.sh
-rm -rf src test_program_bin toml-test
diff --git a/vendor/github.com/pelletier/go-toml/doc.go b/vendor/github.com/pelletier/go-toml/doc.go
index 9156b73..3c89619 100644
--- a/vendor/github.com/pelletier/go-toml/doc.go
+++ b/vendor/github.com/pelletier/go-toml/doc.go
@@ -1,250 +1,23 @@
-// Package toml is a TOML markup language parser.
+// Package toml is a TOML parser and manipulation library.
//
// This version supports the specification as described in
// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md
//
-// TOML Parsing
+// Marshaling
//
-// TOML data may be parsed in two ways: by file, or by string.
+// Go-toml can marshal and unmarshal TOML documents from and to data
+// structures.
//
-// // load TOML data by filename
-// tree, err := toml.LoadFile("filename.toml")
+// TOML document as a tree
//
-// // load TOML data stored in a string
-// tree, err := toml.Load(stringContainingTomlData)
+// Go-toml can operate on a TOML document as a tree. Use one of the Load*
+// functions to parse TOML data and obtain a Tree instance, then one of its
+// methods to manipulate the tree.
//
-// Either way, the result is a TomlTree object that can be used to navigate the
-// structure and data within the original document.
+// JSONPath-like queries
//
-//
-// Getting data from the TomlTree
-//
-// 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.
-//
-// if tree.Has("foo") {
-// fmt.Println("foo is:", tree.Get("foo"))
-// }
-//
-// Working with Paths
-//
-// Go-toml has support for basic dot-separated key paths on the Has(), Get(), Set()
-// and GetDefault() methods. These are the same kind of key paths used within the
-// TOML specification for struct tames.
-//
-// // looks for a key named 'baz', within struct 'bar', within struct 'foo'
-// tree.Has("foo.bar.baz")
-//
-// // returns the key at this path, if it is there
-// tree.Get("foo.bar.baz")
-//
-// TOML allows keys to contain '.', which can cause this syntax to be problematic
-// for some documents. In such cases, use the GetPath(), HasPath(), and SetPath(),
-// methods to explicitly define the path. This form is also faster, since
-// it avoids having to parse the passed key for '.' delimiters.
-//
-// // looks for a key named 'baz', within struct 'bar', within struct 'foo'
-// tree.HasPath([]string{"foo","bar","baz"})
-//
-// // returns the key at this path, if it is there
-// tree.GetPath([]string{"foo","bar","baz"})
-//
-// Note that this is distinct from the heavyweight query syntax supported by
-// TomlTree.Query() and the Query() struct (see below).
-//
-// Position Support
-//
-// Each element within the TomlTree is stored with position metadata, which is
-// invaluable for providing semantic feedback to a user. This helps in
-// 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
-// generated that indicates the problem line and column number in the source
-// TOML document.
-//
-// // load TOML data
-// tree, _ := toml.Load("filename.toml")
-//
-// // get an entry and report an error if it's the wrong type
-// element := tree.Get("foo")
-// if value, ok := element.(int64); !ok {
-// return fmt.Errorf("%v: Element 'foo' must be an integer", tree.GetPosition("foo"))
-// }
-//
-// // report an error if an expected element is missing
-// if !tree.Has("bar") {
-// return fmt.Errorf("%v: Expected 'bar' element", tree.GetPosition(""))
-// }
-//
-// Query Support
-//
-// The TOML query path implementation is based loosely on the JSONPath specification:
-// http://goessner.net/articles/JsonPath/
-//
-// The idea behind a query path is to allow quick access to any element, or set
-// of elements within TOML document, with a single expression.
-//
-// result, err := tree.Query("$.foo.bar.baz")
-//
-// This is roughly equivalent to:
-//
-// next := tree.Get("foo")
-// if next != nil {
-// next = next.Get("bar")
-// if next != nil {
-// next = next.Get("baz")
-// }
-// }
-// result := next
-//
-// err is nil if any parsing exception occurs.
-//
-// If no node in the tree matches the query, result will simply contain an empty list of
-// items.
-//
-// As illustrated above, the query path is much more efficient, especially since
-// the structure of the TOML file can vary. Rather than making assumptions about
-// a document's structure, a query allows the programmer to make structured
-// requests into the document, and get zero or more values as a result.
-//
-// The syntax of a query begins with a root token, followed by any number
-// sub-expressions:
-//
-// $
-// Root of the TOML tree. This must always come first.
-// .name
-// Selects child of this node, where 'name' is a TOML key
-// name.
-// ['name']
-// Selects child of this node, where 'name' is a string
-// containing a TOML key name.
-// [index]
-// Selcts child array element at 'index'.
-// ..expr
-// Recursively selects all children, filtered by an a union,
-// index, or slice expression.
-// ..*
-// Recursive selection of all nodes at this point in the
-// tree.
-// .*
-// Selects all children of the current node.
-// [expr,expr]
-// Union operator - a logical 'or' grouping of two or more
-// sub-expressions: index, key name, or filter.
-// [start:end:step]
-// Slice operator - selects array elements from start to
-// end-1, at the given step. All three arguments are
-// optional.
-// [?(filter)]
-// Named filter expression - the function 'filter' is
-// used to filter children at this node.
-//
-// Query Indexes And Slices
-//
-// Index expressions perform no bounds checking, and will contribute no
-// values to the result set if the provided index or index range is invalid.
-// Negative indexes represent values from the end of the array, counting backwards.
-//
-// // select the last index of the array named 'foo'
-// tree.Query("$.foo[-1]")
-//
-// Slice expressions are supported, by using ':' to separate a start/end index pair.
-//
-// // select up to the first five elements in the array
-// tree.Query("$.foo[0:5]")
-//
-// Slice expressions also allow negative indexes for the start and stop
-// arguments.
-//
-// // select all array elements.
-// tree.Query("$.foo[0:-1]")
-//
-// Slice expressions may have an optional stride/step parameter:
-//
-// // select every other element
-// tree.Query("$.foo[0:-1:2]")
-//
-// Slice start and end parameters are also optional:
-//
-// // these are all equivalent and select all the values in the array
-// tree.Query("$.foo[:]")
-// tree.Query("$.foo[0:]")
-// tree.Query("$.foo[:-1]")
-// tree.Query("$.foo[0:-1:]")
-// tree.Query("$.foo[::1]")
-// tree.Query("$.foo[0::1]")
-// tree.Query("$.foo[:-1:1]")
-// tree.Query("$.foo[0:-1:1]")
-//
-// Query Filters
-//
-// Query filters are used within a Union [,] or single Filter [] expression.
-// A filter only allows nodes that qualify through to the next expression,
-// and/or into the result set.
-//
-// // returns children of foo that are permitted by the 'bar' filter.
-// tree.Query("$.foo[?(bar)]")
-//
-// There are several filters provided with the library:
-//
-// tree
-// Allows nodes of type TomlTree.
-// int
-// Allows nodes of type int64.
-// float
-// Allows nodes of type float64.
-// string
-// Allows nodes of type string.
-// time
-// Allows nodes of type time.Time.
-// bool
-// Allows nodes of type bool.
-//
-// Query Results
-//
-// An executed query returns a QueryResult object. This contains the nodes
-// in the TOML tree that qualify the query expression. Position information
-// is also available for each value in the set.
-//
-// // display the results of a query
-// results := tree.Query("$.foo.bar.baz")
-// for idx, value := results.Values() {
-// fmt.Println("%v: %v", results.Positions()[idx], value)
-// }
-//
-// Compiled Queries
-//
-// Queries may be executed directly on a TomlTree object, or compiled ahead
-// of time and executed discretely. The former is more convienent, but has the
-// penalty of having to recompile the query expression each time.
-//
-// // basic query
-// results := tree.Query("$.foo.bar.baz")
-//
-// // compiled query
-// query := toml.CompileQuery("$.foo.bar.baz")
-// results := query.Execute(tree)
-//
-// // run the compiled query again on a different tree
-// moreResults := query.Execute(anotherTree)
-//
-// User Defined Query Filters
-//
-// Filter expressions may also be user defined by using the SetFilter()
-// function on the Query object. The function must return true/false, which
-// signifies if the passed node is kept or discarded, respectively.
-//
-// // create a query that references a user-defined filter
-// query, _ := CompileQuery("$[?(bazOnly)]")
-//
-// // define the filter, and assign it to the query
-// query.SetFilter("bazOnly", func(node interface{}) bool{
-// if tree, ok := node.(*TomlTree); ok {
-// return tree.Has("baz")
-// }
-// return false // reject all other node types
-// })
-//
-// // run the query
-// query.Execute(tree)
+// The package github.com/pelletier/go-toml/query implements a system
+// similar to JSONPath to quickly retrive elements of a TOML document using a
+// single expression. See the package documentation for more information.
//
package toml
diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go
index 104f3b1..1b6647d 100644
--- a/vendor/github.com/pelletier/go-toml/lexer.go
+++ b/vendor/github.com/pelletier/go-toml/lexer.go
@@ -6,14 +6,12 @@
package toml
import (
+ "bytes"
"errors"
"fmt"
- "io"
"regexp"
"strconv"
"strings"
-
- "github.com/pelletier/go-buffruneio"
)
var dateRegexp *regexp.Regexp
@@ -23,29 +21,29 @@ type tomlLexStateFn func() tomlLexStateFn
// Define lexer
type tomlLexer struct {
- input *buffruneio.Reader // Textual source
- buffer []rune // Runes composing the current token
- tokens chan token
- depth int
- line int
- col int
- endbufferLine int
- endbufferCol int
+ inputIdx int
+ input []rune // Textual source
+ currentTokenStart int
+ currentTokenStop int
+ tokens []token
+ depth int
+ line int
+ col int
+ endbufferLine int
+ endbufferCol int
}
// Basic read operations on input
func (l *tomlLexer) read() rune {
- r, _, err := l.input.ReadRune()
- if err != nil {
- panic(err)
- }
+ r := l.peek()
if r == '\n' {
l.endbufferLine++
l.endbufferCol = 1
} else {
l.endbufferCol++
}
+ l.inputIdx++
return r
}
@@ -53,13 +51,13 @@ func (l *tomlLexer) next() rune {
r := l.read()
if r != eof {
- l.buffer = append(l.buffer, r)
+ l.currentTokenStop++
}
return r
}
func (l *tomlLexer) ignore() {
- l.buffer = make([]rune, 0)
+ l.currentTokenStart = l.currentTokenStop
l.line = l.endbufferLine
l.col = l.endbufferCol
}
@@ -76,49 +74,46 @@ func (l *tomlLexer) fastForward(n int) {
}
func (l *tomlLexer) emitWithValue(t tokenType, value string) {
- l.tokens <- token{
+ l.tokens = append(l.tokens, token{
Position: Position{l.line, l.col},
typ: t,
val: value,
- }
+ })
l.ignore()
}
func (l *tomlLexer) emit(t tokenType) {
- l.emitWithValue(t, string(l.buffer))
+ l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop]))
}
func (l *tomlLexer) peek() rune {
- r, _, err := l.input.ReadRune()
- if err != nil {
- panic(err)
+ if l.inputIdx >= len(l.input) {
+ return eof
}
- l.input.UnreadRune()
- return r
+ return l.input[l.inputIdx]
}
-func (l *tomlLexer) follow(next string) bool {
- for _, expectedRune := range next {
- r, _, err := l.input.ReadRune()
- defer l.input.UnreadRune()
- if err != nil {
- panic(err)
- }
- if expectedRune != r {
- return false
- }
+func (l *tomlLexer) peekString(size int) string {
+ maxIdx := len(l.input)
+ upperIdx := l.inputIdx + size // FIXME: potential overflow
+ if upperIdx > maxIdx {
+ upperIdx = maxIdx
}
- return true
+ return string(l.input[l.inputIdx:upperIdx])
+}
+
+func (l *tomlLexer) follow(next string) bool {
+ return next == l.peekString(len(next))
}
// Error management
func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn {
- l.tokens <- token{
+ l.tokens = append(l.tokens, token{
Position: Position{l.line, l.col},
typ: tokenError,
val: fmt.Sprintf(format, args...),
- }
+ })
return nil
}
@@ -219,7 +214,7 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn {
break
}
- possibleDate := string(l.input.PeekRunes(35))
+ possibleDate := l.peekString(35)
dateMatch := dateRegexp.FindString(possibleDate)
if dateMatch != "" {
l.fastForward(len(dateMatch))
@@ -536,7 +531,7 @@ func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() {
switch r {
case ']':
- if len(l.buffer) > 0 {
+ if l.currentTokenStop > l.currentTokenStart {
l.emit(tokenKeyGroupArray)
}
l.next()
@@ -559,7 +554,7 @@ func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() {
switch r {
case ']':
- if len(l.buffer) > 0 {
+ if l.currentTokenStop > l.currentTokenStart {
l.emit(tokenKeyGroup)
}
l.next()
@@ -634,7 +629,6 @@ func (l *tomlLexer) run() {
for state := l.lexVoid; state != nil; {
state = state()
}
- close(l.tokens)
}
func init() {
@@ -642,16 +636,16 @@ func init() {
}
// Entry point
-func lexToml(input io.Reader) chan token {
- bufferedInput := buffruneio.NewReader(input)
+func lexToml(inputBytes []byte) []token {
+ runes := bytes.Runes(inputBytes)
l := &tomlLexer{
- input: bufferedInput,
- tokens: make(chan token),
+ input: runes,
+ tokens: make([]token, 0, 256),
line: 1,
col: 1,
endbufferLine: 1,
endbufferCol: 1,
}
- go l.run()
+ l.run()
return l.tokens
}
diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go
index a1d7010..ce3bd8d 100644
--- a/vendor/github.com/pelletier/go-toml/marshal.go
+++ b/vendor/github.com/pelletier/go-toml/marshal.go
@@ -1,33 +1,19 @@
package toml
import (
+ "bytes"
"errors"
"fmt"
"reflect"
+ "strconv"
"strings"
"time"
)
-/*
-TomlTree structural types and corresponding marshal types
--------------------------------------------------------------------------------
-*TomlTree (*)struct, (*)map[string]interface{}
-[]*TomlTree (*)[](*)struct, (*)[](*)map[string]interface{}
-[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
-interface{} (*)primitive
-
-TomlTree primitive types and corresponding marshal types
------------------------------------------------------------
-uint64 uint, uint8-uint64, pointers to same
-int64 int, int8-uint64, pointers to same
-float64 float32, float64, pointers to same
-string string, pointers to same
-bool bool, pointers to same
-time.Time time.Time{}, pointers to same
-*/
-
type tomlOpts struct {
name string
+ comment string
+ commented bool
include bool
omitempty bool
}
@@ -35,7 +21,7 @@ type tomlOpts struct {
var timeType = reflect.TypeOf(time.Time{})
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 {
switch mtype.Kind() {
case reflect.Ptr:
@@ -57,7 +43,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 {
switch mtype.Kind() {
case reflect.Slice:
@@ -67,7 +53,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 {
switch mtype.Kind() {
case reflect.Ptr:
@@ -79,7 +65,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 {
switch mtype.Kind() {
case reflect.Map:
@@ -111,9 +97,32 @@ encoder, except that there is no concept of a Marshaler interface or MarshalTOML
function for sub-structs, and currently only definite types can be marshaled
(i.e. no `interface{}`).
+The following struct annotations are supported:
+
+ toml:"Field" Overrides the field's name to output.
+ omitempty When set, empty values and groups are not emitted.
+ comment:"comment" Emits a # comment on the same line. This supports new lines.
+ commented:"true" Emits the value as commented.
+
Note that pointers are automatically assigned the "omitempty" option, as TOML
explicity does not handle null values (saying instead the label should be
dropped).
+
+Tree structural types and corresponding marshal types:
+
+ *Tree (*)struct, (*)map[string]interface{}
+ []*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
+ []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
+ interface{} (*)primitive
+
+Tree primitive types and corresponding marshal types:
+
+ uint64 uint, uint8-uint64, pointers to same
+ int64 int, int8-uint64, pointers to same
+ float64 float32, float64, pointers to same
+ string string, pointers to same
+ bool bool, pointers to same
+ time.Time time.Time{}, pointers to same
*/
func Marshal(v interface{}) ([]byte, error) {
mtype := reflect.TypeOf(v)
@@ -133,11 +142,11 @@ func Marshal(v interface{}) ([]byte, error) {
}
// 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 {
return valueToTree(mtype.Elem(), mval.Elem())
}
- tval := newTomlTree()
+ tval := newTree()
switch mtype.Kind() {
case reflect.Struct:
for i := 0; i < mtype.NumField(); i++ {
@@ -148,7 +157,7 @@ func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
if err != nil {
return nil, err
}
- tval.Set(opts.name, val)
+ tval.Set(opts.name, opts.comment, opts.commented, val)
}
}
case reflect.Map:
@@ -158,15 +167,15 @@ func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
if err != nil {
return nil, err
}
- tval.Set(key.String(), val)
+ tval.Set(key.String(), "", false, val)
}
}
return tval, nil
}
// Convert given marshal slice to slice of Toml trees
-func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*TomlTree, error) {
- tval := make([]*TomlTree, mval.Len(), mval.Len())
+func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
+ tval := make([]*Tree, mval.Len(), mval.Len())
for i := 0; i < mval.Len(); i++ {
val, err := valueToTree(mtype.Elem(), mval.Index(i))
if err != nil {
@@ -224,34 +233,44 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
}
}
-/*
-Unmarshal parses the TOML-encoded data and stores the result in the value
-pointed to by v. Behavior is similar to the Go json encoder, except that there
-is no concept of an Unmarshaler interface or UnmarshalTOML function for
-sub-structs, and currently only definite types can be unmarshaled to (i.e. no
-`interface{}`).
-*/
-func Unmarshal(data []byte, v interface{}) error {
+// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
+// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
+// sub-structs, and only definite types can be unmarshaled.
+func (t *Tree) Unmarshal(v interface{}) error {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
}
- t, err := Load(string(data))
+ sval, err := valueFromTree(mtype.Elem(), t)
if err != nil {
return err
}
+ reflect.ValueOf(v).Elem().Set(sval)
+ return nil
+}
- sval, err := valueFromTree(mtype.Elem(), t)
+// Unmarshal parses the TOML-encoded data and stores the result in the value
+// pointed to by v. Behavior is similar to the Go json encoder, except that there
+// is no concept of an Unmarshaler interface or UnmarshalTOML function for
+// sub-structs, and currently only definite types can be unmarshaled to (i.e. no
+// `interface{}`).
+//
+// The following struct annotations are supported:
+//
+// toml:"Field" Overrides the field's name to map to.
+//
+// See Marshal() documentation for types mapping table.
+func Unmarshal(data []byte, v interface{}) error {
+ t, err := LoadReader(bytes.NewReader(data))
if err != nil {
return err
}
- reflect.ValueOf(v).Elem().Set(sval)
- return nil
+ return t.Unmarshal(v)
}
// 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 {
return unwrapPointer(mtype, tval)
}
@@ -263,15 +282,20 @@ func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
mtypef := mtype.Field(i)
opts := tomlOptions(mtypef)
if opts.include {
- key := opts.name
- exists := tval.Has(key)
- if exists {
+ baseKey := opts.name
+ keysToTry := []string{baseKey, strings.ToLower(baseKey), strings.ToTitle(baseKey)}
+ for _, key := range keysToTry {
+ exists := tval.Has(key)
+ if !exists {
+ continue
+ }
val := tval.Get(key)
mvalf, err := valueFromToml(mtypef.Type, val)
if err != nil {
return mval, formatError(err, tval.GetPosition(key))
}
mval.Field(i).Set(mvalf)
+ break
}
}
}
@@ -290,7 +314,7 @@ func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
}
// 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))
for i := 0; i < len(tval); i++ {
val, err := valueFromTree(mtype.Elem(), tval[i])
@@ -322,9 +346,9 @@ func valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error)
}
switch {
case isTree(mtype):
- return valueFromTree(mtype, tval.(*TomlTree))
+ return valueFromTree(mtype, tval.(*Tree))
case isTreeSlice(mtype):
- return valueFromTreeSlice(mtype, tval.([]*TomlTree))
+ return valueFromTreeSlice(mtype, tval.([]*Tree))
case isOtherSlice(mtype):
return valueFromOtherSlice(mtype, tval.([]interface{}))
default:
@@ -438,7 +462,12 @@ func unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error)
func tomlOptions(vf reflect.StructField) tomlOpts {
tag := vf.Tag.Get("toml")
parse := strings.Split(tag, ",")
- result := tomlOpts{vf.Name, true, false}
+ var comment string
+ if c := vf.Tag.Get("comment"); c != "" {
+ comment = c
+ }
+ commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
+ result := tomlOpts{name: vf.Name, comment: comment, commented: commented, include: true, omitempty: false}
if parse[0] != "" {
if parse[0] == "-" && len(parse) == 1 {
result.include = false
diff --git a/vendor/github.com/pelletier/go-toml/match.go b/vendor/github.com/pelletier/go-toml/match.go
deleted file mode 100644
index 48b0f2a..0000000
--- a/vendor/github.com/pelletier/go-toml/match.go
+++ /dev/null
@@ -1,234 +0,0 @@
-package toml
-
-import (
- "fmt"
-)
-
-// support function to set positions for tomlValues
-// NOTE: this is done to allow ctx.lastPosition to indicate the start of any
-// values returned by the query engines
-func tomlValueCheck(node interface{}, ctx *queryContext) interface{} {
- switch castNode := node.(type) {
- case *tomlValue:
- ctx.lastPosition = castNode.position
- return castNode.value
- case []*TomlTree:
- if len(castNode) > 0 {
- ctx.lastPosition = castNode[0].position
- }
- return node
- default:
- return node
- }
-}
-
-// base match
-type matchBase struct {
- next pathFn
-}
-
-func (f *matchBase) setNext(next pathFn) {
- f.next = next
-}
-
-// terminating functor - gathers results
-type terminatingFn struct {
- // empty
-}
-
-func newTerminatingFn() *terminatingFn {
- return &terminatingFn{}
-}
-
-func (f *terminatingFn) setNext(next pathFn) {
- // do nothing
-}
-
-func (f *terminatingFn) call(node interface{}, ctx *queryContext) {
- switch castNode := node.(type) {
- case *TomlTree:
- ctx.result.appendResult(node, castNode.position)
- case *tomlValue:
- ctx.result.appendResult(node, castNode.position)
- default:
- // use last position for scalars
- ctx.result.appendResult(node, ctx.lastPosition)
- }
-}
-
-// match single key
-type matchKeyFn struct {
- matchBase
- Name string
-}
-
-func newMatchKeyFn(name string) *matchKeyFn {
- return &matchKeyFn{Name: name}
-}
-
-func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
- if array, ok := node.([]*TomlTree); ok {
- for _, tree := range array {
- item := tree.values[f.Name]
- if item != nil {
- f.next.call(item, ctx)
- }
- }
- } else if tree, ok := node.(*TomlTree); ok {
- item := tree.values[f.Name]
- if item != nil {
- f.next.call(item, ctx)
- }
- }
-}
-
-// match single index
-type matchIndexFn struct {
- matchBase
- Idx int
-}
-
-func newMatchIndexFn(idx int) *matchIndexFn {
- return &matchIndexFn{Idx: idx}
-}
-
-func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
- if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
- if f.Idx < len(arr) && f.Idx >= 0 {
- f.next.call(arr[f.Idx], ctx)
- }
- }
-}
-
-// filter by slicing
-type matchSliceFn struct {
- matchBase
- Start, End, Step int
-}
-
-func newMatchSliceFn(start, end, step int) *matchSliceFn {
- return &matchSliceFn{Start: start, End: end, Step: step}
-}
-
-func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
- if arr, ok := tomlValueCheck(node, ctx).([]interface{}); ok {
- // adjust indexes for negative values, reverse ordering
- realStart, realEnd := f.Start, f.End
- if realStart < 0 {
- realStart = len(arr) + realStart
- }
- if realEnd < 0 {
- realEnd = len(arr) + realEnd
- }
- if realEnd < realStart {
- realEnd, realStart = realStart, realEnd // swap
- }
- // loop and gather
- for idx := realStart; idx < realEnd; idx += f.Step {
- f.next.call(arr[idx], ctx)
- }
- }
-}
-
-// match anything
-type matchAnyFn struct {
- matchBase
-}
-
-func newMatchAnyFn() *matchAnyFn {
- return &matchAnyFn{}
-}
-
-func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
- if tree, ok := node.(*TomlTree); ok {
- for _, v := range tree.values {
- f.next.call(v, ctx)
- }
- }
-}
-
-// filter through union
-type matchUnionFn struct {
- Union []pathFn
-}
-
-func (f *matchUnionFn) setNext(next pathFn) {
- for _, fn := range f.Union {
- fn.setNext(next)
- }
-}
-
-func (f *matchUnionFn) call(node interface{}, ctx *queryContext) {
- for _, fn := range f.Union {
- fn.call(node, ctx)
- }
-}
-
-// match every single last node in the tree
-type matchRecursiveFn struct {
- matchBase
-}
-
-func newMatchRecursiveFn() *matchRecursiveFn {
- return &matchRecursiveFn{}
-}
-
-func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
- if tree, ok := node.(*TomlTree); ok {
- var visit func(tree *TomlTree)
- visit = func(tree *TomlTree) {
- for _, v := range tree.values {
- f.next.call(v, ctx)
- switch node := v.(type) {
- case *TomlTree:
- visit(node)
- case []*TomlTree:
- for _, subtree := range node {
- visit(subtree)
- }
- }
- }
- }
- f.next.call(tree, ctx)
- visit(tree)
- }
-}
-
-// match based on an externally provided functional filter
-type matchFilterFn struct {
- matchBase
- Pos Position
- Name string
-}
-
-func newMatchFilterFn(name string, pos Position) *matchFilterFn {
- return &matchFilterFn{Name: name, Pos: pos}
-}
-
-func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
- fn, ok := (*ctx.filters)[f.Name]
- if !ok {
- panic(fmt.Sprintf("%s: query context does not have filter '%s'",
- f.Pos.String(), f.Name))
- }
- switch castNode := tomlValueCheck(node, ctx).(type) {
- case *TomlTree:
- for _, v := range castNode.values {
- if tv, ok := v.(*tomlValue); ok {
- if fn(tv.value) {
- f.next.call(v, ctx)
- }
- } else {
- if fn(v) {
- f.next.call(v, ctx)
- }
- }
- }
- case []interface{}:
- for _, v := range castNode {
- if fn(v) {
- f.next.call(v, ctx)
- }
- }
- }
-}
diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go
index 20e90a3..d492a1e 100644
--- a/vendor/github.com/pelletier/go-toml/parser.go
+++ b/vendor/github.com/pelletier/go-toml/parser.go
@@ -13,9 +13,9 @@ import (
)
type tomlParser struct {
- flow chan token
- tree *TomlTree
- tokensBuffer []token
+ flowIdx int
+ flow []token
+ tree *Tree
currentTable []string
seenTableKeys []string
}
@@ -34,16 +34,10 @@ func (p *tomlParser) run() {
}
func (p *tomlParser) peek() *token {
- if len(p.tokensBuffer) != 0 {
- return &(p.tokensBuffer[0])
- }
-
- tok, ok := <-p.flow
- if !ok {
+ if p.flowIdx >= len(p.flow) {
return nil
}
- p.tokensBuffer = append(p.tokensBuffer, tok)
- return &tok
+ return &p.flow[p.flowIdx]
}
func (p *tomlParser) assume(typ tokenType) {
@@ -57,16 +51,12 @@ func (p *tomlParser) assume(typ tokenType) {
}
func (p *tomlParser) getToken() *token {
- if len(p.tokensBuffer) != 0 {
- tok := p.tokensBuffer[0]
- p.tokensBuffer = p.tokensBuffer[1:]
- return &tok
- }
- tok, ok := <-p.flow
- if !ok {
+ tok := p.peek()
+ if tok == nil {
return nil
}
- return &tok
+ p.flowIdx++
+ return tok
}
func (p *tomlParser) parseStart() tomlParserStateFn {
@@ -106,21 +96,21 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
}
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
destTree := p.tree.GetPath(keys)
- var array []*TomlTree
+ var array []*Tree
if destTree == nil {
- array = make([]*TomlTree, 0)
- } else if target, ok := destTree.([]*TomlTree); ok && target != nil {
- array = destTree.([]*TomlTree)
+ array = make([]*Tree, 0)
+ } else if target, ok := destTree.([]*Tree); ok && target != nil {
+ array = destTree.([]*Tree)
} else {
p.raiseError(key, "key %s is already assigned and not of type table array", key)
}
p.currentTable = keys
// add a new tree to the end of the table array
- newTree := newTomlTree()
+ newTree := newTree()
newTree.position = startToken.Position
array = append(array, newTree)
- p.tree.SetPath(p.currentTable, array)
+ p.tree.SetPath(p.currentTable, "", false, array)
// remove all keys that were children of this table array
prefix := key.val + "."
@@ -183,11 +173,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
}
// find the table to assign, looking out for arrays of tables
- var targetNode *TomlTree
+ var targetNode *Tree
switch node := p.tree.GetPath(tableKey).(type) {
- case []*TomlTree:
+ case []*Tree:
targetNode = node[len(node)-1]
- case *TomlTree:
+ case *Tree:
targetNode = node
default:
p.raiseError(key, "Unknown table type for path: %s",
@@ -212,10 +202,10 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
var toInsert interface{}
switch value.(type) {
- case *TomlTree, []*TomlTree:
+ case *Tree, []*Tree:
toInsert = value
default:
- toInsert = &tomlValue{value, key.Position}
+ toInsert = &tomlValue{value: value, position: key.Position}
}
targetNode.values[keyVal] = toInsert
return p.parseStart
@@ -289,8 +279,8 @@ func tokenIsComma(t *token) bool {
return t != nil && t.typ == tokenComma
}
-func (p *tomlParser) parseInlineTable() *TomlTree {
- tree := newTomlTree()
+func (p *tomlParser) parseInlineTable() *Tree {
+ tree := newTree()
var previous *token
Loop:
for {
@@ -309,7 +299,7 @@ Loop:
key := p.getToken()
p.assume(tokenEqual)
value := p.parseRvalue()
- tree.Set(key.val, value)
+ tree.Set(key.val, "", false, value)
case tokenComma:
if previous == nil {
p.raiseError(follow, "inline table cannot start with a comma")
@@ -360,27 +350,27 @@ func (p *tomlParser) parseArray() interface{} {
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
- // array was not converted from []interface{} to []*TomlTree,
+ // array was not converted from []interface{} to []*Tree,
// the two notations would not be equivalent.
- if arrayType == reflect.TypeOf(newTomlTree()) {
- tomlArray := make([]*TomlTree, len(array))
+ if arrayType == reflect.TypeOf(newTree()) {
+ tomlArray := make([]*Tree, len(array))
for i, v := range array {
- tomlArray[i] = v.(*TomlTree)
+ tomlArray[i] = v.(*Tree)
}
return tomlArray
}
return array
}
-func parseToml(flow chan token) *TomlTree {
- result := newTomlTree()
+func parseToml(flow []token) *Tree {
+ result := newTree()
result.position = Position{1, 1}
parser := &tomlParser{
+ flowIdx: 0,
flow: flow,
tree: result,
- tokensBuffer: make([]token, 0),
currentTable: make([]string, 0),
seenTableKeys: make([]string, 0),
}
diff --git a/vendor/github.com/pelletier/go-toml/query.go b/vendor/github.com/pelletier/go-toml/query.go
deleted file mode 100644
index 307a1ec..0000000
--- a/vendor/github.com/pelletier/go-toml/query.go
+++ /dev/null
@@ -1,153 +0,0 @@
-package toml
-
-import (
- "time"
-)
-
-// NodeFilterFn represents a user-defined filter function, for use with
-// Query.SetFilter().
-//
-// The return value of the function must indicate if 'node' is to be included
-// at this stage of the TOML path. Returning true will include the node, and
-// returning false will exclude it.
-//
-// NOTE: Care should be taken to write script callbacks such that they are safe
-// to use from multiple goroutines.
-type NodeFilterFn func(node interface{}) bool
-
-// QueryResult is the result of Executing a Query.
-type QueryResult struct {
- items []interface{}
- positions []Position
-}
-
-// appends a value/position pair to the result set.
-func (r *QueryResult) appendResult(node interface{}, pos Position) {
- r.items = append(r.items, node)
- r.positions = append(r.positions, pos)
-}
-
-// Values is a set of values within a QueryResult. The order of values is not
-// guaranteed to be in document order, and may be different each time a query is
-// executed.
-func (r QueryResult) Values() []interface{} {
- values := make([]interface{}, len(r.items))
- for i, v := range r.items {
- o, ok := v.(*tomlValue)
- if ok {
- values[i] = o.value
- } else {
- values[i] = v
- }
- }
- return values
-}
-
-// Positions is a set of positions for values within a QueryResult. Each index
-// in Positions() corresponds to the entry in Value() of the same index.
-func (r QueryResult) Positions() []Position {
- return r.positions
-}
-
-// runtime context for executing query paths
-type queryContext struct {
- result *QueryResult
- filters *map[string]NodeFilterFn
- lastPosition Position
-}
-
-// generic path functor interface
-type pathFn interface {
- setNext(next pathFn)
- call(node interface{}, ctx *queryContext)
-}
-
-// A Query is the representation of a compiled TOML path. A Query is safe
-// for concurrent use by multiple goroutines.
-type Query struct {
- root pathFn
- tail pathFn
- filters *map[string]NodeFilterFn
-}
-
-func newQuery() *Query {
- return &Query{
- root: nil,
- tail: nil,
- filters: &defaultFilterFunctions,
- }
-}
-
-func (q *Query) appendPath(next pathFn) {
- if q.root == nil {
- q.root = next
- } else {
- q.tail.setNext(next)
- }
- q.tail = next
- next.setNext(newTerminatingFn()) // init the next functor
-}
-
-// CompileQuery compiles a TOML path expression. The returned Query can be used
-// to match elements within a TomlTree and its descendants.
-func CompileQuery(path string) (*Query, error) {
- return parseQuery(lexQuery(path))
-}
-
-// Execute executes a query against a TomlTree, and returns the result of the query.
-func (q *Query) Execute(tree *TomlTree) *QueryResult {
- result := &QueryResult{
- items: []interface{}{},
- positions: []Position{},
- }
- if q.root == nil {
- result.appendResult(tree, tree.GetPosition(""))
- } else {
- ctx := &queryContext{
- result: result,
- filters: q.filters,
- }
- q.root.call(tree, ctx)
- }
- return result
-}
-
-// SetFilter sets a user-defined filter function. These may be used inside
-// "?(..)" query expressions to filter TOML document elements within a query.
-func (q *Query) SetFilter(name string, fn NodeFilterFn) {
- if q.filters == &defaultFilterFunctions {
- // clone the static table
- q.filters = &map[string]NodeFilterFn{}
- for k, v := range defaultFilterFunctions {
- (*q.filters)[k] = v
- }
- }
- (*q.filters)[name] = fn
-}
-
-var defaultFilterFunctions = map[string]NodeFilterFn{
- "tree": func(node interface{}) bool {
- _, ok := node.(*TomlTree)
- return ok
- },
- "int": func(node interface{}) bool {
- _, ok := node.(int64)
- return ok
- },
- "float": func(node interface{}) bool {
- _, ok := node.(float64)
- return ok
- },
- "string": func(node interface{}) bool {
- _, ok := node.(string)
- return ok
- },
- "time": func(node interface{}) bool {
- _, ok := node.(time.Time)
- return ok
- },
- "bool": func(node interface{}) bool {
- _, ok := node.(bool)
- return ok
- },
-}
diff --git a/vendor/github.com/pelletier/go-toml/querylexer.go b/vendor/github.com/pelletier/go-toml/querylexer.go
deleted file mode 100644
index 960681d..0000000
--- a/vendor/github.com/pelletier/go-toml/querylexer.go
+++ /dev/null
@@ -1,356 +0,0 @@
-// TOML JSONPath lexer.
-//
-// Written using the principles developed by Rob Pike in
-// http://www.youtube.com/watch?v=HxaD_trXwRE
-
-package toml
-
-import (
- "fmt"
- "strconv"
- "strings"
- "unicode/utf8"
-)
-
-// Lexer state function
-type queryLexStateFn func() queryLexStateFn
-
-// Lexer definition
-type queryLexer struct {
- input string
- start int
- pos int
- width int
- tokens chan token
- depth int
- line int
- col int
- stringTerm string
-}
-
-func (l *queryLexer) run() {
- for state := l.lexVoid; state != nil; {
- state = state()
- }
- close(l.tokens)
-}
-
-func (l *queryLexer) nextStart() {
- // iterate by runes (utf8 characters)
- // search for newlines and advance line/col counts
- for i := l.start; i < l.pos; {
- r, width := utf8.DecodeRuneInString(l.input[i:])
- if r == '\n' {
- l.line++
- l.col = 1
- } else {
- l.col++
- }
- i += width
- }
- // advance start position to next token
- l.start = l.pos
-}
-
-func (l *queryLexer) emit(t tokenType) {
- l.tokens <- token{
- Position: Position{l.line, l.col},
- typ: t,
- val: l.input[l.start:l.pos],
- }
- l.nextStart()
-}
-
-func (l *queryLexer) emitWithValue(t tokenType, value string) {
- l.tokens <- token{
- Position: Position{l.line, l.col},
- typ: t,
- val: value,
- }
- l.nextStart()
-}
-
-func (l *queryLexer) next() rune {
- if l.pos >= len(l.input) {
- l.width = 0
- return eof
- }
- var r rune
- r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
- l.pos += l.width
- return r
-}
-
-func (l *queryLexer) ignore() {
- l.nextStart()
-}
-
-func (l *queryLexer) backup() {
- l.pos -= l.width
-}
-
-func (l *queryLexer) errorf(format string, args ...interface{}) queryLexStateFn {
- l.tokens <- token{
- Position: Position{l.line, l.col},
- typ: tokenError,
- val: fmt.Sprintf(format, args...),
- }
- return nil
-}
-
-func (l *queryLexer) peek() rune {
- r := l.next()
- l.backup()
- return r
-}
-
-func (l *queryLexer) accept(valid string) bool {
- if strings.ContainsRune(valid, l.next()) {
- return true
- }
- l.backup()
- return false
-}
-
-func (l *queryLexer) follow(next string) bool {
- return strings.HasPrefix(l.input[l.pos:], next)
-}
-
-func (l *queryLexer) lexVoid() queryLexStateFn {
- for {
- next := l.peek()
- switch next {
- case '$':
- l.pos++
- l.emit(tokenDollar)
- continue
- case '.':
- if l.follow("..") {
- l.pos += 2
- l.emit(tokenDotDot)
- } else {
- l.pos++
- l.emit(tokenDot)
- }
- continue
- case '[':
- l.pos++
- l.emit(tokenLeftBracket)
- continue
- case ']':
- l.pos++
- l.emit(tokenRightBracket)
- continue
- case ',':
- l.pos++
- l.emit(tokenComma)
- continue
- case '*':
- l.pos++
- l.emit(tokenStar)
- continue
- case '(':
- l.pos++
- l.emit(tokenLeftParen)
- continue
- case ')':
- l.pos++
- l.emit(tokenRightParen)
- continue
- case '?':
- l.pos++
- l.emit(tokenQuestion)
- continue
- case ':':
- l.pos++
- l.emit(tokenColon)
- continue
- case '\'':
- l.ignore()
- l.stringTerm = string(next)
- return l.lexString
- case '"':
- l.ignore()
- l.stringTerm = string(next)
- return l.lexString
- }
-
- if isSpace(next) {
- l.next()
- l.ignore()
- continue
- }
-
- if isAlphanumeric(next) {
- return l.lexKey
- }
-
- if next == '+' || next == '-' || isDigit(next) {
- return l.lexNumber
- }
-
- if l.next() == eof {
- break
- }
-
- return l.errorf("unexpected char: '%v'", next)
- }
- l.emit(tokenEOF)
- return nil
-}
-
-func (l *queryLexer) lexKey() queryLexStateFn {
- for {
- next := l.peek()
- if !isAlphanumeric(next) {
- l.emit(tokenKey)
- return l.lexVoid
- }
-
- if l.next() == eof {
- break
- }
- }
- l.emit(tokenEOF)
- return nil
-}
-
-func (l *queryLexer) lexString() queryLexStateFn {
- l.pos++
- l.ignore()
- growingString := ""
-
- for {
- if l.follow(l.stringTerm) {
- l.emitWithValue(tokenString, growingString)
- l.pos++
- l.ignore()
- return l.lexVoid
- }
-
- if l.follow("\\\"") {
- l.pos++
- growingString += "\""
- } else if l.follow("\\'") {
- l.pos++
- growingString += "'"
- } else if l.follow("\\n") {
- l.pos++
- growingString += "\n"
- } else if l.follow("\\b") {
- l.pos++
- growingString += "\b"
- } else if l.follow("\\f") {
- l.pos++
- growingString += "\f"
- } else if l.follow("\\/") {
- l.pos++
- growingString += "/"
- } else if l.follow("\\t") {
- l.pos++
- growingString += "\t"
- } else if l.follow("\\r") {
- l.pos++
- growingString += "\r"
- } else if l.follow("\\\\") {
- l.pos++
- growingString += "\\"
- } else if l.follow("\\u") {
- l.pos += 2
- code := ""
- for i := 0; i < 4; i++ {
- c := l.peek()
- l.pos++
- if !isHexDigit(c) {
- return l.errorf("unfinished unicode escape")
- }
- code = code + string(c)
- }
- l.pos--
- intcode, err := strconv.ParseInt(code, 16, 32)
- if err != nil {
- return l.errorf("invalid unicode escape: \\u" + code)
- }
- growingString += string(rune(intcode))
- } else if l.follow("\\U") {
- l.pos += 2
- code := ""
- for i := 0; i < 8; i++ {
- c := l.peek()
- l.pos++
- if !isHexDigit(c) {
- return l.errorf("unfinished unicode escape")
- }
- code = code + string(c)
- }
- l.pos--
- intcode, err := strconv.ParseInt(code, 16, 32)
- if err != nil {
- return l.errorf("invalid unicode escape: \\u" + code)
- }
- growingString += string(rune(intcode))
- } else if l.follow("\\") {
- l.pos++
- return l.errorf("invalid escape sequence: \\" + string(l.peek()))
- } else {
- growingString += string(l.peek())
- }
-
- if l.next() == eof {
- break
- }
- }
-
- return l.errorf("unclosed string")
-}
-
-func (l *queryLexer) lexNumber() queryLexStateFn {
- l.ignore()
- if !l.accept("+") {
- l.accept("-")
- }
- pointSeen := false
- digitSeen := false
- for {
- next := l.next()
- if next == '.' {
- if pointSeen {
- return l.errorf("cannot have two dots in one float")
- }
- if !isDigit(l.peek()) {
- return l.errorf("float cannot end with a dot")
- }
- pointSeen = true
- } else if isDigit(next) {
- digitSeen = true
- } else {
- l.backup()
- break
- }
- if pointSeen && !digitSeen {
- return l.errorf("cannot start float with a dot")
- }
- }
-
- if !digitSeen {
- return l.errorf("no digit in that number")
- }
- if pointSeen {
- l.emit(tokenFloat)
- } else {
- l.emit(tokenInteger)
- }
- return l.lexVoid
-}
-
-// Entry point
-func lexQuery(input string) chan token {
- l := &queryLexer{
- input: input,
- tokens: make(chan token),
- line: 1,
- col: 1,
- }
- go l.run()
- return l.tokens
-}
diff --git a/vendor/github.com/pelletier/go-toml/queryparser.go b/vendor/github.com/pelletier/go-toml/queryparser.go
deleted file mode 100644
index 1cbfc83..0000000
--- a/vendor/github.com/pelletier/go-toml/queryparser.go
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- Based on the "jsonpath" spec/concept.
-
- http://goessner.net/articles/JsonPath/
- https://code.google.com/p/json-path/
-*/
-
-package toml
-
-import (
- "fmt"
-)
-
-const maxInt = int(^uint(0) >> 1)
-
-type queryParser struct {
- flow chan token
- tokensBuffer []token
- query *Query
- union []pathFn
- err error
-}
-
-type queryParserStateFn func() queryParserStateFn
-
-// Formats and panics an error message based on a token
-func (p *queryParser) parseError(tok *token, msg string, args ...interface{}) queryParserStateFn {
- p.err = fmt.Errorf(tok.Position.String()+": "+msg, args...)
- return nil // trigger parse to end
-}
-
-func (p *queryParser) run() {
- for state := p.parseStart; state != nil; {
- state = state()
- }
-}
-
-func (p *queryParser) backup(tok *token) {
- p.tokensBuffer = append(p.tokensBuffer, *tok)
-}
-
-func (p *queryParser) peek() *token {
- if len(p.tokensBuffer) != 0 {
- return &(p.tokensBuffer[0])
- }
-
- tok, ok := <-p.flow
- if !ok {
- return nil
- }
- p.backup(&tok)
- return &tok
-}
-
-func (p *queryParser) lookahead(types ...tokenType) bool {
- result := true
- buffer := []token{}
-
- for _, typ := range types {
- tok := p.getToken()
- if tok == nil {
- result = false
- break
- }
- buffer = append(buffer, *tok)
- if tok.typ != typ {
- result = false
- break
- }
- }
- // add the tokens back to the buffer, and return
- p.tokensBuffer = append(p.tokensBuffer, buffer...)
- return result
-}
-
-func (p *queryParser) getToken() *token {
- if len(p.tokensBuffer) != 0 {
- tok := p.tokensBuffer[0]
- p.tokensBuffer = p.tokensBuffer[1:]
- return &tok
- }
- tok, ok := <-p.flow
- if !ok {
- return nil
- }
- return &tok
-}
-
-func (p *queryParser) parseStart() queryParserStateFn {
- tok := p.getToken()
-
- if tok == nil || tok.typ == tokenEOF {
- return nil
- }
-
- if tok.typ != tokenDollar {
- return p.parseError(tok, "Expected '$' at start of expression")
- }
-
- return p.parseMatchExpr
-}
-
-// handle '.' prefix, '[]', and '..'
-func (p *queryParser) parseMatchExpr() queryParserStateFn {
- tok := p.getToken()
- switch tok.typ {
- case tokenDotDot:
- p.query.appendPath(&matchRecursiveFn{})
- // nested parse for '..'
- tok := p.getToken()
- switch tok.typ {
- case tokenKey:
- p.query.appendPath(newMatchKeyFn(tok.val))
- return p.parseMatchExpr
- case tokenLeftBracket:
- return p.parseBracketExpr
- case tokenStar:
- // do nothing - the recursive predicate is enough
- return p.parseMatchExpr
- }
-
- case tokenDot:
- // nested parse for '.'
- tok := p.getToken()
- switch tok.typ {
- case tokenKey:
- p.query.appendPath(newMatchKeyFn(tok.val))
- return p.parseMatchExpr
- case tokenStar:
- p.query.appendPath(&matchAnyFn{})
- return p.parseMatchExpr
- }
-
- case tokenLeftBracket:
- return p.parseBracketExpr
-
- case tokenEOF:
- return nil // allow EOF at this stage
- }
- return p.parseError(tok, "expected match expression")
-}
-
-func (p *queryParser) parseBracketExpr() queryParserStateFn {
- if p.lookahead(tokenInteger, tokenColon) {
- return p.parseSliceExpr
- }
- if p.peek().typ == tokenColon {
- return p.parseSliceExpr
- }
- return p.parseUnionExpr
-}
-
-func (p *queryParser) parseUnionExpr() queryParserStateFn {
- var tok *token
-
- // this state can be traversed after some sub-expressions
- // so be careful when setting up state in the parser
- if p.union == nil {
- p.union = []pathFn{}
- }
-
-loop: // labeled loop for easy breaking
- for {
- if len(p.union) > 0 {
- // parse delimiter or terminator
- tok = p.getToken()
- switch tok.typ {
- case tokenComma:
- // do nothing
- case tokenRightBracket:
- break loop
- default:
- return p.parseError(tok, "expected ',' or ']', not '%s'", tok.val)
- }
- }
-
- // parse sub expression
- tok = p.getToken()
- switch tok.typ {
- case tokenInteger:
- p.union = append(p.union, newMatchIndexFn(tok.Int()))
- case tokenKey:
- p.union = append(p.union, newMatchKeyFn(tok.val))
- case tokenString:
- p.union = append(p.union, newMatchKeyFn(tok.val))
- case tokenQuestion:
- return p.parseFilterExpr
- default:
- return p.parseError(tok, "expected union sub expression, not '%s', %d", tok.val, len(p.union))
- }
- }
-
- // if there is only one sub-expression, use that instead
- if len(p.union) == 1 {
- p.query.appendPath(p.union[0])
- } else {
- p.query.appendPath(&matchUnionFn{p.union})
- }
-
- p.union = nil // clear out state
- return p.parseMatchExpr
-}
-
-func (p *queryParser) parseSliceExpr() queryParserStateFn {
- // init slice to grab all elements
- start, end, step := 0, maxInt, 1
-
- // parse optional start
- tok := p.getToken()
- if tok.typ == tokenInteger {
- start = tok.Int()
- tok = p.getToken()
- }
- if tok.typ != tokenColon {
- return p.parseError(tok, "expected ':'")
- }
-
- // parse optional end
- tok = p.getToken()
- if tok.typ == tokenInteger {
- end = tok.Int()
- tok = p.getToken()
- }
- if tok.typ == tokenRightBracket {
- p.query.appendPath(newMatchSliceFn(start, end, step))
- return p.parseMatchExpr
- }
- if tok.typ != tokenColon {
- return p.parseError(tok, "expected ']' or ':'")
- }
-
- // parse optional step
- tok = p.getToken()
- if tok.typ == tokenInteger {
- step = tok.Int()
- if step < 0 {
- return p.parseError(tok, "step must be a positive value")
- }
- tok = p.getToken()
- }
- if tok.typ != tokenRightBracket {
- return p.parseError(tok, "expected ']'")
- }
-
- p.query.appendPath(newMatchSliceFn(start, end, step))
- return p.parseMatchExpr
-}
-
-func (p *queryParser) parseFilterExpr() queryParserStateFn {
- tok := p.getToken()
- if tok.typ != tokenLeftParen {
- return p.parseError(tok, "expected left-parenthesis for filter expression")
- }
- tok = p.getToken()
- if tok.typ != tokenKey && tok.typ != tokenString {
- return p.parseError(tok, "expected key or string for filter funciton name")
- }
- name := tok.val
- tok = p.getToken()
- if tok.typ != tokenRightParen {
- return p.parseError(tok, "expected right-parenthesis for filter expression")
- }
- p.union = append(p.union, newMatchFilterFn(name, tok.Position))
- return p.parseUnionExpr
-}
-
-func parseQuery(flow chan token) (*Query, error) {
- parser := &queryParser{
- flow: flow,
- tokensBuffer: []token{},
- query: newQuery(),
- }
- parser.run()
- return parser.query, parser.err
-}
diff --git a/vendor/github.com/pelletier/go-toml/test.sh b/vendor/github.com/pelletier/go-toml/test.sh
index 436d2fb..91a8896 100755
--- a/vendor/github.com/pelletier/go-toml/test.sh
+++ b/vendor/github.com/pelletier/go-toml/test.sh
@@ -19,11 +19,16 @@ function git_clone() {
popd
}
+# Remove potential previous runs
+rm -rf src test_program_bin toml-test
+
# Run go vet
go vet ./...
go get github.com/pelletier/go-buffruneio
go get github.com/davecgh/go-spew/spew
+go get gopkg.in/yaml.v2
+go get github.com/BurntSushi/toml
# get code for BurntSushi TOML validation
# pinning all to 'HEAD' for version 0.3.x work (TODO: pin to commit hash when tests stabilize)
@@ -36,13 +41,16 @@ go build -o toml-test github.com/BurntSushi/toml-test
# vendorize the current lib for testing
# NOTE: this basically mocks an install without having to go back out to github for code
mkdir -p src/github.com/pelletier/go-toml/cmd
+mkdir -p src/github.com/pelletier/go-toml/query
cp *.go *.toml src/github.com/pelletier/go-toml
cp -R cmd/* src/github.com/pelletier/go-toml/cmd
+cp -R query/* src/github.com/pelletier/go-toml/query
go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go
# Run basic unit tests
-go test github.com/pelletier/go-toml -v -covermode=count -coverprofile=coverage.out
+go test github.com/pelletier/go-toml -covermode=count -coverprofile=coverage.out
go test github.com/pelletier/go-toml/cmd/tomljson
+go test github.com/pelletier/go-toml/query
# run the entire BurntSushi test suite
if [[ $# -eq 0 ]] ; then
diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go
index 1ba56a1..c3e3243 100644
--- a/vendor/github.com/pelletier/go-toml/toml.go
+++ b/vendor/github.com/pelletier/go-toml/toml.go
@@ -4,40 +4,50 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"os"
"runtime"
"strings"
)
type tomlValue struct {
- value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
- position Position
+ value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
+ comment string
+ commented bool
+ position Position
}
-// TomlTree is the result of the parsing of a TOML file.
-type TomlTree struct {
- values map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree
- position Position
+// Tree is the result of the parsing of a TOML file.
+type Tree struct {
+ values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
+ comment string
+ commented bool
+ position Position
}
-func newTomlTree() *TomlTree {
- return &TomlTree{
+func newTree() *Tree {
+ return &Tree{
values: make(map[string]interface{}),
position: Position{},
}
}
-// TreeFromMap initializes a new TomlTree object using the given map.
-func TreeFromMap(m map[string]interface{}) (*TomlTree, error) {
+// TreeFromMap initializes a new Tree object using the given map.
+func TreeFromMap(m map[string]interface{}) (*Tree, error) {
result, err := toTree(m)
if err != nil {
return nil, err
}
- return result.(*TomlTree), nil
+ return result.(*Tree), nil
+}
+
+// Position returns the position of the tree.
+func (t *Tree) Position() Position {
+ return t.position
}
// 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 == "" {
return false
}
@@ -45,25 +55,26 @@ func (t *TomlTree) Has(key string) bool {
}
// 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
}
-// Keys returns the keys of the toplevel tree.
-// Warning: this is a costly operation.
-func (t *TomlTree) Keys() []string {
- var keys []string
+// Keys returns the keys of the toplevel tree (does not recurse).
+func (t *Tree) Keys() []string {
+ keys := make([]string, len(t.values))
+ i := 0
for k := range t.values {
- keys = append(keys, k)
+ keys[i] = k
+ i++
}
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).
// Returns nil if the path does not exist in the tree.
// 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 == "" {
return t
}
@@ -76,7 +87,7 @@ func (t *TomlTree) Get(key string) interface{} {
// GetPath returns the element in the tree indicated by 'keys'.
// 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 {
return t
}
@@ -87,9 +98,9 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
return nil
}
switch node := value.(type) {
- case *TomlTree:
+ case *Tree:
subtree = node
- case []*TomlTree:
+ case []*Tree:
// go to most recent element
if len(node) == 0 {
return nil
@@ -109,7 +120,7 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
}
// GetPosition returns the position of the given key.
-func (t *TomlTree) GetPosition(key string) Position {
+func (t *Tree) GetPosition(key string) Position {
if key == "" {
return t.position
}
@@ -118,7 +129,7 @@ func (t *TomlTree) GetPosition(key string) Position {
// GetPositionPath returns the element in the tree indicated by 'keys'.
// 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 {
return t.position
}
@@ -129,9 +140,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
return Position{0, 0}
}
switch node := value.(type) {
- case *TomlTree:
+ case *Tree:
subtree = node
- case []*TomlTree:
+ case []*Tree:
// go to most recent element
if len(node) == 0 {
return Position{0, 0}
@@ -145,9 +156,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
switch node := subtree.values[keys[len(keys)-1]].(type) {
case *tomlValue:
return node.position
- case *TomlTree:
+ case *Tree:
return node.position
- case []*TomlTree:
+ case []*Tree:
// go to most recent element
if len(node) == 0 {
return Position{0, 0}
@@ -159,7 +170,7 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
}
// 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)
if val == nil {
return def
@@ -169,30 +180,30 @@ func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
// Set an element in the tree.
// Key is a dot-separated path (e.g. a.b.c).
-// Creates all necessary intermediates trees, if needed.
-func (t *TomlTree) Set(key string, value interface{}) {
- t.SetPath(strings.Split(key, "."), value)
+// Creates all necessary intermediate trees, if needed.
+func (t *Tree) Set(key string, comment string, commented bool, value interface{}) {
+ t.SetPath(strings.Split(key, "."), comment, commented, value)
}
// SetPath sets an element in the tree.
// Keys is an array of path elements (e.g. {"a","b","c"}).
-// Creates all necessary intermediates trees, if needed.
-func (t *TomlTree) SetPath(keys []string, value interface{}) {
+// Creates all necessary intermediate trees, if needed.
+func (t *Tree) SetPath(keys []string, comment string, commented bool, value interface{}) {
subtree := t
for _, intermediateKey := range keys[:len(keys)-1] {
nextTree, exists := subtree.values[intermediateKey]
if !exists {
- nextTree = newTomlTree()
+ nextTree = newTree()
subtree.values[intermediateKey] = nextTree // add new element here
}
switch node := nextTree.(type) {
- case *TomlTree:
+ case *Tree:
subtree = node
- case []*TomlTree:
+ case []*Tree:
// go to most recent element
if len(node) == 0 {
// create element if it does not exist
- subtree.values[intermediateKey] = append(node, newTomlTree())
+ subtree.values[intermediateKey] = append(node, newTree())
}
subtree = node[len(node)-1]
}
@@ -201,14 +212,18 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
var toInsert interface{}
switch value.(type) {
- case *TomlTree:
+ case *Tree:
+ tt := value.(*Tree)
+ tt.comment = comment
toInsert = value
- case []*TomlTree:
+ case []*Tree:
toInsert = value
case *tomlValue:
- toInsert = value
+ tt := value.(*tomlValue)
+ tt.comment = comment
+ toInsert = tt
default:
- toInsert = &tomlValue{value: value}
+ toInsert = &tomlValue{value: value, comment: comment, commented: commented}
}
subtree.values[keys[len(keys)-1]] = toInsert
@@ -221,21 +236,21 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
// and tree[a][b][c]
//
// 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
for _, intermediateKey := range keys {
nextTree, exists := subtree.values[intermediateKey]
if !exists {
- tree := newTomlTree()
+ tree := newTree()
tree.position = pos
subtree.values[intermediateKey] = tree
nextTree = tree
}
switch node := nextTree.(type) {
- case []*TomlTree:
+ case []*Tree:
subtree = node[len(node)-1]
- case *TomlTree:
+ case *Tree:
subtree = node
default:
return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
@@ -245,17 +260,8 @@ func (t *TomlTree) createSubTree(keys []string, pos Position) error {
return nil
}
-// Query compiles and executes a query on a tree and returns the query result.
-func (t *TomlTree) Query(query string) (*QueryResult, error) {
- q, err := CompileQuery(query)
- if err != nil {
- return nil, err
- }
- return q.Execute(t), nil
-}
-
-// LoadReader creates a TomlTree from any io.Reader.
-func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
+// LoadBytes creates a Tree from a []byte.
+func LoadBytes(b []byte) (tree *Tree, err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
@@ -264,17 +270,27 @@ func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
err = errors.New(r.(string))
}
}()
- tree = parseToml(lexToml(reader))
+ tree = parseToml(lexToml(b))
+ return
+}
+
+// LoadReader creates a Tree from any io.Reader.
+func LoadReader(reader io.Reader) (tree *Tree, err error) {
+ inputBytes, err := ioutil.ReadAll(reader)
+ if err != nil {
+ return
+ }
+ tree, err = LoadBytes(inputBytes)
return
}
-// Load creates a TomlTree from a string.
-func Load(content string) (tree *TomlTree, err error) {
- return LoadReader(strings.NewReader(content))
+// Load creates a Tree from a string.
+func Load(content string) (tree *Tree, err error) {
+ return LoadBytes([]byte(content))
}
-// LoadFile creates a TomlTree from a file.
-func LoadFile(path string) (tree *TomlTree, err error) {
+// LoadFile creates a Tree from a file.
+func LoadFile(path string) (tree *Tree, err error) {
file, err := os.Open(path)
if err != nil {
return nil, err
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go
index c6054f3..79610e9 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_create.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go
@@ -6,10 +6,7 @@ import (
"time"
)
-// supported values:
-// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
-
-var kindToTypeMapping = map[reflect.Kind]reflect.Type{
+var kindToType = [reflect.String + 1]reflect.Type{
reflect.Bool: reflect.TypeOf(true),
reflect.String: reflect.TypeOf(""),
reflect.Float32: reflect.TypeOf(float64(1)),
@@ -26,6 +23,16 @@ var kindToTypeMapping = map[reflect.Kind]reflect.Type{
reflect.Uint64: reflect.TypeOf(uint64(1)),
}
+// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
+// supported values:
+// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
+func typeFor(k reflect.Kind) reflect.Type {
+ if k > 0 && int(k) < len(kindToType) {
+ return kindToType[k]
+ }
+ return nil
+}
+
func simpleValueCoercion(object interface{}) (interface{}, error) {
switch original := object.(type) {
case string, bool, int64, uint64, float64, time.Time:
@@ -51,7 +58,7 @@ func simpleValueCoercion(object interface{}) (interface{}, error) {
case fmt.Stringer:
return original.String(), nil
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 +66,7 @@ func sliceToTree(object interface{}) (interface{}, error) {
// arrays are a bit tricky, since they can represent either a
// collection of simple values, which is represented by one
// *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
value := reflect.ValueOf(object)
@@ -70,19 +77,19 @@ func sliceToTree(object interface{}) (interface{}, error) {
}
if insideType.Kind() == reflect.Map {
// this is considered as an array of tables
- tablesArray := make([]*TomlTree, 0, length)
+ tablesArray := make([]*Tree, 0, length)
for i := 0; i < length; i++ {
table := value.Index(i)
tree, err := toTree(table.Interface())
if err != nil {
return nil, err
}
- tablesArray = append(tablesArray, tree.(*TomlTree))
+ tablesArray = append(tablesArray, tree.(*Tree))
}
return tablesArray, nil
}
- sliceType := kindToTypeMapping[insideType.Kind()]
+ sliceType := typeFor(insideType.Kind())
if sliceType == nil {
sliceType = insideType
}
@@ -97,7 +104,7 @@ func sliceToTree(object interface{}) (interface{}, error) {
}
arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
}
- return &tomlValue{arrayValue.Interface(), Position{}}, nil
+ return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
}
func toTree(object interface{}) (interface{}, error) {
@@ -120,7 +127,7 @@ func toTree(object interface{}) (interface{}, error) {
}
values[key.String()] = newValue
}
- return &TomlTree{values, Position{}}, nil
+ return &Tree{values: values, position: Position{}}, nil
}
if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
@@ -131,5 +138,5 @@ func toTree(object interface{}) (interface{}, error) {
if err != nil {
return nil, err
}
- return &tomlValue{simpleValue, Position{}}, nil
+ return &tomlValue{value: simpleValue, position: Position{}}, nil
}
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go
index 6a7fa17..449f35a 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_write.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go
@@ -4,42 +4,44 @@ import (
"bytes"
"fmt"
"io"
+ "math"
+ "reflect"
"sort"
"strconv"
"strings"
"time"
- "reflect"
)
// 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) {
@@ -49,6 +51,11 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
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.
+ if math.Trunc(value) == value {
+ return strconv.FormatFloat(value, 'f', 1, 32), nil
+ }
return strconv.FormatFloat(value, 'f', -1, 32), nil
case string:
return "\"" + encodeTomlString(value) + "\"", nil
@@ -83,14 +90,14 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
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)
complexValuesKeys := make([]string, 0)
for k := range t.values {
v := t.values[k]
switch v.(type) {
- case *TomlTree, []*TomlTree:
+ case *Tree, []*Tree:
complexValuesKeys = append(complexValuesKeys, k)
default:
simpleValuesKeys = append(simpleValuesKeys, k)
@@ -111,8 +118,24 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
return bytesCount, err
}
- kvRepr := fmt.Sprintf("%s%s = %s\n", indent, k, repr)
- writtenBytesCount, err := w.Write([]byte(kvRepr))
+ 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
+ }
+ }
+
+ 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
@@ -126,12 +149,31 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
if keyspace != "" {
combinedKey = keyspace + "." + combinedKey
}
+ var commented string
+ if t.commented {
+ commented = "# "
+ }
switch node := v.(type) {
// node has to be of those two types given how keys are sorted above
- case *TomlTree:
- tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
- writtenBytesCount, err := w.Write([]byte(tableName))
+ 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
+ }
+ }
+ writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
bytesCount += int64(writtenBytesCount)
if err != nil {
return bytesCount, err
@@ -140,20 +182,17 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
if err != nil {
return bytesCount, err
}
- case []*TomlTree:
+ case []*Tree:
for _, subTree := range node {
- if len(subTree.values) > 0 {
- tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
- writtenBytesCount, err := w.Write([]byte(tableArrayName))
- bytesCount += int64(writtenBytesCount)
- if err != nil {
- return bytesCount, err
- }
-
- bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount)
- if err != nil {
- return bytesCount, err
- }
+ 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)
+ if err != nil {
+ return bytesCount, err
}
}
}
@@ -162,16 +201,28 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
return bytesCount, nil
}
-// WriteTo encode the TomlTree as Toml and writes it to the writer w.
+func writeStrings(w io.Writer, s ...string) (int, error) {
+ var n int
+ for i := range s {
+ b, err := io.WriteString(w, s[i])
+ n += b
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// 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.
-func (t *TomlTree) WriteTo(w io.Writer) (int64, error) {
+func (t *Tree) WriteTo(w io.Writer) (int64, error) {
return t.writeTo(w, "", "", 0)
}
// ToTomlString generates a human-readable representation of the current tree.
// 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 *TomlTree) ToTomlString() (string, error) {
+func (t *Tree) ToTomlString() (string, error) {
var buf bytes.Buffer
_, err := t.WriteTo(&buf)
if err != nil {
@@ -182,32 +233,34 @@ func (t *TomlTree) ToTomlString() (string, error) {
// String generates a human-readable representation of the current tree.
// Alias of ToString. Present to implement the fmt.Stringer interface.
-func (t *TomlTree) String() string {
+func (t *Tree) String() string {
result, _ := t.ToTomlString()
return result
}
// ToMap recursively generates a representation of the tree using Go built-in structures.
// The following types are used:
-// * uint64
-// * int64
-// * bool
-// * string
-// * time.Time
-// * map[string]interface{} (where interface{} is any of this list)
-// * []interface{} (where interface{} is any of this list)
-func (t *TomlTree) ToMap() map[string]interface{} {
+//
+// * bool
+// * float64
+// * int64
+// * string
+// * uint64
+// * time.Time
+// * map[string]interface{} (where interface{} is any of this list)
+// * []interface{} (where interface{} is any of this list)
+func (t *Tree) ToMap() map[string]interface{} {
result := map[string]interface{}{}
for k, v := range t.values {
switch node := v.(type) {
- case []*TomlTree:
+ case []*Tree:
var array []interface{}
for _, item := range node {
array = append(array, item.ToMap())
}
result[k] = array
- case *TomlTree:
+ case *Tree:
result[k] = node.ToMap()
case *tomlValue:
result[k] = node.value