summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Häggqvist <[email protected]>2022-09-14 23:54:17 +0200
committerVictor Häggqvist <[email protected]>2022-09-14 23:54:23 +0200
commit1bbce1aa65e4af84a144b137ea2037004eb2881d (patch)
treefa02ab592746556a884a8e75d480fb3804d26805
parent4e0fb944f18411381366e620ef5193f886957b6f (diff)
go bump
-rw-r--r--go.mod8
-rw-r--r--go.sum12
-rw-r--r--main.go2
-rw-r--r--vendor/github.com/gocarina/gocsv/.travis.yml3
-rw-r--r--vendor/github.com/gocarina/gocsv/README.md2
-rw-r--r--vendor/github.com/gocarina/gocsv/csv.go76
-rw-r--r--vendor/github.com/gocarina/gocsv/decode.go69
-rw-r--r--vendor/github.com/gocarina/gocsv/encode.go32
-rw-r--r--vendor/github.com/gocarina/gocsv/go.mod3
-rw-r--r--vendor/github.com/gocarina/gocsv/reflect.go95
-rw-r--r--vendor/github.com/gocarina/gocsv/safe_csv.go6
-rw-r--r--vendor/github.com/gocarina/gocsv/types.go22
-rw-r--r--vendor/github.com/gocarina/gocsv/unmarshaller.go20
-rw-r--r--vendor/github.com/spf13/pflag/go.mod3
-rw-r--r--vendor/github.com/spf13/pflag/go.sum0
-rw-r--r--vendor/gopkg.in/yaml.v2/.travis.yml16
-rw-r--r--vendor/gopkg.in/yaml.v2/LICENSE201
-rw-r--r--vendor/gopkg.in/yaml.v2/encode.go390
-rw-r--r--vendor/gopkg.in/yaml.v2/go.mod5
-rw-r--r--vendor/gopkg.in/yaml.v2/writerc.go26
-rw-r--r--vendor/gopkg.in/yaml.v3/LICENSE (renamed from vendor/gopkg.in/yaml.v2/LICENSE.libyaml)39
-rw-r--r--vendor/gopkg.in/yaml.v3/NOTICE (renamed from vendor/gopkg.in/yaml.v2/NOTICE)0
-rw-r--r--vendor/gopkg.in/yaml.v3/README.md (renamed from vendor/gopkg.in/yaml.v2/README.md)31
-rw-r--r--vendor/gopkg.in/yaml.v3/apic.go (renamed from vendor/gopkg.in/yaml.v2/apic.go)56
-rw-r--r--vendor/gopkg.in/yaml.v3/decode.go (renamed from vendor/gopkg.in/yaml.v2/decode.go)629
-rw-r--r--vendor/gopkg.in/yaml.v3/emitterc.go (renamed from vendor/gopkg.in/yaml.v2/emitterc.go)413
-rw-r--r--vendor/gopkg.in/yaml.v3/encode.go577
-rw-r--r--vendor/gopkg.in/yaml.v3/parserc.go (renamed from vendor/gopkg.in/yaml.v2/parserc.go)165
-rw-r--r--vendor/gopkg.in/yaml.v3/readerc.go (renamed from vendor/gopkg.in/yaml.v2/readerc.go)24
-rw-r--r--vendor/gopkg.in/yaml.v3/resolve.go (renamed from vendor/gopkg.in/yaml.v2/resolve.go)138
-rw-r--r--vendor/gopkg.in/yaml.v3/scannerc.go (renamed from vendor/gopkg.in/yaml.v2/scannerc.go)363
-rw-r--r--vendor/gopkg.in/yaml.v3/sorter.go (renamed from vendor/gopkg.in/yaml.v2/sorter.go)25
-rw-r--r--vendor/gopkg.in/yaml.v3/writerc.go48
-rw-r--r--vendor/gopkg.in/yaml.v3/yaml.go (renamed from vendor/gopkg.in/yaml.v2/yaml.go)340
-rw-r--r--vendor/gopkg.in/yaml.v3/yamlh.go (renamed from vendor/gopkg.in/yaml.v2/yamlh.go)80
-rw-r--r--vendor/gopkg.in/yaml.v3/yamlprivateh.go (renamed from vendor/gopkg.in/yaml.v2/yamlprivateh.go)37
-rw-r--r--vendor/modules.txt14
37 files changed, 2828 insertions, 1142 deletions
diff --git a/go.mod b/go.mod
index 4d86b7e..890b954 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,9 @@
module go.snilius.com/goboom
-go 1.14
+go 1.19
require (
- github.com/gocarina/gocsv v0.0.0-20200330101823-46266ca37bd3
- github.com/ogier/pflag v0.0.1 // indirect
+ github.com/gocarina/gocsv v0.0.0-20220914091333-ceebdd90b590
github.com/spf13/pflag v1.0.5
- github.com/victorhaggqvist/pflag v0.0.2-0.20160203232644-de7e39409b47 // indirect
- gopkg.in/yaml.v2 v2.2.8
+ gopkg.in/yaml.v3 v3.0.1
)
diff --git a/go.sum b/go.sum
index aaca0c6..6170ad4 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,8 @@
-github.com/gocarina/gocsv v0.0.0-20200330101823-46266ca37bd3 h1:B7k6N+JlLM/u1xrIkpifUfE7GRJsZIYHoHbiAa5cSP4=
-github.com/gocarina/gocsv v0.0.0-20200330101823-46266ca37bd3/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
-github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
+github.com/gocarina/gocsv v0.0.0-20220914091333-ceebdd90b590 h1:kIpPkB0pou96A3BcLtWVtyPyX4Egz+8kcpjCkjmLwvc=
+github.com/gocarina/gocsv v0.0.0-20220914091333-ceebdd90b590/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/victorhaggqvist/pflag v0.0.2-0.20160203232644-de7e39409b47 h1:SiSUP1nVzbAyiveT2jIitSS2dcVwGUVclSTgIxX79Cc=
-github.com/victorhaggqvist/pflag v0.0.2-0.20160203232644-de7e39409b47/go.mod h1:MbC1MDJQV0btWa/MNc+eRjUYCZ4bC0KR1fplO35NvAc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
index 5ccfd0b..3b21834 100644
--- a/main.go
+++ b/main.go
@@ -13,7 +13,7 @@ import (
"github.com/gocarina/gocsv"
flag "github.com/spf13/pflag"
- "gopkg.in/yaml.v2"
+ "gopkg.in/yaml.v3"
)
var version = "0.0.0" // injected at build time
diff --git a/vendor/github.com/gocarina/gocsv/.travis.yml b/vendor/github.com/gocarina/gocsv/.travis.yml
index 4f2ee4d..61c24c6 100644
--- a/vendor/github.com/gocarina/gocsv/.travis.yml
+++ b/vendor/github.com/gocarina/gocsv/.travis.yml
@@ -1 +1,4 @@
language: go
+arch:
+ - amd64
+ - ppc64le
diff --git a/vendor/github.com/gocarina/gocsv/README.md b/vendor/github.com/gocarina/gocsv/README.md
index e606ac7..6f0d344 100644
--- a/vendor/github.com/gocarina/gocsv/README.md
+++ b/vendor/github.com/gocarina/gocsv/README.md
@@ -152,7 +152,7 @@ func main() {
...
- gocsv.SetCSVWriter(func(out io.Writer) *SafeCSVWriter {
+ gocsv.SetCSVWriter(func(out io.Writer) *gocsv.SafeCSVWriter {
writer := csv.NewWriter(out)
writer.Comma = '|'
return gocsv.NewSafeCSVWriter(writer)
diff --git a/vendor/github.com/gocarina/gocsv/csv.go b/vendor/github.com/gocarina/gocsv/csv.go
index 22846c0..3ba3efb 100644
--- a/vendor/github.com/gocarina/gocsv/csv.go
+++ b/vendor/github.com/gocarina/gocsv/csv.go
@@ -127,6 +127,15 @@ func MarshalString(in interface{}) (out string, err error) {
return bufferString.String(), nil
}
+// MarshalStringWithoutHeaders returns the CSV string from the interface.
+func MarshalStringWithoutHeaders(in interface{}) (out string, err error) {
+ bufferString := bytes.NewBufferString(out)
+ if err := MarshalWithoutHeaders(in, bufferString); err != nil {
+ return "", err
+ }
+ return bufferString.String(), nil
+}
+
// MarshalBytes returns the CSV bytes from the interface.
func MarshalBytes(in interface{}) (out []byte, err error) {
bufferString := bytes.NewBuffer(out)
@@ -149,17 +158,22 @@ func MarshalWithoutHeaders(in interface{}, out io.Writer) (err error) {
}
// MarshalChan returns the CSV read from the channel.
-func MarshalChan(c <-chan interface{}, out *SafeCSVWriter) error {
- return writeFromChan(out, c)
+func MarshalChan(c <-chan interface{}, out CSVWriter) error {
+ return writeFromChan(out, c, false)
+}
+
+// MarshalChanWithoutHeaders returns the CSV read from the channel.
+func MarshalChanWithoutHeaders(c <-chan interface{}, out CSVWriter) error {
+ return writeFromChan(out, c, true)
}
// MarshalCSV returns the CSV in writer from the interface.
-func MarshalCSV(in interface{}, out *SafeCSVWriter) (err error) {
+func MarshalCSV(in interface{}, out CSVWriter) (err error) {
return writeTo(out, in, false)
}
// MarshalCSVWithoutHeaders returns the CSV in writer from the interface.
-func MarshalCSVWithoutHeaders(in interface{}, out *SafeCSVWriter) (err error) {
+func MarshalCSVWithoutHeaders(in interface{}, out CSVWriter) (err error) {
return writeTo(out, in, true)
}
@@ -216,6 +230,43 @@ func UnmarshalCSV(in CSVReader, out interface{}) error {
return readTo(csvDecoder{in}, out)
}
+// UnmarshalCSVToMap parses a CSV of 2 columns into a map.
+func UnmarshalCSVToMap(in CSVReader, out interface{}) error {
+ decoder := NewSimpleDecoderFromCSVReader(in)
+ header, err := decoder.GetCSVRow()
+ if err != nil {
+ return err
+ }
+ if len(header) != 2 {
+ return fmt.Errorf("maps can only be created for csv of two columns")
+ }
+ outValue, outType := getConcreteReflectValueAndType(out)
+ if outType.Kind() != reflect.Map {
+ return fmt.Errorf("cannot use " + outType.String() + ", only map supported")
+ }
+ keyType := outType.Key()
+ valueType := outType.Elem()
+ outValue.Set(reflect.MakeMap(outType))
+ for {
+ key := reflect.New(keyType)
+ value := reflect.New(valueType)
+ line, err := decoder.GetCSVRow()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ return err
+ }
+ if err := setField(key, line[0], false); err != nil {
+ return err
+ }
+ if err := setField(value, line[1], false); err != nil {
+ return err
+ }
+ outValue.SetMapIndex(key.Elem(), value.Elem())
+ }
+ return nil
+}
+
// UnmarshalToChan parses the CSV from the reader and send each value in the chan c.
// The channel must have a concrete type.
func UnmarshalToChan(in io.Reader, c interface{}) error {
@@ -278,7 +329,13 @@ func UnmarshalToCallback(in io.Reader, f interface{}) error {
if !notClosed || v.Interface() == nil {
break
}
- valueFunc.Call([]reflect.Value{v})
+ callResults := valueFunc.Call([]reflect.Value{v})
+ // if last returned value from Call() is an error, return it
+ if len(callResults) > 0 {
+ if err, ok := callResults[len(callResults)-1].Interface().(error); ok {
+ return err
+ }
+ }
}
return nil
}
@@ -340,7 +397,7 @@ func UnmarshalToCallbackWithError(in io.Reader, f interface{}) error {
return fmt.Errorf("the given function must have exactly one return value")
}
if !isErrorType(t.Out(0)) {
- return fmt.Errorf("the given function must only return error.")
+ return fmt.Errorf("the given function must only return error")
}
cerr := make(chan error)
@@ -361,6 +418,9 @@ func UnmarshalToCallbackWithError(in io.Reader, f interface{}) error {
}
v, notClosed := c.Recv()
if !notClosed || v.Interface() == nil {
+ if err := <-cerr; err != nil {
+ fErr = err
+ }
break
}
@@ -405,7 +465,7 @@ func UnmarshalStringToCallbackWithError(in string, c interface{}) (err error) {
// CSVToMap creates a simple map from a CSV of 2 columns.
func CSVToMap(in io.Reader) (map[string]string, error) {
decoder := newSimpleDecoderFromReader(in)
- header, err := decoder.getCSVRow()
+ header, err := decoder.GetCSVRow()
if err != nil {
return nil, err
}
@@ -414,7 +474,7 @@ func CSVToMap(in io.Reader) (map[string]string, error) {
}
m := make(map[string]string)
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
diff --git a/vendor/github.com/gocarina/gocsv/decode.go b/vendor/github.com/gocarina/gocsv/decode.go
index a832e84..537251d 100644
--- a/vendor/github.com/gocarina/gocsv/decode.go
+++ b/vendor/github.com/gocarina/gocsv/decode.go
@@ -10,13 +10,13 @@ import (
// Decoder .
type Decoder interface {
- getCSVRows() ([][]string, error)
+ GetCSVRows() ([][]string, error)
}
// SimpleDecoder .
type SimpleDecoder interface {
- getCSVRow() ([]string, error)
- getCSVRows() ([][]string, error)
+ GetCSVRow() ([]string, error)
+ GetCSVRows() ([][]string, error)
}
type CSVReader interface {
@@ -32,6 +32,11 @@ func newSimpleDecoderFromReader(r io.Reader) SimpleDecoder {
return csvDecoder{getCSVReader(r)}
}
+var (
+ ErrEmptyCSVFile = errors.New("empty csv file given")
+ ErrNoStructTags = errors.New("no csv struct tags found")
+)
+
// NewSimpleDecoderFromCSVReader creates a SimpleDecoder, which may be passed
// to the UnmarshalDecoder* family of functions, from a CSV reader. Note that
// encoding/csv.Reader implements CSVReader, so you can pass one of those
@@ -40,11 +45,11 @@ func NewSimpleDecoderFromCSVReader(r CSVReader) SimpleDecoder {
return csvDecoder{r}
}
-func (c csvDecoder) getCSVRows() ([][]string, error) {
+func (c csvDecoder) GetCSVRows() ([][]string, error) {
return c.ReadAll()
}
-func (c csvDecoder) getCSVRow() ([]string, error) {
+func (c csvDecoder) GetCSVRow() ([]string, error) {
return c.Read()
}
@@ -137,19 +142,19 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf
if err := ensureOutInnerType(outInnerType); err != nil {
return err
}
- csvRows, err := decoder.getCSVRows() // Get the CSV csvRows
+ csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows
if err != nil {
return err
}
if len(csvRows) == 0 {
- return errors.New("empty csv file given")
+ return ErrEmptyCSVFile
}
if err := ensureOutCapacity(&outValue, len(csvRows)); err != nil { // Ensure the container is big enough to hold the CSV content
return err
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
headers := normalizeHeaders(csvRows[0])
@@ -203,8 +208,11 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf
continue
}
}
-
- if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct
+ value := csvColumnContent
+ if value == "" {
+ value = fieldInfo.defaultValue
+ }
+ if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, value, fieldInfo.omitEmpty); err != nil { // Set field of struct
parseError := csv.ParseError{
Line: i + 2, //add 2 to account for the header & 0-indexing of arrays
Column: j + 1,
@@ -234,7 +242,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
defer outValue.Close()
- headers, err := decoder.getCSVRow()
+ headers, err := decoder.GetCSVRow()
if err != nil {
return err
}
@@ -246,7 +254,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
csvHeadersLabels := make(map[int]*fieldInfo, len(outInnerStructInfo.Fields)) // Used to store the correspondance header <-> position in CSV
headerCount := map[string]int{}
@@ -272,7 +280,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
i := 0
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
@@ -309,12 +317,12 @@ func readEachWithoutHeaders(decoder SimpleDecoder, c interface{}) error {
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
i := 0
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
@@ -346,19 +354,19 @@ func readToWithoutHeaders(decoder Decoder, out interface{}) error {
if err := ensureOutInnerType(outInnerType); err != nil {
return err
}
- csvRows, err := decoder.getCSVRows() // Get the CSV csvRows
+ csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows
if err != nil {
return err
}
if len(csvRows) == 0 {
- return errors.New("empty csv file given")
+ return ErrEmptyCSVFile
}
if err := ensureOutCapacity(&outValue, len(csvRows)+1); err != nil { // Ensure the container is big enough to hold the CSV content
return err
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
for i, csvRow := range csvRows {
@@ -446,6 +454,31 @@ func setInnerField(outInner *reflect.Value, outInnerWasPointer bool, index []int
}
oi = outInner.Elem()
}
+
+ if oi.Kind() == reflect.Slice || oi.Kind() == reflect.Array {
+ i := index[0]
+
+ // grow slice when needed
+ if i >= oi.Cap() {
+ newcap := oi.Cap() + oi.Cap()/2
+ if newcap < 4 {
+ newcap = 4
+ }
+ newoi := reflect.MakeSlice(oi.Type(), oi.Len(), newcap)
+ reflect.Copy(newoi, oi)
+ oi.Set(newoi)
+ }
+ if i >= oi.Len() {
+ oi.SetLen(i + 1)
+ }
+
+ item := oi.Index(i)
+ if len(index) > 1 {
+ return setInnerField(&item, false, index[1:], value, omitEmpty)
+ }
+ return setField(item, value, omitEmpty)
+ }
+
// because pointers can be nil need to recurse one index at a time and perform nil check
if len(index) > 1 {
nextField := oi.Field(index[0])
diff --git a/vendor/github.com/gocarina/gocsv/encode.go b/vendor/github.com/gocarina/gocsv/encode.go
index 8671533..a7c0e72 100644
--- a/vendor/github.com/gocarina/gocsv/encode.go
+++ b/vendor/github.com/gocarina/gocsv/encode.go
@@ -1,11 +1,16 @@
package gocsv
import (
+ "errors"
"fmt"
"io"
"reflect"
)
+var (
+ ErrChannelIsClosed = errors.New("channel is closed")
+)
+
type encoder struct {
out io.Writer
}
@@ -14,11 +19,11 @@ func newEncoder(out io.Writer) *encoder {
return &encoder{out}
}
-func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
+func writeFromChan(writer CSVWriter, c <-chan interface{}, omitHeaders bool) error {
// Get the first value. It wil determine the header structure.
firstValue, ok := <-c
if !ok {
- return fmt.Errorf("channel is closed")
+ return ErrChannelIsClosed
}
inValue, inType := getConcreteReflectValueAndType(firstValue) // Get the concrete type
if err := ensureStructOrPtr(inType); err != nil {
@@ -30,8 +35,10 @@ func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
}
- if err := writer.Write(csvHeadersLabels); err != nil {
- return err
+ if !omitHeaders {
+ if err := writer.Write(csvHeadersLabels); err != nil {
+ return err
+ }
}
write := func(val reflect.Value) error {
for j, fieldInfo := range inInnerStructInfo.Fields {
@@ -63,7 +70,7 @@ func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
return writer.Error()
}
-func writeTo(writer *SafeCSVWriter, in interface{}, omitHeaders bool) error {
+func writeTo(writer CSVWriter, in interface{}, omitHeaders bool) error {
inValue, inType := getConcreteReflectValueAndType(in) // Get the concrete type (not pointer) (Slice<?> or Array<?>)
if err := ensureInType(inType); err != nil {
return err
@@ -138,6 +145,21 @@ func getInnerField(outInner reflect.Value, outInnerWasPointer bool, index []int)
}
oi = outInner.Elem()
}
+
+ if oi.Kind() == reflect.Slice || oi.Kind() == reflect.Array {
+ i := index[0]
+
+ if i >= oi.Len() {
+ return "", nil
+ }
+
+ item := oi.Index(i)
+ if len(index) > 1 {
+ return getInnerField(item, false, index[1:])
+ }
+ return getFieldAsString(item)
+ }
+
// because pointers can be nil need to recurse one index at a time and perform nil check
if len(index) > 1 {
nextField := oi.Field(index[0])
diff --git a/vendor/github.com/gocarina/gocsv/go.mod b/vendor/github.com/gocarina/gocsv/go.mod
deleted file mode 100644
index c746a5a..0000000
--- a/vendor/github.com/gocarina/gocsv/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/gocarina/gocsv
-
-go 1.13
diff --git a/vendor/github.com/gocarina/gocsv/reflect.go b/vendor/github.com/gocarina/gocsv/reflect.go
index dfc63b3..309f80b 100644
--- a/vendor/github.com/gocarina/gocsv/reflect.go
+++ b/vendor/github.com/gocarina/gocsv/reflect.go
@@ -1,7 +1,9 @@
package gocsv
import (
+ "fmt"
"reflect"
+ "strconv"
"strings"
"sync"
)
@@ -17,9 +19,10 @@ type structInfo struct {
// Each IndexChain element before the last is the index of an the embedded struct field
// that defines Key as a tag
type fieldInfo struct {
- keys []string
- omitEmpty bool
- IndexChain []int
+ keys []string
+ omitEmpty bool
+ IndexChain []int
+ defaultValue string
}
func (f fieldInfo) getFirstKey() string {
@@ -64,18 +67,17 @@ func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo {
var cpy = make([]int, len(parentIndexChain))
copy(cpy, parentIndexChain)
indexChain := append(cpy, i)
-
// if the field is a pointer to a struct, follow the pointer then create fieldinfo for each field
if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
- if !(canMarshal(field.Type.Elem())) {
+ if !(canMarshal(field.Type.Elem()) || canMarshal(field.Type)) {
fieldsList = append(fieldsList, getFieldInfos(field.Type.Elem(), indexChain)...)
}
}
// if the field is a struct, create a fieldInfo for each of its fields
if field.Type.Kind() == reflect.Struct {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
if !(canMarshal(field.Type)) {
fieldsList = append(fieldsList, getFieldInfos(field.Type, indexChain)...)
@@ -87,26 +89,91 @@ func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo {
continue
}
- fieldInfo := fieldInfo{IndexChain: indexChain}
+ currFieldInfo := fieldInfo{IndexChain: indexChain}
fieldTag := field.Tag.Get(TagName)
fieldTags := strings.Split(fieldTag, TagSeparator)
filteredTags := []string{}
for _, fieldTagEntry := range fieldTags {
- if fieldTagEntry != "omitempty" {
- filteredTags = append(filteredTags, normalizeName(fieldTagEntry))
+ trimmedFieldTagEntry := strings.TrimSpace(fieldTagEntry) // handles cases like `csv:"foo, omitempty, default=test"`
+ if trimmedFieldTagEntry == "omitempty" {
+ currFieldInfo.omitEmpty = true
+ } else if strings.HasPrefix(trimmedFieldTagEntry, "default=") {
+ currFieldInfo.defaultValue = strings.TrimPrefix(trimmedFieldTagEntry, "default=")
} else {
- fieldInfo.omitEmpty = true
+ filteredTags = append(filteredTags, normalizeName(trimmedFieldTagEntry))
}
}
if len(filteredTags) == 1 && filteredTags[0] == "-" {
continue
} else if len(filteredTags) > 0 && filteredTags[0] != "" {
- fieldInfo.keys = filteredTags
+ currFieldInfo.keys = filteredTags
+ } else {
+ currFieldInfo.keys = []string{normalizeName(field.Name)}
+ }
+
+ if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array {
+ var arrayLength = -1
+ if arrayTag, ok := field.Tag.Lookup(TagName + "[]"); ok {
+ arrayLength, _ = strconv.Atoi(arrayTag)
+ }
+
+ // When the field is a slice/array of structs, create a fieldInfo for each index and each field
+ if field.Type.Elem().Kind() == reflect.Struct {
+ fieldInfos := getFieldInfos(field.Type.Elem(), []int{})
+
+ for idx := 0; idx < arrayLength; idx++ {
+ // copy index chain and append array index
+ var cpy2 = make([]int, len(indexChain))
+ copy(cpy2, indexChain)
+ arrayIndexChain := append(cpy2, idx)
+ for _, childFieldInfo := range fieldInfos {
+ // copy array index chain and append array index
+ var cpy3 = make([]int, len(arrayIndexChain))
+ copy(cpy3, arrayIndexChain)
+
+ arrayFieldInfo := fieldInfo{
+ IndexChain: append(cpy3, childFieldInfo.IndexChain...),
+ omitEmpty: childFieldInfo.omitEmpty,
+ defaultValue: childFieldInfo.defaultValue,
+ }
+
+ // create cartesian product of keys
+ // eg: array field keys x struct field keys
+ for _, akey := range currFieldInfo.keys {
+ for _, fkey := range childFieldInfo.keys {
+ arrayFieldInfo.keys = append(arrayFieldInfo.keys, normalizeName(fmt.Sprintf("%s[%d].%s", akey, idx, fkey)))
+ }
+ }
+
+ fieldsList = append(fieldsList, arrayFieldInfo)
+ }
+ }
+ } else if arrayLength > 0 {
+ // When the field is a slice/array of primitives, create a fieldInfo for each index
+ for idx := 0; idx < arrayLength; idx++ {
+ // copy index chain and append array index
+ var cpy2 = make([]int, len(indexChain))
+ copy(cpy2, indexChain)
+
+ arrayFieldInfo := fieldInfo{
+ IndexChain: append(cpy2, idx),
+ omitEmpty: currFieldInfo.omitEmpty,
+ defaultValue: currFieldInfo.defaultValue,
+ }
+
+ for _, akey := range currFieldInfo.keys {
+ arrayFieldInfo.keys = append(arrayFieldInfo.keys, normalizeName(fmt.Sprintf("%s[%d]", akey, idx)))
+ }
+
+ fieldsList = append(fieldsList, arrayFieldInfo)
+ }
+ } else {
+ fieldsList = append(fieldsList, currFieldInfo)
+ }
} else {
- fieldInfo.keys = []string{normalizeName(field.Name)}
+ fieldsList = append(fieldsList, currFieldInfo)
}
- fieldsList = append(fieldsList, fieldInfo)
}
return fieldsList
}
diff --git a/vendor/github.com/gocarina/gocsv/safe_csv.go b/vendor/github.com/gocarina/gocsv/safe_csv.go
index 4b2882f..858b078 100644
--- a/vendor/github.com/gocarina/gocsv/safe_csv.go
+++ b/vendor/github.com/gocarina/gocsv/safe_csv.go
@@ -6,6 +6,12 @@ import (
"sync"
)
+type CSVWriter interface {
+ Write(row []string) error
+ Flush()
+ Error() error
+}
+
type SafeCSVWriter struct {
*csv.Writer
m sync.Mutex
diff --git a/vendor/github.com/gocarina/gocsv/types.go b/vendor/github.com/gocarina/gocsv/types.go
index a5dda89..537151a 100644
--- a/vendor/github.com/gocarina/gocsv/types.go
+++ b/vendor/github.com/gocarina/gocsv/types.go
@@ -182,6 +182,7 @@ func toFloat(in interface{}) (float64, error) {
if s == "" {
return 0, nil
}
+ s = strings.Replace(s, ",", ".", -1)
return strconv.ParseFloat(s, 64)
case reflect.Bool:
if inValue.Bool() {
@@ -279,6 +280,10 @@ func setField(field reflect.Value, value string, omitEmpty bool) error {
}
field.SetFloat(f)
case reflect.Slice, reflect.Struct:
+ if value == "" {
+ return nil
+ }
+
err := json.Unmarshal([]byte(value), field.Addr().Interface())
if err != nil {
return err
@@ -300,8 +305,6 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
return "", nil
}
return getFieldAsString(field.Elem())
- case reflect.String:
- return field.String(), nil
default:
// Check if field is go native type
switch field.Interface().(type) {
@@ -363,6 +366,15 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
if err != nil {
return str, err
}
+ case reflect.Slice:
+ fallthrough
+ case reflect.Array:
+ b, err := json.Marshal(field.Addr().Interface())
+ if err != nil {
+ return str, err
+ }
+
+ str = string(b)
}
} else {
return str, nil
@@ -376,11 +388,13 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
// Un/serializations helpers
func canMarshal(t reflect.Type) bool {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
_, canMarshalText := t.MethodByName("MarshalText")
_, canMarshalCSV := t.MethodByName("MarshalCSV")
- return canMarshalCSV || canMarshalText
+ _, canUnmarshalText := t.MethodByName("UnmarshalText")
+ _, canUnmarshalCSV := t.MethodByName("UnmarshalCSV")
+ return canMarshalCSV || canMarshalText || canUnmarshalText || canUnmarshalCSV
}
func unmarshall(field reflect.Value, value string) error {
diff --git a/vendor/github.com/gocarina/gocsv/unmarshaller.go b/vendor/github.com/gocarina/gocsv/unmarshaller.go
index 87e6a8f..50d528e 100644
--- a/vendor/github.com/gocarina/gocsv/unmarshaller.go
+++ b/vendor/github.com/gocarina/gocsv/unmarshaller.go
@@ -2,7 +2,6 @@ package gocsv
import (
"encoding/csv"
- "errors"
"fmt"
"reflect"
)
@@ -15,6 +14,7 @@ type Unmarshaller struct {
MismatchedHeaders []string
MismatchedStructFields []string
outType reflect.Type
+ out interface{}
}
// NewUnmarshaller creates an unmarshaller from a csv.Reader and a struct.
@@ -66,7 +66,7 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error {
}
structInfo := getStructInfo(concreteType) // Get struct info to get CSV annotations.
if len(structInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
csvHeadersLabels := make([]*fieldInfo, len(headers)) // Used to store the corresponding header <-> position in CSV
headerCount := map[string]int{}
@@ -91,6 +91,7 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error {
um.fieldInfoMap = csvHeadersLabels
um.MismatchedHeaders = mismatchHeaderFields(structInfo.Fields, headers)
um.MismatchedStructFields = mismatchStructFields(structInfo.Fields, headers)
+ um.out = s
return nil
}
@@ -116,3 +117,18 @@ func (um *Unmarshaller) unmarshalRow(row []string, unmatched map[string]string)
}
return outValue.Interface(), nil
}
+
+// RenormalizeHeaders will remap the header names based on the headerNormalizer.
+// This can be used to map a CSV to a struct where the CSV header names do not match in the file but a mapping is known
+func (um *Unmarshaller) RenormalizeHeaders(headerNormalizer func([]string) []string) error {
+ headers := um.Headers
+ if headerNormalizer != nil {
+ headers = headerNormalizer(headers)
+ }
+ err := validate(um, um.out, headers)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/spf13/pflag/go.mod b/vendor/github.com/spf13/pflag/go.mod
deleted file mode 100644
index b2287ee..0000000
--- a/vendor/github.com/spf13/pflag/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/spf13/pflag
-
-go 1.12
diff --git a/vendor/github.com/spf13/pflag/go.sum b/vendor/github.com/spf13/pflag/go.sum
deleted file mode 100644
index e69de29..0000000
--- a/vendor/github.com/spf13/pflag/go.sum
+++ /dev/null
diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml
deleted file mode 100644
index 055480b..0000000
--- a/vendor/gopkg.in/yaml.v2/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: go
-
-go:
- - "1.4.x"
- - "1.5.x"
- - "1.6.x"
- - "1.7.x"
- - "1.8.x"
- - "1.9.x"
- - "1.10.x"
- - "1.11.x"
- - "1.12.x"
- - "1.13.x"
- - "tip"
-
-go_import_path: gopkg.in/yaml.v2
diff --git a/vendor/gopkg.in/yaml.v2/LICENSE b/vendor/gopkg.in/yaml.v2/LICENSE
deleted file mode 100644
index 8dada3e..0000000
--- a/vendor/gopkg.in/yaml.v2/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright {yyyy} {name of copyright owner}
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v2/encode.go b/vendor/gopkg.in/yaml.v2/encode.go
deleted file mode 100644
index 0ee738e..0000000
--- a/vendor/gopkg.in/yaml.v2/encode.go
+++ /dev/null
@@ -1,390 +0,0 @@
-package yaml
-
-import (
- "encoding"
- "fmt"
- "io"
- "reflect"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "time"
- "unicode/utf8"
-)
-
-// jsonNumber is the interface of the encoding/json.Number datatype.
-// Repeating the interface here avoids a dependency on encoding/json, and also
-// supports other libraries like jsoniter, which use a similar datatype with
-// the same interface. Detecting this interface is useful when dealing with
-// structures containing json.Number, which is a string under the hood. The
-// encoder should prefer the use of Int64(), Float64() and string(), in that
-// order, when encoding this type.
-type jsonNumber interface {
- Float64() (float64, error)
- Int64() (int64, error)
- String() string
-}
-
-type encoder struct {
- emitter yaml_emitter_t
- event yaml_event_t
- out []byte
- flow bool
- // doneInit holds whether the initial stream_start_event has been
- // emitted.
- doneInit bool
-}
-
-func newEncoder() *encoder {
- e := &encoder{}
- yaml_emitter_initialize(&e.emitter)
- yaml_emitter_set_output_string(&e.emitter, &e.out)
- yaml_emitter_set_unicode(&e.emitter, true)
- return e
-}
-
-func newEncoderWithWriter(w io.Writer) *encoder {
- e := &encoder{}
- yaml_emitter_initialize(&e.emitter)
- yaml_emitter_set_output_writer(&e.emitter, w)
- yaml_emitter_set_unicode(&e.emitter, true)
- return e
-}
-
-func (e *encoder) init() {
- if e.doneInit {
- return
- }
- yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
- e.emit()
- e.doneInit = true
-}
-
-func (e *encoder) finish() {
- e.emitter.open_ended = false
- yaml_stream_end_event_initialize(&e.event)
- e.emit()
-}
-
-func (e *encoder) destroy() {
- yaml_emitter_delete(&e.emitter)
-}
-
-func (e *encoder) emit() {
- // This will internally delete the e.event value.
- e.must(yaml_emitter_emit(&e.emitter, &e.event))
-}
-
-func (e *encoder) must(ok bool) {
- if !ok {
- msg := e.emitter.problem
- if msg == "" {
- msg = "unknown problem generating YAML content"
- }
- failf("%s", msg)
- }
-}
-
-func (e *encoder) marshalDoc(tag string, in reflect.Value) {
- e.init()
- yaml_document_start_event_initialize(&e.event, nil, nil, true)
- e.emit()
- e.marshal(tag, in)
- yaml_document_end_event_initialize(&e.event, true)
- e.emit()
-}
-
-func (e *encoder) marshal(tag string, in reflect.Value) {
- if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
- e.nilv()
- return
- }
- iface := in.Interface()
- switch m := iface.(type) {
- case jsonNumber:
- integer, err := m.Int64()
- if err == nil {
- // In this case the json.Number is a valid int64
- in = reflect.ValueOf(integer)
- break
- }
- float, err := m.Float64()
- if err == nil {
- // In this case the json.Number is a valid float64
- in = reflect.ValueOf(float)
- break
- }
- // fallback case - no number could be obtained
- in = reflect.ValueOf(m.String())
- case time.Time, *time.Time:
- // Although time.Time implements TextMarshaler,
- // we don't want to treat it as a string for YAML
- // purposes because YAML has special support for
- // timestamps.
- case Marshaler:
- v, err := m.MarshalYAML()
- if err != nil {
- fail(err)
- }
- if v == nil {
- e.nilv()
- return
- }
- in = reflect.ValueOf(v)
- case encoding.TextMarshaler:
- text, err := m.MarshalText()
- if err != nil {
- fail(err)
- }
- in = reflect.ValueOf(string(text))
- case nil:
- e.nilv()
- return
- }
- switch in.Kind() {
- case reflect.Interface:
- e.marshal(tag, in.Elem())
- case reflect.Map:
- e.mapv(tag, in)
- case reflect.Ptr:
- if in.Type() == ptrTimeType {
- e.timev(tag, in.Elem())
- } else {
- e.marshal(tag, in.Elem())
- }
- case reflect.Struct:
- if in.Type() == timeType {
- e.timev(tag, in)
- } else {
- e.structv(tag, in)
- }
- case reflect.Slice, reflect.Array:
- if in.Type().Elem() == mapItemType {
- e.itemsv(tag, in)
- } else {
- e.slicev(tag, in)
- }
- case reflect.String:
- e.stringv(tag, in)
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- if in.Type() == durationType {
- e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
- } else {
- e.intv(tag, in)
- }
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- e.uintv(tag, in)
- case reflect.Float32, reflect.Float64:
- e.floatv(tag, in)
- case reflect.Bool:
- e.boolv(tag, in)
- default:
- panic("cannot marshal type: " + in.Type().String())
- }
-}
-
-func (e *encoder) mapv(tag string, in reflect.Value) {
- e.mappingv(tag, func() {
- keys := keyList(in.MapKeys())
- sort.Sort(keys)
- for _, k := range keys {
- e.marshal("", k)
- e.marshal("", in.MapIndex(k))
- }
- })
-}
-
-func (e *encoder) itemsv(tag string, in reflect.Value) {
- e.mappingv(tag, func() {
- slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
- for _, item := range slice {
- e.marshal("", reflect.ValueOf(item.Key))
- e.marshal("", reflect.ValueOf(item.Value))
- }
- })
-}
-
-func (e *encoder) structv(tag string, in reflect.Value) {
- sinfo, err := getStructInfo(in.Type())
- if err != nil {
- panic(err)
- }
- e.mappingv(tag, func() {
- for _, info := range sinfo.FieldsList {
- var value reflect.Value
- if info.Inline == nil {
- value = in.Field(info.Num)
- } else {
- value = in.FieldByIndex(info.Inline)
- }
- if info.OmitEmpty && isZero(value) {
- continue
- }
- e.marshal("", reflect.ValueOf(info.Key))
- e.flow = info.Flow
- e.marshal("", value)
- }
- if sinfo.InlineMap >= 0 {
- m := in.Field(sinfo.InlineMap)
- if m.Len() > 0 {
- e.flow = false
- keys := keyList(m.MapKeys())
- sort.Sort(keys)
- for _, k := range keys {
- if _, found := sinfo.FieldsMap[k.String()]; found {
- panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
- }
- e.marshal("", k)
- e.flow = false
- e.marshal("", m.MapIndex(k))
- }
- }
- }
- })
-}
-
-func (e *encoder) mappingv(tag string, f func()) {
- implicit := tag == ""
- style := yaml_BLOCK_MAPPING_STYLE
- if e.flow {
- e.flow = false
- style = yaml_FLOW_MAPPING_STYLE
- }
- yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
- e.emit()
- f()
- yaml_mapping_end_event_initialize(&e.event)
- e.emit()
-}
-
-func (e *encoder) slicev(tag string, in reflect.Value) {
- implicit := tag == ""
- style := yaml_BLOCK_SEQUENCE_STYLE
- if e.flow {
- e.flow = false
- style = yaml_FLOW_SEQUENCE_STYLE
- }
- e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
- e.emit()
- n := in.Len()
- for i := 0; i < n; i++ {
- e.marshal("", in.Index(i))
- }
- e.must(yaml_sequence_end_event_initialize(&e.event))
- e.emit()
-}
-
-// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
-//
-// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
-// in YAML 1.2 and by this package, but these should be marshalled quoted for
-// the time being for compatibility with other parsers.
-func isBase60Float(s string) (result bool) {
- // Fast path.
- if s == "" {
- return false
- }
- c := s[0]
- if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
- return false
- }
- // Do the full match.
- return base60float.MatchString(s)
-}
-
-// From http://yaml.org/type/float.html, except the regular expression there
-// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
-var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
-
-func (e *encoder) stringv(tag string, in reflect.Value) {
- var style yaml_scalar_style_t
- s := in.String()
- canUsePlain := true
- switch {
- case !utf8.ValidString(s):
- if tag == yaml_BINARY_TAG {
- failf("explicitly tagged !!binary data must be base64-encoded")
- }
- if tag != "" {
- failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
- }
- // It can't be encoded directly as YAML so use a binary tag
- // and encode it as base64.
- tag = yaml_BINARY_TAG
- s = encodeBase64(s)
- case tag == "":
- // Check to see if it would resolve to a specific
- // tag when encoded unquoted. If it doesn't,
- // there's no need to quote it.
- rtag, _ := resolve("", s)
- canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
- }
- // Note: it's possible for user code to emit invalid YAML
- // if they explicitly specify a tag and a string containing
- // text that's incompatible with that tag.
- switch {
- case strings.Contains(s, "\n"):
- style = yaml_LITERAL_SCALAR_STYLE
- case canUsePlain:
- style = yaml_PLAIN_SCALAR_STYLE
- default:
- style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
- }
- e.emitScalar(s, "", tag, style)
-}
-
-func (e *encoder) boolv(tag string, in reflect.Value) {
- var s string
- if in.Bool() {
- s = "true"
- } else {
- s = "false"
- }
- e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) intv(tag string, in reflect.Value) {
- s := strconv.FormatInt(in.Int(), 10)
- e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) uintv(tag string, in reflect.Value) {
- s := strconv.FormatUint(in.Uint(), 10)
- e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) timev(tag string, in reflect.Value) {
- t := in.Interface().(time.Time)
- s := t.Format(time.RFC3339Nano)
- e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) floatv(tag string, in reflect.Value) {
- // Issue #352: When formatting, use the precision of the underlying value
- precision := 64
- if in.Kind() == reflect.Float32 {
- precision = 32
- }
-
- s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
- switch s {
- case "+Inf":
- s = ".inf"
- case "-Inf":
- s = "-.inf"
- case "NaN":
- s = ".nan"
- }
- e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) nilv() {
- e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
- implicit := tag == ""
- e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
- e.emit()
-}
diff --git a/vendor/gopkg.in/yaml.v2/go.mod b/vendor/gopkg.in/yaml.v2/go.mod
deleted file mode 100644
index 1934e87..0000000
--- a/vendor/gopkg.in/yaml.v2/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module "gopkg.in/yaml.v2"
-
-require (
- "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
-)
diff --git a/vendor/gopkg.in/yaml.v2/writerc.go b/vendor/gopkg.in/yaml.v2/writerc.go
deleted file mode 100644
index a2dde60..0000000
--- a/vendor/gopkg.in/yaml.v2/writerc.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package yaml
-
-// Set the writer error and return false.
-func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
- emitter.error = yaml_WRITER_ERROR
- emitter.problem = problem
- return false
-}
-
-// Flush the output buffer.
-func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
- if emitter.write_handler == nil {
- panic("write handler not set")
- }
-
- // Check if the buffer is empty.
- if emitter.buffer_pos == 0 {
- return true
- }
-
- if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
- return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
- }
- emitter.buffer_pos = 0
- return true
-}
diff --git a/vendor/gopkg.in/yaml.v2/LICENSE.libyaml b/vendor/gopkg.in/yaml.v3/LICENSE
index 8da58fb..2683e4b 100644
--- a/vendor/gopkg.in/yaml.v2/LICENSE.libyaml
+++ b/vendor/gopkg.in/yaml.v3/LICENSE
@@ -1,16 +1,17 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
The following files were ported to Go from C files of libyaml, and thus
-are still covered by their original copyright and license:
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
- apic.go
- emitterc.go
- parserc.go
- readerc.go
- scannerc.go
- writerc.go
- yamlh.go
- yamlprivateh.go
+ apic.go emitterc.go parserc.go readerc.go scannerc.go
+ writerc.go yamlh.go yamlprivateh.go
-Copyright (c) 2006 Kirill Simonov
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@@ -29,3 +30,21 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v2/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE
index 866d74a..866d74a 100644
--- a/vendor/gopkg.in/yaml.v2/NOTICE
+++ b/vendor/gopkg.in/yaml.v3/NOTICE
diff --git a/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v3/README.md
index b50c6e8..08eb1ba 100644
--- a/vendor/gopkg.in/yaml.v2/README.md
+++ b/vendor/gopkg.in/yaml.v3/README.md
@@ -12,7 +12,23 @@ C library to parse and generate YAML data quickly and reliably.
Compatibility
-------------
-The yaml package supports most of YAML 1.1 and 1.2, including support for
+The yaml package supports most of YAML 1.2, but preserves some behavior
+from 1.1 for backwards compatibility.
+
+Specifically, as of v3 of the yaml package:
+
+ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
+ decoded into a typed bool value. Otherwise they behave as a string. Booleans
+ in YAML 1.2 are _true/false_ only.
+ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
+ as specified in YAML 1.2, because most parsers still use the old format.
+ Octals in the _0o777_ format are supported though, so new files work.
+ - Does not support base-60 floats. These are gone from YAML 1.2, and were
+ actually never supported by this package as it's clearly a poor choice.
+
+and offers backwards
+compatibility with YAML 1.1 in some cases.
+1.2, including support for
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
implemented, and base-60 floats from YAML 1.1 are purposefully not
supported since they're a poor design and are gone in YAML 1.2.
@@ -20,29 +36,30 @@ supported since they're a poor design and are gone in YAML 1.2.
Installation and usage
----------------------
-The import path for the package is *gopkg.in/yaml.v2*.
+The import path for the package is *gopkg.in/yaml.v3*.
To install it, run:
- go get gopkg.in/yaml.v2
+ go get gopkg.in/yaml.v3
API documentation
-----------------
If opened in a browser, the import path itself leads to the API documentation:
- * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
+ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
API stability
-------------
-The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
+The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
License
-------
-The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
Example
@@ -55,7 +72,7 @@ import (
"fmt"
"log"
- "gopkg.in/yaml.v2"
+ "gopkg.in/yaml.v3"
)
var data = `
diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v3/apic.go
index 1f7e87e..ae7d049 100644
--- a/vendor/gopkg.in/yaml.v2/apic.go
+++ b/vendor/gopkg.in/yaml.v3/apic.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -86,6 +108,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) {
raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size),
+ best_width: -1,
}
}
@@ -138,7 +161,7 @@ func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
emitter.canonical = canonical
}
-//// Set the indentation increment.
+// Set the indentation increment.
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
if indent < 2 || indent > 9 {
indent = 2
@@ -288,29 +311,14 @@ func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
}
}
-///*
-// * Create ALIAS.
-// */
-//
-//YAML_DECLARE(int)
-//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
-//{
-// mark yaml_mark_t = { 0, 0, 0 }
-// anchor_copy *yaml_char_t = NULL
-//
-// assert(event) // Non-NULL event object is expected.
-// assert(anchor) // Non-NULL anchor is expected.
-//
-// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
-//
-// anchor_copy = yaml_strdup(anchor)
-// if (!anchor_copy)
-// return 0
-//
-// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
-//
-// return 1
-//}
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ anchor: anchor,
+ }
+ return true
+}
// Create SCALAR.
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v3/decode.go
index 129bc2a..0173b69 100644
--- a/vendor/gopkg.in/yaml.v2/decode.go
+++ b/vendor/gopkg.in/yaml.v3/decode.go
@@ -1,3 +1,18 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package yaml
import (
@@ -11,34 +26,16 @@ import (
"time"
)
-const (
- documentNode = 1 << iota
- mappingNode
- sequenceNode
- scalarNode
- aliasNode
-)
-
-type node struct {
- kind int
- line, column int
- tag string
- // For an alias node, alias holds the resolved alias.
- alias *node
- value string
- implicit bool
- children []*node
- anchors map[string]*node
-}
-
// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.
type parser struct {
parser yaml_parser_t
event yaml_event_t
- doc *node
+ doc *Node
+ anchors map[string]*Node
doneInit bool
+ textless bool
}
func newParser(b []byte) *parser {
@@ -66,6 +63,7 @@ func (p *parser) init() {
if p.doneInit {
return
}
+ p.anchors = make(map[string]*Node)
p.expect(yaml_STREAM_START_EVENT)
p.doneInit = true
}
@@ -102,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t {
if p.event.typ != yaml_NO_EVENT {
return p.event.typ
}
- if !yaml_parser_parse(&p.parser, &p.event) {
+ // It's curious choice from the underlying API to generally return a
+ // positive result on success, but on this case return true in an error
+ // scenario. This was the source of bugs in the past (issue #666).
+ if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
p.fail()
}
return p.event.typ
@@ -111,14 +112,18 @@ func (p *parser) peek() yaml_event_type_t {
func (p *parser) fail() {
var where string
var line int
- if p.parser.problem_mark.line != 0 {
+ if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.problem_mark.line != 0 {
line = p.parser.problem_mark.line
// Scanner errors don't iterate line before returning error
if p.parser.error == yaml_SCANNER_ERROR {
line++
}
- } else if p.parser.context_mark.line != 0 {
- line = p.parser.context_mark.line
}
if line != 0 {
where = "line " + strconv.Itoa(line) + ": "
@@ -132,13 +137,14 @@ func (p *parser) fail() {
failf("%s%s", where, msg)
}
-func (p *parser) anchor(n *node, anchor []byte) {
+func (p *parser) anchor(n *Node, anchor []byte) {
if anchor != nil {
- p.doc.anchors[string(anchor)] = n
+ n.Anchor = string(anchor)
+ p.anchors[n.Anchor] = n
}
}
-func (p *parser) parse() *node {
+func (p *parser) parse() *Node {
p.init()
switch p.peek() {
case yaml_SCALAR_EVENT:
@@ -154,67 +160,148 @@ func (p *parser) parse() *node {
case yaml_STREAM_END_EVENT:
// Happens when attempting to decode an empty buffer.
return nil
+ case yaml_TAIL_COMMENT_EVENT:
+ panic("internal error: unexpected tail comment event (please report)")
default:
- panic("attempted to parse unknown event: " + p.event.typ.String())
+ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
}
}
-func (p *parser) node(kind int) *node {
- return &node{
- kind: kind,
- line: p.event.start_mark.line,
- column: p.event.start_mark.column,
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+ var style Style
+ if tag != "" && tag != "!" {
+ tag = shortTag(tag)
+ style = TaggedStyle
+ } else if defaultTag != "" {
+ tag = defaultTag
+ } else if kind == ScalarNode {
+ tag, _ = resolve("", value)
}
+ n := &Node{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ Style: style,
+ }
+ if !p.textless {
+ n.Line = p.event.start_mark.line + 1
+ n.Column = p.event.start_mark.column + 1
+ n.HeadComment = string(p.event.head_comment)
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ }
+ return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+ child := p.parse()
+ parent.Content = append(parent.Content, child)
+ return child
}
-func (p *parser) document() *node {
- n := p.node(documentNode)
- n.anchors = make(map[string]*node)
+func (p *parser) document() *Node {
+ n := p.node(DocumentNode, "", "", "")
p.doc = n
p.expect(yaml_DOCUMENT_START_EVENT)
- n.children = append(n.children, p.parse())
+ p.parseChild(n)
+ if p.peek() == yaml_DOCUMENT_END_EVENT {
+ n.FootComment = string(p.event.foot_comment)
+ }
p.expect(yaml_DOCUMENT_END_EVENT)
return n
}
-func (p *parser) alias() *node {
- n := p.node(aliasNode)
- n.value = string(p.event.anchor)
- n.alias = p.doc.anchors[n.value]
- if n.alias == nil {
- failf("unknown anchor '%s' referenced", n.value)
+func (p *parser) alias() *Node {
+ n := p.node(AliasNode, "", "", string(p.event.anchor))
+ n.Alias = p.anchors[n.Value]
+ if n.Alias == nil {
+ failf("unknown anchor '%s' referenced", n.Value)
}
p.expect(yaml_ALIAS_EVENT)
return n
}
-func (p *parser) scalar() *node {
- n := p.node(scalarNode)
- n.value = string(p.event.value)
- n.tag = string(p.event.tag)
- n.implicit = p.event.implicit
+func (p *parser) scalar() *Node {
+ var parsedStyle = p.event.scalar_style()
+ var nodeStyle Style
+ switch {
+ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = DoubleQuotedStyle
+ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = SingleQuotedStyle
+ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+ nodeStyle = LiteralStyle
+ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+ nodeStyle = FoldedStyle
+ }
+ var nodeValue = string(p.event.value)
+ var nodeTag = string(p.event.tag)
+ var defaultTag string
+ if nodeStyle == 0 {
+ if nodeValue == "<<" {
+ defaultTag = mergeTag
+ }
+ } else {
+ defaultTag = strTag
+ }
+ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+ n.Style |= nodeStyle
p.anchor(n, p.event.anchor)
p.expect(yaml_SCALAR_EVENT)
return n
}
-func (p *parser) sequence() *node {
- n := p.node(sequenceNode)
+func (p *parser) sequence() *Node {
+ n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+ n.Style |= FlowStyle
+ }
p.anchor(n, p.event.anchor)
p.expect(yaml_SEQUENCE_START_EVENT)
for p.peek() != yaml_SEQUENCE_END_EVENT {
- n.children = append(n.children, p.parse())
+ p.parseChild(n)
}
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
p.expect(yaml_SEQUENCE_END_EVENT)
return n
}
-func (p *parser) mapping() *node {
- n := p.node(mappingNode)
+func (p *parser) mapping() *Node {
+ n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+ block := true
+ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+ block = false
+ n.Style |= FlowStyle
+ }
p.anchor(n, p.event.anchor)
p.expect(yaml_MAPPING_START_EVENT)
for p.peek() != yaml_MAPPING_END_EVENT {
- n.children = append(n.children, p.parse(), p.parse())
+ k := p.parseChild(n)
+ if block && k.FootComment != "" {
+ // Must be a foot comment for the prior value when being dedented.
+ if len(n.Content) > 2 {
+ n.Content[len(n.Content)-3].FootComment = k.FootComment
+ k.FootComment = ""
+ }
+ }
+ v := p.parseChild(n)
+ if k.FootComment == "" && v.FootComment != "" {
+ k.FootComment = v.FootComment
+ v.FootComment = ""
+ }
+ if p.peek() == yaml_TAIL_COMMENT_EVENT {
+ if k.FootComment == "" {
+ k.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_TAIL_COMMENT_EVENT)
+ }
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+ n.Content[len(n.Content)-2].FootComment = n.FootComment
+ n.FootComment = ""
}
p.expect(yaml_MAPPING_END_EVENT)
return n
@@ -224,48 +311,70 @@ func (p *parser) mapping() *node {
// Decoder, unmarshals a node into a provided value.
type decoder struct {
- doc *node
- aliases map[*node]bool
- mapType reflect.Type
+ doc *Node
+ aliases map[*Node]bool
terrors []string
- strict bool
+ stringMapType reflect.Type
+ generalMapType reflect.Type
+
+ knownFields bool
+ uniqueKeys bool
decodeCount int
aliasCount int
aliasDepth int
+
+ mergedFields map[interface{}]bool
}
var (
- mapItemType = reflect.TypeOf(MapItem{})
+ nodeType = reflect.TypeOf(Node{})
durationType = reflect.TypeOf(time.Duration(0))
- defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
- ifaceType = defaultMapType.Elem()
+ stringMapType = reflect.TypeOf(map[string]interface{}{})
+ generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = generalMapType.Elem()
timeType = reflect.TypeOf(time.Time{})
ptrTimeType = reflect.TypeOf(&time.Time{})
)
-func newDecoder(strict bool) *decoder {
- d := &decoder{mapType: defaultMapType, strict: strict}
- d.aliases = make(map[*node]bool)
+func newDecoder() *decoder {
+ d := &decoder{
+ stringMapType: stringMapType,
+ generalMapType: generalMapType,
+ uniqueKeys: true,
+ }
+ d.aliases = make(map[*Node]bool)
return d
}
-func (d *decoder) terror(n *node, tag string, out reflect.Value) {
- if n.tag != "" {
- tag = n.tag
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+ if n.Tag != "" {
+ tag = n.Tag
}
- value := n.value
- if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
+ value := n.Value
+ if tag != seqTag && tag != mapTag {
if len(value) > 10 {
value = " `" + value[:7] + "...`"
} else {
value = " `" + value + "`"
}
}
- d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+ err := u.UnmarshalYAML(n)
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
}
-func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
terrlen := len(d.terrors)
err := u.UnmarshalYAML(func(v interface{}) (err error) {
defer handleErr(&err)
@@ -294,8 +403,8 @@ func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
// its types unmarshalled appropriately.
//
// If n holds a null value, prepare returns before doing anything.
-func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
- if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.ShortTag() == nullTag {
return out, false, false
}
again := true
@@ -309,15 +418,40 @@ func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unm
again = true
}
if out.CanAddr() {
- if u, ok := out.Addr().Interface().(Unmarshaler); ok {
+ outi := out.Addr().Interface()
+ if u, ok := outi.(Unmarshaler); ok {
good = d.callUnmarshaler(n, u)
return out, true, good
}
+ if u, ok := outi.(obsoleteUnmarshaler); ok {
+ good = d.callObsoleteUnmarshaler(n, u)
+ return out, true, good
+ }
}
}
return out, false, false
}
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+ if n.ShortTag() == nullTag {
+ return reflect.Value{}
+ }
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
const (
// 400,000 decode operations is ~500kb of dense object declarations, or
// ~5kb of dense object declarations with 10000% alias expansion
@@ -347,7 +481,7 @@ func allowedAliasRatio(decodeCount int) float64 {
}
}
-func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
d.decodeCount++
if d.aliasDepth > 0 {
d.aliasCount++
@@ -355,46 +489,55 @@ func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
failf("document contains excessive aliasing")
}
- switch n.kind {
- case documentNode:
+ if out.Type() == nodeType {
+ out.Set(reflect.ValueOf(n).Elem())
+ return true
+ }
+ switch n.Kind {
+ case DocumentNode:
return d.document(n, out)
- case aliasNode:
+ case AliasNode:
return d.alias(n, out)
}
out, unmarshaled, good := d.prepare(n, out)
if unmarshaled {
return good
}
- switch n.kind {
- case scalarNode:
+ switch n.Kind {
+ case ScalarNode:
good = d.scalar(n, out)
- case mappingNode:
+ case MappingNode:
good = d.mapping(n, out)
- case sequenceNode:
+ case SequenceNode:
good = d.sequence(n, out)
+ case 0:
+ if n.IsZero() {
+ return d.null(out)
+ }
+ fallthrough
default:
- panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
+ failf("cannot decode node with unknown kind %d", n.Kind)
}
return good
}
-func (d *decoder) document(n *node, out reflect.Value) (good bool) {
- if len(n.children) == 1 {
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+ if len(n.Content) == 1 {
d.doc = n
- d.unmarshal(n.children[0], out)
+ d.unmarshal(n.Content[0], out)
return true
}
return false
}
-func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
if d.aliases[n] {
// TODO this could actually be allowed in some circumstances.
- failf("anchor '%s' value contains itself", n.value)
+ failf("anchor '%s' value contains itself", n.Value)
}
d.aliases[n] = true
d.aliasDepth++
- good = d.unmarshal(n.alias, out)
+ good = d.unmarshal(n.Alias, out)
d.aliasDepth--
delete(d.aliases, n)
return good
@@ -408,15 +551,26 @@ func resetMap(out reflect.Value) {
}
}
-func (d *decoder) scalar(n *node, out reflect.Value) bool {
+func (d *decoder) null(out reflect.Value) bool {
+ if out.CanAddr() {
+ switch out.Kind() {
+ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+ out.Set(reflect.Zero(out.Type()))
+ return true
+ }
+ }
+ return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
var tag string
var resolved interface{}
- if n.tag == "" && !n.implicit {
- tag = yaml_STR_TAG
- resolved = n.value
+ if n.indicatedString() {
+ tag = strTag
+ resolved = n.Value
} else {
- tag, resolved = resolve(n.tag, n.value)
- if tag == yaml_BINARY_TAG {
+ tag, resolved = resolve(n.Tag, n.Value)
+ if tag == binaryTag {
data, err := base64.StdEncoding.DecodeString(resolved.(string))
if err != nil {
failf("!!binary value contains invalid base64 data")
@@ -425,12 +579,7 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool {
}
}
if resolved == nil {
- if out.Kind() == reflect.Map && !out.CanAddr() {
- resetMap(out)
- } else {
- out.Set(reflect.Zero(out.Type()))
- }
- return true
+ return d.null(out)
}
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
// We've resolved to exactly the type we want, so use that.
@@ -443,13 +592,13 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool {
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
if ok {
var text []byte
- if tag == yaml_BINARY_TAG {
+ if tag == binaryTag {
text = []byte(resolved.(string))
} else {
// We let any value be unmarshaled into TextUnmarshaler.
// That might be more lax than we'd like, but the
// TextUnmarshaler itself should bowl out any dubious values.
- text = []byte(n.value)
+ text = []byte(n.Value)
}
err := u.UnmarshalText(text)
if err != nil {
@@ -460,47 +609,37 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool {
}
switch out.Kind() {
case reflect.String:
- if tag == yaml_BINARY_TAG {
+ if tag == binaryTag {
out.SetString(resolved.(string))
return true
}
- if resolved != nil {
- out.SetString(n.value)
- return true
- }
+ out.SetString(n.Value)
+ return true
case reflect.Interface:
- if resolved == nil {
- out.Set(reflect.Zero(out.Type()))
- } else if tag == yaml_TIMESTAMP_TAG {
- // It looks like a timestamp but for backward compatibility
- // reasons we set it as a string, so that code that unmarshals
- // timestamp-like values into interface{} will continue to
- // see a string and not a time.Time.
- // TODO(v3) Drop this.
- out.Set(reflect.ValueOf(n.value))
- } else {
- out.Set(reflect.ValueOf(resolved))
- }
+ out.Set(reflect.ValueOf(resolved))
return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ // This used to work in v2, but it's very unfriendly.
+ isDuration := out.Type() == durationType
+
switch resolved := resolved.(type) {
case int:
- if !out.OverflowInt(int64(resolved)) {
+ if !isDuration && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
case int64:
- if !out.OverflowInt(resolved) {
+ if !isDuration && !out.OverflowInt(resolved) {
out.SetInt(resolved)
return true
}
case uint64:
- if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
case float64:
- if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
@@ -541,6 +680,17 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool {
case bool:
out.SetBool(resolved)
return true
+ case string:
+ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+ // It only works if explicitly attempting to unmarshal into a typed bool value.
+ switch resolved {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+ out.SetBool(true)
+ return true
+ case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ out.SetBool(false)
+ return true
+ }
}
case reflect.Float32, reflect.Float64:
switch resolved := resolved.(type) {
@@ -563,13 +713,7 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool {
return true
}
case reflect.Ptr:
- if out.Type().Elem() == reflect.TypeOf(resolved) {
- // TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
- elem := reflect.New(out.Type().Elem())
- elem.Elem().Set(reflect.ValueOf(resolved))
- out.Set(elem)
- return true
- }
+ panic("yaml internal error: please report the issue")
}
d.terror(n, tag, out)
return false
@@ -582,8 +726,8 @@ func settableValueOf(i interface{}) reflect.Value {
return sv
}
-func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
- l := len(n.children)
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
var iface reflect.Value
switch out.Kind() {
@@ -598,7 +742,7 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
iface = out
out = settableValueOf(make([]interface{}, l))
default:
- d.terror(n, yaml_SEQ_TAG, out)
+ d.terror(n, seqTag, out)
return false
}
et := out.Type().Elem()
@@ -606,7 +750,7 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
j := 0
for i := 0; i < l; i++ {
e := reflect.New(et).Elem()
- if ok := d.unmarshal(n.children[i], e); ok {
+ if ok := d.unmarshal(n.Content[i], e); ok {
out.Index(j).Set(e)
j++
}
@@ -620,51 +764,79 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
return true
}
-func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+ if d.uniqueKeys {
+ nerrs := len(d.terrors)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ for j := i + 2; j < l; j += 2 {
+ nj := n.Content[j]
+ if ni.Kind == nj.Kind && ni.Value == nj.Value {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+ }
+ }
+ }
+ if len(d.terrors) > nerrs {
+ return false
+ }
+ }
switch out.Kind() {
case reflect.Struct:
return d.mappingStruct(n, out)
- case reflect.Slice:
- return d.mappingSlice(n, out)
case reflect.Map:
// okay
case reflect.Interface:
- if d.mapType.Kind() == reflect.Map {
- iface := out
- out = reflect.MakeMap(d.mapType)
- iface.Set(out)
+ iface := out
+ if isStringMap(n) {
+ out = reflect.MakeMap(d.stringMapType)
} else {
- slicev := reflect.New(d.mapType).Elem()
- if !d.mappingSlice(n, slicev) {
- return false
- }
- out.Set(slicev)
- return true
+ out = reflect.MakeMap(d.generalMapType)
}
+ iface.Set(out)
default:
- d.terror(n, yaml_MAP_TAG, out)
+ d.terror(n, mapTag, out)
return false
}
+
outt := out.Type()
kt := outt.Key()
et := outt.Elem()
- mapType := d.mapType
- if outt.Key() == ifaceType && outt.Elem() == ifaceType {
- d.mapType = outt
+ stringMapType := d.stringMapType
+ generalMapType := d.generalMapType
+ if outt.Elem() == ifaceType {
+ if outt.Key().Kind() == reflect.String {
+ d.stringMapType = outt
+ } else if outt.Key() == ifaceType {
+ d.generalMapType = outt
+ }
}
+ mergedFields := d.mergedFields
+ d.mergedFields = nil
+
+ var mergeNode *Node
+
+ mapIsNew := false
if out.IsNil() {
out.Set(reflect.MakeMap(outt))
+ mapIsNew = true
}
- l := len(n.children)
for i := 0; i < l; i += 2 {
- if isMerge(n.children[i]) {
- d.merge(n.children[i+1], out)
+ if isMerge(n.Content[i]) {
+ mergeNode = n.Content[i+1]
continue
}
k := reflect.New(kt).Elem()
- if d.unmarshal(n.children[i], k) {
+ if d.unmarshal(n.Content[i], k) {
+ if mergedFields != nil {
+ ki := k.Interface()
+ if mergedFields[ki] {
+ continue
+ }
+ mergedFields[ki] = true
+ }
kkind := k.Kind()
if kkind == reflect.Interface {
kkind = k.Elem().Kind()
@@ -673,87 +845,83 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
failf("invalid map key: %#v", k.Interface())
}
e := reflect.New(et).Elem()
- if d.unmarshal(n.children[i+1], e) {
- d.setMapIndex(n.children[i+1], out, k, e)
+ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+ out.SetMapIndex(k, e)
}
}
}
- d.mapType = mapType
- return true
-}
-func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
- if d.strict && out.MapIndex(k) != zeroValue {
- d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
- return
+ d.mergedFields = mergedFields
+ if mergeNode != nil {
+ d.merge(n, mergeNode, out)
}
- out.SetMapIndex(k, v)
+
+ d.stringMapType = stringMapType
+ d.generalMapType = generalMapType
+ return true
}
-func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
- outt := out.Type()
- if outt.Elem() != mapItemType {
- d.terror(n, yaml_MAP_TAG, out)
+func isStringMap(n *Node) bool {
+ if n.Kind != MappingNode {
return false
}
-
- mapType := d.mapType
- d.mapType = outt
-
- var slice []MapItem
- var l = len(n.children)
+ l := len(n.Content)
for i := 0; i < l; i += 2 {
- if isMerge(n.children[i]) {
- d.merge(n.children[i+1], out)
- continue
- }
- item := MapItem{}
- k := reflect.ValueOf(&item.Key).Elem()
- if d.unmarshal(n.children[i], k) {
- v := reflect.ValueOf(&item.Value).Elem()
- if d.unmarshal(n.children[i+1], v) {
- slice = append(slice, item)
- }
+ shortTag := n.Content[i].ShortTag()
+ if shortTag != strTag && shortTag != mergeTag {
+ return false
}
}
- out.Set(reflect.ValueOf(slice))
- d.mapType = mapType
return true
}
-func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
sinfo, err := getStructInfo(out.Type())
if err != nil {
panic(err)
}
- name := settableValueOf("")
- l := len(n.children)
var inlineMap reflect.Value
var elemType reflect.Type
if sinfo.InlineMap != -1 {
inlineMap = out.Field(sinfo.InlineMap)
- inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
elemType = inlineMap.Type().Elem()
}
+ for _, index := range sinfo.InlineUnmarshalers {
+ field := d.fieldByIndex(n, out, index)
+ d.prepare(n, field)
+ }
+
+ mergedFields := d.mergedFields
+ d.mergedFields = nil
+ var mergeNode *Node
var doneFields []bool
- if d.strict {
+ if d.uniqueKeys {
doneFields = make([]bool, len(sinfo.FieldsList))
}
+ name := settableValueOf("")
+ l := len(n.Content)
for i := 0; i < l; i += 2 {
- ni := n.children[i]
+ ni := n.Content[i]
if isMerge(ni) {
- d.merge(n.children[i+1], out)
+ mergeNode = n.Content[i+1]
continue
}
if !d.unmarshal(ni, name) {
continue
}
- if info, ok := sinfo.FieldsMap[name.String()]; ok {
- if d.strict {
+ sname := name.String()
+ if mergedFields != nil {
+ if mergedFields[sname] {
+ continue
+ }
+ mergedFields[sname] = true
+ }
+ if info, ok := sinfo.FieldsMap[sname]; ok {
+ if d.uniqueKeys {
if doneFields[info.Id] {
- d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
continue
}
doneFields[info.Id] = true
@@ -762,20 +930,25 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
if info.Inline == nil {
field = out.Field(info.Num)
} else {
- field = out.FieldByIndex(info.Inline)
+ field = d.fieldByIndex(n, out, info.Inline)
}
- d.unmarshal(n.children[i+1], field)
+ d.unmarshal(n.Content[i+1], field)
} else if sinfo.InlineMap != -1 {
if inlineMap.IsNil() {
inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
}
value := reflect.New(elemType).Elem()
- d.unmarshal(n.children[i+1], value)
- d.setMapIndex(n.children[i+1], inlineMap, name, value)
- } else if d.strict {
- d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
+ d.unmarshal(n.Content[i+1], value)
+ inlineMap.SetMapIndex(name, value)
+ } else if d.knownFields {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
}
}
+
+ d.mergedFields = mergedFields
+ if mergeNode != nil {
+ d.merge(n, mergeNode, out)
+ }
return true
}
@@ -783,24 +956,34 @@ func failWantMap() {
failf("map merge requires map or sequence of maps as the value")
}
-func (d *decoder) merge(n *node, out reflect.Value) {
- switch n.kind {
- case mappingNode:
- d.unmarshal(n, out)
- case aliasNode:
- if n.alias != nil && n.alias.kind != mappingNode {
+func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
+ mergedFields := d.mergedFields
+ if mergedFields == nil {
+ d.mergedFields = make(map[interface{}]bool)
+ for i := 0; i < len(parent.Content); i += 2 {
+ k := reflect.New(ifaceType).Elem()
+ if d.unmarshal(parent.Content[i], k) {
+ d.mergedFields[k.Interface()] = true
+ }
+ }
+ }
+
+ switch merge.Kind {
+ case MappingNode:
+ d.unmarshal(merge, out)
+ case AliasNode:
+ if merge.Alias != nil && merge.Alias.Kind != MappingNode {
failWantMap()
}
- d.unmarshal(n, out)
- case sequenceNode:
- // Step backwards as earlier nodes take precedence.
- for i := len(n.children) - 1; i >= 0; i-- {
- ni := n.children[i]
- if ni.kind == aliasNode {
- if ni.alias != nil && ni.alias.kind != mappingNode {
+ d.unmarshal(merge, out)
+ case SequenceNode:
+ for i := 0; i < len(merge.Content); i++ {
+ ni := merge.Content[i]
+ if ni.Kind == AliasNode {
+ if ni.Alias != nil && ni.Alias.Kind != MappingNode {
failWantMap()
}
- } else if ni.kind != mappingNode {
+ } else if ni.Kind != MappingNode {
failWantMap()
}
d.unmarshal(ni, out)
@@ -808,8 +991,10 @@ func (d *decoder) merge(n *node, out reflect.Value) {
default:
failWantMap()
}
+
+ d.mergedFields = mergedFields
}
-func isMerge(n *node) bool {
- return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
+func isMerge(n *Node) bool {
+ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
}
diff --git a/vendor/gopkg.in/yaml.v2/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go
index a1c2cc5..0f47c9c 100644
--- a/vendor/gopkg.in/yaml.v2/emitterc.go
+++ b/vendor/gopkg.in/yaml.v3/emitterc.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -43,8 +65,13 @@ func put_break(emitter *yaml_emitter_t) bool {
default:
panic("unknown line break setting")
}
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
emitter.column = 0
emitter.line++
+ // [Go] Do this here and below and drop from everywhere else (see commented lines).
+ emitter.indention = true
return true
}
@@ -97,8 +124,13 @@ func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
if !write(emitter, s, i) {
return false
}
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
emitter.column = 0
emitter.line++
+ // [Go] Do this here and above and drop from everywhere else (see commented lines).
+ emitter.indention = true
}
return true
}
@@ -203,7 +235,14 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
emitter.indent = 0
}
} else if !indentless {
- emitter.indent += emitter.best_indent
+ // [Go] This was changed so that indentations are more regular.
+ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+ // The first indent inside a sequence will just skip the "- " indicator.
+ emitter.indent += 2
+ } else {
+ // Everything else aligns to the chosen indentation.
+ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
+ }
}
return true
}
@@ -228,16 +267,22 @@ func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bo
return yaml_emitter_emit_document_end(emitter, event)
case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, true)
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, false)
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, true)
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, false)
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
@@ -298,6 +343,8 @@ func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t
emitter.column = 0
emitter.whitespace = true
emitter.indention = true
+ emitter.space_above = true
+ emitter.foot_indent = -1
if emitter.encoding != yaml_UTF8_ENCODING {
if !yaml_emitter_write_bom(emitter) {
@@ -392,13 +439,22 @@ func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event
if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
return false
}
- if emitter.canonical {
+ if emitter.canonical || true {
if !yaml_emitter_write_indent(emitter) {
return false
}
}
}
+ if len(emitter.head_comment) > 0 {
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ }
+
emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
return true
}
@@ -425,7 +481,20 @@ func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event
// Expect the root node.
func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
- return yaml_emitter_emit_node(emitter, event, true, false, false, false)
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
}
// Expect DOCUMENT-END.
@@ -433,6 +502,12 @@ func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t
if event.typ != yaml_DOCUMENT_END_EVENT {
return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
}
+ // [Go] Force document foot separation.
+ emitter.foot_indent = 0
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.foot_indent = -1
if !yaml_emitter_write_indent(emitter) {
return false
}
@@ -454,7 +529,7 @@ func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t
}
// Expect a flow item node.
-func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
if first {
if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
return false
@@ -466,13 +541,15 @@ func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_e
}
if event.typ == yaml_SEQUENCE_END_EVENT {
- emitter.flow_level--
- emitter.indent = emitter.indents[len(emitter.indents)-1]
- emitter.indents = emitter.indents[:len(emitter.indents)-1]
- if emitter.canonical && !first {
+ if emitter.canonical && !first && !trail {
if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
return false
}
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.column == 0 || emitter.canonical && !first {
if !yaml_emitter_write_indent(emitter) {
return false
}
@@ -480,29 +557,62 @@ func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_e
if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
return false
}
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
emitter.state = emitter.states[len(emitter.states)-1]
emitter.states = emitter.states[:len(emitter.states)-1]
return true
}
- if !first {
+ if !first && !trail {
if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
return false
}
}
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
if emitter.canonical || emitter.column > emitter.best_width {
if !yaml_emitter_write_indent(emitter) {
return false
}
}
- emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
- return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
}
// Expect a flow key node.
-func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
if first {
if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
return false
@@ -514,13 +624,18 @@ func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_eve
}
if event.typ == yaml_MAPPING_END_EVENT {
+ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
emitter.flow_level--
emitter.indent = emitter.indents[len(emitter.indents)-1]
emitter.indents = emitter.indents[:len(emitter.indents)-1]
if emitter.canonical && !first {
- if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
- return false
- }
if !yaml_emitter_write_indent(emitter) {
return false
}
@@ -528,16 +643,33 @@ func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_eve
if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
return false
}
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
emitter.state = emitter.states[len(emitter.states)-1]
emitter.states = emitter.states[:len(emitter.states)-1]
return true
}
- if !first {
+ if !first && !trail {
if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
return false
}
}
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
if emitter.canonical || emitter.column > emitter.best_width {
if !yaml_emitter_write_indent(emitter) {
return false
@@ -571,14 +703,32 @@ func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_e
return false
}
}
- emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
- return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
}
// Expect a block item node.
func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
if first {
- if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
return false
}
}
@@ -589,6 +739,9 @@ func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_
emitter.states = emitter.states[:len(emitter.states)-1]
return true
}
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
if !yaml_emitter_write_indent(emitter) {
return false
}
@@ -596,7 +749,16 @@ func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_
return false
}
emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
- return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
}
// Expect a block key node.
@@ -606,6 +768,9 @@ func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_ev
return false
}
}
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
if event.typ == yaml_MAPPING_END_EVENT {
emitter.indent = emitter.indents[len(emitter.indents)-1]
emitter.indents = emitter.indents[:len(emitter.indents)-1]
@@ -616,6 +781,13 @@ func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_ev
if !yaml_emitter_write_indent(emitter) {
return false
}
+ if len(emitter.line_comment) > 0 {
+ // [Go] A line comment was provided for the key. That's unusual as the
+ // scanner associates line comments with the value. Either way,
+ // save the line comment and render it appropriately later.
+ emitter.key_line_comment = emitter.line_comment
+ emitter.line_comment = nil
+ }
if yaml_emitter_check_simple_key(emitter) {
emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
return yaml_emitter_emit_node(emitter, event, false, false, true, true)
@@ -641,8 +813,42 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_
return false
}
}
+ if len(emitter.key_line_comment) > 0 {
+ // [Go] Line comments are generally associated with the value, but when there's
+ // no value on the same line as a mapping key they end up attached to the
+ // key itself.
+ if event.typ == yaml_SCALAR_EVENT {
+ if len(emitter.line_comment) == 0 {
+ // A scalar is coming and it has no line comments by itself yet,
+ // so just let it handle the line comment as usual. If it has a
+ // line comment, we can't have both so the one from the key is lost.
+ emitter.line_comment = emitter.key_line_comment
+ emitter.key_line_comment = nil
+ }
+ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+ // An indented block follows, so write the comment right now.
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ }
+ }
emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
- return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
}
// Expect a node.
@@ -908,6 +1114,71 @@ func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
panic("unknown scalar style")
}
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+ return false
+ }
+ emitter.tail_comment = emitter.tail_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ }
+
+ if len(emitter.head_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+ return false
+ }
+ emitter.head_comment = emitter.head_comment[:0]
+ return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.line_comment) == 0 {
+ return true
+ }
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+ return false
+ }
+ emitter.line_comment = emitter.line_comment[:0]
+ return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.foot_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+ return false
+ }
+ emitter.foot_comment = emitter.foot_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ return true
+}
+
// Check if a %YAML directive is valid.
func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
if version_directive.major != 1 || version_directive.minor != 1 {
@@ -987,6 +1258,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
flow_indicators = false
line_breaks = false
special_characters = false
+ tab_characters = false
leading_space = false
leading_break = false
@@ -1055,7 +1327,9 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
}
}
- if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ if value[i] == '\t' {
+ tab_characters = true
+ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
special_characters = true
}
if is_space(value, i) {
@@ -1110,10 +1384,12 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
emitter.scalar_data.block_plain_allowed = false
emitter.scalar_data.single_quoted_allowed = false
}
- if space_break || special_characters {
+ if space_break || tab_characters || special_characters {
emitter.scalar_data.flow_plain_allowed = false
emitter.scalar_data.block_plain_allowed = false
emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
emitter.scalar_data.block_allowed = false
}
if line_breaks {
@@ -1137,6 +1413,19 @@ func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bo
emitter.tag_data.suffix = nil
emitter.scalar_data.value = nil
+ if len(event.head_comment) > 0 {
+ emitter.head_comment = event.head_comment
+ }
+ if len(event.line_comment) > 0 {
+ emitter.line_comment = event.line_comment
+ }
+ if len(event.foot_comment) > 0 {
+ emitter.foot_comment = event.foot_comment
+ }
+ if len(event.tail_comment) > 0 {
+ emitter.tail_comment = event.tail_comment
+ }
+
switch event.typ {
case yaml_ALIAS_EVENT:
if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
@@ -1208,13 +1497,20 @@ func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
return false
}
}
+ if emitter.foot_indent == indent {
+ if !put_break(emitter) {
+ return false
+ }
+ }
for emitter.column < indent {
if !put(emitter, ' ') {
return false
}
}
emitter.whitespace = true
- emitter.indention = true
+ //emitter.indention = true
+ emitter.space_above = false
+ emitter.foot_indent = -1
return true
}
@@ -1311,7 +1607,7 @@ func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_
}
func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
- if !emitter.whitespace {
+ if len(value) > 0 && !emitter.whitespace {
if !put(emitter, ' ') {
return false
}
@@ -1341,7 +1637,7 @@ func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allo
if !write_break(emitter, value, &i) {
return false
}
- emitter.indention = true
+ //emitter.indention = true
breaks = true
} else {
if breaks {
@@ -1358,7 +1654,9 @@ func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allo
}
}
- emitter.whitespace = false
+ if len(value) > 0 {
+ emitter.whitespace = false
+ }
emitter.indention = false
if emitter.root_context {
emitter.open_ended = true
@@ -1397,7 +1695,7 @@ func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []by
if !write_break(emitter, value, &i) {
return false
}
- emitter.indention = true
+ //emitter.indention = true
breaks = true
} else {
if breaks {
@@ -1596,10 +1894,10 @@ func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bo
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
return false
}
- if !put_break(emitter) {
+ if !yaml_emitter_process_line_comment(emitter) {
return false
}
- emitter.indention = true
+ //emitter.indention = true
emitter.whitespace = true
breaks := true
for i := 0; i < len(value); {
@@ -1607,7 +1905,7 @@ func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bo
if !write_break(emitter, value, &i) {
return false
}
- emitter.indention = true
+ //emitter.indention = true
breaks = true
} else {
if breaks {
@@ -1633,11 +1931,11 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
return false
}
-
- if !put_break(emitter) {
+ if !yaml_emitter_process_line_comment(emitter) {
return false
}
- emitter.indention = true
+
+ //emitter.indention = true
emitter.whitespace = true
breaks := true
@@ -1658,7 +1956,7 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
if !write_break(emitter, value, &i) {
return false
}
- emitter.indention = true
+ //emitter.indention = true
breaks = true
} else {
if breaks {
@@ -1683,3 +1981,40 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
}
return true
}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+ breaks := false
+ pound := false
+ for i := 0; i < len(comment); {
+ if is_break(comment, i) {
+ if !write_break(emitter, comment, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ pound = false
+ } else {
+ if breaks && !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !pound {
+ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+ return false
+ }
+ pound = true
+ }
+ if !write(emitter, comment, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ if !breaks && !put_break(emitter) {
+ return false
+ }
+
+ emitter.whitespace = true
+ //emitter.indention = true
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go
new file mode 100644
index 0000000..de9e72a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ indent int
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ if e.indent == 0 {
+ e.indent = 4
+ }
+ e.emitter.best_indent = e.indent
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ var node *Node
+ if in.IsValid() {
+ node, _ = in.Interface().(*Node)
+ }
+ if node != nil && node.Kind == DocumentNode {
+ e.nodev(in)
+ } else {
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+ }
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ tag = shortTag(tag)
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch value := iface.(type) {
+ case *Node:
+ e.nodev(in)
+ return
+ case Node:
+ if !in.CanAddr() {
+ var n = reflect.New(in.Type()).Elem()
+ n.Set(in)
+ in = n
+ }
+ e.nodev(in.Addr())
+ return
+ case time.Time:
+ e.timev(tag, in)
+ return
+ case *time.Time:
+ e.timev(tag, in.Elem())
+ return
+ case time.Duration:
+ e.stringv(tag, reflect.ValueOf(value.String()))
+ return
+ case Marshaler:
+ v, err := value.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ e.marshal(tag, reflect.ValueOf(v))
+ return
+ case encoding.TextMarshaler:
+ text, err := value.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ e.marshal(tag, in.Elem())
+ case reflect.Struct:
+ e.structv(tag, in)
+ case reflect.Slice, reflect.Array:
+ e.slicev(tag, in)
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ e.intv(tag, in)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = e.fieldByIndex(in, info.Inline)
+ if !value.IsValid() {
+ continue
+ }
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+ switch s {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+ "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ return true
+ default:
+ return false
+ }
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ if e.flow {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ } else {
+ style = yaml_LITERAL_SCALAR_STYLE
+ }
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+ // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+ implicit := tag == ""
+ if !implicit {
+ tag = longTag(tag)
+ }
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.event.head_comment = head
+ e.event.line_comment = line
+ e.event.foot_comment = foot
+ e.event.tail_comment = tail
+ e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+ e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+ // Zero nodes behave as nil.
+ if node.Kind == 0 && node.IsZero() {
+ e.nilv()
+ return
+ }
+
+ // If the tag was not explicitly requested, and dropping it won't change the
+ // implicit tag of the value, don't include it in the presentation.
+ var tag = node.Tag
+ var stag = shortTag(tag)
+ var forceQuoting bool
+ if tag != "" && node.Style&TaggedStyle == 0 {
+ if node.Kind == ScalarNode {
+ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+ tag = ""
+ } else {
+ rtag, _ := resolve("", node.Value)
+ if rtag == stag {
+ tag = ""
+ } else if stag == strTag {
+ tag = ""
+ forceQuoting = true
+ }
+ }
+ } else {
+ var rtag string
+ switch node.Kind {
+ case MappingNode:
+ rtag = mapTag
+ case SequenceNode:
+ rtag = seqTag
+ }
+ if rtag == stag {
+ tag = ""
+ }
+ }
+ }
+
+ switch node.Kind {
+ case DocumentNode:
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ yaml_document_end_event_initialize(&e.event, true)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case SequenceNode:
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case MappingNode:
+ style := yaml_BLOCK_MAPPING_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ e.event.tail_comment = []byte(tail)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+
+ // The tail logic below moves the foot comment of prior keys to the following key,
+ // since the value for each key may be a nested structure and the foot needs to be
+ // processed only the entirety of the value is streamed. The last tail is processed
+ // with the mapping end event.
+ var tail string
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ k := node.Content[i]
+ foot := k.FootComment
+ if foot != "" {
+ kopy := *k
+ kopy.FootComment = ""
+ k = &kopy
+ }
+ e.node(k, tail)
+ tail = foot
+
+ v := node.Content[i+1]
+ e.node(v, "")
+ }
+
+ yaml_mapping_end_event_initialize(&e.event)
+ e.event.tail_comment = []byte(tail)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case AliasNode:
+ yaml_alias_event_initialize(&e.event, []byte(node.Value))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case ScalarNode:
+ value := node.Value
+ if !utf8.ValidString(value) {
+ if stag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if stag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", stag)
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ value = encodeBase64(value)
+ }
+
+ style := yaml_PLAIN_SCALAR_STYLE
+ switch {
+ case node.Style&DoubleQuotedStyle != 0:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ case node.Style&SingleQuotedStyle != 0:
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ case node.Style&LiteralStyle != 0:
+ style = yaml_LITERAL_SCALAR_STYLE
+ case node.Style&FoldedStyle != 0:
+ style = yaml_FOLDED_SCALAR_STYLE
+ case strings.Contains(value, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case forceQuoting:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+ default:
+ failf("cannot encode node with unknown kind %d", node.Kind)
+ }
+}
diff --git a/vendor/gopkg.in/yaml.v2/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go
index 81d05df..268558a 100644
--- a/vendor/gopkg.in/yaml.v2/parserc.go
+++ b/vendor/gopkg.in/yaml.v3/parserc.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -45,11 +67,46 @@ import (
// Peek the next token in the token queue.
func peek_token(parser *yaml_parser_t) *yaml_token_t {
if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
- return &parser.tokens[parser.tokens_head]
+ token := &parser.tokens[parser.tokens_head]
+ yaml_parser_unfold_comments(parser, token)
+ return token
}
return nil
}
+// yaml_parser_unfold_comments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
+ for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
+ comment := &parser.comments[parser.comments_head]
+ if len(comment.head) > 0 {
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ // No heads on ends, so keep comment.head for a follow up token.
+ break
+ }
+ if len(parser.head_comment) > 0 {
+ parser.head_comment = append(parser.head_comment, '\n')
+ }
+ parser.head_comment = append(parser.head_comment, comment.head...)
+ }
+ if len(comment.foot) > 0 {
+ if len(parser.foot_comment) > 0 {
+ parser.foot_comment = append(parser.foot_comment, '\n')
+ }
+ parser.foot_comment = append(parser.foot_comment, comment.foot...)
+ }
+ if len(comment.line) > 0 {
+ if len(parser.line_comment) > 0 {
+ parser.line_comment = append(parser.line_comment, '\n')
+ }
+ parser.line_comment = append(parser.line_comment, comment.line...)
+ }
+ *comment = yaml_comment_t{}
+ parser.comments_head++
+ }
+}
+
// Remove the next token from the queue (must be called after peek_token).
func skip_token(parser *yaml_parser_t) {
parser.token_available = false
@@ -224,10 +281,32 @@ func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t
parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
parser.state = yaml_PARSE_BLOCK_NODE_STATE
+ var head_comment []byte
+ if len(parser.head_comment) > 0 {
+ // [Go] Scan the header comment backwards, and if an empty line is found, break
+ // the header so the part before the last empty line goes into the
+ // document header, while the bottom of it goes into a follow up event.
+ for i := len(parser.head_comment) - 1; i > 0; i-- {
+ if parser.head_comment[i] == '\n' {
+ if i == len(parser.head_comment)-1 {
+ head_comment = parser.head_comment[:i]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ } else if parser.head_comment[i-1] == '\n' {
+ head_comment = parser.head_comment[:i-1]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ }
+ }
+ }
+ }
+
*event = yaml_event_t{
typ: yaml_DOCUMENT_START_EVENT,
start_mark: token.start_mark,
end_mark: token.end_mark,
+
+ head_comment: head_comment,
}
} else if token.typ != yaml_STREAM_END_TOKEN {
@@ -284,6 +363,7 @@ func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event
if token == nil {
return false
}
+
if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
token.typ == yaml_DOCUMENT_START_TOKEN ||
@@ -327,9 +407,25 @@ func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t)
end_mark: end_mark,
implicit: implicit,
}
+ yaml_parser_set_event_comments(parser, event)
+ if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
+ event.foot_comment = event.head_comment
+ event.head_comment = nil
+ }
return true
}
+func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
+ event.head_comment = parser.head_comment
+ event.line_comment = parser.line_comment
+ event.foot_comment = parser.foot_comment
+ parser.head_comment = nil
+ parser.line_comment = nil
+ parser.foot_comment = nil
+ parser.tail_comment = nil
+ parser.stem_comment = nil
+}
+
// Parse the productions:
// block_node_or_indentless_sequence ::=
// ALIAS
@@ -373,6 +469,7 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
end_mark: token.end_mark,
anchor: token.value,
}
+ yaml_parser_set_event_comments(parser, event)
skip_token(parser)
return true
}
@@ -486,6 +583,7 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
quoted_implicit: quoted_implicit,
style: yaml_style_t(token.style),
}
+ yaml_parser_set_event_comments(parser, event)
skip_token(parser)
return true
}
@@ -502,6 +600,7 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
implicit: implicit,
style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
}
+ yaml_parser_set_event_comments(parser, event)
return true
}
if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
@@ -516,6 +615,7 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
implicit: implicit,
style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
}
+ yaml_parser_set_event_comments(parser, event)
return true
}
if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
@@ -530,6 +630,10 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
implicit: implicit,
style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
}
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
return true
}
if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
@@ -544,6 +648,10 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
implicit: implicit,
style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
}
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
return true
}
if len(anchor) > 0 || len(tag) > 0 {
@@ -579,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
+ if token == nil {
+ return false
+ }
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@@ -590,7 +701,9 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
if token.typ == yaml_BLOCK_ENTRY_TOKEN {
mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
token = peek_token(parser)
if token == nil {
return false
@@ -636,7 +749,9 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y
if token.typ == yaml_BLOCK_ENTRY_TOKEN {
mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
token = peek_token(parser)
if token == nil {
return false
@@ -662,6 +777,32 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y
return true
}
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+ if stem_len == 0 {
+ return
+ }
+
+ token := peek_token(parser)
+ if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+ return
+ }
+
+ parser.stem_comment = parser.head_comment[:stem_len]
+ if len(parser.head_comment) == stem_len {
+ parser.head_comment = nil
+ } else {
+ // Copy suffix to prevent very strange bugs if someone ever appends
+ // further bytes to the prefix in the stem_comment slice above.
+ parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+ }
+}
+
// Parse the productions:
// block_mapping ::= BLOCK-MAPPING_START
// *******************
@@ -675,6 +816,9 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
+ if token == nil {
+ return false
+ }
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@@ -684,6 +828,19 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
return false
}
+ // [Go] A tail comment was left from the prior mapping value processed. Emit an event
+ // as it needs to be processed with that value and not the following key.
+ if len(parser.tail_comment) > 0 {
+ *event = yaml_event_t{
+ typ: yaml_TAIL_COMMENT_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ foot_comment: parser.tail_comment,
+ }
+ parser.tail_comment = nil
+ return true
+ }
+
if token.typ == yaml_KEY_TOKEN {
mark := token.end_mark
skip_token(parser)
@@ -709,6 +866,7 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
start_mark: token.start_mark,
end_mark: token.end_mark,
}
+ yaml_parser_set_event_comments(parser, event)
skip_token(parser)
return true
}
@@ -770,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
+ if token == nil {
+ return false
+ }
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@@ -820,6 +981,7 @@ func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_ev
start_mark: token.start_mark,
end_mark: token.end_mark,
}
+ yaml_parser_set_event_comments(parser, event)
skip_token(parser)
return true
@@ -959,6 +1121,7 @@ func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event
start_mark: token.start_mark,
end_mark: token.end_mark,
}
+ yaml_parser_set_event_comments(parser, event)
skip_token(parser)
return true
}
diff --git a/vendor/gopkg.in/yaml.v2/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go
index 7c1f5fa..b7de0a8 100644
--- a/vendor/gopkg.in/yaml.v2/readerc.go
+++ b/vendor/gopkg.in/yaml.v3/readerc.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -95,7 +117,7 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
// [Go] This function was changed to guarantee the requested length size at EOF.
// The fact we need to do this is pretty awful, but the description above implies
- // for that to be the case, and there are tests
+ // for that to be the case, and there are tests
// If the EOF flag is set and the raw buffer is empty, do nothing.
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
diff --git a/vendor/gopkg.in/yaml.v2/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go
index 4120e0c..64ae888 100644
--- a/vendor/gopkg.in/yaml.v2/resolve.go
+++ b/vendor/gopkg.in/yaml.v3/resolve.go
@@ -1,3 +1,18 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package yaml
import (
@@ -34,18 +49,14 @@ func init() {
tag string
l []string
}{
- {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
- {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
- {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
- {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
- {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
- {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
- {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
- {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
- {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
- {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
- {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
- {"<<", yaml_MERGE_TAG, []string{"<<"}},
+ {true, boolTag, []string{"true", "True", "TRUE"}},
+ {false, boolTag, []string{"false", "False", "FALSE"}},
+ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+ {"<<", mergeTag, []string{"<<"}},
}
m := resolveMap
@@ -56,11 +67,37 @@ func init() {
}
}
+const (
+ nullTag = "!!null"
+ boolTag = "!!bool"
+ strTag = "!!str"
+ intTag = "!!int"
+ floatTag = "!!float"
+ timestampTag = "!!timestamp"
+ seqTag = "!!seq"
+ mapTag = "!!map"
+ binaryTag = "!!binary"
+ mergeTag = "!!merge"
+)
+
+var longTags = make(map[string]string)
+var shortTags = make(map[string]string)
+
+func init() {
+ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+ ltag := longTag(stag)
+ longTags[stag] = ltag
+ shortTags[ltag] = stag
+ }
+}
+
const longTagPrefix = "tag:yaml.org,2002:"
func shortTag(tag string) string {
- // TODO This can easily be made faster and produce less garbage.
if strings.HasPrefix(tag, longTagPrefix) {
+ if stag, ok := shortTags[tag]; ok {
+ return stag
+ }
return "!!" + tag[len(longTagPrefix):]
}
return tag
@@ -68,6 +105,9 @@ func shortTag(tag string) string {
func longTag(tag string) string {
if strings.HasPrefix(tag, "!!") {
+ if ltag, ok := longTags[tag]; ok {
+ return ltag
+ }
return longTagPrefix + tag[2:]
}
return tag
@@ -75,7 +115,7 @@ func longTag(tag string) string {
func resolvableTag(tag string) bool {
switch tag {
- case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
+ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
return true
}
return false
@@ -84,23 +124,24 @@ func resolvableTag(tag string) bool {
var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
func resolve(tag string, in string) (rtag string, out interface{}) {
+ tag = shortTag(tag)
if !resolvableTag(tag) {
return tag, in
}
defer func() {
switch tag {
- case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
+ case "", rtag, strTag, binaryTag:
return
- case yaml_FLOAT_TAG:
- if rtag == yaml_INT_TAG {
+ case floatTag:
+ if rtag == intTag {
switch v := out.(type) {
case int64:
- rtag = yaml_FLOAT_TAG
+ rtag = floatTag
out = float64(v)
return
case int:
- rtag = yaml_FLOAT_TAG
+ rtag = floatTag
out = float64(v)
return
}
@@ -115,7 +156,7 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
if in != "" {
hint = resolveTable[in[0]]
}
- if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
+ if hint != 0 && tag != strTag && tag != binaryTag {
// Handle things we can lookup in a map.
if item, ok := resolveMap[in]; ok {
return item.tag, item.value
@@ -133,17 +174,17 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
// Not in the map, so maybe a normal float.
floatv, err := strconv.ParseFloat(in, 64)
if err == nil {
- return yaml_FLOAT_TAG, floatv
+ return floatTag, floatv
}
case 'D', 'S':
// Int, float, or timestamp.
// Only try values as a timestamp if the value is unquoted or there's an explicit
// !!timestamp tag.
- if tag == "" || tag == yaml_TIMESTAMP_TAG {
+ if tag == "" || tag == timestampTag {
t, ok := parseTimestamp(in)
if ok {
- return yaml_TIMESTAMP_TAG, t
+ return timestampTag, t
}
}
@@ -151,49 +192,76 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil {
if intv == int64(int(intv)) {
- return yaml_INT_TAG, int(intv)
+ return intTag, int(intv)
} else {
- return yaml_INT_TAG, intv
+ return intTag, intv
}
}
uintv, err := strconv.ParseUint(plain, 0, 64)
if err == nil {
- return yaml_INT_TAG, uintv
+ return intTag, uintv
}
if yamlStyleFloat.MatchString(plain) {
floatv, err := strconv.ParseFloat(plain, 64)
if err == nil {
- return yaml_FLOAT_TAG, floatv
+ return floatTag, floatv
}
}
if strings.HasPrefix(plain, "0b") {
intv, err := strconv.ParseInt(plain[2:], 2, 64)
if err == nil {
if intv == int64(int(intv)) {
- return yaml_INT_TAG, int(intv)
+ return intTag, int(intv)
} else {
- return yaml_INT_TAG, intv
+ return intTag, intv
}
}
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
if err == nil {
- return yaml_INT_TAG, uintv
+ return intTag, uintv
}
} else if strings.HasPrefix(plain, "-0b") {
- intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
+ intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ }
+ // Octals as introduced in version 1.2 of the spec.
+ // Octals from the 1.1 spec, spelled as 0777, are still
+ // decoded by default in v3 as well for compatibility.
+ // May be dropped in v4 depending on how usage evolves.
+ if strings.HasPrefix(plain, "0o") {
+ intv, err := strconv.ParseInt(plain[2:], 8, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 8, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0o") {
+ intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
if err == nil {
if true || intv == int64(int(intv)) {
- return yaml_INT_TAG, int(intv)
+ return intTag, int(intv)
} else {
- return yaml_INT_TAG, intv
+ return intTag, intv
}
}
}
default:
- panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
+ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
}
}
- return yaml_STR_TAG, in
+ return strTag, in
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go
index 0b9bb60..ca00701 100644
--- a/vendor/gopkg.in/yaml.v2/scannerc.go
+++ b/vendor/gopkg.in/yaml.v3/scannerc.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -489,6 +511,9 @@ func cache(parser *yaml_parser_t, length int) bool {
// Advance the buffer pointer.
func skip(parser *yaml_parser_t) {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
parser.mark.index++
parser.mark.column++
parser.unread--
@@ -502,17 +527,22 @@ func skip_line(parser *yaml_parser_t) {
parser.mark.line++
parser.unread -= 2
parser.buffer_pos += 2
+ parser.newlines++
} else if is_break(parser.buffer, parser.buffer_pos) {
parser.mark.index++
parser.mark.column = 0
parser.mark.line++
parser.unread--
parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ parser.newlines++
}
}
// Copy a character to a string buffer and advance pointers.
func read(parser *yaml_parser_t, s []byte) []byte {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
w := width(parser.buffer[parser.buffer_pos])
if w == 0 {
panic("invalid character sequence")
@@ -564,6 +594,7 @@ func read_line(parser *yaml_parser_t, s []byte) []byte {
parser.mark.column = 0
parser.mark.line++
parser.unread--
+ parser.newlines++
return s
}
@@ -626,9 +657,13 @@ func trace(args ...interface{}) func() {
func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
// While we need more tokens to fetch, do it.
for {
- if parser.tokens_head != len(parser.tokens) {
- // If queue is non-empty, check if any potential simple key may
- // occupy the head position.
+ // [Go] The comment parsing logic requires a lookahead of two tokens
+ // so that foot comments may be parsed in time of associating them
+ // with the tokens that are parsed before them, and also for line
+ // comments to be transformed into head comments in some edge cases.
+ if parser.tokens_head < len(parser.tokens)-2 {
+ // If a potential simple key is at the head position, we need to fetch
+ // the next token to disambiguate it.
head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
if !ok {
break
@@ -649,7 +684,7 @@ func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
}
// The dispatcher for token fetchers.
-func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
// Ensure that the buffer is initialized.
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false
@@ -660,13 +695,19 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
return yaml_parser_fetch_stream_start(parser)
}
+ scan_mark := parser.mark
+
// Eat whitespaces and comments until we reach the next token.
if !yaml_parser_scan_to_next_token(parser) {
return false
}
+ // [Go] While unrolling indents, transform the head comments of prior
+ // indentation levels observed after scan_start into foot comments at
+ // the respective indexes.
+
// Check the indentation level against the current column.
- if !yaml_parser_unroll_indent(parser, parser.mark.column) {
+ if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
return false
}
@@ -699,6 +740,26 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
}
+ comment_mark := parser.mark
+ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+ // Associate any following comments with the prior token.
+ comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
+ }
+ defer func() {
+ if !ok {
+ return
+ }
+ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+ // Sequence indicators alone have no line comments. It becomes
+ // a head comment for whatever follows.
+ return
+ }
+ if !yaml_parser_scan_line_comment(parser, comment_mark) {
+ ok = false
+ return
+ }
+ }()
+
// Is it the flow sequence start indicator?
if buf[pos] == '[' {
return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
@@ -792,7 +853,7 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
// if it is followed by a non-space character.
//
// The last rule is more restrictive than the specification requires.
- // [Go] Make this logic more reasonable.
+ // [Go] TODO Make this logic more reasonable.
//switch parser.buffer[parser.buffer_pos] {
//case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
//}
@@ -965,19 +1026,49 @@ func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml
// Pop indentation levels from the indents stack until the current level
// becomes less or equal to the column. For each indentation level, append
// the BLOCK-END token.
-func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
// In the flow context, do nothing.
if parser.flow_level > 0 {
return true
}
+ block_mark := scan_mark
+ block_mark.index--
+
// Loop through the indentation levels in the stack.
for parser.indent > column {
+
+ // [Go] Reposition the end token before potential following
+ // foot comments of parent blocks. For that, search
+ // backwards for recent comments that were at the same
+ // indent as the block that is ending now.
+ stop_index := block_mark.index
+ for i := len(parser.comments) - 1; i >= 0; i-- {
+ comment := &parser.comments[i]
+
+ if comment.end_mark.index < stop_index {
+ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+ // If requested indent column is < 0, then the document is over and everything else
+ // is a foot anyway.
+ break
+ }
+ if comment.start_mark.column == parser.indent+1 {
+ // This is a good match. But maybe there's a former comment
+ // at that same indent level, so keep searching.
+ block_mark = comment.start_mark
+ }
+
+ // While the end of the former comment matches with
+ // the start of the following one, we know there's
+ // nothing in between and scanning is still safe.
+ stop_index = comment.scan_mark.index
+ }
+
// Create a token and append it to the queue.
token := yaml_token_t{
typ: yaml_BLOCK_END_TOKEN,
- start_mark: parser.mark,
- end_mark: parser.mark,
+ start_mark: block_mark,
+ end_mark: block_mark,
}
yaml_insert_token(parser, -1, &token)
@@ -1026,7 +1117,7 @@ func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
}
// Reset the indentation level.
- if !yaml_parser_unroll_indent(parser, -1) {
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
return false
}
@@ -1050,7 +1141,7 @@ func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
// Reset the indentation level.
- if !yaml_parser_unroll_indent(parser, -1) {
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
return false
}
@@ -1074,7 +1165,7 @@ func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
// Produce the DOCUMENT-START or DOCUMENT-END token.
func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
// Reset the indentation level.
- if !yaml_parser_unroll_indent(parser, -1) {
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
return false
}
@@ -1107,6 +1198,7 @@ func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_
// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+
// The indicators '[' and '{' may start a simple key.
if !yaml_parser_save_simple_key(parser) {
return false
@@ -1442,6 +1534,8 @@ func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
// Eat whitespaces and comments until the next token is found.
func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+ scan_mark := parser.mark
+
// Until the next token is not found.
for {
// Allow the BOM mark to start a line.
@@ -1468,13 +1562,33 @@ func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
}
}
+ // Check if we just had a line comment under a sequence entry that
+ // looks more like a header to the following content. Similar to this:
+ //
+ // - # The comment
+ // - Some data
+ //
+ // If so, transform the line comment to a head comment and reposition.
+ if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+ tokenA := parser.tokens[len(parser.tokens)-2]
+ tokenB := parser.tokens[len(parser.tokens)-1]
+ comment := &parser.comments[len(parser.comments)-1]
+ if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
+ // If it was in the prior line, reposition so it becomes a
+ // header of the follow up token. Otherwise, keep it in place
+ // so it becomes a header of the former.
+ comment.head = comment.line
+ comment.line = nil
+ if comment.start_mark.line == parser.mark.line-1 {
+ comment.token_mark = parser.mark
+ }
+ }
+ }
+
// Eat a comment until a line break.
if parser.buffer[parser.buffer_pos] == '#' {
- for !is_breakz(parser.buffer, parser.buffer_pos) {
- skip(parser)
- if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
- return false
- }
+ if !yaml_parser_scan_comments(parser, scan_mark) {
+ return false
}
}
@@ -1572,6 +1686,10 @@ func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool
}
if parser.buffer[parser.buffer_pos] == '#' {
+ // [Go] Discard this inline comment for the time being.
+ //if !yaml_parser_scan_line_comment(parser, start_mark) {
+ // return false
+ //}
for !is_breakz(parser.buffer, parser.buffer_pos) {
skip(parser)
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -1987,7 +2105,7 @@ func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte
// '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
// '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
// '%'.
- // [Go] Convert this into more reasonable logic.
+ // [Go] TODO Convert this into more reasonable logic.
for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
@@ -2142,6 +2260,9 @@ func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, l
}
}
if parser.buffer[parser.buffer_pos] == '#' {
+ if !yaml_parser_scan_line_comment(parser, start_mark) {
+ return false
+ }
for !is_breakz(parser.buffer, parser.buffer_pos) {
skip(parser)
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -2709,3 +2830,209 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
}
return true
}
+
+func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
+ if parser.newlines > 0 {
+ return true
+ }
+
+ var start_mark yaml_mark_t
+ var text []byte
+
+ for peek := 0; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ if parser.buffer[parser.buffer_pos+peek] == '#' {
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ if len(text) == 0 {
+ start_mark = parser.mark
+ }
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+ }
+ break
+ }
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ token_mark: token_mark,
+ start_mark: start_mark,
+ line: text,
+ })
+ }
+ return true
+}
+
+func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
+ token := parser.tokens[len(parser.tokens)-1]
+
+ if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+ token = parser.tokens[len(parser.tokens)-2]
+ }
+
+ var token_mark = token.start_mark
+ var start_mark yaml_mark_t
+ var next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+
+ var recent_empty = false
+ var first_empty = parser.newlines <= 1
+
+ var line = parser.mark.line
+ var column = parser.mark.column
+
+ var text []byte
+
+ // The foot line is the place where a comment must start to
+ // still be considered as a foot of the prior content.
+ // If there's some content in the currently parsed line, then
+ // the foot is the line below it.
+ var foot_line = -1
+ if scan_mark.line > 0 {
+ foot_line = parser.mark.line-parser.newlines+1
+ if parser.newlines == 0 && parser.mark.column > 1 {
+ foot_line++
+ }
+ }
+
+ var peek = 0
+ for ; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ column++
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ c := parser.buffer[parser.buffer_pos+peek]
+ var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+ if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
+ // Got line break or terminator.
+ if close_flow || !recent_empty {
+ if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
+ // This is the first empty line and there were no empty lines before,
+ // so this initial part of the comment is a foot of the prior token
+ // instead of being a head for the following one. Split it up.
+ // Alternatively, this might also be the last comment inside a flow
+ // scope, so it must be a footer.
+ if len(text) > 0 {
+ if start_mark.column-1 < next_indent {
+ // If dedented it's unrelated to the prior token.
+ token_mark = start_mark
+ }
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+ } else {
+ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+ text = append(text, '\n')
+ }
+ }
+ }
+ if !is_break(parser.buffer, parser.buffer_pos+peek) {
+ break
+ }
+ first_empty = false
+ recent_empty = true
+ column = 0
+ line++
+ continue
+ }
+
+ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
+ // The comment at the different indentation is a foot of the
+ // preceding data rather than a head of the upcoming one.
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+
+ if parser.buffer[parser.buffer_pos+peek] != '#' {
+ break
+ }
+
+ if len(text) == 0 {
+ start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ } else {
+ text = append(text, '\n')
+ }
+
+ recent_empty = false
+
+ // Consume until after the consumed comment line.
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+
+ peek = 0
+ column = 0
+ line = parser.mark.line
+ next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+ }
+
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: start_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column},
+ head: text,
+ })
+ }
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go
index 4c45e66..9210ece 100644
--- a/vendor/gopkg.in/yaml.v2/sorter.go
+++ b/vendor/gopkg.in/yaml.v3/sorter.go
@@ -1,3 +1,18 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package yaml
import (
@@ -37,8 +52,10 @@ func (l keyList) Less(i, j int) bool {
return ak < bk
}
ar, br := []rune(a.String()), []rune(b.String())
+ digits := false
for i := 0; i < len(ar) && i < len(br); i++ {
if ar[i] == br[i] {
+ digits = unicode.IsDigit(ar[i])
continue
}
al := unicode.IsLetter(ar[i])
@@ -47,12 +64,16 @@ func (l keyList) Less(i, j int) bool {
return ar[i] < br[i]
}
if al || bl {
- return bl
+ if digits {
+ return al
+ } else {
+ return bl
+ }
}
var ai, bi int
var an, bn int64
if ar[i] == '0' || br[i] == '0' {
- for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
if ar[j] != '0' {
an = 1
bn = 1
diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go
new file mode 100644
index 0000000..b8a116b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/writerc.go
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_WRITER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return true
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+ }
+ emitter.buffer_pos = 0
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go
index 89650e2..8cec6da 100644
--- a/vendor/gopkg.in/yaml.v2/yaml.go
+++ b/vendor/gopkg.in/yaml.v3/yaml.go
@@ -1,3 +1,18 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
// Package yaml implements YAML support for the Go language.
//
// Source code and other details for the project are available at GitHub:
@@ -13,23 +28,16 @@ import (
"reflect"
"strings"
"sync"
+ "unicode/utf8"
)
-// MapSlice encodes and decodes as a YAML map.
-// The order of keys is preserved when encoding and decoding.
-type MapSlice []MapItem
-
-// MapItem is an item in a MapSlice.
-type MapItem struct {
- Key, Value interface{}
-}
-
// The Unmarshaler interface may be implemented by types to customize their
-// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
-// method receives a function that may be called to unmarshal the original
-// YAML value into a field or variable. It is safe to call the unmarshal
-// function parameter more than once if necessary.
+// behavior when being unmarshaled from a YAML document.
type Unmarshaler interface {
+ UnmarshalYAML(value *Node) error
+}
+
+type obsoleteUnmarshaler interface {
UnmarshalYAML(unmarshal func(interface{}) error) error
}
@@ -81,18 +89,10 @@ func Unmarshal(in []byte, out interface{}) (err error) {
return unmarshal(in, out, false)
}
-// UnmarshalStrict is like Unmarshal except that any fields that are found
-// in the data that do not have corresponding struct members, or mapping
-// keys that are duplicates, will result in
-// an error.
-func UnmarshalStrict(in []byte, out interface{}) (err error) {
- return unmarshal(in, out, true)
-}
-
// A Decoder reads and decodes YAML values from an input stream.
type Decoder struct {
- strict bool
- parser *parser
+ parser *parser
+ knownFields bool
}
// NewDecoder returns a new decoder that reads from r.
@@ -105,10 +105,10 @@ func NewDecoder(r io.Reader) *Decoder {
}
}
-// SetStrict sets whether strict decoding behaviour is enabled when
-// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
-func (dec *Decoder) SetStrict(strict bool) {
- dec.strict = strict
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+ dec.knownFields = enable
}
// Decode reads the next YAML-encoded value from its input
@@ -117,7 +117,8 @@ func (dec *Decoder) SetStrict(strict bool) {
// See the documentation for Unmarshal for details about the
// conversion of YAML into a Go value.
func (dec *Decoder) Decode(v interface{}) (err error) {
- d := newDecoder(dec.strict)
+ d := newDecoder()
+ d.knownFields = dec.knownFields
defer handleErr(&err)
node := dec.parser.parse()
if node == nil {
@@ -134,9 +135,27 @@ func (dec *Decoder) Decode(v interface{}) (err error) {
return nil
}
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v interface{}) (err error) {
+ d := newDecoder()
+ defer handleErr(&err)
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(n, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
defer handleErr(&err)
- d := newDecoder(strict)
+ d := newDecoder()
p := newParser(in)
defer p.destroy()
node := p.parse()
@@ -175,7 +194,7 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
// Zero valued structs will be omitted if all their public
// fields are zero, unless they implement an IsZero
// method (see the IsZeroer interface type), in which
-// case the field will be included if that method returns true.
+// case the field will be excluded if IsZero returns true.
//
// flow Marshal using a flow style (useful for structs,
// sequences and maps).
@@ -233,6 +252,32 @@ func (e *Encoder) Encode(v interface{}) (err error) {
return nil
}
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(v))
+ e.finish()
+ p := newParser(e.out)
+ p.textless = true
+ defer p.destroy()
+ doc := p.parse()
+ *n = *doc.Content[0]
+ return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+ if spaces < 0 {
+ panic("yaml: cannot indent to a negative number of spaces")
+ }
+ e.encoder.indent = spaces
+}
+
// Close closes the encoder by writing any remaining data.
// It does not write a stream terminating string "...".
func (e *Encoder) Close() (err error) {
@@ -275,6 +320,168 @@ func (e *TypeError) Error() string {
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
}
+type Kind uint32
+
+const (
+ DocumentNode Kind = 1 << iota
+ SequenceNode
+ MappingNode
+ ScalarNode
+ AliasNode
+)
+
+type Style uint32
+
+const (
+ TaggedStyle Style = 1 << iota
+ DoubleQuotedStyle
+ SingleQuotedStyle
+ LiteralStyle
+ FoldedStyle
+ FlowStyle
+)
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+// var person struct {
+// Name string
+// Address yaml.Node
+// }
+// err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+// var person Node
+// err := yaml.Unmarshal(data, &person)
+//
+type Node struct {
+ // Kind defines whether the node is a document, a mapping, a sequence,
+ // a scalar value, or an alias to another node. The specific data type of
+ // scalar nodes may be obtained via the ShortTag and LongTag methods.
+ Kind Kind
+
+ // Style allows customizing the apperance of the node in the tree.
+ Style Style
+
+ // Tag holds the YAML tag defining the data type for the value.
+ // When decoding, this field will always be set to the resolved tag,
+ // even when it wasn't explicitly provided in the YAML content.
+ // When encoding, if this field is unset the value type will be
+ // implied from the node properties, and if it is set, it will only
+ // be serialized into the representation if TaggedStyle is used or
+ // the implicit tag diverges from the provided one.
+ Tag string
+
+ // Value holds the unescaped and unquoted represenation of the value.
+ Value string
+
+ // Anchor holds the anchor name for this node, which allows aliases to point to it.
+ Anchor string
+
+ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+ Alias *Node
+
+ // Content holds contained nodes for documents, mappings, and sequences.
+ Content []*Node
+
+ // HeadComment holds any comments in the lines preceding the node and
+ // not separated by an empty line.
+ HeadComment string
+
+ // LineComment holds any comments at the end of the line where the node is in.
+ LineComment string
+
+ // FootComment holds any comments following the node and before empty lines.
+ FootComment string
+
+ // Line and Column hold the node position in the decoded YAML text.
+ // These fields are not respected when encoding the node.
+ Line int
+ Column int
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+ return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+ if n.indicatedString() {
+ return strTag
+ }
+ if n.Tag == "" || n.Tag == "!" {
+ switch n.Kind {
+ case MappingNode:
+ return mapTag
+ case SequenceNode:
+ return seqTag
+ case AliasNode:
+ if n.Alias != nil {
+ return n.Alias.ShortTag()
+ }
+ case ScalarNode:
+ tag, _ := resolve("", n.Value)
+ return tag
+ case 0:
+ // Special case to make the zero value convenient.
+ if n.IsZero() {
+ return nullTag
+ }
+ }
+ return ""
+ }
+ return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+ return n.Kind == ScalarNode &&
+ (shortTag(n.Tag) == strTag ||
+ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+ n.Kind = ScalarNode
+ if utf8.ValidString(s) {
+ n.Value = s
+ n.Tag = strTag
+ } else {
+ n.Value = encodeBase64(s)
+ n.Tag = binaryTag
+ }
+ if strings.Contains(n.Value, "\n") {
+ n.Style = LiteralStyle
+ }
+}
+
// --------------------------------------------------------------------------
// Maintain a mapping of keys to structure field indexes
@@ -289,6 +496,10 @@ type structInfo struct {
// InlineMap is the number of the field in the struct that
// contains an ,inline map, or -1 if there's none.
InlineMap int
+
+ // InlineUnmarshalers holds indexes to inlined fields that
+ // contain unmarshaler values.
+ InlineUnmarshalers [][]int
}
type fieldInfo struct {
@@ -306,6 +517,12 @@ type fieldInfo struct {
var structMap = make(map[reflect.Type]*structInfo)
var fieldMapMutex sync.RWMutex
+var unmarshalerType reflect.Type
+
+func init() {
+ var v Unmarshaler
+ unmarshalerType = reflect.ValueOf(&v).Elem().Type()
+}
func getStructInfo(st reflect.Type) (*structInfo, error) {
fieldMapMutex.RLock()
@@ -319,6 +536,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
fieldsMap := make(map[string]fieldInfo)
fieldsList := make([]fieldInfo, 0, n)
inlineMap := -1
+ inlineUnmarshalers := [][]int(nil)
for i := 0; i != n; i++ {
field := st.Field(i)
if field.PkgPath != "" && !field.Anonymous {
@@ -347,7 +565,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
case "inline":
inline = true
default:
- return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
+ return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
}
}
tag = fields[0]
@@ -357,34 +575,47 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
switch field.Type.Kind() {
case reflect.Map:
if inlineMap >= 0 {
- return nil, errors.New("Multiple ,inline maps in struct " + st.String())
+ return nil, errors.New("multiple ,inline maps in struct " + st.String())
}
if field.Type.Key() != reflect.TypeOf("") {
- return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
+ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
}
inlineMap = info.Num
- case reflect.Struct:
- sinfo, err := getStructInfo(field.Type)
- if err != nil {
- return nil, err
+ case reflect.Struct, reflect.Ptr:
+ ftype := field.Type
+ for ftype.Kind() == reflect.Ptr {
+ ftype = ftype.Elem()
}
- for _, finfo := range sinfo.FieldsList {
- if _, found := fieldsMap[finfo.Key]; found {
- msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
- return nil, errors.New(msg)
+ if ftype.Kind() != reflect.Struct {
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ if reflect.PtrTo(ftype).Implements(unmarshalerType) {
+ inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+ } else {
+ sinfo, err := getStructInfo(ftype)
+ if err != nil {
+ return nil, err
+ }
+ for _, index := range sinfo.InlineUnmarshalers {
+ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
}
- if finfo.Inline == nil {
- finfo.Inline = []int{i, finfo.Num}
- } else {
- finfo.Inline = append([]int{i}, finfo.Inline...)
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
}
- finfo.Id = len(fieldsList)
- fieldsMap[finfo.Key] = finfo
- fieldsList = append(fieldsList, finfo)
}
default:
- //return nil, errors.New("Option ,inline needs a struct value or map field")
- return nil, errors.New("Option ,inline needs a struct value field")
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
}
continue
}
@@ -396,7 +627,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
}
if _, found = fieldsMap[info.Key]; found {
- msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
+ msg := "duplicated key '" + info.Key + "' in struct " + st.String()
return nil, errors.New(msg)
}
@@ -406,9 +637,10 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
}
sinfo = &structInfo{
- FieldsMap: fieldsMap,
- FieldsList: fieldsList,
- InlineMap: inlineMap,
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ InlineUnmarshalers: inlineUnmarshalers,
}
fieldMapMutex.Lock()
diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go
index f6a9c8e..7c6d007 100644
--- a/vendor/gopkg.in/yaml.v2/yamlh.go
+++ b/vendor/gopkg.in/yaml.v3/yamlh.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
import (
@@ -73,13 +95,13 @@ type yaml_scalar_style_t yaml_style_t
// Scalar styles.
const (
// Let the emitter choose the style.
- yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
+ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
- yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
- yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
- yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
- yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
- yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
+ yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
+ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
+ yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
)
type yaml_sequence_style_t yaml_style_t
@@ -238,6 +260,7 @@ const (
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
yaml_MAPPING_START_EVENT // A MAPPING-START event.
yaml_MAPPING_END_EVENT // A MAPPING-END event.
+ yaml_TAIL_COMMENT_EVENT
)
var eventStrings = []string{
@@ -252,6 +275,7 @@ var eventStrings = []string{
yaml_SEQUENCE_END_EVENT: "sequence end",
yaml_MAPPING_START_EVENT: "mapping start",
yaml_MAPPING_END_EVENT: "mapping end",
+ yaml_TAIL_COMMENT_EVENT: "tail comment",
}
func (e yaml_event_type_t) String() string {
@@ -279,6 +303,12 @@ type yaml_event_t struct {
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
tag_directives []yaml_tag_directive_t
+ // The comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
anchor []byte
@@ -554,6 +584,8 @@ type yaml_parser_t struct {
unread int // The number of unread characters in the buffer.
+ newlines int // The number of line breaks since last non-break/non-blank character
+
raw_buffer []byte // The raw buffer.
raw_buffer_pos int // The current position of the buffer.
@@ -562,6 +594,17 @@ type yaml_parser_t struct {
offset int // The offset of the current position (in bytes).
mark yaml_mark_t // The mark of the current position.
+ // Comments
+
+ head_comment []byte // The current head comments
+ line_comment []byte // The current line comments
+ foot_comment []byte // The current foot comments
+ tail_comment []byte // Foot comment that happens at the end of a block.
+ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+ comments []yaml_comment_t // The folded comments for all parsed tokens
+ comments_head int
+
// Scanner stuff
stream_start_produced bool // Have we started to scan the input stream?
@@ -595,6 +638,18 @@ type yaml_parser_t struct {
document *yaml_document_t // The currently parsed document.
}
+type yaml_comment_t struct {
+
+ scan_mark yaml_mark_t // Position where scanning for comments started
+ token_mark yaml_mark_t // Position after which tokens will be associated with this comment
+ start_mark yaml_mark_t // Position of '#' comment mark
+ end_mark yaml_mark_t // Position where comment terminated
+
+ head []byte
+ line []byte
+ foot []byte
+}
+
// Emitter Definitions
// The prototype of a write handler.
@@ -625,8 +680,10 @@ const (
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
@@ -698,6 +755,9 @@ type yaml_emitter_t struct {
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
open_ended bool // If an explicit document end is required?
+ space_above bool // Is there's an empty line above?
+ foot_indent int // The indent used to write the foot comment above, or -1 if none.
+
// Anchor analysis.
anchor_data struct {
anchor []byte // The anchor value.
@@ -721,6 +781,14 @@ type yaml_emitter_t struct {
style yaml_scalar_style_t // The output style.
}
+ // Comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
+ key_line_comment []byte
+
// Dumper stuff
opened bool // If the stream was already opened?
diff --git a/vendor/gopkg.in/yaml.v2/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
index 8110ce3..e88f9c5 100644
--- a/vendor/gopkg.in/yaml.v2/yamlprivateh.go
+++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
package yaml
const (
@@ -114,8 +136,9 @@ func is_crlf(b []byte, i int) bool {
// Check if the character is a line break or NUL.
func is_breakz(b []byte, i int) bool {
//return is_break(b, i) || is_z(b, i)
- return ( // is_break:
- b[i] == '\r' || // CR (#xD)
+ return (
+ // is_break:
+ b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
@@ -127,8 +150,9 @@ func is_breakz(b []byte, i int) bool {
// Check if the character is a line break, space, or NUL.
func is_spacez(b []byte, i int) bool {
//return is_space(b, i) || is_breakz(b, i)
- return ( // is_space:
- b[i] == ' ' ||
+ return (
+ // is_space:
+ b[i] == ' ' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
@@ -141,8 +165,9 @@ func is_spacez(b []byte, i int) bool {
// Check if the character is a line break, space, tab, or NUL.
func is_blankz(b []byte, i int) bool {
//return is_blank(b, i) || is_breakz(b, i)
- return ( // is_blank:
- b[i] == ' ' || b[i] == '\t' ||
+ return (
+ // is_blank:
+ b[i] == ' ' || b[i] == '\t' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 3d48ecd..50f39aa 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,13 +1,9 @@
-# github.com/gocarina/gocsv v0.0.0-20200330101823-46266ca37bd3
-## explicit
+# github.com/gocarina/gocsv v0.0.0-20220914091333-ceebdd90b590
+## explicit; go 1.13
github.com/gocarina/gocsv
-# github.com/ogier/pflag v0.0.1
-## explicit
# github.com/spf13/pflag v1.0.5
-## explicit
+## explicit; go 1.12
github.com/spf13/pflag
-# github.com/victorhaggqvist/pflag v0.0.2-0.20160203232644-de7e39409b47
-## explicit
-# gopkg.in/yaml.v2 v2.2.8
+# gopkg.in/yaml.v3 v3.0.1
## explicit
-gopkg.in/yaml.v2
+gopkg.in/yaml.v3