mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Temporarily patch go-ini/ini with fork (#2255)
This commit is contained in:
		
							
								
								
									
										57
									
								
								vendor/gopkg.in/ini.v1/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								vendor/gopkg.in/ini.v1/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
INI [](https://travis-ci.org/go-ini/ini)
 | 
					INI [](https://travis-ci.org/go-ini/ini) [](https://sourcegraph.com/github.com/go-ini/ini?badge)
 | 
				
			||||||
===
 | 
					===
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
@@ -9,7 +9,7 @@ Package ini provides INI file read and write functionality in Go.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Feature
 | 
					## Feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Load multiple data sources(`[]byte` or file) with overwrites.
 | 
					- Load multiple data sources(`[]byte`, file and `io.ReadCloser`) with overwrites.
 | 
				
			||||||
- Read with recursion values.
 | 
					- Read with recursion values.
 | 
				
			||||||
- Read with parent-child sections.
 | 
					- Read with parent-child sections.
 | 
				
			||||||
- Read with auto-increment key names.
 | 
					- Read with auto-increment key names.
 | 
				
			||||||
@@ -44,10 +44,10 @@ Please add `-u` flag to update in the future.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Loading from data sources
 | 
					### Loading from data sources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many data sources as you want**. Passing other types will simply return an error.
 | 
					A **Data Source** is either raw data in type `[]byte`, a file name with type `string` or `io.ReadCloser`. You can load **as many data sources as you want**. Passing other types will simply return an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
cfg, err := ini.Load([]byte("raw data"), "filename")
 | 
					cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Or start with an empty object:
 | 
					Or start with an empty object:
 | 
				
			||||||
@@ -83,8 +83,8 @@ sec1, err := cfg.GetSection("Section")
 | 
				
			|||||||
sec2, err := cfg.GetSection("SecTIOn")
 | 
					sec2, err := cfg.GetSection("SecTIOn")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// key1 and key2 are the exactly same key object
 | 
					// key1 and key2 are the exactly same key object
 | 
				
			||||||
key1, err := cfg.GetKey("Key")
 | 
					key1, err := sec1.GetKey("Key")
 | 
				
			||||||
key2, err := cfg.GetKey("KeY")
 | 
					key2, err := sec2.GetKey("KeY")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### MySQL-like boolean key 
 | 
					#### MySQL-like boolean key 
 | 
				
			||||||
@@ -106,6 +106,28 @@ cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
 | 
					The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To generate such keys in your program, you could use `NewBooleanKey`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					key, err := sec.NewBooleanKey("skip-host-cache")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Comment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Take care that following format will be treated as comment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Line begins with `#` or `;`
 | 
				
			||||||
 | 
					2. Words after `#` or `;`
 | 
				
			||||||
 | 
					3. Words after section name (i.e words after `[some section name]`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or ``` """ ```.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, you can use following `LoadOptions` to completely ignore inline comments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Working with sections
 | 
					### Working with sections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To get a section, you would need to:
 | 
					To get a section, you would need to:
 | 
				
			||||||
@@ -123,7 +145,7 @@ section, err := cfg.GetSection("")
 | 
				
			|||||||
When you're pretty sure the section exists, following code could make your life easier:
 | 
					When you're pretty sure the section exists, following code could make your life easier:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
section := cfg.Section("")
 | 
					section := cfg.Section("section name")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
 | 
					What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
 | 
				
			||||||
@@ -400,6 +422,12 @@ cfg.WriteTo(writer)
 | 
				
			|||||||
cfg.WriteToIndent(writer, "\t")
 | 
					cfg.WriteToIndent(writer, "\t")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default, spaces are used to align "=" sign between key and values, to disable that:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					ini.PrettyFormat = false
 | 
				
			||||||
 | 
					``` 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Advanced Usage
 | 
					## Advanced Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Recursive Values
 | 
					### Recursive Values
 | 
				
			||||||
@@ -447,6 +475,21 @@ cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
 | 
				
			|||||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
 | 
					cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Unparseable Sections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
 | 
				
			||||||
 | 
					<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body := cfg.Section("COMMENTS").Body()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* --- start ---
 | 
				
			||||||
 | 
					<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
 | 
				
			||||||
 | 
					------  end  --- */
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Auto-increment Key Names
 | 
					### Auto-increment Key Names
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
 | 
					If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										63
									
								
								vendor/gopkg.in/ini.v1/README_ZH.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										63
									
								
								vendor/gopkg.in/ini.v1/README_ZH.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 功能特性
 | 
					## 功能特性
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 支持覆盖加载多个数据源(`[]byte` 或文件)
 | 
					- 支持覆盖加载多个数据源(`[]byte`、文件和 `io.ReadCloser`)
 | 
				
			||||||
- 支持递归读取键值
 | 
					- 支持递归读取键值
 | 
				
			||||||
- 支持读取父子分区
 | 
					- 支持读取父子分区
 | 
				
			||||||
- 支持读取自增键名
 | 
					- 支持读取自增键名
 | 
				
			||||||
@@ -37,10 +37,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### 从数据源加载
 | 
					### 从数据源加载
 | 
				
			||||||
 | 
					
 | 
				
			||||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,或 `string` 类型的文件路径。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
 | 
					一个 **数据源** 可以是 `[]byte` 类型的原始数据,`string` 类型的文件路径或 `io.ReadCloser`。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
cfg, err := ini.Load([]byte("raw data"), "filename")
 | 
					cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
或者从一个空白的文件开始:
 | 
					或者从一个空白的文件开始:
 | 
				
			||||||
@@ -76,8 +76,8 @@ sec1, err := cfg.GetSection("Section")
 | 
				
			|||||||
sec2, err := cfg.GetSection("SecTIOn")
 | 
					sec2, err := cfg.GetSection("SecTIOn")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// key1 和 key2 指向同一个键对象
 | 
					// key1 和 key2 指向同一个键对象
 | 
				
			||||||
key1, err := cfg.GetKey("Key")
 | 
					key1, err := sec1.GetKey("Key")
 | 
				
			||||||
key2, err := cfg.GetKey("KeY")
 | 
					key2, err := sec2.GetKey("KeY")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 类似 MySQL 配置中的布尔值键
 | 
					#### 类似 MySQL 配置中的布尔值键
 | 
				
			||||||
@@ -99,6 +99,28 @@ cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
 | 
					这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					如果您想要通过程序来生成此类键,则可以使用 `NewBooleanKey`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					key, err := sec.NewBooleanKey("skip-host-cache")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 关于注释
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					下述几种情况的内容将被视为注释:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 所有以 `#` 或 `;` 开头的行
 | 
				
			||||||
 | 
					2. 所有在 `#` 或 `;` 之后的内容
 | 
				
			||||||
 | 
					3. 分区标签后的文字 (即 `[分区名]` 之后的内容)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					如果你希望使用包含 `#` 或 `;` 的值,请使用 ``` ` ``` 或 ``` """ ``` 进行包覆。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 操作分区(Section)
 | 
					### 操作分区(Section)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
获取指定分区:
 | 
					获取指定分区:
 | 
				
			||||||
@@ -116,7 +138,7 @@ section, err := cfg.GetSection("")
 | 
				
			|||||||
当您非常确定某个分区是存在的,可以使用以下简便方法:
 | 
					当您非常确定某个分区是存在的,可以使用以下简便方法:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
section := cfg.Section("")
 | 
					section := cfg.Section("section name")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
 | 
					如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
 | 
				
			||||||
@@ -393,9 +415,15 @@ cfg.WriteTo(writer)
 | 
				
			|||||||
cfg.WriteToIndent(writer, "\t")
 | 
					cfg.WriteToIndent(writer, "\t")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 高级用法
 | 
					默认情况下,空格将被用于对齐键值之间的等号以美化输出结果,以下代码可以禁用该功能:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 递归读取键值
 | 
					```go
 | 
				
			||||||
 | 
					ini.PrettyFormat = false
 | 
				
			||||||
 | 
					``` 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 高级用法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 递归读取键值
 | 
				
			||||||
 | 
					
 | 
				
			||||||
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
 | 
					在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -415,7 +443,7 @@ cfg.Section("author").Key("GITHUB").String()		// https://github.com/Unknwon
 | 
				
			|||||||
cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
 | 
					cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 读取父子分区
 | 
					### 读取父子分区
 | 
				
			||||||
 | 
					
 | 
				
			||||||
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
 | 
					您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -440,7 +468,22 @@ cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
 | 
				
			|||||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
 | 
					cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 读取自增键名
 | 
					### 无法解析的分区
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
 | 
				
			||||||
 | 
					<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body := cfg.Section("COMMENTS").Body()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* --- start ---
 | 
				
			||||||
 | 
					<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
 | 
				
			||||||
 | 
					------  end  --- */
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 读取自增键名
 | 
				
			||||||
 | 
					
 | 
				
			||||||
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
 | 
					如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										127
									
								
								vendor/gopkg.in/ini.v1/ini.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										127
									
								
								vendor/gopkg.in/ini.v1/ini.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -20,13 +20,12 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -36,7 +35,7 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Maximum allowed depth when recursively substituing variable names.
 | 
						// Maximum allowed depth when recursively substituing variable names.
 | 
				
			||||||
	_DEPTH_VALUES = 99
 | 
						_DEPTH_VALUES = 99
 | 
				
			||||||
	_VERSION      = "1.21.1"
 | 
						_VERSION      = "1.28.1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Version returns current package version literal.
 | 
					// Version returns current package version literal.
 | 
				
			||||||
@@ -59,6 +58,9 @@ var (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Explicitly write DEFAULT section header
 | 
						// Explicitly write DEFAULT section header
 | 
				
			||||||
	DefaultHeader = false
 | 
						DefaultHeader = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Indicate whether to put a line between sections
 | 
				
			||||||
 | 
						PrettySection = true
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
@@ -108,7 +110,16 @@ type sourceData struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
 | 
					func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
 | 
				
			||||||
	return &bytesReadCloser{bytes.NewReader(s.data)}, nil
 | 
						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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// File represents a combination of a or more INI file(s) in memory.
 | 
					// File represents a combination of a or more INI file(s) in memory.
 | 
				
			||||||
@@ -149,6 +160,8 @@ func parseDataSource(source interface{}) (dataSource, error) {
 | 
				
			|||||||
		return sourceFile{s}, nil
 | 
							return sourceFile{s}, nil
 | 
				
			||||||
	case []byte:
 | 
						case []byte:
 | 
				
			||||||
		return &sourceData{s}, nil
 | 
							return &sourceData{s}, nil
 | 
				
			||||||
 | 
						case io.ReadCloser:
 | 
				
			||||||
 | 
							return &sourceReadCloser{s}, nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s)
 | 
							return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -161,9 +174,16 @@ type LoadOptions struct {
 | 
				
			|||||||
	Insensitive bool
 | 
						Insensitive bool
 | 
				
			||||||
	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
 | 
						// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
 | 
				
			||||||
	IgnoreContinuation bool
 | 
						IgnoreContinuation bool
 | 
				
			||||||
 | 
						// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
 | 
				
			||||||
 | 
						IgnoreInlineComment bool
 | 
				
			||||||
	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
 | 
						// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
 | 
				
			||||||
	// This type of keys are mostly used in my.cnf.
 | 
						// This type of keys are mostly used in my.cnf.
 | 
				
			||||||
	AllowBooleanKeys bool
 | 
						AllowBooleanKeys bool
 | 
				
			||||||
 | 
						// AllowShadows indicates whether to keep track of keys with same name under same section.
 | 
				
			||||||
 | 
						AllowShadows bool
 | 
				
			||||||
 | 
						// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
 | 
				
			||||||
 | 
						// conform to key/value pairs. Specify the names of those blocks here.
 | 
				
			||||||
 | 
						UnparseableSections []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
 | 
					func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
 | 
				
			||||||
@@ -204,6 +224,12 @@ func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
 | 
				
			|||||||
	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
 | 
						return LoadSources(LoadOptions{Insensitive: true}, source, others...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// InsensitiveLoad has exactly same functionality as Load function
 | 
				
			||||||
 | 
					// except it allows have shadow keys.
 | 
				
			||||||
 | 
					func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
 | 
				
			||||||
 | 
						return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Empty returns an empty file object.
 | 
					// Empty returns an empty file object.
 | 
				
			||||||
func Empty() *File {
 | 
					func Empty() *File {
 | 
				
			||||||
	// Ignore error here, we sure our data is good.
 | 
						// Ignore error here, we sure our data is good.
 | 
				
			||||||
@@ -233,6 +259,18 @@ func (f *File) NewSection(name string) (*Section, error) {
 | 
				
			|||||||
	return f.sections[name], nil
 | 
						return f.sections[name], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewRawSection creates a new section with an unparseable body.
 | 
				
			||||||
 | 
					func (f *File) NewRawSection(name, body string) (*Section, error) {
 | 
				
			||||||
 | 
						section, err := f.NewSection(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						section.isRawSection = true
 | 
				
			||||||
 | 
						section.rawBody = body
 | 
				
			||||||
 | 
						return section, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewSections creates a list of sections.
 | 
					// NewSections creates a list of sections.
 | 
				
			||||||
func (f *File) NewSections(names ...string) (err error) {
 | 
					func (f *File) NewSections(names ...string) (err error) {
 | 
				
			||||||
	for _, name := range names {
 | 
						for _, name := range names {
 | 
				
			||||||
@@ -284,6 +322,11 @@ func (f *File) Sections() []*Section {
 | 
				
			|||||||
	return sections
 | 
						return sections
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ChildSections returns a list of child sections of given section name.
 | 
				
			||||||
 | 
					func (f *File) ChildSections(name string) []*Section {
 | 
				
			||||||
 | 
						return f.Section(name).ChildSections()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SectionStrings returns list of section names.
 | 
					// SectionStrings returns list of section names.
 | 
				
			||||||
func (f *File) SectionStrings() []string {
 | 
					func (f *File) SectionStrings() []string {
 | 
				
			||||||
	list := make([]string, len(f.sectionList))
 | 
						list := make([]string, len(f.sectionList))
 | 
				
			||||||
@@ -353,10 +396,7 @@ func (f *File) Append(source interface{}, others ...interface{}) error {
 | 
				
			|||||||
	return f.Reload()
 | 
						return f.Reload()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WriteToIndent writes content into io.Writer with given indention.
 | 
					func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
 | 
				
			||||||
// If PrettyFormat has been set to be true,
 | 
					 | 
				
			||||||
// it will align "=" sign with spaces under each section.
 | 
					 | 
				
			||||||
func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
					 | 
				
			||||||
	equalSign := "="
 | 
						equalSign := "="
 | 
				
			||||||
	if PrettyFormat {
 | 
						if PrettyFormat {
 | 
				
			||||||
		equalSign = " = "
 | 
							equalSign = " = "
 | 
				
			||||||
@@ -370,14 +410,14 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
			if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
 | 
								if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
 | 
				
			||||||
				sec.Comment = "; " + sec.Comment
 | 
									sec.Comment = "; " + sec.Comment
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil {
 | 
								if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
 | 
				
			||||||
				return 0, err
 | 
									return nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if i > 0 || DefaultHeader {
 | 
							if i > 0 || DefaultHeader {
 | 
				
			||||||
			if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
 | 
								if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
 | 
				
			||||||
				return 0, err
 | 
									return nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Write nothing if default section is empty
 | 
								// Write nothing if default section is empty
 | 
				
			||||||
@@ -386,6 +426,13 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if sec.isRawSection {
 | 
				
			||||||
 | 
								if _, err := buf.WriteString(sec.rawBody); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Count and generate alignment length and buffer spaces using the
 | 
							// Count and generate alignment length and buffer spaces using the
 | 
				
			||||||
		// longest key. Keys may be modifed if they contain certain characters so
 | 
							// longest key. Keys may be modifed if they contain certain characters so
 | 
				
			||||||
		// we need to take that into account in our calculation.
 | 
							// we need to take that into account in our calculation.
 | 
				
			||||||
@@ -407,6 +454,7 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
 | 
							alignSpaces := bytes.Repeat([]byte(" "), alignLength)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						KEY_LIST:
 | 
				
			||||||
		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 {
 | 
				
			||||||
@@ -416,8 +464,8 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
				if key.Comment[0] != '#' && key.Comment[0] != ';' {
 | 
									if key.Comment[0] != '#' && key.Comment[0] != ';' {
 | 
				
			||||||
					key.Comment = "; " + key.Comment
 | 
										key.Comment = "; " + key.Comment
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if _, err = buf.WriteString(key.Comment + LineBreak); err != nil {
 | 
									if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
 | 
				
			||||||
					return 0, err
 | 
										return nil, err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -433,12 +481,17 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
			case strings.Contains(kname, "`"):
 | 
								case strings.Contains(kname, "`"):
 | 
				
			||||||
				kname = `"""` + kname + `"""`
 | 
									kname = `"""` + kname + `"""`
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if _, err = buf.WriteString(kname); err != nil {
 | 
					
 | 
				
			||||||
				return 0, err
 | 
								for _, val := range key.ValueWithShadows() {
 | 
				
			||||||
 | 
									if _, err := buf.WriteString(kname); err != nil {
 | 
				
			||||||
 | 
										return nil, err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if key.isBooleanType {
 | 
									if key.isBooleanType {
 | 
				
			||||||
				continue
 | 
										if kname != sec.keyList[len(sec.keyList)-1] {
 | 
				
			||||||
 | 
											buf.WriteString(LineBreak)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										continue KEY_LIST
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Write out alignment spaces before "=" sign
 | 
									// Write out alignment spaces before "=" sign
 | 
				
			||||||
@@ -446,24 +499,37 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 | 
				
			|||||||
					buf.Write(alignSpaces[:alignLength-len(kname)])
 | 
										buf.Write(alignSpaces[:alignLength-len(kname)])
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			val := key.value
 | 
					 | 
				
			||||||
				// In case key value contains "\n", "`", "\"", "#" or ";"
 | 
									// In case key value contains "\n", "`", "\"", "#" or ";"
 | 
				
			||||||
				if strings.ContainsAny(val, "\n`") {
 | 
									if strings.ContainsAny(val, "\n`") {
 | 
				
			||||||
					val = `"""` + val + `"""`
 | 
										val = `"""` + val + `"""`
 | 
				
			||||||
			} else if strings.ContainsAny(val, "#;") {
 | 
									} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
 | 
				
			||||||
					val = "`" + val + "`"
 | 
										val = "`" + val + "`"
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			if _, err = buf.WriteString(equalSign + val + LineBreak); err != nil {
 | 
									if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
 | 
				
			||||||
				return 0, err
 | 
										return nil, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if PrettySection {
 | 
				
			||||||
			// Put a line between sections
 | 
								// Put a line between sections
 | 
				
			||||||
		if _, err = buf.WriteString(LineBreak); err != nil {
 | 
								if _, err := buf.WriteString(LineBreak); err != nil {
 | 
				
			||||||
			return 0, err
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buf, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WriteToIndent writes content into io.Writer with given indention.
 | 
				
			||||||
 | 
					// If PrettyFormat has been set to be true,
 | 
				
			||||||
 | 
					// it will align "=" sign with spaces under each section.
 | 
				
			||||||
 | 
					func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
 | 
				
			||||||
 | 
						buf, err := f.writeToBuffer(indent)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return buf.WriteTo(w)
 | 
						return buf.WriteTo(w)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -476,23 +542,12 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
 | 
				
			|||||||
func (f *File) SaveToIndent(filename, indent string) error {
 | 
					func (f *File) SaveToIndent(filename, indent string) error {
 | 
				
			||||||
	// Note: Because we are truncating with os.Create,
 | 
						// Note: Because we are truncating with os.Create,
 | 
				
			||||||
	// 	so it's safer to save to a temporary file location and rename afte done.
 | 
						// 	so it's safer to save to a temporary file location and rename afte done.
 | 
				
			||||||
	tmpPath := filename + "." + strconv.Itoa(time.Now().Nanosecond()) + ".tmp"
 | 
						buf, err := f.writeToBuffer(indent);
 | 
				
			||||||
	defer os.Remove(tmpPath)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fw, err := os.Create(tmpPath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err = f.WriteToIndent(fw, indent); err != nil {
 | 
						return ioutil.WriteFile(filename, buf.Bytes(), 0666)
 | 
				
			||||||
		fw.Close()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fw.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove old file and rename the new one.
 | 
					 | 
				
			||||||
	os.Remove(filename)
 | 
					 | 
				
			||||||
	return os.Rename(tmpPath, filename)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SaveTo writes content to file system.
 | 
					// SaveTo writes content to file system.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										148
									
								
								vendor/gopkg.in/ini.v1/key.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										148
									
								
								vendor/gopkg.in/ini.v1/key.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -15,6 +15,7 @@
 | 
				
			|||||||
package ini
 | 
					package ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -29,9 +30,42 @@ type Key struct {
 | 
				
			|||||||
	isAutoIncrement bool
 | 
						isAutoIncrement bool
 | 
				
			||||||
	isBooleanType   bool
 | 
						isBooleanType   bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isShadow bool
 | 
				
			||||||
 | 
						shadows  []*Key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Comment string
 | 
						Comment string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newKey simply return a key object with given values.
 | 
				
			||||||
 | 
					func newKey(s *Section, name, val string) *Key {
 | 
				
			||||||
 | 
						return &Key{
 | 
				
			||||||
 | 
							s:     s,
 | 
				
			||||||
 | 
							name:  name,
 | 
				
			||||||
 | 
							value: val,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (k *Key) addShadow(val string) error {
 | 
				
			||||||
 | 
						if k.isShadow {
 | 
				
			||||||
 | 
							return errors.New("cannot add shadow to another shadow key")
 | 
				
			||||||
 | 
						} else if k.isAutoIncrement || k.isBooleanType {
 | 
				
			||||||
 | 
							return errors.New("cannot add shadow to auto-increment or boolean key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shadow := newKey(k.s, k.name, val)
 | 
				
			||||||
 | 
						shadow.isShadow = true
 | 
				
			||||||
 | 
						k.shadows = append(k.shadows, shadow)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddShadow adds a new shadow key to itself.
 | 
				
			||||||
 | 
					func (k *Key) AddShadow(val string) error {
 | 
				
			||||||
 | 
						if !k.s.f.options.AllowShadows {
 | 
				
			||||||
 | 
							return errors.New("shadow key is not allowed")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return k.addShadow(val)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
 | 
					// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
 | 
				
			||||||
type ValueMapper func(string) string
 | 
					type ValueMapper func(string) string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,16 +79,29 @@ func (k *Key) Value() string {
 | 
				
			|||||||
	return k.value
 | 
						return k.value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// String returns string representation of value.
 | 
					// ValueWithShadows returns raw values of key and its shadows if any.
 | 
				
			||||||
func (k *Key) String() string {
 | 
					func (k *Key) ValueWithShadows() []string {
 | 
				
			||||||
	val := k.value
 | 
						if len(k.shadows) == 0 {
 | 
				
			||||||
 | 
							return []string{k.value}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vals := make([]string, len(k.shadows)+1)
 | 
				
			||||||
 | 
						vals[0] = k.value
 | 
				
			||||||
 | 
						for i := range k.shadows {
 | 
				
			||||||
 | 
							vals[i+1] = k.shadows[i].value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return vals
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// transformValue takes a raw value and transforms to its final string.
 | 
				
			||||||
 | 
					func (k *Key) transformValue(val string) string {
 | 
				
			||||||
	if k.s.f.ValueMapper != nil {
 | 
						if k.s.f.ValueMapper != nil {
 | 
				
			||||||
		val = k.s.f.ValueMapper(val)
 | 
							val = k.s.f.ValueMapper(val)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if strings.Index(val, "%") == -1 {
 | 
					
 | 
				
			||||||
 | 
						// Fail-fast if no indicate char found for recursive value
 | 
				
			||||||
 | 
						if !strings.Contains(val, "%") {
 | 
				
			||||||
		return val
 | 
							return val
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < _DEPTH_VALUES; i++ {
 | 
						for i := 0; i < _DEPTH_VALUES; i++ {
 | 
				
			||||||
		vr := varPattern.FindString(val)
 | 
							vr := varPattern.FindString(val)
 | 
				
			||||||
		if len(vr) == 0 {
 | 
							if len(vr) == 0 {
 | 
				
			||||||
@@ -78,6 +125,11 @@ func (k *Key) String() string {
 | 
				
			|||||||
	return val
 | 
						return val
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String returns string representation of value.
 | 
				
			||||||
 | 
					func (k *Key) String() string {
 | 
				
			||||||
 | 
						return k.transformValue(k.value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Validate accepts a validate function which can
 | 
					// Validate accepts a validate function which can
 | 
				
			||||||
// return modifed result as key value.
 | 
					// return modifed result as key value.
 | 
				
			||||||
func (k *Key) Validate(fn func(string) string) string {
 | 
					func (k *Key) Validate(fn func(string) string) string {
 | 
				
			||||||
@@ -394,45 +446,65 @@ func (k *Key) Strings(delim string) []string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	vals := strings.Split(str, delim)
 | 
						vals := strings.Split(str, delim)
 | 
				
			||||||
	for i := range vals {
 | 
						for i := range vals {
 | 
				
			||||||
 | 
							// vals[i] = k.transformValue(strings.TrimSpace(vals[i]))
 | 
				
			||||||
		vals[i] = strings.TrimSpace(vals[i])
 | 
							vals[i] = strings.TrimSpace(vals[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StringsWithShadows returns list of string divided by given delimiter.
 | 
				
			||||||
 | 
					// Shadows will also be appended if any.
 | 
				
			||||||
 | 
					func (k *Key) StringsWithShadows(delim string) []string {
 | 
				
			||||||
 | 
						vals := k.ValueWithShadows()
 | 
				
			||||||
 | 
						results := make([]string, 0, len(vals)*2)
 | 
				
			||||||
 | 
						for i := range vals {
 | 
				
			||||||
 | 
							if len(vals) == 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							results = append(results, strings.Split(vals[i], delim)...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := range results {
 | 
				
			||||||
 | 
							results[i] = k.transformValue(strings.TrimSpace(results[i]))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return results
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
					// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
				
			||||||
func (k *Key) Float64s(delim string) []float64 {
 | 
					func (k *Key) Float64s(delim string) []float64 {
 | 
				
			||||||
	vals, _ := k.getFloat64s(delim, true, false)
 | 
						vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
 | 
					// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
 | 
				
			||||||
func (k *Key) Ints(delim string) []int {
 | 
					func (k *Key) Ints(delim string) []int {
 | 
				
			||||||
	vals, _ := k.getInts(delim, true, false)
 | 
						vals, _ := k.parseInts(k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
					// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
				
			||||||
func (k *Key) Int64s(delim string) []int64 {
 | 
					func (k *Key) Int64s(delim string) []int64 {
 | 
				
			||||||
	vals, _ := k.getInt64s(delim, true, false)
 | 
						vals, _ := k.parseInt64s(k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
 | 
					// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
 | 
				
			||||||
func (k *Key) Uints(delim string) []uint {
 | 
					func (k *Key) Uints(delim string) []uint {
 | 
				
			||||||
	vals, _ := k.getUints(delim, true, false)
 | 
						vals, _ := k.parseUints(k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
					// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
 | 
				
			||||||
func (k *Key) Uint64s(delim string) []uint64 {
 | 
					func (k *Key) Uint64s(delim string) []uint64 {
 | 
				
			||||||
	vals, _ := k.getUint64s(delim, true, false)
 | 
						vals, _ := k.parseUint64s(k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						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 {
 | 
				
			||||||
	vals, _ := k.getTimesFormat(format, delim, true, false)
 | 
						vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -445,41 +517,41 @@ func (k *Key) Times(delim string) []time.Time {
 | 
				
			|||||||
// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
 | 
					// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
 | 
				
			||||||
// it will not be included to result list.
 | 
					// it will not be included to result list.
 | 
				
			||||||
func (k *Key) ValidFloat64s(delim string) []float64 {
 | 
					func (k *Key) ValidFloat64s(delim string) []float64 {
 | 
				
			||||||
	vals, _ := k.getFloat64s(delim, false, false)
 | 
						vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
 | 
					// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
 | 
				
			||||||
// not be included to result list.
 | 
					// not be included to result list.
 | 
				
			||||||
func (k *Key) ValidInts(delim string) []int {
 | 
					func (k *Key) ValidInts(delim string) []int {
 | 
				
			||||||
	vals, _ := k.getInts(delim, false, false)
 | 
						vals, _ := k.parseInts(k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
 | 
					// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
 | 
				
			||||||
// then it will not be included to result list.
 | 
					// then it will not be included to result list.
 | 
				
			||||||
func (k *Key) ValidInt64s(delim string) []int64 {
 | 
					func (k *Key) ValidInt64s(delim string) []int64 {
 | 
				
			||||||
	vals, _ := k.getInt64s(delim, false, false)
 | 
						vals, _ := k.parseInt64s(k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
 | 
					// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
 | 
				
			||||||
// then it will not be included to result list.
 | 
					// then it will not be included to result list.
 | 
				
			||||||
func (k *Key) ValidUints(delim string) []uint {
 | 
					func (k *Key) ValidUints(delim string) []uint {
 | 
				
			||||||
	vals, _ := k.getUints(delim, false, false)
 | 
						vals, _ := k.parseUints(k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
 | 
					// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
 | 
				
			||||||
// integer, then it will not be included to result list.
 | 
					// integer, then it will not be included to result list.
 | 
				
			||||||
func (k *Key) ValidUint64s(delim string) []uint64 {
 | 
					func (k *Key) ValidUint64s(delim string) []uint64 {
 | 
				
			||||||
	vals, _ := k.getUint64s(delim, false, false)
 | 
						vals, _ := k.parseUint64s(k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						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.getTimesFormat(format, delim, false, false)
 | 
						vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
 | 
				
			||||||
	return vals
 | 
						return vals
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -490,33 +562,33 @@ func (k *Key) ValidTimes(delim string) []time.Time {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
 | 
					// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
 | 
				
			||||||
func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
 | 
					func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
 | 
				
			||||||
	return k.getFloat64s(delim, false, true)
 | 
						return k.parseFloat64s(k.Strings(delim), false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StrictInts returns list of int divided by given delimiter or error on first invalid input.
 | 
					// StrictInts returns list of int divided by given delimiter or error on first invalid input.
 | 
				
			||||||
func (k *Key) StrictInts(delim string) ([]int, error) {
 | 
					func (k *Key) StrictInts(delim string) ([]int, error) {
 | 
				
			||||||
	return k.getInts(delim, false, true)
 | 
						return k.parseInts(k.Strings(delim), false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
 | 
					// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
 | 
				
			||||||
func (k *Key) StrictInt64s(delim string) ([]int64, error) {
 | 
					func (k *Key) StrictInt64s(delim string) ([]int64, error) {
 | 
				
			||||||
	return k.getInt64s(delim, false, true)
 | 
						return k.parseInt64s(k.Strings(delim), false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
 | 
					// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
 | 
				
			||||||
func (k *Key) StrictUints(delim string) ([]uint, error) {
 | 
					func (k *Key) StrictUints(delim string) ([]uint, error) {
 | 
				
			||||||
	return k.getUints(delim, false, true)
 | 
						return k.parseUints(k.Strings(delim), false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
 | 
					// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
 | 
				
			||||||
func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
 | 
					func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
 | 
				
			||||||
	return k.getUint64s(delim, false, true)
 | 
						return k.parseUint64s(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) {
 | 
				
			||||||
	return k.getTimesFormat(format, delim, false, true)
 | 
						return k.parseTimesFormat(format, k.Strings(delim), false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
 | 
					// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
 | 
				
			||||||
@@ -525,9 +597,8 @@ func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
 | 
				
			|||||||
	return k.StrictTimesFormat(time.RFC3339, delim)
 | 
						return k.StrictTimesFormat(time.RFC3339, delim)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getFloat64s returns list of float64 divided by given delimiter.
 | 
					// parseFloat64s transforms strings to float64s.
 | 
				
			||||||
func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]float64, error) {
 | 
					func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]float64, 0, len(strs))
 | 
						vals := make([]float64, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := strconv.ParseFloat(str, 64)
 | 
							val, err := strconv.ParseFloat(str, 64)
 | 
				
			||||||
@@ -541,9 +612,8 @@ func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]flo
 | 
				
			|||||||
	return vals, nil
 | 
						return vals, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getInts returns list of int divided by given delimiter.
 | 
					// parseInts transforms strings to ints.
 | 
				
			||||||
func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, error) {
 | 
					func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]int, 0, len(strs))
 | 
						vals := make([]int, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := strconv.Atoi(str)
 | 
							val, err := strconv.Atoi(str)
 | 
				
			||||||
@@ -557,9 +627,8 @@ func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, er
 | 
				
			|||||||
	return vals, nil
 | 
						return vals, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getInt64s returns list of int64 divided by given delimiter.
 | 
					// parseInt64s transforms strings to int64s.
 | 
				
			||||||
func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64, error) {
 | 
					func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]int64, 0, len(strs))
 | 
						vals := make([]int64, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := strconv.ParseInt(str, 10, 64)
 | 
							val, err := strconv.ParseInt(str, 10, 64)
 | 
				
			||||||
@@ -573,9 +642,8 @@ func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64
 | 
				
			|||||||
	return vals, nil
 | 
						return vals, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getUints returns list of uint divided by given delimiter.
 | 
					// parseUints transforms strings to uints.
 | 
				
			||||||
func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint, error) {
 | 
					func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]uint, 0, len(strs))
 | 
						vals := make([]uint, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := strconv.ParseUint(str, 10, 0)
 | 
							val, err := strconv.ParseUint(str, 10, 0)
 | 
				
			||||||
@@ -589,9 +657,8 @@ func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint,
 | 
				
			|||||||
	return vals, nil
 | 
						return vals, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getUint64s returns list of uint64 divided by given delimiter.
 | 
					// parseUint64s transforms strings to uint64s.
 | 
				
			||||||
func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
 | 
					func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]uint64, 0, len(strs))
 | 
						vals := make([]uint64, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := strconv.ParseUint(str, 10, 64)
 | 
							val, err := strconv.ParseUint(str, 10, 64)
 | 
				
			||||||
@@ -605,9 +672,8 @@ func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint
 | 
				
			|||||||
	return vals, nil
 | 
						return vals, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
 | 
					// parseTimesFormat transforms strings to times in given format.
 | 
				
			||||||
func (k *Key) getTimesFormat(format, delim string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
 | 
					func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
 | 
				
			||||||
	strs := k.Strings(delim)
 | 
					 | 
				
			||||||
	vals := make([]time.Time, 0, len(strs))
 | 
						vals := make([]time.Time, 0, len(strs))
 | 
				
			||||||
	for _, str := range strs {
 | 
						for _, str := range strs {
 | 
				
			||||||
		val, err := time.Parse(format, str)
 | 
							val, err := time.Parse(format, str)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										66
									
								
								vendor/gopkg.in/ini.v1/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								vendor/gopkg.in/ini.v1/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -48,17 +48,32 @@ func newParser(r io.Reader) *parser {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BOM handles header of BOM-UTF8 format.
 | 
					// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
 | 
				
			||||||
// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
 | 
					// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
 | 
				
			||||||
func (p *parser) BOM() error {
 | 
					func (p *parser) BOM() error {
 | 
				
			||||||
 | 
						mask, err := p.buf.Peek(2)
 | 
				
			||||||
 | 
						if err != nil && err != io.EOF {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						} else if len(mask) < 2 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case mask[0] == 254 && mask[1] == 255:
 | 
				
			||||||
 | 
							fallthrough
 | 
				
			||||||
 | 
						case mask[0] == 255 && mask[1] == 254:
 | 
				
			||||||
 | 
							p.buf.Read(mask)
 | 
				
			||||||
 | 
						case mask[0] == 239 && mask[1] == 187:
 | 
				
			||||||
		mask, err := p.buf.Peek(3)
 | 
							mask, err := p.buf.Peek(3)
 | 
				
			||||||
		if err != nil && err != io.EOF {
 | 
							if err != nil && err != io.EOF {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		} else if len(mask) < 3 {
 | 
							} else if len(mask) < 3 {
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
	} else if mask[0] == 239 && mask[1] == 187 && mask[2] == 191 {
 | 
							}
 | 
				
			||||||
 | 
							if mask[2] == 191 {
 | 
				
			||||||
			p.buf.Read(mask)
 | 
								p.buf.Read(mask)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,11 +189,11 @@ func (p *parser) readContinuationLines(val string) (string, error) {
 | 
				
			|||||||
// are quotes \" or \'.
 | 
					// are quotes \" or \'.
 | 
				
			||||||
// It returns false if any other parts also contain same kind of quotes.
 | 
					// It returns false if any other parts also contain same kind of quotes.
 | 
				
			||||||
func hasSurroundedQuote(in string, quote byte) bool {
 | 
					func hasSurroundedQuote(in string, quote byte) bool {
 | 
				
			||||||
	return len(in) > 2 && in[0] == quote && in[len(in)-1] == quote &&
 | 
						return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
 | 
				
			||||||
		strings.IndexByte(in[1:], quote) == len(in)-2
 | 
							strings.IndexByte(in[1:], quote) == len(in)-2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
 | 
					func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment 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 {
 | 
				
			||||||
		return "", nil
 | 
							return "", nil
 | 
				
			||||||
@@ -202,19 +217,22 @@ func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
 | 
				
			|||||||
		return line[startIdx : pos+startIdx], nil
 | 
							return line[startIdx : pos+startIdx], nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Won't be able to reach here if value only contains whitespace.
 | 
						// Won't be able to reach here if value only contains whitespace
 | 
				
			||||||
	line = strings.TrimSpace(line)
 | 
						line = strings.TrimSpace(line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check continuation lines when desired.
 | 
						// Check continuation lines when desired
 | 
				
			||||||
	if !ignoreContinuation && line[len(line)-1] == '\\' {
 | 
						if !ignoreContinuation && line[len(line)-1] == '\\' {
 | 
				
			||||||
		return p.readContinuationLines(line[:len(line)-1])
 | 
							return p.readContinuationLines(line[:len(line)-1])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if ignore inline comment
 | 
				
			||||||
 | 
						if !ignoreInlineComment {
 | 
				
			||||||
		i := strings.IndexAny(line, "#;")
 | 
							i := strings.IndexAny(line, "#;")
 | 
				
			||||||
		if i > -1 {
 | 
							if i > -1 {
 | 
				
			||||||
			p.comment.WriteString(line[i:])
 | 
								p.comment.WriteString(line[i:])
 | 
				
			||||||
			line = strings.TrimSpace(line[:i])
 | 
								line = strings.TrimSpace(line[:i])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Trim single quotes
 | 
						// Trim single quotes
 | 
				
			||||||
	if hasSurroundedQuote(line, '\'') ||
 | 
						if hasSurroundedQuote(line, '\'') ||
 | 
				
			||||||
@@ -235,6 +253,7 @@ func (f *File) parse(reader io.Reader) (err error) {
 | 
				
			|||||||
	section, _ := f.NewSection(DEFAULT_SECTION)
 | 
						section, _ := f.NewSection(DEFAULT_SECTION)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var line []byte
 | 
						var line []byte
 | 
				
			||||||
 | 
						var inUnparseableSection bool
 | 
				
			||||||
	for !p.isEOF {
 | 
						for !p.isEOF {
 | 
				
			||||||
		line, err = p.readUntil('\n')
 | 
							line, err = p.readUntil('\n')
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -280,6 +299,21 @@ func (f *File) parse(reader io.Reader) (err error) {
 | 
				
			|||||||
			// Reset aotu-counter and comments
 | 
								// Reset aotu-counter and comments
 | 
				
			||||||
			p.comment.Reset()
 | 
								p.comment.Reset()
 | 
				
			||||||
			p.count = 1
 | 
								p.count = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								inUnparseableSection = false
 | 
				
			||||||
 | 
								for i := range f.options.UnparseableSections {
 | 
				
			||||||
 | 
									if f.options.UnparseableSections[i] == name ||
 | 
				
			||||||
 | 
										(f.options.Insensitive && strings.ToLower(f.options.UnparseableSections[i]) == strings.ToLower(name)) {
 | 
				
			||||||
 | 
										inUnparseableSection = true
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if inUnparseableSection {
 | 
				
			||||||
 | 
								section.isRawSection = true
 | 
				
			||||||
 | 
								section.rawBody += string(line)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -287,11 +321,14 @@ func (f *File) parse(reader io.Reader) (err error) {
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// Treat as boolean key when desired, and whole line is key name.
 | 
								// Treat as boolean key when desired, and whole line is key name.
 | 
				
			||||||
			if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
 | 
								if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
 | 
				
			||||||
				key, err := section.NewKey(string(line), "true")
 | 
									kname, err := p.readValue(line, f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									key, err := section.NewBooleanKey(kname)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				key.isBooleanType = true
 | 
					 | 
				
			||||||
				key.Comment = strings.TrimSpace(p.comment.String())
 | 
									key.Comment = strings.TrimSpace(p.comment.String())
 | 
				
			||||||
				p.comment.Reset()
 | 
									p.comment.Reset()
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
@@ -307,17 +344,16 @@ func (f *File) parse(reader io.Reader) (err error) {
 | 
				
			|||||||
			p.count++
 | 
								p.count++
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key, err := section.NewKey(kname, "")
 | 
							value, err := p.readValue(line[offset:], f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							key, err := section.NewKey(kname, value)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		key.isAutoIncrement = isAutoIncr
 | 
							key.isAutoIncrement = isAutoIncr
 | 
				
			||||||
 | 
					 | 
				
			||||||
		value, err := p.readValue(line[offset:], f.options.IgnoreContinuation)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		key.SetValue(value)
 | 
					 | 
				
			||||||
		key.Comment = strings.TrimSpace(p.comment.String())
 | 
							key.Comment = strings.TrimSpace(p.comment.String())
 | 
				
			||||||
		p.comment.Reset()
 | 
							p.comment.Reset()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								vendor/gopkg.in/ini.v1/section.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								vendor/gopkg.in/ini.v1/section.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -28,10 +28,19 @@ type Section struct {
 | 
				
			|||||||
	keys     map[string]*Key
 | 
						keys     map[string]*Key
 | 
				
			||||||
	keyList  []string
 | 
						keyList  []string
 | 
				
			||||||
	keysHash map[string]string
 | 
						keysHash map[string]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isRawSection bool
 | 
				
			||||||
 | 
						rawBody      string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newSection(f *File, name string) *Section {
 | 
					func newSection(f *File, name string) *Section {
 | 
				
			||||||
	return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)}
 | 
						return &Section{
 | 
				
			||||||
 | 
							f:        f,
 | 
				
			||||||
 | 
							name:     name,
 | 
				
			||||||
 | 
							keys:     make(map[string]*Key),
 | 
				
			||||||
 | 
							keyList:  make([]string, 0, 10),
 | 
				
			||||||
 | 
							keysHash: make(map[string]string),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Name returns name of Section.
 | 
					// Name returns name of Section.
 | 
				
			||||||
@@ -39,6 +48,12 @@ func (s *Section) Name() string {
 | 
				
			|||||||
	return s.name
 | 
						return s.name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Body returns rawBody of Section if the section was marked as unparseable.
 | 
				
			||||||
 | 
					// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
 | 
				
			||||||
 | 
					func (s *Section) Body() string {
 | 
				
			||||||
 | 
						return strings.TrimSpace(s.rawBody)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewKey creates a new key to given section.
 | 
					// NewKey creates a new key to given section.
 | 
				
			||||||
func (s *Section) NewKey(name, val string) (*Key, error) {
 | 
					func (s *Section) NewKey(name, val string) (*Key, error) {
 | 
				
			||||||
	if len(name) == 0 {
 | 
						if len(name) == 0 {
 | 
				
			||||||
@@ -53,20 +68,33 @@ func (s *Section) NewKey(name, val string) (*Key, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if inSlice(name, s.keyList) {
 | 
						if inSlice(name, s.keyList) {
 | 
				
			||||||
 | 
							if s.f.options.AllowShadows {
 | 
				
			||||||
 | 
								if err := s.keys[name].addShadow(val); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			s.keys[name].value = val
 | 
								s.keys[name].value = val
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return s.keys[name], nil
 | 
							return s.keys[name], nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s.keyList = append(s.keyList, name)
 | 
						s.keyList = append(s.keyList, name)
 | 
				
			||||||
	s.keys[name] = &Key{
 | 
						s.keys[name] = newKey(s, name, val)
 | 
				
			||||||
		s:     s,
 | 
					 | 
				
			||||||
		name:  name,
 | 
					 | 
				
			||||||
		value: val,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.keysHash[name] = val
 | 
						s.keysHash[name] = val
 | 
				
			||||||
	return s.keys[name], nil
 | 
						return s.keys[name], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewBooleanKey creates a new boolean type key to given section.
 | 
				
			||||||
 | 
					func (s *Section) NewBooleanKey(name string) (*Key, error) {
 | 
				
			||||||
 | 
						key, err := s.NewKey(name, "true")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key.isBooleanType = true
 | 
				
			||||||
 | 
						return key, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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?
 | 
						// FIXME: change to section level lock?
 | 
				
			||||||
@@ -204,3 +232,17 @@ func (s *Section) DeleteKey(name string) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ChildSections returns a list of child sections of current section.
 | 
				
			||||||
 | 
					// For example, "[parent.child1]" and "[parent.child12]" are child sections
 | 
				
			||||||
 | 
					// of section "[parent]".
 | 
				
			||||||
 | 
					func (s *Section) ChildSections() []*Section {
 | 
				
			||||||
 | 
						prefix := s.name + "."
 | 
				
			||||||
 | 
						children := make([]*Section, 0, 3)
 | 
				
			||||||
 | 
						for _, name := range s.f.sectionList {
 | 
				
			||||||
 | 
							if strings.HasPrefix(name, prefix) {
 | 
				
			||||||
 | 
								children = append(children, s.f.sections[name])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return children
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										119
									
								
								vendor/gopkg.in/ini.v1/struct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										119
									
								
								vendor/gopkg.in/ini.v1/struct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -78,34 +78,44 @@ func parseDelim(actual string) string {
 | 
				
			|||||||
var reflectTime = reflect.TypeOf(time.Now()).Kind()
 | 
					var reflectTime = reflect.TypeOf(time.Now()).Kind()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// setSliceWithProperType sets proper values to slice based on its type.
 | 
					// setSliceWithProperType sets proper values to slice based on its type.
 | 
				
			||||||
func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
 | 
					func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
 | 
				
			||||||
	strs := key.Strings(delim)
 | 
						var strs []string
 | 
				
			||||||
 | 
						if allowShadow {
 | 
				
			||||||
 | 
							strs = key.StringsWithShadows(delim)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							strs = key.Strings(delim)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	numVals := len(strs)
 | 
						numVals := len(strs)
 | 
				
			||||||
	if numVals == 0 {
 | 
						if numVals == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var vals interface{}
 | 
						var vals interface{}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sliceOf := field.Type().Elem().Kind()
 | 
						sliceOf := field.Type().Elem().Kind()
 | 
				
			||||||
	switch sliceOf {
 | 
						switch sliceOf {
 | 
				
			||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		vals = strs
 | 
							vals = strs
 | 
				
			||||||
	case reflect.Int:
 | 
						case reflect.Int:
 | 
				
			||||||
		vals = key.Ints(delim)
 | 
							vals, err = key.parseInts(strs, true, false)
 | 
				
			||||||
	case reflect.Int64:
 | 
						case reflect.Int64:
 | 
				
			||||||
		vals = key.Int64s(delim)
 | 
							vals, err = key.parseInt64s(strs, true, false)
 | 
				
			||||||
	case reflect.Uint:
 | 
						case reflect.Uint:
 | 
				
			||||||
		vals = key.Uints(delim)
 | 
							vals, err = key.parseUints(strs, true, false)
 | 
				
			||||||
	case reflect.Uint64:
 | 
						case reflect.Uint64:
 | 
				
			||||||
		vals = key.Uint64s(delim)
 | 
							vals, err = key.parseUint64s(strs, true, false)
 | 
				
			||||||
	case reflect.Float64:
 | 
						case reflect.Float64:
 | 
				
			||||||
		vals = key.Float64s(delim)
 | 
							vals, err = key.parseFloat64s(strs, true, false)
 | 
				
			||||||
	case reflectTime:
 | 
						case reflectTime:
 | 
				
			||||||
		vals = key.Times(delim)
 | 
							vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
 | 
							return fmt.Errorf("unsupported type '[]%s'", sliceOf)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if isStrict {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
 | 
						slice := reflect.MakeSlice(field.Type(), numVals, numVals)
 | 
				
			||||||
	for i := 0; i < numVals; i++ {
 | 
						for i := 0; i < numVals; i++ {
 | 
				
			||||||
@@ -130,10 +140,17 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func wrapStrictError(err error, isStrict bool) error {
 | 
				
			||||||
 | 
						if isStrict {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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 strcut.
 | 
				
			||||||
func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) 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:
 | 
				
			||||||
		if len(key.String()) == 0 {
 | 
							if len(key.String()) == 0 {
 | 
				
			||||||
@@ -143,7 +160,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 | 
				
			|||||||
	case reflect.Bool:
 | 
						case reflect.Bool:
 | 
				
			||||||
		boolVal, err := key.Bool()
 | 
							boolVal, err := key.Bool()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil
 | 
								return wrapStrictError(err, isStrict)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.SetBool(boolVal)
 | 
							field.SetBool(boolVal)
 | 
				
			||||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
				
			||||||
@@ -155,8 +172,8 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		intVal, err := key.Int64()
 | 
							intVal, err := key.Int64()
 | 
				
			||||||
		if err != nil || intVal == 0 {
 | 
							if err != nil {
 | 
				
			||||||
			return nil
 | 
								return wrapStrictError(err, isStrict)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.SetInt(intVal)
 | 
							field.SetInt(intVal)
 | 
				
			||||||
	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
 | 
						//	byte is an alias for uint8, so supporting uint8 breaks support for byte
 | 
				
			||||||
@@ -170,31 +187,43 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		uintVal, err := key.Uint64()
 | 
							uintVal, err := key.Uint64()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil
 | 
								return wrapStrictError(err, isStrict)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.SetUint(uintVal)
 | 
							field.SetUint(uintVal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case reflect.Float64:
 | 
						case reflect.Float32, reflect.Float64:
 | 
				
			||||||
		floatVal, err := key.Float64()
 | 
							floatVal, err := key.Float64()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil
 | 
								return wrapStrictError(err, isStrict)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.SetFloat(floatVal)
 | 
							field.SetFloat(floatVal)
 | 
				
			||||||
	case reflectTime:
 | 
						case reflectTime:
 | 
				
			||||||
		timeVal, err := key.Time()
 | 
							timeVal, err := key.Time()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil
 | 
								return wrapStrictError(err, isStrict)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.Set(reflect.ValueOf(timeVal))
 | 
							field.Set(reflect.ValueOf(timeVal))
 | 
				
			||||||
	case reflect.Slice:
 | 
						case reflect.Slice:
 | 
				
			||||||
		return setSliceWithProperType(key, field, delim)
 | 
							return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("unsupported type '%s'", t)
 | 
							return fmt.Errorf("unsupported type '%s'", t)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Section) mapTo(val reflect.Value) error {
 | 
					func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool) {
 | 
				
			||||||
 | 
						opts := strings.SplitN(tag, ",", 3)
 | 
				
			||||||
 | 
						rawName = opts[0]
 | 
				
			||||||
 | 
						if len(opts) > 1 {
 | 
				
			||||||
 | 
							omitEmpty = opts[1] == "omitempty"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(opts) > 2 {
 | 
				
			||||||
 | 
							allowShadow = opts[2] == "allowshadow"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rawName, omitEmpty, allowShadow
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
 | 
				
			||||||
	if val.Kind() == reflect.Ptr {
 | 
						if val.Kind() == reflect.Ptr {
 | 
				
			||||||
		val = val.Elem()
 | 
							val = val.Elem()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -209,8 +238,8 @@ func (s *Section) mapTo(val reflect.Value) error {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		opts := strings.SplitN(tag, ",", 2) // strip off possible omitempty
 | 
							rawName, _, allowShadow := parseTagOptions(tag)
 | 
				
			||||||
		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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -223,7 +252,7 @@ func (s *Section) mapTo(val reflect.Value) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if isAnonymous || isStruct {
 | 
							if isAnonymous || isStruct {
 | 
				
			||||||
			if sec, err := s.f.GetSection(fieldName); err == nil {
 | 
								if sec, err := s.f.GetSection(fieldName); err == nil {
 | 
				
			||||||
				if err = sec.mapTo(field); 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)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
@@ -231,7 +260,8 @@ func (s *Section) mapTo(val reflect.Value) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if key, err := s.GetKey(fieldName); err == nil {
 | 
							if key, err := s.GetKey(fieldName); err == nil {
 | 
				
			||||||
			if err = setWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
 | 
								delim := parseDelim(tpField.Tag.Get("delim"))
 | 
				
			||||||
 | 
								if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
 | 
				
			||||||
				return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
 | 
									return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -250,7 +280,22 @@ func (s *Section) MapTo(v interface{}) error {
 | 
				
			|||||||
		return errors.New("cannot map to non-pointer struct")
 | 
							return errors.New("cannot map to non-pointer struct")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return s.mapTo(val)
 | 
						return s.mapTo(val, false)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MapTo 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)
 | 
				
			||||||
 | 
						val := reflect.ValueOf(v)
 | 
				
			||||||
 | 
						if typ.Kind() == reflect.Ptr {
 | 
				
			||||||
 | 
							typ = typ.Elem()
 | 
				
			||||||
 | 
							val = val.Elem()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return errors.New("cannot map to non-pointer struct")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s.mapTo(val, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MapTo maps file to given struct.
 | 
					// MapTo maps file to given struct.
 | 
				
			||||||
@@ -258,6 +303,12 @@ 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,
 | 
				
			||||||
 | 
					// 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.
 | 
					// MapTo 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...)
 | 
				
			||||||
@@ -268,11 +319,28 @@ func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, other
 | 
				
			|||||||
	return cfg.MapTo(v)
 | 
						return cfg.MapTo(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
 | 
				
			||||||
 | 
					// which returns all possible error including value parsing error.
 | 
				
			||||||
 | 
					func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
 | 
				
			||||||
 | 
						cfg, err := Load(source, others...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cfg.NameMapper = mapper
 | 
				
			||||||
 | 
						return cfg.StrictMapTo(v)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MapTo maps data sources to given struct.
 | 
					// MapTo maps data sources to given struct.
 | 
				
			||||||
func MapTo(v, source interface{}, others ...interface{}) error {
 | 
					func MapTo(v, source interface{}, others ...interface{}) error {
 | 
				
			||||||
	return MapToWithMapper(v, nil, source, others...)
 | 
						return MapToWithMapper(v, nil, source, others...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StrictMapTo maps data sources to given struct in strict mode,
 | 
				
			||||||
 | 
					// which returns all possible error including value parsing error.
 | 
				
			||||||
 | 
					func StrictMapTo(v, source interface{}, others ...interface{}) error {
 | 
				
			||||||
 | 
						return StrictMapToWithMapper(v, nil, source, others...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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) error {
 | 
				
			||||||
	slice := field.Slice(0, field.Len())
 | 
						slice := field.Slice(0, field.Len())
 | 
				
			||||||
@@ -340,10 +408,11 @@ func isEmptyValue(v reflect.Value) bool {
 | 
				
			|||||||
		return v.Uint() == 0
 | 
							return v.Uint() == 0
 | 
				
			||||||
	case reflect.Float32, reflect.Float64:
 | 
						case reflect.Float32, reflect.Float64:
 | 
				
			||||||
		return v.Float() == 0
 | 
							return v.Float() == 0
 | 
				
			||||||
	case reflectTime:
 | 
					 | 
				
			||||||
		return v.Interface().(time.Time).IsZero()
 | 
					 | 
				
			||||||
	case reflect.Interface, reflect.Ptr:
 | 
						case reflect.Interface, reflect.Ptr:
 | 
				
			||||||
		return v.IsNil()
 | 
							return v.IsNil()
 | 
				
			||||||
 | 
						case reflectTime:
 | 
				
			||||||
 | 
							t, ok := v.Interface().(time.Time)
 | 
				
			||||||
 | 
							return ok && t.IsZero()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							@@ -1466,10 +1466,11 @@
 | 
				
			|||||||
			"revisionTime": "2016-04-11T21:29:32Z"
 | 
								"revisionTime": "2016-04-11T21:29:32Z"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"checksumSHA1": "YRD335tkMvgHzkfbfveMUpsE3Bw=",
 | 
								"checksumSHA1": "MMb7aeIRnJq17iQvuGvevymOIYQ=",
 | 
				
			||||||
 | 
								"origin": "github.com/go-gitea/ini",
 | 
				
			||||||
			"path": "gopkg.in/ini.v1",
 | 
								"path": "gopkg.in/ini.v1",
 | 
				
			||||||
			"revision": "6e4869b434bd001f6983749881c7ead3545887d8",
 | 
								"revision": "88679ba677ac064c7880c9bde81ef5b9fd132e82",
 | 
				
			||||||
			"revisionTime": "2016-08-27T06:11:18Z"
 | 
								"revisionTime": "2017-08-04T04:10:12Z"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"checksumSHA1": "7jPSjzw3mckHVQ2SjY4NvtIJR4g=",
 | 
								"checksumSHA1": "7jPSjzw3mckHVQ2SjY4NvtIJR4g=",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user