mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Use gitea forked macaron (#7933)
Signed-off-by: Tamal Saha <tamal@appscode.com>
This commit is contained in:
committed by
techknowlogick
parent
ca6fb004ac
commit
171b359877
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.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
|
||||
install: skip
|
||||
script:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/smartystreets/goconvey
|
||||
|
20
vendor/gopkg.in/ini.v1/README.md
generated
vendored
20
vendor/gopkg.in/ini.v1/README.md
generated
vendored
@@ -22,19 +22,27 @@ Package ini provides INI file read and write functionality in Go.
|
||||
|
||||
The minimum requirement of Go is **1.6**.
|
||||
|
||||
To use a tagged revision:
|
||||
|
||||
```sh
|
||||
$ go get gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
To use with latest changes:
|
||||
Please add `-u` flag to update in the future.
|
||||
|
||||
```sh
|
||||
$ go get github.com/go-ini/ini
|
||||
## Go Modules
|
||||
|
||||
For historical reason, people use two different import paths for this package: `github.com/go-ini/ini` and `gopkg.in/ini.v1`. If you get error similar to the following one:
|
||||
|
||||
```
|
||||
go: finding github.com/go-ini/ini v0.0.0-00010101000000-000000000000
|
||||
go: github.com/go-ini/ini@v0.0.0-00010101000000-000000000000: unknown revision 000000000000
|
||||
go: error loading module requirements
|
||||
```
|
||||
|
||||
Please add `-u` flag to update in the future.
|
||||
It is because one of your dependencies is using deprecated import path `github.com/go-ini/ini`, you can make a quick fix by adding the following line to your `go.mod` file (`v.1.44.0` was the latest version tagged on `master` branch):
|
||||
|
||||
```
|
||||
replace github.com/go-ini/ini => gopkg.in/ini.v1 v1.44.0
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
|
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"
|
||||
)
|
||||
|
||||
// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
|
||||
type ErrDelimiterNotFound struct {
|
||||
Line string
|
||||
}
|
||||
|
||||
// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
|
||||
func IsErrDelimiterNotFound(err error) bool {
|
||||
_, ok := err.(ErrDelimiterNotFound)
|
||||
return ok
|
||||
|
12
vendor/gopkg.in/ini.v1/file.go
generated
vendored
12
vendor/gopkg.in/ini.v1/file.go
generated
vendored
@@ -68,7 +68,7 @@ func Empty() *File {
|
||||
func (f *File) NewSection(name string) (*Section, error) {
|
||||
if len(name) == 0 {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func (f *File) NewSections(names ...string) (err error) {
|
||||
// GetSection returns section by given name.
|
||||
func (f *File) GetSection(name string) (*Section, error) {
|
||||
if len(name) == 0 {
|
||||
name = DEFAULT_SECTION
|
||||
name = DefaultSection
|
||||
}
|
||||
if f.options.Insensitive {
|
||||
name = strings.ToLower(name)
|
||||
@@ -141,7 +141,7 @@ func (f *File) Section(name string) *Section {
|
||||
return sec
|
||||
}
|
||||
|
||||
// Section returns list of Section.
|
||||
// Sections returns a list of Section stored in the current instance.
|
||||
func (f *File) Sections() []*Section {
|
||||
if f.BlockMode {
|
||||
f.lock.RLock()
|
||||
@@ -175,7 +175,7 @@ func (f *File) DeleteSection(name string) {
|
||||
}
|
||||
|
||||
if len(name) == 0 {
|
||||
name = DEFAULT_SECTION
|
||||
name = DefaultSection
|
||||
}
|
||||
|
||||
for i, s := range f.sectionList {
|
||||
@@ -306,7 +306,7 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
||||
for _, kname := range sec.keyList {
|
||||
key := sec.Key(kname)
|
||||
if len(key.Comment) > 0 {
|
||||
if len(indent) > 0 && sname != DEFAULT_SECTION {
|
||||
if len(indent) > 0 && sname != DefaultSection {
|
||||
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)
|
||||
}
|
||||
|
||||
|
32
vendor/gopkg.in/ini.v1/ini.go
generated
vendored
32
vendor/gopkg.in/ini.v1/ini.go
generated
vendored
@@ -28,44 +28,46 @@ import (
|
||||
)
|
||||
|
||||
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.
|
||||
DEFAULT_SECTION = "DEFAULT"
|
||||
DefaultSection = "DEFAULT"
|
||||
// Deprecated: Use "DefaultSection" instead.
|
||||
DEFAULT_SECTION = DefaultSection
|
||||
|
||||
// Maximum allowed depth when recursively substituing variable names.
|
||||
_DEPTH_VALUES = 99
|
||||
_VERSION = "1.42.0"
|
||||
depthValues = 99
|
||||
version = "1.46.0"
|
||||
)
|
||||
|
||||
// Version returns current package version literal.
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
return version
|
||||
}
|
||||
|
||||
var (
|
||||
// Delimiter to determine or compose a new line.
|
||||
// This variable will be changed to "\r\n" automatically on Windows
|
||||
// at package init time.
|
||||
// LineBreak is the delimiter to determine or compose a new line.
|
||||
// This variable will be changed to "\r\n" automatically on Windows at package init time.
|
||||
LineBreak = "\n"
|
||||
|
||||
// Place custom spaces when PrettyFormat and PrettyEqual are both disabled
|
||||
DefaultFormatLeft = ""
|
||||
// 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 = ""
|
||||
|
||||
// Variable regexp pattern: %(variable)s
|
||||
varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`)
|
||||
|
||||
// Indicate whether to align "=" sign with spaces to produce pretty output
|
||||
// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
|
||||
// or reduce all possible spaces for compact format.
|
||||
PrettyFormat = true
|
||||
|
||||
// Place spaces around "=" sign even when PrettyFormat is false
|
||||
// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
|
||||
PrettyEqual = false
|
||||
|
||||
// Explicitly write DEFAULT section header
|
||||
// DefaultHeader explicitly writes default section header.
|
||||
DefaultHeader = false
|
||||
|
||||
// Indicate whether to put a line between sections
|
||||
// PrettySection indicates whether to put a line between sections.
|
||||
PrettySection = true
|
||||
)
|
||||
|
||||
@@ -129,6 +131,7 @@ func parseDataSource(source interface{}) (dataSource, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// LoadOptions contains all customized options used for load data source(s).
|
||||
type LoadOptions struct {
|
||||
// Loose indicates whether the parser should ignore nonexistent files or return error.
|
||||
Loose bool
|
||||
@@ -174,6 +177,7 @@ type LoadOptions struct {
|
||||
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) {
|
||||
sources := make([]dataSource, len(others)+1)
|
||||
sources[0], err = parseDataSource(source)
|
||||
|
11
vendor/gopkg.in/ini.v1/key.go
generated
vendored
11
vendor/gopkg.in/ini.v1/key.go
generated
vendored
@@ -77,6 +77,7 @@ func (k *Key) addNestedValue(val string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddNestedValue adds a nested value to the key.
|
||||
func (k *Key) AddNestedValue(val string) error {
|
||||
if !k.s.f.options.AllowNestedValues {
|
||||
return errors.New("nested value is not allowed")
|
||||
@@ -126,7 +127,7 @@ func (k *Key) transformValue(val string) string {
|
||||
if !strings.Contains(val, "%") {
|
||||
return val
|
||||
}
|
||||
for i := 0; i < _DEPTH_VALUES; i++ {
|
||||
for i := 0; i < depthValues; i++ {
|
||||
vr := varPattern.FindString(val)
|
||||
if len(vr) == 0 {
|
||||
break
|
||||
@@ -186,8 +187,8 @@ func (k *Key) Float64() (float64, error) {
|
||||
|
||||
// Int returns int type value.
|
||||
func (k *Key) Int() (int, error) {
|
||||
v, err := strconv.ParseInt(k.String(), 0, 64)
|
||||
return int(v), err
|
||||
v, err := strconv.ParseInt(k.String(), 0, 64)
|
||||
return int(v), err
|
||||
}
|
||||
|
||||
// Int64 returns int64 type value.
|
||||
@@ -491,7 +492,7 @@ func (k *Key) Strings(delim string) []string {
|
||||
buf.WriteRune(runes[idx])
|
||||
}
|
||||
}
|
||||
idx += 1
|
||||
idx++
|
||||
if idx == len(runes) {
|
||||
break
|
||||
}
|
||||
@@ -669,7 +670,7 @@ func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int,
|
||||
vals := make([]int, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
valInt64, err := strconv.ParseInt(str, 0, 64)
|
||||
val := int(valInt64)
|
||||
val := int(valInt64)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
|
147
vendor/gopkg.in/ini.v1/parser.go
generated
vendored
147
vendor/gopkg.in/ini.v1/parser.go
generated
vendored
@@ -27,25 +27,29 @@ import (
|
||||
|
||||
var pythonMultiline = regexp.MustCompile("^(\\s+)([^\n]+)")
|
||||
|
||||
type tokenType int
|
||||
|
||||
const (
|
||||
_TOKEN_INVALID tokenType = iota
|
||||
_TOKEN_COMMENT
|
||||
_TOKEN_SECTION
|
||||
_TOKEN_KEY
|
||||
)
|
||||
type parserOptions struct {
|
||||
IgnoreContinuation bool
|
||||
IgnoreInlineComment bool
|
||||
AllowPythonMultilineValues bool
|
||||
SpaceBeforeInlineComment bool
|
||||
UnescapeValueDoubleQuotes bool
|
||||
UnescapeValueCommentSymbols bool
|
||||
PreserveSurroundedQuote bool
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
buf *bufio.Reader
|
||||
options parserOptions
|
||||
|
||||
isEOF bool
|
||||
count int
|
||||
comment *bytes.Buffer
|
||||
}
|
||||
|
||||
func newParser(r io.Reader) *parser {
|
||||
func newParser(r io.Reader, opts parserOptions) *parser {
|
||||
return &parser{
|
||||
buf: bufio.NewReader(r),
|
||||
options: opts,
|
||||
count: 1,
|
||||
comment: &bytes.Buffer{},
|
||||
}
|
||||
@@ -196,12 +200,13 @@ func hasSurroundedQuote(in string, quote byte) bool {
|
||||
strings.IndexByte(in[1:], quote) == len(in)-2
|
||||
}
|
||||
|
||||
func (p *parser) readValue(in []byte,
|
||||
parserBufferSize int,
|
||||
ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols, allowPythonMultilines, spaceBeforeInlineComment, preserveSurroundedQuote bool) (string, error) {
|
||||
func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
|
||||
|
||||
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
||||
if len(line) == 0 {
|
||||
if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
|
||||
return p.readPythonMultilines(line, bufferSize)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -210,7 +215,7 @@ func (p *parser) readValue(in []byte,
|
||||
valQuote = `"""`
|
||||
} else if line[0] == '`' {
|
||||
valQuote = "`"
|
||||
} else if unescapeValueDoubleQuotes && line[0] == '"' {
|
||||
} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
|
||||
valQuote = `"`
|
||||
}
|
||||
|
||||
@@ -222,7 +227,7 @@ func (p *parser) readValue(in []byte,
|
||||
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 line[startIdx : pos+startIdx], nil
|
||||
@@ -234,14 +239,14 @@ func (p *parser) readValue(in []byte,
|
||||
trimmedLastChar := line[len(line)-1]
|
||||
|
||||
// Check continuation lines when desired
|
||||
if !ignoreContinuation && trimmedLastChar == '\\' {
|
||||
if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
|
||||
return p.readContinuationLines(line[:len(line)-1])
|
||||
}
|
||||
|
||||
// Check if ignore inline comment
|
||||
if !ignoreInlineComment {
|
||||
if !p.options.IgnoreInlineComment {
|
||||
var i int
|
||||
if spaceBeforeInlineComment {
|
||||
if p.options.SpaceBeforeInlineComment {
|
||||
i = strings.Index(line, " #")
|
||||
if i == -1 {
|
||||
i = strings.Index(line, " ;")
|
||||
@@ -260,65 +265,75 @@ func (p *parser) readValue(in []byte,
|
||||
|
||||
// Trim single and double quotes
|
||||
if (hasSurroundedQuote(line, '\'') ||
|
||||
hasSurroundedQuote(line, '"')) && !preserveSurroundedQuote {
|
||||
hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
|
||||
line = line[1 : len(line)-1]
|
||||
} else if len(valQuote) == 0 && unescapeValueCommentSymbols {
|
||||
} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
|
||||
if strings.Contains(line, `\;`) {
|
||||
line = strings.Replace(line, `\;`, ";", -1)
|
||||
}
|
||||
if strings.Contains(line, `\#`) {
|
||||
line = strings.Replace(line, `\#`, "#", -1)
|
||||
}
|
||||
} else if allowPythonMultilines && lastChar == '\n' {
|
||||
parserBufferPeekResult, _ := p.buf.Peek(parserBufferSize)
|
||||
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
||||
|
||||
val := line
|
||||
|
||||
for {
|
||||
peekData, peekErr := peekBuffer.ReadBytes('\n')
|
||||
if peekErr != nil {
|
||||
if peekErr == io.EOF {
|
||||
return val, nil
|
||||
}
|
||||
return "", peekErr
|
||||
}
|
||||
|
||||
peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
|
||||
if len(peekMatches) != 3 {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// NOTE: Return if not a python-ini multi-line value.
|
||||
currentIdentSize := len(peekMatches[1])
|
||||
if currentIdentSize <= 0 {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
||||
_, err := p.readUntil('\n')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
val += fmt.Sprintf("\n%s", peekMatches[2])
|
||||
}
|
||||
} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
|
||||
return p.readPythonMultilines(line, bufferSize)
|
||||
}
|
||||
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
|
||||
parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
|
||||
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
||||
|
||||
for {
|
||||
peekData, peekErr := peekBuffer.ReadBytes('\n')
|
||||
if peekErr != nil {
|
||||
if peekErr == io.EOF {
|
||||
return line, nil
|
||||
}
|
||||
return "", peekErr
|
||||
}
|
||||
|
||||
peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
|
||||
if len(peekMatches) != 3 {
|
||||
return line, nil
|
||||
}
|
||||
|
||||
// NOTE: Return if not a python-ini multi-line value.
|
||||
currentIdentSize := len(peekMatches[1])
|
||||
if currentIdentSize <= 0 {
|
||||
return line, nil
|
||||
}
|
||||
|
||||
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
||||
_, err := p.readUntil('\n')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
line += fmt.Sprintf("\n%s", peekMatches[2])
|
||||
}
|
||||
}
|
||||
|
||||
// parse parses data through an io.Reader.
|
||||
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 {
|
||||
return fmt.Errorf("BOM: %v", err)
|
||||
}
|
||||
|
||||
// Ignore error because default section name is never empty string.
|
||||
name := DEFAULT_SECTION
|
||||
name := DefaultSection
|
||||
if f.options.Insensitive {
|
||||
name = strings.ToLower(DEFAULT_SECTION)
|
||||
name = strings.ToLower(DefaultSection)
|
||||
}
|
||||
section, _ := f.NewSection(name)
|
||||
|
||||
@@ -426,15 +441,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
if IsErrDelimiterNotFound(err) {
|
||||
switch {
|
||||
case f.options.AllowBooleanKeys:
|
||||
kname, err := p.readValue(line,
|
||||
parserBufferSize,
|
||||
f.options.IgnoreContinuation,
|
||||
f.options.IgnoreInlineComment,
|
||||
f.options.UnescapeValueDoubleQuotes,
|
||||
f.options.UnescapeValueCommentSymbols,
|
||||
f.options.AllowPythonMultilineValues,
|
||||
f.options.SpaceBeforeInlineComment,
|
||||
f.options.PreserveSurroundedQuote)
|
||||
kname, err := p.readValue(line, parserBufferSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -461,15 +468,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
p.count++
|
||||
}
|
||||
|
||||
value, err := p.readValue(line[offset:],
|
||||
parserBufferSize,
|
||||
f.options.IgnoreContinuation,
|
||||
f.options.IgnoreInlineComment,
|
||||
f.options.UnescapeValueDoubleQuotes,
|
||||
f.options.UnescapeValueCommentSymbols,
|
||||
f.options.AllowPythonMultilineValues,
|
||||
f.options.SpaceBeforeInlineComment,
|
||||
f.options.PreserveSurroundedQuote)
|
||||
value, err := p.readValue(line[offset:], parserBufferSize)
|
||||
if err != nil {
|
||||
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.
|
||||
func (s *Section) GetKey(name string) (*Key, error) {
|
||||
// FIXME: change to section level lock?
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.RLock()
|
||||
}
|
||||
@@ -129,9 +128,8 @@ func (s *Section) GetKey(name string) (*Key, error) {
|
||||
continue
|
||||
}
|
||||
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)
|
||||
}
|
||||
@@ -144,8 +142,7 @@ func (s *Section) HasKey(name string) bool {
|
||||
return key != nil
|
||||
}
|
||||
|
||||
// Haskey is a backwards-compatible name for HasKey.
|
||||
// TODO: delete me in v2
|
||||
// Deprecated: Use "HasKey" instead.
|
||||
func (s *Section) Haskey(name string) bool {
|
||||
return s.HasKey(name)
|
||||
}
|
||||
|
83
vendor/gopkg.in/ini.v1/struct.go
generated
vendored
83
vendor/gopkg.in/ini.v1/struct.go
generated
vendored
@@ -149,7 +149,7 @@ func wrapStrictError(err error, isStrict bool) error {
|
||||
|
||||
// setWithProperType sets proper value to field based on its type,
|
||||
// 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 {
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
@@ -205,6 +205,17 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
||||
field.Set(reflect.ValueOf(timeVal))
|
||||
case reflect.Slice:
|
||||
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:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
@@ -244,14 +255,21 @@ func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
|
||||
continue
|
||||
}
|
||||
|
||||
isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
|
||||
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 {
|
||||
field.Set(reflect.New(tpField.Type.Elem()))
|
||||
}
|
||||
|
||||
if isAnonymous || isStruct {
|
||||
if isAnonymous || isStruct || isStructPtr {
|
||||
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 {
|
||||
return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
|
||||
}
|
||||
@@ -283,7 +301,7 @@ func (s *Section) MapTo(v interface{}) error {
|
||||
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.
|
||||
func (s *Section) StrictMapTo(v interface{}) error {
|
||||
typ := reflect.TypeOf(v)
|
||||
@@ -303,13 +321,13 @@ func (f *File) MapTo(v interface{}) error {
|
||||
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.
|
||||
func (f *File) StrictMapTo(v interface{}) error {
|
||||
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 {
|
||||
cfg, err := Load(source, others...)
|
||||
if err != nil {
|
||||
@@ -342,14 +360,43 @@ func StrictMapTo(v, source interface{}, others ...interface{}) error {
|
||||
}
|
||||
|
||||
// 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())
|
||||
if field.Len() == 0 {
|
||||
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 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
|
||||
sliceOf := field.Type().Elem().Kind()
|
||||
for i := 0; i < field.Len(); i++ {
|
||||
switch sliceOf {
|
||||
case reflect.String:
|
||||
@@ -367,12 +414,12 @@ func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) err
|
||||
}
|
||||
buf.WriteString(delim)
|
||||
}
|
||||
key.SetValue(buf.String()[:buf.Len()-1])
|
||||
key.SetValue(buf.String()[:buf.Len()-len(delim)])
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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() {
|
||||
case reflect.String:
|
||||
key.SetValue(field.String())
|
||||
@@ -387,7 +434,11 @@ func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim
|
||||
case reflectTime:
|
||||
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
|
||||
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:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
@@ -432,12 +483,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
continue
|
||||
}
|
||||
|
||||
opts := strings.SplitN(tag, ",", 2)
|
||||
if len(opts) == 2 && opts[1] == "omitempty" && isEmptyValue(field) {
|
||||
rawName, omitEmpty, allowShadow := parseTagOptions(tag)
|
||||
if omitEmpty && isEmptyValue(field) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
||||
fieldName := s.parseFieldName(tpField.Name, rawName)
|
||||
if len(fieldName) == 0 || !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
@@ -473,7 +524,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -500,7 +551,7 @@ func (f *File) ReflectFrom(v interface{}) error {
|
||||
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 {
|
||||
cfg.NameMapper = mapper
|
||||
return cfg.ReflectFrom(v)
|
||||
|
Reference in New Issue
Block a user