updated vendors
This commit is contained in:
parent
e48d201427
commit
f9e1d06e70
2
vendor/gopkg.in/ini.v1/.travis.yml
generated
vendored
2
vendor/gopkg.in/ini.v1/.travis.yml
generated
vendored
@ -7,7 +7,9 @@ go:
|
|||||||
- 1.9.x
|
- 1.9.x
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
- 1.11.x
|
- 1.11.x
|
||||||
|
- 1.12.x
|
||||||
|
|
||||||
|
install: skip
|
||||||
script:
|
script:
|
||||||
- go get golang.org/x/tools/cmd/cover
|
- go get golang.org/x/tools/cmd/cover
|
||||||
- go get github.com/smartystreets/goconvey
|
- go get github.com/smartystreets/goconvey
|
||||||
|
8
vendor/gopkg.in/ini.v1/README.md
generated
vendored
8
vendor/gopkg.in/ini.v1/README.md
generated
vendored
@ -22,18 +22,10 @@ Package ini provides INI file read and write functionality in Go.
|
|||||||
|
|
||||||
The minimum requirement of Go is **1.6**.
|
The minimum requirement of Go is **1.6**.
|
||||||
|
|
||||||
To use a tagged revision:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go get gopkg.in/ini.v1
|
$ go get gopkg.in/ini.v1
|
||||||
```
|
```
|
||||||
|
|
||||||
To use with latest changes:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ go get github.com/go-ini/ini
|
|
||||||
```
|
|
||||||
|
|
||||||
Please add `-u` flag to update in the future.
|
Please add `-u` flag to update in the future.
|
||||||
|
|
||||||
## Getting Help
|
## Getting Help
|
||||||
|
74
vendor/gopkg.in/ini.v1/data_source.go
generated
vendored
Normal file
74
vendor/gopkg.in/ini.v1/data_source.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2019 Unknwon
|
||||||
|
//
|
||||||
|
// 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 ini
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ dataSource = (*sourceFile)(nil)
|
||||||
|
_ dataSource = (*sourceData)(nil)
|
||||||
|
_ dataSource = (*sourceReadCloser)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// dataSource is an interface that returns object which can be read and closed.
|
||||||
|
type dataSource interface {
|
||||||
|
ReadCloser() (io.ReadCloser, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sourceFile represents an object that contains content on the local file system.
|
||||||
|
type sourceFile struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
|
||||||
|
return os.Open(s.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sourceData represents an object that contains content in memory.
|
||||||
|
type sourceData struct {
|
||||||
|
data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
|
||||||
|
return ioutil.NopCloser(bytes.NewReader(s.data)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// sourceReadCloser represents an input stream with Close method.
|
||||||
|
type sourceReadCloser struct {
|
||||||
|
reader io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
|
||||||
|
return s.reader, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDataSource(source interface{}) (dataSource, error) {
|
||||||
|
switch s := source.(type) {
|
||||||
|
case string:
|
||||||
|
return sourceFile{s}, nil
|
||||||
|
case []byte:
|
||||||
|
return &sourceData{s}, nil
|
||||||
|
case io.ReadCloser:
|
||||||
|
return &sourceReadCloser{s}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
|
||||||
|
}
|
||||||
|
}
|
25
vendor/gopkg.in/ini.v1/deprecated.go
generated
vendored
Normal file
25
vendor/gopkg.in/ini.v1/deprecated.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2019 Unknwon
|
||||||
|
//
|
||||||
|
// 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 ini
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Deprecated: Use "DefaultSection" instead.
|
||||||
|
DEFAULT_SECTION = DefaultSection
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
|
||||||
|
AllCapsUnderscore = SnackCase
|
||||||
|
)
|
2
vendor/gopkg.in/ini.v1/error.go
generated
vendored
2
vendor/gopkg.in/ini.v1/error.go
generated
vendored
@ -18,10 +18,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
|
||||||
type ErrDelimiterNotFound struct {
|
type ErrDelimiterNotFound struct {
|
||||||
Line string
|
Line string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
|
||||||
func IsErrDelimiterNotFound(err error) bool {
|
func IsErrDelimiterNotFound(err error) bool {
|
||||||
_, ok := err.(ErrDelimiterNotFound)
|
_, ok := err.(ErrDelimiterNotFound)
|
||||||
return ok
|
return ok
|
||||||
|
16
vendor/gopkg.in/ini.v1/file.go
generated
vendored
16
vendor/gopkg.in/ini.v1/file.go
generated
vendored
@ -68,7 +68,7 @@ func Empty() *File {
|
|||||||
func (f *File) NewSection(name string) (*Section, error) {
|
func (f *File) NewSection(name string) (*Section, error) {
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return nil, errors.New("error creating new section: empty section name")
|
return nil, errors.New("error creating new section: empty section name")
|
||||||
} else if f.options.Insensitive && name != DEFAULT_SECTION {
|
} else if f.options.Insensitive && name != DefaultSection {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func (f *File) NewSections(names ...string) (err error) {
|
|||||||
// GetSection returns section by given name.
|
// GetSection returns section by given name.
|
||||||
func (f *File) GetSection(name string) (*Section, error) {
|
func (f *File) GetSection(name string) (*Section, error) {
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
name = DEFAULT_SECTION
|
name = DefaultSection
|
||||||
}
|
}
|
||||||
if f.options.Insensitive {
|
if f.options.Insensitive {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
@ -141,7 +141,7 @@ func (f *File) Section(name string) *Section {
|
|||||||
return sec
|
return sec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section returns list of Section.
|
// Sections returns a list of Section stored in the current instance.
|
||||||
func (f *File) Sections() []*Section {
|
func (f *File) Sections() []*Section {
|
||||||
if f.BlockMode {
|
if f.BlockMode {
|
||||||
f.lock.RLock()
|
f.lock.RLock()
|
||||||
@ -175,7 +175,7 @@ func (f *File) DeleteSection(name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
name = DEFAULT_SECTION
|
name = DefaultSection
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, s := range f.sectionList {
|
for i, s := range f.sectionList {
|
||||||
@ -302,11 +302,11 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
|||||||
}
|
}
|
||||||
alignSpaces := bytes.Repeat([]byte(" "), alignLength)
|
alignSpaces := bytes.Repeat([]byte(" "), alignLength)
|
||||||
|
|
||||||
KEY_LIST:
|
KeyList:
|
||||||
for _, kname := range sec.keyList {
|
for _, kname := range sec.keyList {
|
||||||
key := sec.Key(kname)
|
key := sec.Key(kname)
|
||||||
if len(key.Comment) > 0 {
|
if len(key.Comment) > 0 {
|
||||||
if len(indent) > 0 && sname != DEFAULT_SECTION {
|
if len(indent) > 0 && sname != DefaultSection {
|
||||||
buf.WriteString(indent)
|
buf.WriteString(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(indent) > 0 && sname != DEFAULT_SECTION {
|
if len(indent) > 0 && sname != DefaultSection {
|
||||||
buf.WriteString(indent)
|
buf.WriteString(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
|||||||
if kname != sec.keyList[len(sec.keyList)-1] {
|
if kname != sec.keyList[len(sec.keyList)-1] {
|
||||||
buf.WriteString(LineBreak)
|
buf.WriteString(LineBreak)
|
||||||
}
|
}
|
||||||
continue KEY_LIST
|
continue KeyList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out alignment spaces before "=" sign
|
// Write out alignment spaces before "=" sign
|
||||||
|
24
vendor/gopkg.in/ini.v1/helper.go
generated
vendored
Normal file
24
vendor/gopkg.in/ini.v1/helper.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2019 Unknwon
|
||||||
|
//
|
||||||
|
// 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 ini
|
||||||
|
|
||||||
|
func inSlice(str string, s []string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if str == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
102
vendor/gopkg.in/ini.v1/ini.go
generated
vendored
102
vendor/gopkg.in/ini.v1/ini.go
generated
vendored
@ -18,55 +18,47 @@
|
|||||||
package ini
|
package ini
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Name for default section. You can use this constant or the string literal.
|
// DefaultSection is the name of default section. You can use this constant or the string literal.
|
||||||
// In most of cases, an empty string is all you need to access the section.
|
// In most of cases, an empty string is all you need to access the section.
|
||||||
DEFAULT_SECTION = "DEFAULT"
|
DefaultSection = "DEFAULT"
|
||||||
|
|
||||||
// Maximum allowed depth when recursively substituing variable names.
|
// Maximum allowed depth when recursively substituing variable names.
|
||||||
_DEPTH_VALUES = 99
|
depthValues = 99
|
||||||
_VERSION = "1.42.0"
|
version = "1.48.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version returns current package version literal.
|
// Version returns current package version literal.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return _VERSION
|
return version
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Delimiter to determine or compose a new line.
|
// LineBreak is the delimiter to determine or compose a new line.
|
||||||
// This variable will be changed to "\r\n" automatically on Windows
|
// This variable will be changed to "\r\n" automatically on Windows at package init time.
|
||||||
// at package init time.
|
|
||||||
LineBreak = "\n"
|
LineBreak = "\n"
|
||||||
|
|
||||||
// Place custom spaces when PrettyFormat and PrettyEqual are both disabled
|
|
||||||
DefaultFormatLeft = ""
|
|
||||||
DefaultFormatRight = ""
|
|
||||||
|
|
||||||
// Variable regexp pattern: %(variable)s
|
// Variable regexp pattern: %(variable)s
|
||||||
varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`)
|
varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)
|
||||||
|
|
||||||
// Indicate whether to align "=" sign with spaces to produce pretty output
|
// DefaultHeader explicitly writes default section header.
|
||||||
// or reduce all possible spaces for compact format.
|
|
||||||
PrettyFormat = true
|
|
||||||
|
|
||||||
// Place spaces around "=" sign even when PrettyFormat is false
|
|
||||||
PrettyEqual = false
|
|
||||||
|
|
||||||
// Explicitly write DEFAULT section header
|
|
||||||
DefaultHeader = false
|
DefaultHeader = false
|
||||||
|
|
||||||
// Indicate whether to put a line between sections
|
// PrettySection indicates whether to put a line between sections.
|
||||||
PrettySection = true
|
PrettySection = true
|
||||||
|
// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
|
||||||
|
// or reduce all possible spaces for compact format.
|
||||||
|
PrettyFormat = true
|
||||||
|
// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
|
||||||
|
PrettyEqual = false
|
||||||
|
// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
|
||||||
|
DefaultFormatLeft = ""
|
||||||
|
// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
|
||||||
|
DefaultFormatRight = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -75,60 +67,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func inSlice(str string, s []string) bool {
|
// LoadOptions contains all customized options used for load data source(s).
|
||||||
for _, v := range s {
|
|
||||||
if str == v {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// dataSource is an interface that returns object which can be read and closed.
|
|
||||||
type dataSource interface {
|
|
||||||
ReadCloser() (io.ReadCloser, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceFile represents an object that contains content on the local file system.
|
|
||||||
type sourceFile struct {
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
|
|
||||||
return os.Open(s.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceData represents an object that contains content in memory.
|
|
||||||
type sourceData struct {
|
|
||||||
data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
|
|
||||||
return ioutil.NopCloser(bytes.NewReader(s.data)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceReadCloser represents an input stream with Close method.
|
|
||||||
type sourceReadCloser struct {
|
|
||||||
reader io.ReadCloser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
|
|
||||||
return s.reader, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDataSource(source interface{}) (dataSource, error) {
|
|
||||||
switch s := source.(type) {
|
|
||||||
case string:
|
|
||||||
return sourceFile{s}, nil
|
|
||||||
case []byte:
|
|
||||||
return &sourceData{s}, nil
|
|
||||||
case io.ReadCloser:
|
|
||||||
return &sourceReadCloser{s}, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoadOptions struct {
|
type LoadOptions struct {
|
||||||
// Loose indicates whether the parser should ignore nonexistent files or return error.
|
// Loose indicates whether the parser should ignore nonexistent files or return error.
|
||||||
Loose bool
|
Loose bool
|
||||||
@ -174,6 +113,7 @@ type LoadOptions struct {
|
|||||||
PreserveSurroundedQuote bool
|
PreserveSurroundedQuote bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadSources allows caller to apply customized options for loading from data source(s).
|
||||||
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
||||||
sources := make([]dataSource, len(others)+1)
|
sources := make([]dataSource, len(others)+1)
|
||||||
sources[0], err = parseDataSource(source)
|
sources[0], err = parseDataSource(source)
|
||||||
|
48
vendor/gopkg.in/ini.v1/key.go
generated
vendored
48
vendor/gopkg.in/ini.v1/key.go
generated
vendored
@ -54,6 +54,16 @@ func (k *Key) addShadow(val string) error {
|
|||||||
return errors.New("cannot add shadow to auto-increment or boolean key")
|
return errors.New("cannot add shadow to auto-increment or boolean key")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deduplicate shadows based on their values.
|
||||||
|
if k.value == val {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i := range k.shadows {
|
||||||
|
if k.shadows[i].value == val {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shadow := newKey(k.s, k.name, val)
|
shadow := newKey(k.s, k.name, val)
|
||||||
shadow.isShadow = true
|
shadow.isShadow = true
|
||||||
k.shadows = append(k.shadows, shadow)
|
k.shadows = append(k.shadows, shadow)
|
||||||
@ -77,6 +87,7 @@ func (k *Key) addNestedValue(val string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddNestedValue adds a nested value to the key.
|
||||||
func (k *Key) AddNestedValue(val string) error {
|
func (k *Key) AddNestedValue(val string) error {
|
||||||
if !k.s.f.options.AllowNestedValues {
|
if !k.s.f.options.AllowNestedValues {
|
||||||
return errors.New("nested value is not allowed")
|
return errors.New("nested value is not allowed")
|
||||||
@ -126,7 +137,7 @@ func (k *Key) transformValue(val string) string {
|
|||||||
if !strings.Contains(val, "%") {
|
if !strings.Contains(val, "%") {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
for i := 0; i < _DEPTH_VALUES; i++ {
|
for i := 0; i < depthValues; i++ {
|
||||||
vr := varPattern.FindString(val)
|
vr := varPattern.FindString(val)
|
||||||
if len(vr) == 0 {
|
if len(vr) == 0 {
|
||||||
break
|
break
|
||||||
@ -491,7 +502,7 @@ func (k *Key) Strings(delim string) []string {
|
|||||||
buf.WriteRune(runes[idx])
|
buf.WriteRune(runes[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx += 1
|
idx++
|
||||||
if idx == len(runes) {
|
if idx == len(runes) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -553,6 +564,12 @@ func (k *Key) Uint64s(delim string) []uint64 {
|
|||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Bools(delim string) []bool {
|
||||||
|
vals, _ := k.parseBools(k.Strings(delim), true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||||
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
||||||
func (k *Key) TimesFormat(format, delim string) []time.Time {
|
func (k *Key) TimesFormat(format, delim string) []time.Time {
|
||||||
@ -601,6 +618,13 @@ func (k *Key) ValidUint64s(delim string) []uint64 {
|
|||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned
|
||||||
|
// integer, then it will not be included to result list.
|
||||||
|
func (k *Key) ValidBools(delim string) []bool {
|
||||||
|
vals, _ := k.parseBools(k.Strings(delim), false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||||
func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
|
func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
|
||||||
vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
|
vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
|
||||||
@ -637,6 +661,11 @@ func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
|
|||||||
return k.parseUint64s(k.Strings(delim), false, true)
|
return k.parseUint64s(k.Strings(delim), false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StrictBools returns list of bool divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictBools(delim string) ([]bool, error) {
|
||||||
|
return k.parseBools(k.Strings(delim), false, true)
|
||||||
|
}
|
||||||
|
|
||||||
// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
|
// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
|
||||||
// or error on first invalid input.
|
// or error on first invalid input.
|
||||||
func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
|
func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
|
||||||
@ -649,6 +678,21 @@ func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
|
|||||||
return k.StrictTimesFormat(time.RFC3339, delim)
|
return k.StrictTimesFormat(time.RFC3339, delim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseBools transforms strings to bools.
|
||||||
|
func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) {
|
||||||
|
vals := make([]bool, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := parseBool(str)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
// parseFloat64s transforms strings to float64s.
|
// parseFloat64s transforms strings to float64s.
|
||||||
func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
|
func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
|
||||||
vals := make([]float64, 0, len(strs))
|
vals := make([]float64, 0, len(strs))
|
||||||
|
101
vendor/gopkg.in/ini.v1/parser.go
generated
vendored
101
vendor/gopkg.in/ini.v1/parser.go
generated
vendored
@ -27,25 +27,29 @@ import (
|
|||||||
|
|
||||||
var pythonMultiline = regexp.MustCompile("^(\\s+)([^\n]+)")
|
var pythonMultiline = regexp.MustCompile("^(\\s+)([^\n]+)")
|
||||||
|
|
||||||
type tokenType int
|
type parserOptions struct {
|
||||||
|
IgnoreContinuation bool
|
||||||
const (
|
IgnoreInlineComment bool
|
||||||
_TOKEN_INVALID tokenType = iota
|
AllowPythonMultilineValues bool
|
||||||
_TOKEN_COMMENT
|
SpaceBeforeInlineComment bool
|
||||||
_TOKEN_SECTION
|
UnescapeValueDoubleQuotes bool
|
||||||
_TOKEN_KEY
|
UnescapeValueCommentSymbols bool
|
||||||
)
|
PreserveSurroundedQuote bool
|
||||||
|
}
|
||||||
|
|
||||||
type parser struct {
|
type parser struct {
|
||||||
buf *bufio.Reader
|
buf *bufio.Reader
|
||||||
|
options parserOptions
|
||||||
|
|
||||||
isEOF bool
|
isEOF bool
|
||||||
count int
|
count int
|
||||||
comment *bytes.Buffer
|
comment *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParser(r io.Reader) *parser {
|
func newParser(r io.Reader, opts parserOptions) *parser {
|
||||||
return &parser{
|
return &parser{
|
||||||
buf: bufio.NewReader(r),
|
buf: bufio.NewReader(r),
|
||||||
|
options: opts,
|
||||||
count: 1,
|
count: 1,
|
||||||
comment: &bytes.Buffer{},
|
comment: &bytes.Buffer{},
|
||||||
}
|
}
|
||||||
@ -196,12 +200,13 @@ func hasSurroundedQuote(in string, quote byte) bool {
|
|||||||
strings.IndexByte(in[1:], quote) == len(in)-2
|
strings.IndexByte(in[1:], quote) == len(in)-2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) readValue(in []byte,
|
func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
|
||||||
parserBufferSize int,
|
|
||||||
ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols, allowPythonMultilines, spaceBeforeInlineComment, preserveSurroundedQuote bool) (string, error) {
|
|
||||||
|
|
||||||
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
|
if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
|
||||||
|
return p.readPythonMultilines(line, bufferSize)
|
||||||
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +215,7 @@ func (p *parser) readValue(in []byte,
|
|||||||
valQuote = `"""`
|
valQuote = `"""`
|
||||||
} else if line[0] == '`' {
|
} else if line[0] == '`' {
|
||||||
valQuote = "`"
|
valQuote = "`"
|
||||||
} else if unescapeValueDoubleQuotes && line[0] == '"' {
|
} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
|
||||||
valQuote = `"`
|
valQuote = `"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +227,7 @@ func (p *parser) readValue(in []byte,
|
|||||||
return p.readMultilines(line, line[startIdx:], valQuote)
|
return p.readMultilines(line, line[startIdx:], valQuote)
|
||||||
}
|
}
|
||||||
|
|
||||||
if unescapeValueDoubleQuotes && valQuote == `"` {
|
if p.options.UnescapeValueDoubleQuotes && valQuote == `"` {
|
||||||
return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
|
return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
|
||||||
}
|
}
|
||||||
return line[startIdx : pos+startIdx], nil
|
return line[startIdx : pos+startIdx], nil
|
||||||
@ -234,14 +239,14 @@ func (p *parser) readValue(in []byte,
|
|||||||
trimmedLastChar := line[len(line)-1]
|
trimmedLastChar := line[len(line)-1]
|
||||||
|
|
||||||
// Check continuation lines when desired
|
// Check continuation lines when desired
|
||||||
if !ignoreContinuation && trimmedLastChar == '\\' {
|
if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
|
||||||
return p.readContinuationLines(line[:len(line)-1])
|
return p.readContinuationLines(line[:len(line)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if ignore inline comment
|
// Check if ignore inline comment
|
||||||
if !ignoreInlineComment {
|
if !p.options.IgnoreInlineComment {
|
||||||
var i int
|
var i int
|
||||||
if spaceBeforeInlineComment {
|
if p.options.SpaceBeforeInlineComment {
|
||||||
i = strings.Index(line, " #")
|
i = strings.Index(line, " #")
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
i = strings.Index(line, " ;")
|
i = strings.Index(line, " ;")
|
||||||
@ -260,39 +265,44 @@ func (p *parser) readValue(in []byte,
|
|||||||
|
|
||||||
// Trim single and double quotes
|
// Trim single and double quotes
|
||||||
if (hasSurroundedQuote(line, '\'') ||
|
if (hasSurroundedQuote(line, '\'') ||
|
||||||
hasSurroundedQuote(line, '"')) && !preserveSurroundedQuote {
|
hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
|
||||||
line = line[1 : len(line)-1]
|
line = line[1 : len(line)-1]
|
||||||
} else if len(valQuote) == 0 && unescapeValueCommentSymbols {
|
} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
|
||||||
if strings.Contains(line, `\;`) {
|
if strings.Contains(line, `\;`) {
|
||||||
line = strings.Replace(line, `\;`, ";", -1)
|
line = strings.Replace(line, `\;`, ";", -1)
|
||||||
}
|
}
|
||||||
if strings.Contains(line, `\#`) {
|
if strings.Contains(line, `\#`) {
|
||||||
line = strings.Replace(line, `\#`, "#", -1)
|
line = strings.Replace(line, `\#`, "#", -1)
|
||||||
}
|
}
|
||||||
} else if allowPythonMultilines && lastChar == '\n' {
|
} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
|
||||||
parserBufferPeekResult, _ := p.buf.Peek(parserBufferSize)
|
return p.readPythonMultilines(line, bufferSize)
|
||||||
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
}
|
||||||
|
|
||||||
val := line
|
return line, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
|
||||||
|
parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
|
||||||
|
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
peekData, peekErr := peekBuffer.ReadBytes('\n')
|
peekData, peekErr := peekBuffer.ReadBytes('\n')
|
||||||
if peekErr != nil {
|
if peekErr != nil {
|
||||||
if peekErr == io.EOF {
|
if peekErr == io.EOF {
|
||||||
return val, nil
|
return line, nil
|
||||||
}
|
}
|
||||||
return "", peekErr
|
return "", peekErr
|
||||||
}
|
}
|
||||||
|
|
||||||
peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
|
peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
|
||||||
if len(peekMatches) != 3 {
|
if len(peekMatches) != 3 {
|
||||||
return val, nil
|
return line, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Return if not a python-ini multi-line value.
|
// NOTE: Return if not a python-ini multi-line value.
|
||||||
currentIdentSize := len(peekMatches[1])
|
currentIdentSize := len(peekMatches[1])
|
||||||
if currentIdentSize <= 0 {
|
if currentIdentSize <= 0 {
|
||||||
return val, nil
|
return line, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
||||||
@ -301,24 +311,29 @@ func (p *parser) readValue(in []byte,
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
val += fmt.Sprintf("\n%s", peekMatches[2])
|
line += fmt.Sprintf("\n%s", peekMatches[2])
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return line, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse parses data through an io.Reader.
|
// parse parses data through an io.Reader.
|
||||||
func (f *File) parse(reader io.Reader) (err error) {
|
func (f *File) parse(reader io.Reader) (err error) {
|
||||||
p := newParser(reader)
|
p := newParser(reader, parserOptions{
|
||||||
|
IgnoreContinuation: f.options.IgnoreContinuation,
|
||||||
|
IgnoreInlineComment: f.options.IgnoreInlineComment,
|
||||||
|
AllowPythonMultilineValues: f.options.AllowPythonMultilineValues,
|
||||||
|
SpaceBeforeInlineComment: f.options.SpaceBeforeInlineComment,
|
||||||
|
UnescapeValueDoubleQuotes: f.options.UnescapeValueDoubleQuotes,
|
||||||
|
UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols,
|
||||||
|
PreserveSurroundedQuote: f.options.PreserveSurroundedQuote,
|
||||||
|
})
|
||||||
if err = p.BOM(); err != nil {
|
if err = p.BOM(); err != nil {
|
||||||
return fmt.Errorf("BOM: %v", err)
|
return fmt.Errorf("BOM: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore error because default section name is never empty string.
|
// Ignore error because default section name is never empty string.
|
||||||
name := DEFAULT_SECTION
|
name := DefaultSection
|
||||||
if f.options.Insensitive {
|
if f.options.Insensitive {
|
||||||
name = strings.ToLower(DEFAULT_SECTION)
|
name = strings.ToLower(DefaultSection)
|
||||||
}
|
}
|
||||||
section, _ := f.NewSection(name)
|
section, _ := f.NewSection(name)
|
||||||
|
|
||||||
@ -426,15 +441,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
if IsErrDelimiterNotFound(err) {
|
if IsErrDelimiterNotFound(err) {
|
||||||
switch {
|
switch {
|
||||||
case f.options.AllowBooleanKeys:
|
case f.options.AllowBooleanKeys:
|
||||||
kname, err := p.readValue(line,
|
kname, err := p.readValue(line, parserBufferSize)
|
||||||
parserBufferSize,
|
|
||||||
f.options.IgnoreContinuation,
|
|
||||||
f.options.IgnoreInlineComment,
|
|
||||||
f.options.UnescapeValueDoubleQuotes,
|
|
||||||
f.options.UnescapeValueCommentSymbols,
|
|
||||||
f.options.AllowPythonMultilineValues,
|
|
||||||
f.options.SpaceBeforeInlineComment,
|
|
||||||
f.options.PreserveSurroundedQuote)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -461,15 +468,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
p.count++
|
p.count++
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := p.readValue(line[offset:],
|
value, err := p.readValue(line[offset:], parserBufferSize)
|
||||||
parserBufferSize,
|
|
||||||
f.options.IgnoreContinuation,
|
|
||||||
f.options.IgnoreInlineComment,
|
|
||||||
f.options.UnescapeValueDoubleQuotes,
|
|
||||||
f.options.UnescapeValueCommentSymbols,
|
|
||||||
f.options.AllowPythonMultilineValues,
|
|
||||||
f.options.SpaceBeforeInlineComment,
|
|
||||||
f.options.PreserveSurroundedQuote)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
7
vendor/gopkg.in/ini.v1/section.go
generated
vendored
7
vendor/gopkg.in/ini.v1/section.go
generated
vendored
@ -106,7 +106,6 @@ func (s *Section) NewBooleanKey(name string) (*Key, error) {
|
|||||||
|
|
||||||
// GetKey returns key in section by given name.
|
// GetKey returns key in section by given name.
|
||||||
func (s *Section) GetKey(name string) (*Key, error) {
|
func (s *Section) GetKey(name string) (*Key, error) {
|
||||||
// FIXME: change to section level lock?
|
|
||||||
if s.f.BlockMode {
|
if s.f.BlockMode {
|
||||||
s.f.lock.RLock()
|
s.f.lock.RLock()
|
||||||
}
|
}
|
||||||
@ -129,9 +128,8 @@ func (s *Section) GetKey(name string) (*Key, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return sec.GetKey(name)
|
return sec.GetKey(name)
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
|
return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
|
||||||
}
|
}
|
||||||
@ -144,8 +142,7 @@ func (s *Section) HasKey(name string) bool {
|
|||||||
return key != nil
|
return key != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Haskey is a backwards-compatible name for HasKey.
|
// Deprecated: Use "HasKey" instead.
|
||||||
// TODO: delete me in v2
|
|
||||||
func (s *Section) Haskey(name string) bool {
|
func (s *Section) Haskey(name string) bool {
|
||||||
return s.HasKey(name)
|
return s.HasKey(name)
|
||||||
}
|
}
|
||||||
|
97
vendor/gopkg.in/ini.v1/struct.go
generated
vendored
97
vendor/gopkg.in/ini.v1/struct.go
generated
vendored
@ -29,8 +29,8 @@ type NameMapper func(string) string
|
|||||||
|
|
||||||
// Built-in name getters.
|
// Built-in name getters.
|
||||||
var (
|
var (
|
||||||
// AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
|
// SnackCase converts to format SNACK_CASE.
|
||||||
AllCapsUnderscore NameMapper = func(raw string) string {
|
SnackCase NameMapper = func(raw string) string {
|
||||||
newstr := make([]rune, 0, len(raw))
|
newstr := make([]rune, 0, len(raw))
|
||||||
for i, chr := range raw {
|
for i, chr := range raw {
|
||||||
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
|
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
|
||||||
@ -50,7 +50,7 @@ var (
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
newstr = append(newstr, '_')
|
newstr = append(newstr, '_')
|
||||||
}
|
}
|
||||||
chr -= ('A' - 'a')
|
chr -= 'A' - 'a'
|
||||||
}
|
}
|
||||||
newstr = append(newstr, chr)
|
newstr = append(newstr, chr)
|
||||||
}
|
}
|
||||||
@ -108,6 +108,8 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowSh
|
|||||||
vals, err = key.parseUint64s(strs, true, false)
|
vals, err = key.parseUint64s(strs, true, false)
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
vals, err = key.parseFloat64s(strs, true, false)
|
vals, err = key.parseFloat64s(strs, true, false)
|
||||||
|
case reflect.Bool:
|
||||||
|
vals, err = key.parseBools(strs, true, false)
|
||||||
case reflectTime:
|
case reflectTime:
|
||||||
vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
|
vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
|
||||||
default:
|
default:
|
||||||
@ -132,6 +134,8 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowSh
|
|||||||
slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
|
slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
|
slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
|
||||||
|
case reflect.Bool:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i]))
|
||||||
case reflectTime:
|
case reflectTime:
|
||||||
slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
|
slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
|
||||||
}
|
}
|
||||||
@ -149,7 +153,7 @@ func wrapStrictError(err error, isStrict bool) error {
|
|||||||
|
|
||||||
// setWithProperType sets proper value to field based on its type,
|
// setWithProperType sets proper value to field based on its type,
|
||||||
// but it does not return error for failing parsing,
|
// but it does not return error for failing parsing,
|
||||||
// because we want to use default value that is already assigned to strcut.
|
// because we want to use default value that is already assigned to struct.
|
||||||
func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
|
func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
@ -205,6 +209,17 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
|||||||
field.Set(reflect.ValueOf(timeVal))
|
field.Set(reflect.ValueOf(timeVal))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
|
return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
|
||||||
|
case reflect.Ptr:
|
||||||
|
switch t.Elem().Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
boolVal, err := key.Bool()
|
||||||
|
if err != nil {
|
||||||
|
return wrapStrictError(err, isStrict)
|
||||||
|
}
|
||||||
|
field.Set(reflect.ValueOf(&boolVal))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type '%s'", t)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type '%s'", t)
|
return fmt.Errorf("unsupported type '%s'", t)
|
||||||
}
|
}
|
||||||
@ -244,14 +259,21 @@ func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
|
|
||||||
isStruct := tpField.Type.Kind() == reflect.Struct
|
isStruct := tpField.Type.Kind() == reflect.Struct
|
||||||
|
isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
|
||||||
|
isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
|
||||||
if isAnonymous {
|
if isAnonymous {
|
||||||
field.Set(reflect.New(tpField.Type.Elem()))
|
field.Set(reflect.New(tpField.Type.Elem()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if isAnonymous || isStruct {
|
if isAnonymous || isStruct || isStructPtr {
|
||||||
if sec, err := s.f.GetSection(fieldName); err == nil {
|
if sec, err := s.f.GetSection(fieldName); err == nil {
|
||||||
|
// Only set the field to non-nil struct value if we have
|
||||||
|
// a section for it. Otherwise, we end up with a non-nil
|
||||||
|
// struct ptr even though there is no data.
|
||||||
|
if isStructPtr && field.IsNil() {
|
||||||
|
field.Set(reflect.New(tpField.Type.Elem()))
|
||||||
|
}
|
||||||
if err = sec.mapTo(field, isStrict); err != nil {
|
if err = sec.mapTo(field, isStrict); err != nil {
|
||||||
return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
|
return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
|
||||||
}
|
}
|
||||||
@ -283,7 +305,7 @@ func (s *Section) MapTo(v interface{}) error {
|
|||||||
return s.mapTo(val, false)
|
return s.mapTo(val, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapTo maps section to given struct in strict mode,
|
// StrictMapTo maps section to given struct in strict mode,
|
||||||
// which returns all possible error including value parsing error.
|
// which returns all possible error including value parsing error.
|
||||||
func (s *Section) StrictMapTo(v interface{}) error {
|
func (s *Section) StrictMapTo(v interface{}) error {
|
||||||
typ := reflect.TypeOf(v)
|
typ := reflect.TypeOf(v)
|
||||||
@ -303,13 +325,13 @@ func (f *File) MapTo(v interface{}) error {
|
|||||||
return f.Section("").MapTo(v)
|
return f.Section("").MapTo(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapTo maps file to given struct in strict mode,
|
// StrictMapTo maps file to given struct in strict mode,
|
||||||
// which returns all possible error including value parsing error.
|
// which returns all possible error including value parsing error.
|
||||||
func (f *File) StrictMapTo(v interface{}) error {
|
func (f *File) StrictMapTo(v interface{}) error {
|
||||||
return f.Section("").StrictMapTo(v)
|
return f.Section("").StrictMapTo(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapTo maps data sources to given struct with name mapper.
|
// MapToWithMapper maps data sources to given struct with name mapper.
|
||||||
func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
|
func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
|
||||||
cfg, err := Load(source, others...)
|
cfg, err := Load(source, others...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -342,14 +364,45 @@ func StrictMapTo(v, source interface{}, others ...interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
|
// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
|
||||||
func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) error {
|
func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
|
||||||
slice := field.Slice(0, field.Len())
|
slice := field.Slice(0, field.Len())
|
||||||
if field.Len() == 0 {
|
if field.Len() == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
sliceOf := field.Type().Elem().Kind()
|
||||||
|
|
||||||
|
if allowShadow {
|
||||||
|
var keyWithShadows *Key
|
||||||
|
for i := 0; i < field.Len(); i++ {
|
||||||
|
var val string
|
||||||
|
switch sliceOf {
|
||||||
|
case reflect.String:
|
||||||
|
val = slice.Index(i).String()
|
||||||
|
case reflect.Int, reflect.Int64:
|
||||||
|
val = fmt.Sprint(slice.Index(i).Int())
|
||||||
|
case reflect.Uint, reflect.Uint64:
|
||||||
|
val = fmt.Sprint(slice.Index(i).Uint())
|
||||||
|
case reflect.Float64:
|
||||||
|
val = fmt.Sprint(slice.Index(i).Float())
|
||||||
|
case reflect.Bool:
|
||||||
|
val = fmt.Sprint(slice.Index(i).Bool())
|
||||||
|
case reflectTime:
|
||||||
|
val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
keyWithShadows = newKey(key.s, key.name, val)
|
||||||
|
} else {
|
||||||
|
keyWithShadows.AddShadow(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key = keyWithShadows
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
sliceOf := field.Type().Elem().Kind()
|
|
||||||
for i := 0; i < field.Len(); i++ {
|
for i := 0; i < field.Len(); i++ {
|
||||||
switch sliceOf {
|
switch sliceOf {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
@ -360,6 +413,8 @@ func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) err
|
|||||||
buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
|
buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
|
buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
|
||||||
|
case reflect.Bool:
|
||||||
|
buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
|
||||||
case reflectTime:
|
case reflectTime:
|
||||||
buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
||||||
default:
|
default:
|
||||||
@ -367,12 +422,12 @@ func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) err
|
|||||||
}
|
}
|
||||||
buf.WriteString(delim)
|
buf.WriteString(delim)
|
||||||
}
|
}
|
||||||
key.SetValue(buf.String()[:buf.Len()-1])
|
key.SetValue(buf.String()[:buf.Len()-len(delim)])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// reflectWithProperType does the opposite thing as setWithProperType.
|
// reflectWithProperType does the opposite thing as setWithProperType.
|
||||||
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
key.SetValue(field.String())
|
key.SetValue(field.String())
|
||||||
@ -387,7 +442,11 @@ func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim
|
|||||||
case reflectTime:
|
case reflectTime:
|
||||||
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
|
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return reflectSliceWithProperType(key, field, delim)
|
return reflectSliceWithProperType(key, field, delim, allowShadow)
|
||||||
|
case reflect.Ptr:
|
||||||
|
if !field.IsNil() {
|
||||||
|
return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type '%s'", t)
|
return fmt.Errorf("unsupported type '%s'", t)
|
||||||
}
|
}
|
||||||
@ -432,12 +491,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := strings.SplitN(tag, ",", 2)
|
rawName, omitEmpty, allowShadow := parseTagOptions(tag)
|
||||||
if len(opts) == 2 && opts[1] == "omitempty" && isEmptyValue(field) {
|
if omitEmpty && isEmptyValue(field) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
fieldName := s.parseFieldName(tpField.Name, rawName)
|
||||||
if len(fieldName) == 0 || !field.CanSet() {
|
if len(fieldName) == 0 || !field.CanSet() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -473,7 +532,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
|||||||
key.Comment = tpField.Tag.Get("comment")
|
key.Comment = tpField.Tag.Get("comment")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim")), allowShadow); err != nil {
|
||||||
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +559,7 @@ func (f *File) ReflectFrom(v interface{}) error {
|
|||||||
return f.Section("").ReflectFrom(v)
|
return f.Section("").ReflectFrom(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReflectFrom reflects data sources from given struct with name mapper.
|
// ReflectFromWithMapper reflects data sources from given struct with name mapper.
|
||||||
func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
|
func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
|
||||||
cfg.NameMapper = mapper
|
cfg.NameMapper = mapper
|
||||||
return cfg.ReflectFrom(v)
|
return cfg.ReflectFrom(v)
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -1,2 +1,2 @@
|
|||||||
# gopkg.in/ini.v1 v1.42.0
|
# gopkg.in/ini.v1 v1.48.0
|
||||||
gopkg.in/ini.v1
|
gopkg.in/ini.v1
|
||||||
|
Loading…
Reference in New Issue
Block a user