1
0
Fork 0
mirror of https://github.com/Luzifer/git-changerelease.git synced 2024-10-18 14:14:20 +00:00

Update vendored libraries

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2018-07-02 16:54:44 +02:00
parent ffa65b0c68
commit 9a94a0bfe6
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
55 changed files with 3293 additions and 1226 deletions

19
Gopkg.lock generated
View file

@ -4,23 +4,32 @@
[[projects]] [[projects]]
name = "github.com/Luzifer/rconfig" name = "github.com/Luzifer/rconfig"
packages = ["."] packages = ["."]
revision = "c27bd3a64b5b19556914d9fec69922cf3852d585" revision = "7aef1d393c1e2d0758901853b59981c7adc67c7e"
version = "v1.1.0" version = "v1.2.0"
[[projects]] [[projects]]
branch = "master"
name = "github.com/mitchellh/go-homedir" name = "github.com/mitchellh/go-homedir"
packages = ["."] packages = ["."]
revision = "981ab348d865cf048eb7d17e78ac7192632d8415" revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66"
[[projects]] [[projects]]
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
revision = "367864438f1b1a3c7db4da06a2f55b144e6784e0" revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
branch = "v2"
name = "gopkg.in/validator.v2"
packages = ["."]
revision = "135c24b11c19e52befcae2ec3fca5d9b78c4e98e"
[[projects]] [[projects]]
name = "gopkg.in/yaml.v2" name = "gopkg.in/yaml.v2"
packages = ["."] packages = ["."]
revision = "53feefa2559fb8dfa8d81baad31be332c97d6c77" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"

View file

@ -30,5 +30,6 @@
version = "1.1.0" version = "1.1.0"
[prune] [prune]
non-go = true
go-tests = true go-tests = true
unused-packages = true unused-packages = true

View file

@ -1,8 +0,0 @@
language: go
go:
- 1.4
- 1.5
- tip
script: go test -v -race -cover ./...

View file

@ -1,5 +0,0 @@
# 1.1.0 / 2016-06-28
* Support time.Duration config parameters
* Added goreportcard badge
* Added testcase for using bool with ENV and default

View file

@ -1,94 +0,0 @@
[![Build Status](https://travis-ci.org/Luzifer/rconfig.svg?branch=master)](https://travis-ci.org/Luzifer/rconfig)
[![License: Apache v2.0](https://badge.luzifer.io/v1/badge?color=5d79b5&title=license&text=Apache+v2.0)](http://www.apache.org/licenses/LICENSE-2.0)
[![Documentation](https://badge.luzifer.io/v1/badge?title=godoc&text=reference)](https://godoc.org/github.com/Luzifer/rconfig)
[![Go Report](http://goreportcard.com/badge/Luzifer/rconfig)](http://goreportcard.com/report/Luzifer/rconfig)
## Description
> Package rconfig implements a CLI configuration reader with struct-embedded defaults, environment variables and posix compatible flag parsing using the [pflag](https://github.com/spf13/pflag) library.
## Installation
Install by running:
```
go get -u github.com/Luzifer/rconfig
```
OR fetch a specific version:
```
go get -u gopkg.in/luzifer/rconfig.v1
```
Run tests by running:
```
go test -v -race -cover github.com/Luzifer/rconfig
```
## Usage
As a first step define a struct holding your configuration:
```go
type config struct {
Username string `default:"unknown" flag:"user" description:"Your name"`
Details struct {
Age int `default:"25" flag:"age" env:"age" description:"Your age"`
}
}
```
Next create an instance of that struct and let `rconfig` fill that config:
```go
var cfg config
func init() {
cfg = config{}
rconfig.Parse(&cfg)
}
```
You're ready to access your configuration:
```go
func main() {
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
cfg.Username,
cfg.Details.Age)
}
```
### Provide variable defaults by using a file
Given you have a file `~/.myapp.yml` containing some secrets or usernames (for the example below username is assumed to be "luzifer") as a default configuration for your application you can use this source code to load the defaults from that file using the `vardefault` tag in your configuration struct.
The order of the directives (lower number = higher precedence):
1. Flags provided in command line
1. Environment variables
1. Variable defaults (`vardefault` tag in the struct)
1. `default` tag in the struct
```go
type config struct {
Username string `vardefault:"username" flag:"username" description:"Your username"`
}
var cfg = config{}
func init() {
rconfig.SetVariableDefaults(rconfig.VarDefaultsFromYAMLFile("~/.myapp.yml"))
rconfig.Parse(&cfg)
}
func main() {
fmt.Printf("Username = %s", cfg.Username)
// Output: Username = luzifer
}
```
## More info
You can see the full reference documentation of the rconfig package [at godoc.org](https://godoc.org/github.com/Luzifer/rconfig), or through go's standard documentation system by running `godoc -http=:6060` and browsing to [http://localhost:6060/pkg/github.com/Luzifer/rconfig](http://localhost:6060/pkg/github.com/Luzifer/rconfig) after installation.

View file

@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/spf13/pflag" "github.com/spf13/pflag"
validator "gopkg.in/validator.v2"
) )
var ( var (
@ -45,6 +46,15 @@ func Parse(config interface{}) error {
return parse(config, nil) return parse(config, nil)
} }
// ParseAndValidate works exactly like Parse but implements an additional run of
// the go-validator package on the configuration struct. Therefore additonal struct
// tags are supported like described in the readme file of the go-validator package:
//
// https://github.com/go-validator/validator/tree/v2#usage
func ParseAndValidate(config interface{}) error {
return parseAndValidate(config, nil)
}
// Args returns the non-flag command-line arguments. // Args returns the non-flag command-line arguments.
func Args() []string { func Args() []string {
return fs.Args() return fs.Args()
@ -65,6 +75,14 @@ func SetVariableDefaults(defaults map[string]string) {
variableDefaults = defaults variableDefaults = defaults
} }
func parseAndValidate(in interface{}, args []string) error {
if err := parse(in, args); err != nil {
return err
}
return validator.Validate(in)
}
func parse(in interface{}, args []string) error { func parse(in interface{}, args []string) error {
if args == nil { if args == nil {
args = os.Args args = os.Args

View file

@ -1,14 +0,0 @@
# go-homedir
This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.
Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
for a user, and `homedir.Expand()` to expand the `~` in a path to the home
directory.
**Why not just use `os/user`?** The built-in `os/user` package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for `os/user` is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.

View file

@ -77,18 +77,35 @@ func Expand(path string) (string, error) {
} }
func dirUnix() (string, error) { func dirUnix() (string, error) {
homeEnv := "HOME"
if runtime.GOOS == "plan9" {
// On plan9, env vars are lowercase.
homeEnv = "home"
}
// First prefer the HOME environmental variable // First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" { if home := os.Getenv(homeEnv); home != "" {
return home, nil return home, nil
} }
// If that fails, try getent
var stdout bytes.Buffer var stdout bytes.Buffer
// If that fails, try OS specific commands
if runtime.GOOS == "darwin" {
cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`)
cmd.Stdout = &stdout
if err := cmd.Run(); err == nil {
result := strings.TrimSpace(stdout.String())
if result != "" {
return result, nil
}
}
} else {
cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
cmd.Stdout = &stdout cmd.Stdout = &stdout
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
// If "getent" is missing, ignore it // If the error is ErrNotFound, we ignore it. Otherwise, return it.
if err == exec.ErrNotFound { if err != exec.ErrNotFound {
return "", err return "", err
} }
} else { } else {
@ -100,10 +117,11 @@ func dirUnix() (string, error) {
} }
} }
} }
}
// If all else fails, try the shell // If all else fails, try the shell
stdout.Reset() stdout.Reset()
cmd = exec.Command("sh", "-c", "cd && pwd") cmd := exec.Command("sh", "-c", "cd && pwd")
cmd.Stdout = &stdout cmd.Stdout = &stdout
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
return "", err return "", err
@ -118,6 +136,11 @@ func dirUnix() (string, error) {
} }
func dirWindows() (string, error) { func dirWindows() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
drive := os.Getenv("HOMEDRIVE") drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH") path := os.Getenv("HOMEPATH")
home := drive + path home := drive + path

View file

@ -1,17 +0,0 @@
sudo: false
language: go
go:
- 1.5
- 1.6
- tip
install:
- go get github.com/golang/lint/golint
- export PATH=$GOPATH/bin:$PATH
- go install ./...
script:
- verify/all.sh -v
- go test ./...

View file

@ -1,275 +0,0 @@
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
## Description
pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.
pflag is compatible with the [GNU extensions to the POSIX recommendations
for command-line options][1]. For a more precise description, see the
"Command-line flag syntax" section below.
[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
pflag is available under the same style of BSD license as the Go language,
which can be found in the LICENSE file.
## Installation
pflag is available using the standard `go get` command.
Install by running:
go get github.com/spf13/pflag
Run tests by running:
go test github.com/spf13/pflag
## Usage
pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function
with no changes.
``` go
import flag "github.com/spf13/pflag"
```
There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore
unaffected.
Define flags using flag.String(), Bool(), Int(), etc.
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
``` go
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
```
If you like, you can bind the flag to a variable using the Var() functions.
``` go
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
```
Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
``` go
flag.Var(&flagVal, "name", "help message for flagname")
```
For such flags, the default value is just the initial value of the variable.
After all flags are defined, call
``` go
flag.Parse()
```
to parse the command line into the defined flags.
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
``` go
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)
```
There are helpers function to get values later if you have the FlagSet but
it was difficult to keep up with all of the flag pointers in your code.
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
can use GetInt() to get the int value. But notice that 'flagname' must exist
and it must be an int. GetString("flagname") will fail.
``` go
i, err := flagset.GetInt("flagname")
```
After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.
The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.
``` go
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP("boolname", "b", true, "help message")
}
flag.VarP(&flagVar, "varname", "v", 1234, "help message")
```
Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.
The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
## Setting no option default values for flags
After you create a flag it is possible to set the pflag.NoOptDefVal for
the given flag. Doing this changes the meaning of the flag slightly. If
a flag has a NoOptDefVal and the flag is set on the command line without
an option the flag will be set to the NoOptDefVal. For example given:
``` go
var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"
```
Would result in something like
| Parsed Arguments | Resulting Value |
| ------------- | ------------- |
| --flagname=1357 | ip=1357 |
| --flagname | ip=4321 |
| [nothing] | ip=1234 |
## Command line flag syntax
```
--flag // boolean flags, or flags with no option default values
--flag x // only on flags without a default value
--flag=x
```
Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags
or a flag with a default value
```
// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID
// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234
// mixed
-abcs "hello"
-absd="hello"
-abcs1234
```
Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
TRUE, FALSE, True, False.
Duration flags accept any input valid for time.ParseDuration.
## Mutating or "Normalizing" Flag names
It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow.
**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag
``` go
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
from := []string{"-", "_"}
to := "."
for _, sep := range from {
name = strings.Replace(name, sep, to, -1)
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)
```
**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name
``` go
func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
switch name {
case "old-flag-name":
name = "new-flag-name"
break
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)
```
## Deprecating a flag or its shorthand
It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used.
**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead.
```go
// deprecate a flag by specifying its name and a usage message
flags.MarkDeprecated("badflag", "please use --good-flag instead")
```
This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used.
**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n".
```go
// deprecate a flag shorthand by specifying its flag name and a usage message
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")
```
This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used.
Note that usage message is essential here, and it should not be empty.
## Hidden flags
It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.
**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available.
```go
// hide a flag by specifying its name
flags.MarkHidden("secretFlag")
```
## Supporting Go flags when using pflag
In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary
to support flags defined by third-party dependencies (e.g. `golang/glog`).
**Example**: You want to add the Go flags to the `CommandLine` flagset
```go
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
flag.Parse()
}
```
## More info
You can see the full reference documentation of the pflag package
[at godoc.org][3], or through go's standard documentation system by
running `godoc -http=:6060` and browsing to
[http://localhost:6060/pkg/github.com/ogier/pflag][2] after
installation.
[2]: http://localhost:6060/pkg/github.com/ogier/pflag
[3]: http://godoc.org/github.com/ogier/pflag

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// optional interface to indicate boolean flags that can be // optional interface to indicate boolean flags that can be
// supplied without "=value" text // supplied without "=value" text
@ -30,7 +27,7 @@ func (b *boolValue) Type() string {
return "bool" return "bool"
} }
func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
func (b *boolValue) IsBoolFlag() bool { return true } func (b *boolValue) IsBoolFlag() bool { return true }

147
vendor/github.com/spf13/pflag/bool_slice.go generated vendored Normal file
View file

@ -0,0 +1,147 @@
package pflag
import (
"io"
"strconv"
"strings"
)
// -- boolSlice Value
type boolSliceValue struct {
value *[]bool
changed bool
}
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
bsv := new(boolSliceValue)
bsv.value = p
*bsv.value = val
return bsv
}
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
func (s *boolSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse boolean values into slice
out := make([]bool, 0, len(boolStrSlice))
for _, boolStr := range boolStrSlice {
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
if err != nil {
return err
}
out = append(out, b)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *boolSliceValue) Type() string {
return "boolSlice"
}
// String defines a "native" format for this boolean slice flag value.
func (s *boolSliceValue) String() string {
boolStrSlice := make([]string, len(*s.value))
for i, b := range *s.value {
boolStrSlice[i] = strconv.FormatBool(b)
}
out, _ := writeAsCSV(boolStrSlice)
return "[" + out + "]"
}
func boolSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []bool{}, nil
}
ss := strings.Split(val, ",")
out := make([]bool, len(ss))
for i, t := range ss {
var err error
out[i], err = strconv.ParseBool(t)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetBoolSlice returns the []bool value of a flag with the given name.
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
if err != nil {
return []bool{}, err
}
return val.([]bool), nil
}
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, "", value, usage)
return &p
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func BoolSlice(name string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, "", value, usage)
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, shorthand, value, usage)
}

105
vendor/github.com/spf13/pflag/bytes.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
package pflag
import (
"encoding/hex"
"fmt"
"strings"
)
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
type bytesHexValue []byte
func (bytesHex bytesHexValue) String() string {
return fmt.Sprintf("%X", []byte(bytesHex))
}
func (bytesHex *bytesHexValue) Set(value string) error {
bin, err := hex.DecodeString(strings.TrimSpace(value))
if err != nil {
return err
}
*bytesHex = bin
return nil
}
func (*bytesHexValue) Type() string {
return "bytesHex"
}
func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue {
*p = val
return (*bytesHexValue)(p)
}
func bytesHexConv(sval string) (interface{}, error) {
bin, err := hex.DecodeString(sval)
if err == nil {
return bin, nil
}
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
}
// GetBytesHex return the []byte value of a flag with the given name
func (f *FlagSet) GetBytesHex(name string) ([]byte, error) {
val, err := f.getFlagType(name, "bytesHex", bytesHexConv)
if err != nil {
return []byte{}, err
}
return val.([]byte), nil
}
// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
// The argument p points to an []byte variable in which to store the value of the flag.
func (f *FlagSet) BytesHexVar(p *[]byte, name string, value []byte, usage string) {
f.VarP(newBytesHexValue(value, p), name, "", usage)
}
// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
f.VarP(newBytesHexValue(value, p), name, shorthand, usage)
}
// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
// The argument p points to an []byte variable in which to store the value of the flag.
func BytesHexVar(p *[]byte, name string, value []byte, usage string) {
CommandLine.VarP(newBytesHexValue(value, p), name, "", usage)
}
// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
func BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
CommandLine.VarP(newBytesHexValue(value, p), name, shorthand, usage)
}
// BytesHex defines an []byte flag with specified name, default value, and usage string.
// The return value is the address of an []byte variable that stores the value of the flag.
func (f *FlagSet) BytesHex(name string, value []byte, usage string) *[]byte {
p := new([]byte)
f.BytesHexVarP(p, name, "", value, usage)
return p
}
// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
p := new([]byte)
f.BytesHexVarP(p, name, shorthand, value, usage)
return p
}
// BytesHex defines an []byte flag with specified name, default value, and usage string.
// The return value is the address of an []byte variable that stores the value of the flag.
func BytesHex(name string, value []byte, usage string) *[]byte {
return CommandLine.BytesHexP(name, "", value, usage)
}
// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
return CommandLine.BytesHexP(name, shorthand, value, usage)
}

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- count Value // -- count Value
type countValue int type countValue int
@ -14,13 +11,13 @@ func newCountValue(val int, p *int) *countValue {
} }
func (i *countValue) Set(s string) error { func (i *countValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64) // "+1" means that no specific value was passed, so increment
// -1 means that no specific value was passed, so increment if s == "+1" {
if v == -1 {
*i = countValue(*i + 1) *i = countValue(*i + 1)
} else { return nil
*i = countValue(v)
} }
v, err := strconv.ParseInt(s, 0, 0)
*i = countValue(v)
return err return err
} }
@ -28,7 +25,7 @@ func (i *countValue) Type() string {
return "count" return "count"
} }
func (i *countValue) String() string { return fmt.Sprintf("%v", *i) } func (i *countValue) String() string { return strconv.Itoa(int(*i)) }
func countConv(sval string) (interface{}, error) { func countConv(sval string) (interface{}, error) {
i, err := strconv.Atoi(sval) i, err := strconv.Atoi(sval)
@ -57,7 +54,7 @@ func (f *FlagSet) CountVar(p *int, name string, usage string) {
// CountVarP is like CountVar only take a shorthand for the flag name. // CountVarP is like CountVar only take a shorthand for the flag name.
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) { func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage) flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
flag.NoOptDefVal = "-1" flag.NoOptDefVal = "+1"
} }
// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set // CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
@ -86,7 +83,9 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
return p return p
} }
// Count like Count only the flag is placed on the CommandLine isntead of a given flag set // Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line
func Count(name string, usage string) *int { func Count(name string, usage string) *int {
return CommandLine.CountP(name, "", usage) return CommandLine.CountP(name, "", usage)
} }

128
vendor/github.com/spf13/pflag/duration_slice.go generated vendored Normal file
View file

@ -0,0 +1,128 @@
package pflag
import (
"fmt"
"strings"
"time"
)
// -- durationSlice Value
type durationSliceValue struct {
value *[]time.Duration
changed bool
}
func newDurationSliceValue(val []time.Duration, p *[]time.Duration) *durationSliceValue {
dsv := new(durationSliceValue)
dsv.value = p
*dsv.value = val
return dsv
}
func (s *durationSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]time.Duration, len(ss))
for i, d := range ss {
var err error
out[i], err = time.ParseDuration(d)
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *durationSliceValue) Type() string {
return "durationSlice"
}
func (s *durationSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%s", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func durationSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []time.Duration{}, nil
}
ss := strings.Split(val, ",")
out := make([]time.Duration, len(ss))
for i, d := range ss {
var err error
out[i], err = time.ParseDuration(d)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetDurationSlice returns the []time.Duration value of a flag with the given name
func (f *FlagSet) GetDurationSlice(name string) ([]time.Duration, error) {
val, err := f.getFlagType(name, "durationSlice", durationSliceConv)
if err != nil {
return []time.Duration{}, err
}
return val.([]time.Duration), nil
}
// DurationSliceVar defines a durationSlice flag with specified name, default value, and usage string.
// The argument p points to a []time.Duration variable in which to store the value of the flag.
func (f *FlagSet) DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
f.VarP(newDurationSliceValue(value, p), name, "", usage)
}
// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
f.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
}
// DurationSliceVar defines a duration[] flag with specified name, default value, and usage string.
// The argument p points to a duration[] variable in which to store the value of the flag.
func DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
CommandLine.VarP(newDurationSliceValue(value, p), name, "", usage)
}
// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
func DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
CommandLine.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
}
// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a []time.Duration variable that stores the value of the flag.
func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
p := []time.Duration{}
f.DurationSliceVarP(&p, name, "", value, usage)
return &p
}
// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
p := []time.Duration{}
f.DurationSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a []time.Duration variable that stores the value of the flag.
func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
return CommandLine.DurationSliceP(name, "", value, usage)
}
// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
func DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
return CommandLine.DurationSliceP(name, shorthand, value, usage)
}

505
vendor/github.com/spf13/pflag/flag.go generated vendored
View file

@ -16,7 +16,7 @@ pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function pflag under the name "flag" then all code should continue to function
with no changes. with no changes.
import flag "github.com/ogier/pflag" import flag "github.com/spf13/pflag"
There is one exception to this: if you directly instantiate the Flag struct There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set. there is one more field "Shorthand" that you will need to set.
@ -101,6 +101,7 @@ package pflag
import ( import (
"bytes" "bytes"
"errors" "errors"
goflag "flag"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -123,6 +124,12 @@ const (
PanicOnError PanicOnError
) )
// ParseErrorsWhitelist defines the parsing errors that can be ignored
type ParseErrorsWhitelist struct {
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
UnknownFlags bool
}
// NormalizedName is a flag name that has been normalized according to rules // NormalizedName is a flag name that has been normalized according to rules
// for the FlagSet (e.g. making '-' and '_' equivalent). // for the FlagSet (e.g. making '-' and '_' equivalent).
type NormalizedName string type NormalizedName string
@ -134,18 +141,30 @@ type FlagSet struct {
// a custom error handler. // a custom error handler.
Usage func() Usage func()
// SortFlags is used to indicate, if user wants to have sorted flags in
// help/usage messages.
SortFlags bool
// ParseErrorsWhitelist is used to configure a whitelist of errors
ParseErrorsWhitelist ParseErrorsWhitelist
name string name string
parsed bool parsed bool
actual map[NormalizedName]*Flag actual map[NormalizedName]*Flag
orderedActual []*Flag
sortedActual []*Flag
formal map[NormalizedName]*Flag formal map[NormalizedName]*Flag
orderedFormal []*Flag
sortedFormal []*Flag
shorthands map[byte]*Flag shorthands map[byte]*Flag
args []string // arguments after flags args []string // arguments after flags
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
exitOnError bool // does the program exit if there's an error?
errorHandling ErrorHandling errorHandling ErrorHandling
output io.Writer // nil means stderr; use out() accessor output io.Writer // nil means stderr; use out() accessor
interspersed bool // allow interspersed option/non-option args interspersed bool // allow interspersed option/non-option args
normalizeNameFunc func(f *FlagSet, name string) NormalizedName normalizeNameFunc func(f *FlagSet, name string) NormalizedName
addedGoFlagSets []*goflag.FlagSet
} }
// A Flag represents the state of a flag. // A Flag represents the state of a flag.
@ -194,11 +213,19 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
// "--getUrl" which may also be translated to "geturl" and everything will work. // "--getUrl" which may also be translated to "geturl" and everything will work.
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
f.normalizeNameFunc = n f.normalizeNameFunc = n
for k, v := range f.formal { f.sortedFormal = f.sortedFormal[:0]
delete(f.formal, k) for fname, flag := range f.formal {
nname := f.normalizeFlagName(string(k)) nname := f.normalizeFlagName(flag.Name)
f.formal[nname] = v if fname == nname {
v.Name = string(nname) continue
}
flag.Name = string(nname)
delete(f.formal, fname)
f.formal[nname] = flag
if _, set := f.actual[fname]; set {
delete(f.actual, fname)
f.actual[nname] = flag
}
} }
} }
@ -229,46 +256,78 @@ func (f *FlagSet) SetOutput(output io.Writer) {
f.output = output f.output = output
} }
// VisitAll visits the flags in lexicographical order, calling fn for each. // VisitAll visits the flags in lexicographical order or
// in primordial order if f.SortFlags is false, calling fn for each.
// It visits all flags, even those not set. // It visits all flags, even those not set.
func (f *FlagSet) VisitAll(fn func(*Flag)) { func (f *FlagSet) VisitAll(fn func(*Flag)) {
for _, flag := range sortFlags(f.formal) { if len(f.formal) == 0 {
return
}
var flags []*Flag
if f.SortFlags {
if len(f.formal) != len(f.sortedFormal) {
f.sortedFormal = sortFlags(f.formal)
}
flags = f.sortedFormal
} else {
flags = f.orderedFormal
}
for _, flag := range flags {
fn(flag) fn(flag)
} }
} }
// HasFlags returns a bool to indicate if the FlagSet has any flags definied. // HasFlags returns a bool to indicate if the FlagSet has any flags defined.
func (f *FlagSet) HasFlags() bool { func (f *FlagSet) HasFlags() bool {
return len(f.formal) > 0 return len(f.formal) > 0
} }
// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags // HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
// definied that are not hidden or deprecated. // that are not hidden.
func (f *FlagSet) HasAvailableFlags() bool { func (f *FlagSet) HasAvailableFlags() bool {
for _, flag := range f.formal { for _, flag := range f.formal {
if !flag.Hidden && len(flag.Deprecated) == 0 { if !flag.Hidden {
return true return true
} }
} }
return false return false
} }
// VisitAll visits the command-line flags in lexicographical order, calling // VisitAll visits the command-line flags in lexicographical order or
// fn for each. It visits all flags, even those not set. // in primordial order if f.SortFlags is false, calling fn for each.
// It visits all flags, even those not set.
func VisitAll(fn func(*Flag)) { func VisitAll(fn func(*Flag)) {
CommandLine.VisitAll(fn) CommandLine.VisitAll(fn)
} }
// Visit visits the flags in lexicographical order, calling fn for each. // Visit visits the flags in lexicographical order or
// in primordial order if f.SortFlags is false, calling fn for each.
// It visits only those flags that have been set. // It visits only those flags that have been set.
func (f *FlagSet) Visit(fn func(*Flag)) { func (f *FlagSet) Visit(fn func(*Flag)) {
for _, flag := range sortFlags(f.actual) { if len(f.actual) == 0 {
return
}
var flags []*Flag
if f.SortFlags {
if len(f.actual) != len(f.sortedActual) {
f.sortedActual = sortFlags(f.actual)
}
flags = f.sortedActual
} else {
flags = f.orderedActual
}
for _, flag := range flags {
fn(flag) fn(flag)
} }
} }
// Visit visits the command-line flags in lexicographical order, calling fn // Visit visits the command-line flags in lexicographical order or
// for each. It visits only those flags that have been set. // in primordial order if f.SortFlags is false, calling fn for each.
// It visits only those flags that have been set.
func Visit(fn func(*Flag)) { func Visit(fn func(*Flag)) {
CommandLine.Visit(fn) CommandLine.Visit(fn)
} }
@ -278,6 +337,22 @@ func (f *FlagSet) Lookup(name string) *Flag {
return f.lookup(f.normalizeFlagName(name)) return f.lookup(f.normalizeFlagName(name))
} }
// ShorthandLookup returns the Flag structure of the short handed flag,
// returning nil if none exists.
// It panics, if len(name) > 1.
func (f *FlagSet) ShorthandLookup(name string) *Flag {
if name == "" {
return nil
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.out(), msg)
panic(msg)
}
c := name[0]
return f.shorthands[c]
}
// lookup returns the Flag structure of the named flag, returning nil if none exists. // lookup returns the Flag structure of the named flag, returning nil if none exists.
func (f *FlagSet) lookup(name NormalizedName) *Flag { func (f *FlagSet) lookup(name NormalizedName) *Flag {
return f.formal[name] return f.formal[name]
@ -319,10 +394,11 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
if flag == nil { if flag == nil {
return fmt.Errorf("flag %q does not exist", name) return fmt.Errorf("flag %q does not exist", name)
} }
if len(usageMessage) == 0 { if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name) return fmt.Errorf("deprecated message for flag %q must be set", name)
} }
flag.Deprecated = usageMessage flag.Deprecated = usageMessage
flag.Hidden = true
return nil return nil
} }
@ -334,7 +410,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
if flag == nil { if flag == nil {
return fmt.Errorf("flag %q does not exist", name) return fmt.Errorf("flag %q does not exist", name)
} }
if len(usageMessage) == 0 { if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name) return fmt.Errorf("deprecated message for flag %q must be set", name)
} }
flag.ShorthandDeprecated = usageMessage flag.ShorthandDeprecated = usageMessage
@ -358,6 +434,12 @@ func Lookup(name string) *Flag {
return CommandLine.Lookup(name) return CommandLine.Lookup(name)
} }
// ShorthandLookup returns the Flag structure of the short handed flag,
// returning nil if none exists.
func ShorthandLookup(name string) *Flag {
return CommandLine.ShorthandLookup(name)
}
// Set sets the value of the named flag. // Set sets the value of the named flag.
func (f *FlagSet) Set(name, value string) error { func (f *FlagSet) Set(name, value string) error {
normalName := f.normalizeFlagName(name) normalName := f.normalizeFlagName(name)
@ -365,17 +447,30 @@ func (f *FlagSet) Set(name, value string) error {
if !ok { if !ok {
return fmt.Errorf("no such flag -%v", name) return fmt.Errorf("no such flag -%v", name)
} }
err := flag.Value.Set(value) err := flag.Value.Set(value)
if err != nil { if err != nil {
return err var flagName string
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
} else {
flagName = fmt.Sprintf("--%s", flag.Name)
} }
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
}
if !flag.Changed {
if f.actual == nil { if f.actual == nil {
f.actual = make(map[NormalizedName]*Flag) f.actual = make(map[NormalizedName]*Flag)
} }
f.actual[normalName] = flag f.actual[normalName] = flag
f.orderedActual = append(f.orderedActual, flag)
flag.Changed = true flag.Changed = true
if len(flag.Deprecated) > 0 { }
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
if flag.Deprecated != "" {
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
} }
return nil return nil
} }
@ -416,13 +511,28 @@ func Set(name, value string) error {
// otherwise, the default values of all defined flags in the set. // otherwise, the default values of all defined flags in the set.
func (f *FlagSet) PrintDefaults() { func (f *FlagSet) PrintDefaults() {
usages := f.FlagUsages() usages := f.FlagUsages()
fmt.Fprintf(f.out(), "%s", usages) fmt.Fprint(f.out(), usages)
} }
// isZeroValue guesses whether the string represents the zero // defaultIsZeroValue returns true if the default value for this flag represents
// value for a flag. It is not accurate but in practice works OK. // a zero value.
func isZeroValue(value string) bool { func (f *Flag) defaultIsZeroValue() bool {
switch value { switch f.Value.(type) {
case boolFlag:
return f.DefValue == "false"
case *durationValue:
// Beginning in Go 1.7, duration zero values are "0s"
return f.DefValue == "0" || f.DefValue == "0s"
case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value:
return f.DefValue == "0"
case *stringValue:
return f.DefValue == ""
case *ipValue, *ipMaskValue, *ipNetValue:
return f.DefValue == "<nil>"
case *intSliceValue, *stringSliceValue, *stringArrayValue:
return f.DefValue == "[]"
default:
switch f.Value.String() {
case "false": case "false":
return true return true
case "<nil>": case "<nil>":
@ -434,6 +544,7 @@ func isZeroValue(value string) bool {
} }
return false return false
} }
}
// UnquoteUsage extracts a back-quoted name from the usage // UnquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage. // string for a flag and returns it and the un-quoted usage.
@ -455,57 +566,136 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
break // Only one back quote; use type name. break // Only one back quote; use type name.
} }
} }
// No explicit name, so use type if we can find one.
name = "value" name = flag.Value.Type()
switch flag.Value.(type) { switch name {
case boolFlag: case "bool":
name = "" name = ""
case *durationValue: case "float64":
name = "duration"
case *float64Value:
name = "float" name = "float"
case *intValue, *int64Value: case "int64":
name = "int" name = "int"
case *stringValue: case "uint64":
name = "string"
case *uintValue, *uint64Value:
name = "uint" name = "uint"
case "stringSlice":
name = "strings"
case "intSlice":
name = "ints"
case "uintSlice":
name = "uints"
case "boolSlice":
name = "bools"
} }
return return
} }
// FlagUsages Returns a string containing the usage information for all flags in // Splits the string `s` on whitespace into an initial substring up to
// the FlagSet // `i` runes in length and the remainder. Will go `slop` over `i` if
func (f *FlagSet) FlagUsages() string { // that encompasses the entire string (which allows the caller to
x := new(bytes.Buffer) // avoid short orphan words on the final line).
func wrapN(i, slop int, s string) (string, string) {
if i+slop > len(s) {
return s, ""
}
w := strings.LastIndexAny(s[:i], " \t\n")
if w <= 0 {
return s, ""
}
nlPos := strings.LastIndex(s[:i], "\n")
if nlPos > 0 && nlPos < w {
return s[:nlPos], s[nlPos+1:]
}
return s[:w], s[w+1:]
}
// Wraps the string `s` to a maximum width `w` with leading indent
// `i`. The first line is not indented (this is assumed to be done by
// caller). Pass `w` == 0 to do no wrapping
func wrap(i, w int, s string) string {
if w == 0 {
return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
}
// space between indent i and end of line width w into which
// we should wrap the text.
wrap := w - i
var r, l string
// Not enough space for sensible wrapping. Wrap as a block on
// the next line instead.
if wrap < 24 {
i = 16
wrap = w - i
r += "\n" + strings.Repeat(" ", i)
}
// If still not enough space then don't even try to wrap.
if wrap < 24 {
return strings.Replace(s, "\n", r, -1)
}
// Try to avoid short orphan words on the final line, by
// allowing wrapN to go a bit over if that would fit in the
// remainder of the line.
slop := 5
wrap = wrap - slop
// Handle first line, which is indented by the caller (or the
// special case above)
l, s = wrapN(wrap, slop, s)
r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
// Now wrap the rest
for s != "" {
var t string
t, s = wrapN(wrap, slop, s)
r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
}
return r
}
// FlagUsagesWrapped returns a string containing the usage information
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
// wrapping)
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
buf := new(bytes.Buffer)
lines := make([]string, 0, len(f.formal)) lines := make([]string, 0, len(f.formal))
maxlen := 0 maxlen := 0
f.VisitAll(func(flag *Flag) { f.VisitAll(func(flag *Flag) {
if len(flag.Deprecated) > 0 || flag.Hidden { if flag.Hidden {
return return
} }
line := "" line := ""
if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
} else { } else {
line = fmt.Sprintf(" --%s", flag.Name) line = fmt.Sprintf(" --%s", flag.Name)
} }
varname, usage := UnquoteUsage(flag) varname, usage := UnquoteUsage(flag)
if len(varname) > 0 { if varname != "" {
line += " " + varname line += " " + varname
} }
if len(flag.NoOptDefVal) > 0 { if flag.NoOptDefVal != "" {
switch flag.Value.Type() { switch flag.Value.Type() {
case "string": case "string":
line += fmt.Sprintf("[=%q]", flag.NoOptDefVal) line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
case "bool": case "bool":
if flag.NoOptDefVal != "true" { if flag.NoOptDefVal != "true" {
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
} }
case "count":
if flag.NoOptDefVal != "+1" {
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
}
default: default:
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
} }
@ -519,13 +709,16 @@ func (f *FlagSet) FlagUsages() string {
} }
line += usage line += usage
if !isZeroValue(flag.DefValue) { if !flag.defaultIsZeroValue() {
if flag.Value.Type() == "string" { if flag.Value.Type() == "string" {
line += fmt.Sprintf(" (default %q)", flag.DefValue) line += fmt.Sprintf(" (default %q)", flag.DefValue)
} else { } else {
line += fmt.Sprintf(" (default %s)", flag.DefValue) line += fmt.Sprintf(" (default %s)", flag.DefValue)
} }
} }
if len(flag.Deprecated) != 0 {
line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
}
lines = append(lines, line) lines = append(lines, line)
}) })
@ -533,10 +726,17 @@ func (f *FlagSet) FlagUsages() string {
for _, line := range lines { for _, line := range lines {
sidx := strings.Index(line, "\x00") sidx := strings.Index(line, "\x00")
spacing := strings.Repeat(" ", maxlen-sidx) spacing := strings.Repeat(" ", maxlen-sidx)
fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:]) // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
} }
return x.String() return buf.String()
}
// FlagUsages returns a string containing the usage information for all flags in
// the FlagSet
func (f *FlagSet) FlagUsages() string {
return f.FlagUsagesWrapped(0)
} }
// PrintDefaults prints to standard error the default values of all defined command-line flags. // PrintDefaults prints to standard error the default values of all defined command-line flags.
@ -622,16 +822,15 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. // VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
_ = f.VarPF(value, name, shorthand, usage) f.VarPF(value, name, shorthand, usage)
} }
// AddFlag will add the flag to the FlagSet // AddFlag will add the flag to the FlagSet
func (f *FlagSet) AddFlag(flag *Flag) { func (f *FlagSet) AddFlag(flag *Flag) {
// Call normalizeFlagName function only once
normalizedFlagName := f.normalizeFlagName(flag.Name) normalizedFlagName := f.normalizeFlagName(flag.Name)
_, alreadythere := f.formal[normalizedFlagName] _, alreadyThere := f.formal[normalizedFlagName]
if alreadythere { if alreadyThere {
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
fmt.Fprintln(f.out(), msg) fmt.Fprintln(f.out(), msg)
panic(msg) // Happens only if flags are declared with identical names panic(msg) // Happens only if flags are declared with identical names
@ -642,28 +841,31 @@ func (f *FlagSet) AddFlag(flag *Flag) {
flag.Name = string(normalizedFlagName) flag.Name = string(normalizedFlagName)
f.formal[normalizedFlagName] = flag f.formal[normalizedFlagName] = flag
f.orderedFormal = append(f.orderedFormal, flag)
if len(flag.Shorthand) == 0 { if flag.Shorthand == "" {
return return
} }
if len(flag.Shorthand) > 1 { if len(flag.Shorthand) > 1 {
fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand) msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
panic("shorthand is more than one character") fmt.Fprintf(f.out(), msg)
panic(msg)
} }
if f.shorthands == nil { if f.shorthands == nil {
f.shorthands = make(map[byte]*Flag) f.shorthands = make(map[byte]*Flag)
} }
c := flag.Shorthand[0] c := flag.Shorthand[0]
old, alreadythere := f.shorthands[c] used, alreadyThere := f.shorthands[c]
if alreadythere { if alreadyThere {
fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name) msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
panic("shorthand redefinition") fmt.Fprintf(f.out(), msg)
panic(msg)
} }
f.shorthands[c] = flag f.shorthands[c] = flag
} }
// AddFlagSet adds one FlagSet to another. If a flag is already present in f // AddFlagSet adds one FlagSet to another. If a flag is already present in f
// the flag from newSet will be ignored // the flag from newSet will be ignored.
func (f *FlagSet) AddFlagSet(newSet *FlagSet) { func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
if newSet == nil { if newSet == nil {
return return
@ -694,8 +896,10 @@ func VarP(value Value, name, shorthand, usage string) {
// returns the error. // returns the error.
func (f *FlagSet) failf(format string, a ...interface{}) error { func (f *FlagSet) failf(format string, a ...interface{}) error {
err := fmt.Errorf(format, a...) err := fmt.Errorf(format, a...)
if f.errorHandling != ContinueOnError {
fmt.Fprintln(f.out(), err) fmt.Fprintln(f.out(), err)
f.usage() f.usage()
}
return err return err
} }
@ -711,57 +915,61 @@ func (f *FlagSet) usage() {
} }
} }
func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error { //--unknown (args will be empty)
if err := flag.Value.Set(value); err != nil { //--unknown --next-flag ... (args will be --next-flag ...)
return f.failf("invalid argument %q for %s: %v", value, origArg, err) //--unknown arg ... (args will be arg ...)
} func stripUnknownFlagValue(args []string) []string {
// mark as visited for Visit() if len(args) == 0 {
if f.actual == nil { //--unknown
f.actual = make(map[NormalizedName]*Flag) return args
}
f.actual[f.normalizeFlagName(flag.Name)] = flag
flag.Changed = true
if len(flag.Deprecated) > 0 {
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
}
if len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) {
fmt.Fprintf(os.Stderr, "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
return nil
} }
func containsShorthand(arg, shorthand string) bool { first := args[0]
// filter out flags --<flag_name> if first[0] == '-' {
if strings.HasPrefix(arg, "-") { //--unknown --next-flag ...
return false return args
}
arg = strings.SplitN(arg, "=", 2)[0]
return strings.Contains(arg, shorthand)
} }
func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) { //--unknown arg ... (args will be arg ...)
return args[1:]
}
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
a = args a = args
name := s[2:] name := s[2:]
if len(name) == 0 || name[0] == '-' || name[0] == '=' { if len(name) == 0 || name[0] == '-' || name[0] == '=' {
err = f.failf("bad flag syntax: %s", s) err = f.failf("bad flag syntax: %s", s)
return return
} }
split := strings.SplitN(name, "=", 2) split := strings.SplitN(name, "=", 2)
name = split[0] name = split[0]
flag, alreadythere := f.formal[f.normalizeFlagName(name)] flag, exists := f.formal[f.normalizeFlagName(name)]
if !alreadythere {
if name == "help" { // special case for nice help message. if !exists {
switch {
case name == "help":
f.usage() f.usage()
return a, ErrHelp return a, ErrHelp
case f.ParseErrorsWhitelist.UnknownFlags:
// --unknown=unknownval arg ...
// we do not want to lose arg in this case
if len(split) >= 2 {
return a, nil
} }
return stripUnknownFlagValue(a), nil
default:
err = f.failf("unknown flag: --%s", name) err = f.failf("unknown flag: --%s", name)
return return
} }
}
var value string var value string
if len(split) == 2 { if len(split) == 2 {
// '--flag=arg' // '--flag=arg'
value = split[1] value = split[1]
} else if len(flag.NoOptDefVal) > 0 { } else if flag.NoOptDefVal != "" {
// '--flag' (arg was optional) // '--flag' (arg was optional)
value = flag.NoOptDefVal value = flag.NoOptDefVal
} else if len(a) > 0 { } else if len(a) > 0 {
@ -773,55 +981,86 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
err = f.failf("flag needs an argument: %s", s) err = f.failf("flag needs an argument: %s", s)
return return
} }
err = f.setFlag(flag, value, s)
err = fn(flag, value)
if err != nil {
f.failf(err.Error())
}
return return
} }
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
if strings.HasPrefix(shorthands, "test.") { if strings.HasPrefix(shorthands, "test.") {
return return
} }
outArgs = args outArgs = args
outShorts = shorthands[1:] outShorts = shorthands[1:]
c := shorthands[0] c := shorthands[0]
flag, alreadythere := f.shorthands[c] flag, exists := f.shorthands[c]
if !alreadythere { if !exists {
if c == 'h' { // special case for nice help message. switch {
case c == 'h':
f.usage() f.usage()
err = ErrHelp err = ErrHelp
return return
case f.ParseErrorsWhitelist.UnknownFlags:
// '-f=arg arg ...'
// we do not want to lose arg in this case
if len(shorthands) > 2 && shorthands[1] == '=' {
outShorts = ""
return
} }
//TODO continue on error
outArgs = stripUnknownFlagValue(outArgs)
return
default:
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
return return
} }
}
var value string var value string
if len(shorthands) > 2 && shorthands[1] == '=' { if len(shorthands) > 2 && shorthands[1] == '=' {
// '-f=arg'
value = shorthands[2:] value = shorthands[2:]
outShorts = "" outShorts = ""
} else if len(flag.NoOptDefVal) > 0 { } else if flag.NoOptDefVal != "" {
// '-f' (arg was optional)
value = flag.NoOptDefVal value = flag.NoOptDefVal
} else if len(shorthands) > 1 { } else if len(shorthands) > 1 {
// '-farg'
value = shorthands[1:] value = shorthands[1:]
outShorts = "" outShorts = ""
} else if len(args) > 0 { } else if len(args) > 0 {
// '-f arg'
value = args[0] value = args[0]
outArgs = args[1:] outArgs = args[1:]
} else { } else {
// '-f' (arg was required)
err = f.failf("flag needs an argument: %q in -%s", c, shorthands) err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
return return
} }
err = f.setFlag(flag, value, shorthands)
if flag.ShorthandDeprecated != "" {
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
err = fn(flag, value)
if err != nil {
f.failf(err.Error())
}
return return
} }
func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
a = args a = args
shorthands := s[1:] shorthands := s[1:]
// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
for len(shorthands) > 0 { for len(shorthands) > 0 {
shorthands, a, err = f.parseSingleShortArg(shorthands, args) shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
if err != nil { if err != nil {
return return
} }
@ -830,7 +1069,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
return return
} }
func (f *FlagSet) parseArgs(args []string) (err error) { func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
for len(args) > 0 { for len(args) > 0 {
s := args[0] s := args[0]
args = args[1:] args = args[1:]
@ -850,9 +1089,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
f.args = append(f.args, args...) f.args = append(f.args, args...)
break break
} }
args, err = f.parseLongArg(s, args) args, err = f.parseLongArg(s, args, fn)
} else { } else {
args, err = f.parseShortArg(s, args) args, err = f.parseShortArg(s, args, fn)
} }
if err != nil { if err != nil {
return return
@ -866,9 +1105,50 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
// are defined and before flags are accessed by the program. // are defined and before flags are accessed by the program.
// The return value will be ErrHelp if -help was set but not defined. // The return value will be ErrHelp if -help was set but not defined.
func (f *FlagSet) Parse(arguments []string) error { func (f *FlagSet) Parse(arguments []string) error {
if f.addedGoFlagSets != nil {
for _, goFlagSet := range f.addedGoFlagSets {
goFlagSet.Parse(nil)
}
}
f.parsed = true
if len(arguments) < 0 {
return nil
}
f.args = make([]string, 0, len(arguments))
set := func(flag *Flag, value string) error {
return f.Set(flag.Name, value)
}
err := f.parseArgs(arguments, set)
if err != nil {
switch f.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
fmt.Println(err)
os.Exit(2)
case PanicOnError:
panic(err)
}
}
return nil
}
type parseFunc func(flag *Flag, value string) error
// ParseAll parses flag definitions from the argument list, which should not
// include the command name. The arguments for fn are flag and value. Must be
// called after all flags in the FlagSet are defined and before flags are
// accessed by the program. The return value will be ErrHelp if -help was set
// but not defined.
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
f.parsed = true f.parsed = true
f.args = make([]string, 0, len(arguments)) f.args = make([]string, 0, len(arguments))
err := f.parseArgs(arguments)
err := f.parseArgs(arguments, fn)
if err != nil { if err != nil {
switch f.errorHandling { switch f.errorHandling {
case ContinueOnError: case ContinueOnError:
@ -894,6 +1174,14 @@ func Parse() {
CommandLine.Parse(os.Args[1:]) CommandLine.Parse(os.Args[1:])
} }
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
// The arguments for fn are flag and value. Must be called after all flags are
// defined and before flags are accessed by the program.
func ParseAll(fn func(flag *Flag, value string) error) {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.ParseAll(os.Args[1:], fn)
}
// SetInterspersed sets whether to support interspersed option/non-option arguments. // SetInterspersed sets whether to support interspersed option/non-option arguments.
func SetInterspersed(interspersed bool) { func SetInterspersed(interspersed bool) {
CommandLine.SetInterspersed(interspersed) CommandLine.SetInterspersed(interspersed)
@ -907,14 +1195,15 @@ func Parsed() bool {
// CommandLine is the default set of command-line flags, parsed from os.Args. // CommandLine is the default set of command-line flags, parsed from os.Args.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError) var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
// NewFlagSet returns a new, empty flag set with the specified name and // NewFlagSet returns a new, empty flag set with the specified name,
// error handling property. // error handling property and SortFlags set to true.
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{ f := &FlagSet{
name: name, name: name,
errorHandling: errorHandling, errorHandling: errorHandling,
argsLenAtDash: -1, argsLenAtDash: -1,
interspersed: true, interspersed: true,
SortFlags: true,
} }
return f return f
} }

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- float32 Value // -- float32 Value
type float32Value float32 type float32Value float32
@ -23,7 +20,7 @@ func (f *float32Value) Type() string {
return "float32" return "float32"
} }
func (f *float32Value) String() string { return fmt.Sprintf("%v", *f) } func (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) }
func float32Conv(sval string) (interface{}, error) { func float32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseFloat(sval, 32) v, err := strconv.ParseFloat(sval, 32)

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- float64 Value // -- float64 Value
type float64Value float64 type float64Value float64
@ -23,7 +20,7 @@ func (f *float64Value) Type() string {
return "float64" return "float64"
} }
func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
func float64Conv(sval string) (interface{}, error) { func float64Conv(sval string) (interface{}, error) {
return strconv.ParseFloat(sval, 64) return strconv.ParseFloat(sval, 64)

View file

@ -6,13 +6,10 @@ package pflag
import ( import (
goflag "flag" goflag "flag"
"fmt"
"reflect" "reflect"
"strings" "strings"
) )
var _ = fmt.Print
// flagValueWrapper implements pflag.Value around a flag.Value. The main // flagValueWrapper implements pflag.Value around a flag.Value. The main
// difference here is the addition of the Type method that returns a string // difference here is the addition of the Type method that returns a string
// name of the type. As this is generally unknown, we approximate that with // name of the type. As this is generally unknown, we approximate that with
@ -101,4 +98,8 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
newSet.VisitAll(func(goflag *goflag.Flag) { newSet.VisitAll(func(goflag *goflag.Flag) {
f.AddGoFlag(goflag) f.AddGoFlag(goflag)
}) })
if f.addedGoFlagSets == nil {
f.addedGoFlagSets = make([]*goflag.FlagSet, 0)
}
f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
} }

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- int Value // -- int Value
type intValue int type intValue int
@ -23,7 +20,7 @@ func (i *intValue) Type() string {
return "int" return "int"
} }
func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
func intConv(sval string) (interface{}, error) { func intConv(sval string) (interface{}, error) {
return strconv.Atoi(sval) return strconv.Atoi(sval)

88
vendor/github.com/spf13/pflag/int16.go generated vendored Normal file
View file

@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- int16 Value
type int16Value int16
func newInt16Value(val int16, p *int16) *int16Value {
*p = val
return (*int16Value)(p)
}
func (i *int16Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 16)
*i = int16Value(v)
return err
}
func (i *int16Value) Type() string {
return "int16"
}
func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int16Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 16)
if err != nil {
return 0, err
}
return int16(v), nil
}
// GetInt16 returns the int16 value of a flag with the given name
func (f *FlagSet) GetInt16(name string) (int16, error) {
val, err := f.getFlagType(name, "int16", int16Conv)
if err != nil {
return 0, err
}
return val.(int16), nil
}
// Int16Var defines an int16 flag with specified name, default value, and usage string.
// The argument p points to an int16 variable in which to store the value of the flag.
func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) {
f.VarP(newInt16Value(value, p), name, "", usage)
}
// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
f.VarP(newInt16Value(value, p), name, shorthand, usage)
}
// Int16Var defines an int16 flag with specified name, default value, and usage string.
// The argument p points to an int16 variable in which to store the value of the flag.
func Int16Var(p *int16, name string, value int16, usage string) {
CommandLine.VarP(newInt16Value(value, p), name, "", usage)
}
// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
func Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage)
}
// Int16 defines an int16 flag with specified name, default value, and usage string.
// The return value is the address of an int16 variable that stores the value of the flag.
func (f *FlagSet) Int16(name string, value int16, usage string) *int16 {
p := new(int16)
f.Int16VarP(p, name, "", value, usage)
return p
}
// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 {
p := new(int16)
f.Int16VarP(p, name, shorthand, value, usage)
return p
}
// Int16 defines an int16 flag with specified name, default value, and usage string.
// The return value is the address of an int16 variable that stores the value of the flag.
func Int16(name string, value int16, usage string) *int16 {
return CommandLine.Int16P(name, "", value, usage)
}
// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
func Int16P(name, shorthand string, value int16, usage string) *int16 {
return CommandLine.Int16P(name, shorthand, value, usage)
}

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- int32 Value // -- int32 Value
type int32Value int32 type int32Value int32
@ -23,7 +20,7 @@ func (i *int32Value) Type() string {
return "int32" return "int32"
} }
func (i *int32Value) String() string { return fmt.Sprintf("%v", *i) } func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int32Conv(sval string) (interface{}, error) { func int32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 32) v, err := strconv.ParseInt(sval, 0, 32)

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- int64 Value // -- int64 Value
type int64Value int64 type int64Value int64
@ -23,7 +20,7 @@ func (i *int64Value) Type() string {
return "int64" return "int64"
} }
func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int64Conv(sval string) (interface{}, error) { func int64Conv(sval string) (interface{}, error) {
return strconv.ParseInt(sval, 0, 64) return strconv.ParseInt(sval, 0, 64)

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- int8 Value // -- int8 Value
type int8Value int8 type int8Value int8
@ -23,7 +20,7 @@ func (i *int8Value) Type() string {
return "int8" return "int8"
} }
func (i *int8Value) String() string { return fmt.Sprintf("%v", *i) } func (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int8Conv(sval string) (interface{}, error) { func int8Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 8) v, err := strconv.ParseInt(sval, 0, 8)

View file

@ -6,8 +6,6 @@ import (
"strings" "strings"
) )
var _ = strings.TrimSpace
// -- net.IP value // -- net.IP value
type ipValue net.IP type ipValue net.IP

148
vendor/github.com/spf13/pflag/ip_slice.go generated vendored Normal file
View file

@ -0,0 +1,148 @@
package pflag
import (
"fmt"
"io"
"net"
"strings"
)
// -- ipSlice Value
type ipSliceValue struct {
value *[]net.IP
changed bool
}
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
ipsv := new(ipSliceValue)
ipsv.value = p
*ipsv.value = val
return ipsv
}
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
func (s *ipSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse ip values into slice
out := make([]net.IP, 0, len(ipStrSlice))
for _, ipStr := range ipStrSlice {
ip := net.ParseIP(strings.TrimSpace(ipStr))
if ip == nil {
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
}
out = append(out, ip)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *ipSliceValue) Type() string {
return "ipSlice"
}
// String defines a "native" format for this net.IP slice flag value.
func (s *ipSliceValue) String() string {
ipStrSlice := make([]string, len(*s.value))
for i, ip := range *s.value {
ipStrSlice[i] = ip.String()
}
out, _ := writeAsCSV(ipStrSlice)
return "[" + out + "]"
}
func ipSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Emtpy string would cause a slice with one (empty) entry
if len(val) == 0 {
return []net.IP{}, nil
}
ss := strings.Split(val, ",")
out := make([]net.IP, len(ss))
for i, sval := range ss {
ip := net.ParseIP(strings.TrimSpace(sval))
if ip == nil {
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
}
out[i] = ip
}
return out, nil
}
// GetIPSlice returns the []net.IP value of a flag with the given name
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
if err != nil {
return []net.IP{}, err
}
return val.([]net.IP), nil
}
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of that flag.
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, "", value, usage)
return &p
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of the flag.
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, "", value, usage)
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, shorthand, value, usage)
}

View file

@ -27,8 +27,6 @@ func (*ipNetValue) Type() string {
return "ipNet" return "ipNet"
} }
var _ = strings.TrimSpace
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
*p = val *p = val
return (*ipNetValue)(p) return (*ipNetValue)(p)

View file

@ -1,7 +1,5 @@
package pflag package pflag
import "fmt"
// -- string Value // -- string Value
type stringValue string type stringValue string
@ -18,7 +16,7 @@ func (s *stringValue) Type() string {
return "string" return "string"
} }
func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } func (s *stringValue) String() string { return string(*s) }
func stringConv(sval string) (interface{}, error) { func stringConv(sval string) (interface{}, error) {
return sval, nil return sval, nil

103
vendor/github.com/spf13/pflag/string_array.go generated vendored Normal file
View file

@ -0,0 +1,103 @@
package pflag
// -- stringArray Value
type stringArrayValue struct {
value *[]string
changed bool
}
func newStringArrayValue(val []string, p *[]string) *stringArrayValue {
ssv := new(stringArrayValue)
ssv.value = p
*ssv.value = val
return ssv
}
func (s *stringArrayValue) Set(val string) error {
if !s.changed {
*s.value = []string{val}
s.changed = true
} else {
*s.value = append(*s.value, val)
}
return nil
}
func (s *stringArrayValue) Type() string {
return "stringArray"
}
func (s *stringArrayValue) String() string {
str, _ := writeAsCSV(*s.value)
return "[" + str + "]"
}
func stringArrayConv(sval string) (interface{}, error) {
sval = sval[1 : len(sval)-1]
// An empty string would cause a array with one (empty) string
if len(sval) == 0 {
return []string{}, nil
}
return readAsCSV(sval)
}
// GetStringArray return the []string value of a flag with the given name
func (f *FlagSet) GetStringArray(name string) ([]string, error) {
val, err := f.getFlagType(name, "stringArray", stringArrayConv)
if err != nil {
return []string{}, err
}
return val.([]string), nil
}
// StringArrayVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
f.VarP(newStringArrayValue(value, p), name, "", usage)
}
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
f.VarP(newStringArrayValue(value, p), name, shorthand, usage)
}
// StringArrayVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
func StringArrayVar(p *[]string, name string, value []string, usage string) {
CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
}
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage)
}
// StringArray defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
p := []string{}
f.StringArrayVarP(&p, name, "", value, usage)
return &p
}
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string {
p := []string{}
f.StringArrayVarP(&p, name, shorthand, value, usage)
return &p
}
// StringArray defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
func StringArray(name string, value []string, usage string) *[]string {
return CommandLine.StringArrayP(name, "", value, usage)
}
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
func StringArrayP(name, shorthand string, value []string, usage string) *[]string {
return CommandLine.StringArrayP(name, shorthand, value, usage)
}

View file

@ -1,13 +1,11 @@
package pflag package pflag
import ( import (
"bytes"
"encoding/csv" "encoding/csv"
"fmt"
"strings" "strings"
) )
var _ = fmt.Fprint
// -- stringSlice Value // -- stringSlice Value
type stringSliceValue struct { type stringSliceValue struct {
value *[]string value *[]string
@ -21,10 +19,28 @@ func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
return ssv return ssv
} }
func (s *stringSliceValue) Set(val string) error { func readAsCSV(val string) ([]string, error) {
if val == "" {
return []string{}, nil
}
stringReader := strings.NewReader(val) stringReader := strings.NewReader(val)
csvReader := csv.NewReader(stringReader) csvReader := csv.NewReader(stringReader)
v, err := csvReader.Read() return csvReader.Read()
}
func writeAsCSV(vals []string) (string, error) {
b := &bytes.Buffer{}
w := csv.NewWriter(b)
err := w.Write(vals)
if err != nil {
return "", err
}
w.Flush()
return strings.TrimSuffix(b.String(), "\n"), nil
}
func (s *stringSliceValue) Set(val string) error {
v, err := readAsCSV(val)
if err != nil { if err != nil {
return err return err
} }
@ -41,16 +57,18 @@ func (s *stringSliceValue) Type() string {
return "stringSlice" return "stringSlice"
} }
func (s *stringSliceValue) String() string { return "[" + strings.Join(*s.value, ",") + "]" } func (s *stringSliceValue) String() string {
str, _ := writeAsCSV(*s.value)
return "[" + str + "]"
}
func stringSliceConv(sval string) (interface{}, error) { func stringSliceConv(sval string) (interface{}, error) {
sval = strings.Trim(sval, "[]") sval = sval[1 : len(sval)-1]
// An empty string would cause a slice with one (empty) string // An empty string would cause a slice with one (empty) string
if len(sval) == 0 { if len(sval) == 0 {
return []string{}, nil return []string{}, nil
} }
v := strings.Split(sval, ",") return readAsCSV(sval)
return v, nil
} }
// GetStringSlice return the []string value of a flag with the given name // GetStringSlice return the []string value of a flag with the given name
@ -64,6 +82,11 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
// StringSliceVar defines a string flag with specified name, default value, and usage string. // StringSliceVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag. // The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" -ss="v3"
// will result in
// []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
f.VarP(newStringSliceValue(value, p), name, "", usage) f.VarP(newStringSliceValue(value, p), name, "", usage)
} }
@ -75,6 +98,11 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
// StringSliceVar defines a string flag with specified name, default value, and usage string. // StringSliceVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag. // The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" -ss="v3"
// will result in
// []string{"v1", "v2", "v3"}
func StringSliceVar(p *[]string, name string, value []string, usage string) { func StringSliceVar(p *[]string, name string, value []string, usage string) {
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage) CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
} }
@ -86,6 +114,11 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
// StringSlice defines a string flag with specified name, default value, and usage string. // StringSlice defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag. // The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" -ss="v3"
// will result in
// []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
p := []string{} p := []string{}
f.StringSliceVarP(&p, name, "", value, usage) f.StringSliceVarP(&p, name, "", value, usage)
@ -101,6 +134,11 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
// StringSlice defines a string flag with specified name, default value, and usage string. // StringSlice defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag. // The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" -ss="v3"
// will result in
// []string{"v1", "v2", "v3"}
func StringSlice(name string, value []string, usage string) *[]string { func StringSlice(name string, value []string, usage string) *[]string {
return CommandLine.StringSliceP(name, "", value, usage) return CommandLine.StringSliceP(name, "", value, usage)
} }

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- uint Value // -- uint Value
type uintValue uint type uintValue uint
@ -23,7 +20,7 @@ func (i *uintValue) Type() string {
return "uint" return "uint"
} }
func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uintConv(sval string) (interface{}, error) { func uintConv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 0) v, err := strconv.ParseUint(sval, 0, 0)

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- uint16 value // -- uint16 value
type uint16Value uint16 type uint16Value uint16
@ -12,7 +9,7 @@ func newUint16Value(val uint16, p *uint16) *uint16Value {
*p = val *p = val
return (*uint16Value)(p) return (*uint16Value)(p)
} }
func (i *uint16Value) String() string { return fmt.Sprintf("%d", *i) }
func (i *uint16Value) Set(s string) error { func (i *uint16Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 16) v, err := strconv.ParseUint(s, 0, 16)
*i = uint16Value(v) *i = uint16Value(v)
@ -23,6 +20,8 @@ func (i *uint16Value) Type() string {
return "uint16" return "uint16"
} }
func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint16Conv(sval string) (interface{}, error) { func uint16Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 16) v, err := strconv.ParseUint(sval, 0, 16)
if err != nil { if err != nil {

View file

@ -1,18 +1,15 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- uint16 value // -- uint32 value
type uint32Value uint32 type uint32Value uint32
func newUint32Value(val uint32, p *uint32) *uint32Value { func newUint32Value(val uint32, p *uint32) *uint32Value {
*p = val *p = val
return (*uint32Value)(p) return (*uint32Value)(p)
} }
func (i *uint32Value) String() string { return fmt.Sprintf("%d", *i) }
func (i *uint32Value) Set(s string) error { func (i *uint32Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 32) v, err := strconv.ParseUint(s, 0, 32)
*i = uint32Value(v) *i = uint32Value(v)
@ -23,6 +20,8 @@ func (i *uint32Value) Type() string {
return "uint32" return "uint32"
} }
func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint32Conv(sval string) (interface{}, error) { func uint32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 32) v, err := strconv.ParseUint(sval, 0, 32)
if err != nil { if err != nil {

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- uint64 Value // -- uint64 Value
type uint64Value uint64 type uint64Value uint64
@ -23,7 +20,7 @@ func (i *uint64Value) Type() string {
return "uint64" return "uint64"
} }
func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint64Conv(sval string) (interface{}, error) { func uint64Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 64) v, err := strconv.ParseUint(sval, 0, 64)

View file

@ -1,9 +1,6 @@
package pflag package pflag
import ( import "strconv"
"fmt"
"strconv"
)
// -- uint8 Value // -- uint8 Value
type uint8Value uint8 type uint8Value uint8
@ -23,7 +20,7 @@ func (i *uint8Value) Type() string {
return "uint8" return "uint8"
} }
func (i *uint8Value) String() string { return fmt.Sprintf("%v", *i) } func (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint8Conv(sval string) (interface{}, error) { func uint8Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 8) v, err := strconv.ParseUint(sval, 0, 8)

126
vendor/github.com/spf13/pflag/uint_slice.go generated vendored Normal file
View file

@ -0,0 +1,126 @@
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- uintSlice Value
type uintSliceValue struct {
value *[]uint
changed bool
}
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
uisv := new(uintSliceValue)
uisv.value = p
*uisv.value = val
return uisv
}
func (s *uintSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return err
}
out[i] = uint(u)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *uintSliceValue) Type() string {
return "uintSlice"
}
func (s *uintSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func uintSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []uint{}, nil
}
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return nil, err
}
out[i] = uint(u)
}
return out, nil
}
// GetUintSlice returns the []uint value of a flag with the given name.
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
if err != nil {
return []uint{}, err
}
return val.([]uint), nil
}
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
// The argument p points to a []uint variable in which to store the value of the flag.
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
// The argument p points to a uint[] variable in which to store the value of the flag.
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, "", value, usage)
return &p
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func UintSlice(name string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, "", value, usage)
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, shorthand, value, usage)
}

201
vendor/gopkg.in/validator.v2/LICENSE generated vendored Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

271
vendor/gopkg.in/validator.v2/builtins.go generated vendored Normal file
View file

@ -0,0 +1,271 @@
// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
"reflect"
"regexp"
"strconv"
)
// nonzero tests whether a variable value non-zero
// as defined by the golang spec.
func nonzero(v interface{}, param string) error {
st := reflect.ValueOf(v)
valid := true
switch st.Kind() {
case reflect.String:
valid = len(st.String()) != 0
case reflect.Ptr, reflect.Interface:
valid = !st.IsNil()
case reflect.Slice, reflect.Map, reflect.Array:
valid = st.Len() != 0
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valid = st.Int() != 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
valid = st.Uint() != 0
case reflect.Float32, reflect.Float64:
valid = st.Float() != 0
case reflect.Bool:
valid = st.Bool()
case reflect.Invalid:
valid = false // always invalid
case reflect.Struct:
valid = true // always valid since only nil pointers are empty
default:
return ErrUnsupported
}
if !valid {
return ErrZeroValue
}
return nil
}
// length tests whether a variable's length is equal to a given
// value. For strings it tests the number of characters whereas
// for maps and slices it tests the number of items.
func length(v interface{}, param string) error {
st := reflect.ValueOf(v)
valid := true
if st.Kind() == reflect.Ptr {
if st.IsNil() {
return nil
}
st = st.Elem()
}
switch st.Kind() {
case reflect.String:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
valid = int64(len(st.String())) == p
case reflect.Slice, reflect.Map, reflect.Array:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
valid = int64(st.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
valid = st.Int() == p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p, err := asUint(param)
if err != nil {
return ErrBadParameter
}
valid = st.Uint() == p
case reflect.Float32, reflect.Float64:
p, err := asFloat(param)
if err != nil {
return ErrBadParameter
}
valid = st.Float() == p
default:
return ErrUnsupported
}
if !valid {
return ErrLen
}
return nil
}
// min tests whether a variable value is larger or equal to a given
// number. For number types, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func min(v interface{}, param string) error {
st := reflect.ValueOf(v)
invalid := false
if st.Kind() == reflect.Ptr {
if st.IsNil() {
return nil
}
st = st.Elem()
}
switch st.Kind() {
case reflect.String:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = int64(len(st.String())) < p
case reflect.Slice, reflect.Map, reflect.Array:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = int64(st.Len()) < p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Int() < p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p, err := asUint(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Uint() < p
case reflect.Float32, reflect.Float64:
p, err := asFloat(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Float() < p
default:
return ErrUnsupported
}
if invalid {
return ErrMin
}
return nil
}
// max tests whether a variable value is lesser than a given
// value. For numbers, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func max(v interface{}, param string) error {
st := reflect.ValueOf(v)
var invalid bool
if st.Kind() == reflect.Ptr {
if st.IsNil() {
return nil
}
st = st.Elem()
}
switch st.Kind() {
case reflect.String:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = int64(len(st.String())) > p
case reflect.Slice, reflect.Map, reflect.Array:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = int64(st.Len()) > p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p, err := asInt(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Int() > p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p, err := asUint(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Uint() > p
case reflect.Float32, reflect.Float64:
p, err := asFloat(param)
if err != nil {
return ErrBadParameter
}
invalid = st.Float() > p
default:
return ErrUnsupported
}
if invalid {
return ErrMax
}
return nil
}
// regex is the builtin validation function that checks
// whether the string variable matches a regular expression
func regex(v interface{}, param string) error {
s, ok := v.(string)
if !ok {
sptr, ok := v.(*string)
if !ok {
return ErrUnsupported
}
if sptr == nil {
return nil
}
s = *sptr
}
re, err := regexp.Compile(param)
if err != nil {
return ErrBadParameter
}
if !re.MatchString(s) {
return ErrRegexp
}
return nil
}
// asInt retuns the parameter as a int64
// or panics if it can't convert
func asInt(param string) (int64, error) {
i, err := strconv.ParseInt(param, 0, 64)
if err != nil {
return 0, ErrBadParameter
}
return i, nil
}
// asUint retuns the parameter as a uint64
// or panics if it can't convert
func asUint(param string) (uint64, error) {
i, err := strconv.ParseUint(param, 0, 64)
if err != nil {
return 0, ErrBadParameter
}
return i, nil
}
// asFloat retuns the parameter as a float64
// or panics if it can't convert
func asFloat(param string) (float64, error) {
i, err := strconv.ParseFloat(param, 64)
if err != nil {
return 0.0, ErrBadParameter
}
return i, nil
}

265
vendor/gopkg.in/validator.v2/doc.go generated vendored Normal file
View file

@ -0,0 +1,265 @@
// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package validator implements value validations based on struct tags.
In code it is often necessary to validate that a given value is valid before
using it for something. A typical example might be something like this.
if age < 18 {
return error.New("age cannot be under 18")
}
This is a simple enough example, but it can get significantly more complex,
especially when dealing with structs.
l := len(strings.Trim(s.Username))
if l < 3 || l > 40 || !regexp.MatchString("^[a-zA-Z]$", s.Username) || s.Age < 18 || s.Password {
return errors.New("Invalid request")
}
You get the idea. Package validator allows one to define valid values as
struct tags when defining a new struct type.
type NewUserRequest struct {
Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]*$"`
Name string `validate:"nonzero"`
Age int `validate:"min=18"`
Password string `validate:"min=8"`
}
Then validating a variable of type NewUserRequest becomes trivial.
nur := NewUserRequest{Username: "something", ...}
if errs := validator.Validate(nur); errs != nil {
// do something
}
Builtin validator functions
Here is the list of validator functions builtin in the package.
len
For numeric numbers, len will simply make sure that the value is
equal to the parameter given. For strings, it checks that
the string length is exactly that number of characters. For slices,
arrays, and maps, validates the number of items. (Usage: len=10)
max
For numeric numbers, max will simply make sure that the value is
lesser or equal to the parameter given. For strings, it checks that
the string length is at most that number of characters. For slices,
arrays, and maps, validates the number of items. (Usage: max=10)
min
For numeric numbers, min will simply make sure that the value is
greater or equal to the parameter given. For strings, it checks that
the string length is at least that number of characters. For slices,
arrays, and maps, validates the number of items. (Usage: min=10)
nonzero
This validates that the value is not zero. The appropriate zero value
is given by the Go spec (e.g. for int it's 0, for string it's "", for
pointers is nil, etc.) Usage: nonzero
regexp
Only valid for string types, it will validate that the value matches
the regular expression provided as parameter. (Usage: regexp=^a.*b$)
Note that there are no tests to prevent conflicting validator parameters. For
instance, these fields will never be valid.
...
A int `validate:"max=0,min=1"`
B string `validate:"len=10,regexp=^$"
...
Custom validation functions
It is possible to define custom validation functions by using SetValidationFunc.
First, one needs to create a validation function.
// Very simple validation func
func notZZ(v interface{}, param string) error {
st := reflect.ValueOf(v)
if st.Kind() != reflect.String {
return validate.ErrUnsupported
}
if st.String() == "ZZ" {
return errors.New("value cannot be ZZ")
}
return nil
}
Then one needs to add it to the list of validation funcs and give it a "tag" name.
validate.SetValidationFunc("notzz", notZZ)
Then it is possible to use the notzz validation tag. This will print
"Field A error: value cannot be ZZ"
type T struct {
A string `validate:"nonzero,notzz"`
}
t := T{"ZZ"}
if errs := validator.Validate(t); errs != nil {
fmt.Printf("Field A error: %s\n", errs["A"][0])
}
To use parameters, it is very similar.
// Very simple validator with parameter
func notSomething(v interface{}, param string) error {
st := reflect.ValueOf(v)
if st.Kind() != reflect.String {
return validate.ErrUnsupported
}
if st.String() == param {
return errors.New("value cannot be " + param)
}
return nil
}
And then the code below should print "Field A error: value cannot be ABC".
validator.SetValidationFunc("notsomething", notSomething)
type T struct {
A string `validate:"notsomething=ABC"`
}
t := T{"ABC"}
if errs := validator.Validate(t); errs != nil {
fmt.Printf("Field A error: %s\n", errs["A"][0])
}
As well, it is possible to overwrite builtin validation functions.
validate.SetValidationFunc("min", myMinFunc)
And you can delete a validation function by setting it to nil.
validate.SetValidationFunc("notzz", nil)
validate.SetValidationFunc("nonzero", nil)
Using a non-existing validation func in a field tag will always return
false and with error validate.ErrUnknownTag.
Finally, package validator also provides a helper function that can be used
to validate simple variables/values.
// errs: nil
errs = validator.Valid(42, "min=10, max=50")
// errs: [validate.ErrZeroValue]
errs = validator.Valid(nil, "nonzero")
// errs: [validate.ErrMin,validate.ErrMax]
errs = validator.Valid("hi", "nonzero,min=3,max=2")
Custom tag name
In case there is a reason why one would not wish to use tag 'validate' (maybe due to
a conflict with a different package), it is possible to tell the package to use
a different tag.
validator.SetTag("valid")
Then.
Type T struct {
A int `valid:"min=8, max=10"`
B string `valid:"nonzero"`
}
SetTag is permanent. The new tag name will be used until it is again changed
with a new call to SetTag. A way to temporarily use a different tag exists.
validator.WithTag("foo").Validate(t)
validator.WithTag("bar").Validate(t)
// But this will go back to using 'validate'
validator.Validate(t)
Multiple validators
You may often need to have a different set of validation
rules for different situations. In all the examples above,
we only used the default validator but you could create a
new one and set specific rules for it.
For instance, you might use the same struct to decode incoming JSON for a REST API
but your needs will change when you're using it to, say, create a new instance
in storage vs. when you need to change something.
type User struct {
Username string `validate:"nonzero"`
Name string `validate:"nonzero"`
Age int `validate:"nonzero"`
Password string `validate:"nonzero"`
}
Maybe when creating a new user, you need to make sure all values in the struct are filled,
but then you use the same struct to handle incoming requests to, say, change the password,
in which case you only need the Username and the Password and don't care for the others.
You might use two different validators.
type User struct {
Username string `creating:"nonzero" chgpw:"nonzero"`
Name string `creating:"nonzero"`
Age int `creating:"nonzero"`
Password string `creating:"nonzero" chgpw:"nonzero"`
}
var (
creationValidator = validator.NewValidator()
chgPwValidator = validator.NewValidator()
)
func init() {
creationValidator.SetTag("creating")
chgPwValidator.SetTag("chgpw")
}
...
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
var u User
json.NewDecoder(r.Body).Decode(&user)
if errs := creationValidator.Validate(user); errs != nil {
// the request did not include all of the User
// struct fields, so send a http.StatusBadRequest
// back or something
}
// create the new user
}
func SetNewUserPasswordHandler(w http.ResponseWriter, r *http.Request) {
var u User
json.NewDecoder(r.Body).Decode(&user)
if errs := chgPwValidator.Validate(user); errs != nil {
// the request did not Username and Password,
// so send a http.StatusBadRequest
// back or something
}
// save the new password
}
It is also possible to do all of that using only the default validator as long
as SetTag is always called before calling validator.Validate() or you chain the
with WithTag().
*/
package validator

369
vendor/gopkg.in/validator.v2/validator.go generated vendored Normal file
View file

@ -0,0 +1,369 @@
// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
"unicode"
)
// TextErr is an error that also implements the TextMarshaller interface for
// serializing out to various plain text encodings. Packages creating their
// own custom errors should use TextErr if they're intending to use serializing
// formats like json, msgpack etc.
type TextErr struct {
Err error
}
// Error implements the error interface.
func (t TextErr) Error() string {
return t.Err.Error()
}
// MarshalText implements the TextMarshaller
func (t TextErr) MarshalText() ([]byte, error) {
return []byte(t.Err.Error()), nil
}
var (
// ErrZeroValue is the error returned when variable has zero valud
// and nonzero was specified
ErrZeroValue = TextErr{errors.New("zero value")}
// ErrMin is the error returned when variable is less than mininum
// value specified
ErrMin = TextErr{errors.New("less than min")}
// ErrMax is the error returned when variable is more than
// maximum specified
ErrMax = TextErr{errors.New("greater than max")}
// ErrLen is the error returned when length is not equal to
// param specified
ErrLen = TextErr{errors.New("invalid length")}
// ErrRegexp is the error returned when the value does not
// match the provided regular expression parameter
ErrRegexp = TextErr{errors.New("regular expression mismatch")}
// ErrUnsupported is the error error returned when a validation rule
// is used with an unsupported variable type
ErrUnsupported = TextErr{errors.New("unsupported type")}
// ErrBadParameter is the error returned when an invalid parameter
// is provided to a validation rule (e.g. a string where an int was
// expected (max=foo,len=bar) or missing a parameter when one is required (len=))
ErrBadParameter = TextErr{errors.New("bad parameter")}
// ErrUnknownTag is the error returned when an unknown tag is found
ErrUnknownTag = TextErr{errors.New("unknown tag")}
// ErrInvalid is the error returned when variable is invalid
// (normally a nil pointer)
ErrInvalid = TextErr{errors.New("invalid value")}
)
// ErrorMap is a map which contains all errors from validating a struct.
type ErrorMap map[string]ErrorArray
// ErrorMap implements the Error interface so we can check error against nil.
// The returned error is if existent the first error which was added to the map.
func (err ErrorMap) Error() string {
for k, errs := range err {
if len(errs) > 0 {
return fmt.Sprintf("%s: %s", k, errs.Error())
}
}
return ""
}
// ErrorArray is a slice of errors returned by the Validate function.
type ErrorArray []error
// ErrorArray implements the Error interface and returns the first error as
// string if existent.
func (err ErrorArray) Error() string {
if len(err) > 0 {
return err[0].Error()
}
return ""
}
// ValidationFunc is a function that receives the value of a
// field and a parameter used for the respective validation tag.
type ValidationFunc func(v interface{}, param string) error
// Validator implements a validator
type Validator struct {
// Tag name being used.
tagName string
// validationFuncs is a map of ValidationFuncs indexed
// by their name.
validationFuncs map[string]ValidationFunc
}
// Helper validator so users can use the
// functions directly from the package
var defaultValidator = NewValidator()
// NewValidator creates a new Validator
func NewValidator() *Validator {
return &Validator{
tagName: "validate",
validationFuncs: map[string]ValidationFunc{
"nonzero": nonzero,
"len": length,
"min": min,
"max": max,
"regexp": regex,
},
}
}
// SetTag allows you to change the tag name used in structs
func SetTag(tag string) {
defaultValidator.SetTag(tag)
}
// SetTag allows you to change the tag name used in structs
func (mv *Validator) SetTag(tag string) {
mv.tagName = tag
}
// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func WithTag(tag string) *Validator {
return defaultValidator.WithTag(tag)
}
// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func (mv *Validator) WithTag(tag string) *Validator {
v := mv.copy()
v.SetTag(tag)
return v
}
// Copy a validator
func (mv *Validator) copy() *Validator {
newFuncs := map[string]ValidationFunc{}
for k, f := range mv.validationFuncs {
newFuncs[k] = f
}
return &Validator{
tagName: mv.tagName,
validationFuncs: newFuncs,
}
}
// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func SetValidationFunc(name string, vf ValidationFunc) error {
return defaultValidator.SetValidationFunc(name, vf)
}
// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error {
if name == "" {
return errors.New("name cannot be empty")
}
if vf == nil {
delete(mv.validationFuncs, name)
return nil
}
mv.validationFuncs[name] = vf
return nil
}
// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func Validate(v interface{}) error {
return defaultValidator.Validate(v)
}
// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func (mv *Validator) Validate(v interface{}) error {
sv := reflect.ValueOf(v)
st := reflect.TypeOf(v)
if sv.Kind() == reflect.Ptr && !sv.IsNil() {
return mv.Validate(sv.Elem().Interface())
}
if sv.Kind() != reflect.Struct && sv.Kind() != reflect.Interface {
return ErrUnsupported
}
nfields := sv.NumField()
m := make(ErrorMap)
for i := 0; i < nfields; i++ {
fname := st.Field(i).Name
if !unicode.IsUpper(rune(fname[0])) {
continue
}
f := sv.Field(i)
// deal with pointers
for f.Kind() == reflect.Ptr && !f.IsNil() {
f = f.Elem()
}
tag := st.Field(i).Tag.Get(mv.tagName)
if tag == "-" {
continue
}
var errs ErrorArray
if tag != "" {
err := mv.Valid(f.Interface(), tag)
if errors, ok := err.(ErrorArray); ok {
errs = errors
} else {
if err != nil {
errs = ErrorArray{err}
}
}
}
mv.deepValidateCollection(f, fname, m) // no-op if field is not a struct, interface, array, slice or map
if len(errs) > 0 {
m[st.Field(i).Name] = errs
}
}
if len(m) > 0 {
return m
}
return nil
}
func (mv *Validator) deepValidateCollection(f reflect.Value, fname string, m ErrorMap) {
switch f.Kind() {
case reflect.Struct, reflect.Interface, reflect.Ptr:
e := mv.Validate(f.Interface())
if e, ok := e.(ErrorMap); ok && len(e) > 0 {
for j, k := range e {
m[fname+"."+j] = k
}
}
case reflect.Array, reflect.Slice:
for i := 0; i < f.Len(); i++ {
mv.deepValidateCollection(f.Index(i), fmt.Sprintf("%s[%d]", fname, i), m)
}
case reflect.Map:
for _, key := range f.MapKeys() {
mv.deepValidateCollection(key, fmt.Sprintf("%s[%+v](key)", fname, key.Interface()), m) // validate the map key
value := f.MapIndex(key)
mv.deepValidateCollection(value, fmt.Sprintf("%s[%+v](value)", fname, key.Interface()), m)
}
}
}
// Valid validates a value based on the provided
// tags and returns errors found or nil.
func Valid(val interface{}, tags string) error {
return defaultValidator.Valid(val, tags)
}
// Valid validates a value based on the provided
// tags and returns errors found or nil.
func (mv *Validator) Valid(val interface{}, tags string) error {
if tags == "-" {
return nil
}
v := reflect.ValueOf(val)
if v.Kind() == reflect.Ptr && !v.IsNil() {
return mv.Valid(v.Elem().Interface(), tags)
}
var err error
switch v.Kind() {
case reflect.Invalid:
err = mv.validateVar(nil, tags)
default:
err = mv.validateVar(val, tags)
}
return err
}
// validateVar validates one single variable
func (mv *Validator) validateVar(v interface{}, tag string) error {
tags, err := mv.parseTags(tag)
if err != nil {
// unknown tag found, give up.
return err
}
errs := make(ErrorArray, 0, len(tags))
for _, t := range tags {
if err := t.Fn(v, t.Param); err != nil {
errs = append(errs, err)
}
}
if len(errs) > 0 {
return errs
}
return nil
}
// tag represents one of the tag items
type tag struct {
Name string // name of the tag
Fn ValidationFunc // validation function to call
Param string // parameter to send to the validation function
}
// separate by no escaped commas
var sepPattern *regexp.Regexp = regexp.MustCompile(`((?:^|[^\\])(?:\\\\)*),`)
func splitUnescapedComma(str string) []string {
ret := []string{}
indexes := sepPattern.FindAllStringIndex(str, -1)
last := 0
for _, is := range indexes {
ret = append(ret, str[last:is[1]-1])
last = is[1]
}
ret = append(ret, str[last:])
return ret
}
// parseTags parses all individual tags found within a struct tag.
func (mv *Validator) parseTags(t string) ([]tag, error) {
tl := splitUnescapedComma(t)
tags := make([]tag, 0, len(tl))
for _, i := range tl {
i = strings.Replace(i, `\,`, ",", -1)
tg := tag{}
v := strings.SplitN(i, "=", 2)
tg.Name = strings.Trim(v[0], " ")
if tg.Name == "" {
return []tag{}, ErrUnknownTag
}
if len(v) > 1 {
tg.Param = strings.Trim(v[1], " ")
}
var found bool
if tg.Fn, found = mv.validationFuncs[tg.Name]; !found {
return []tag{}, ErrUnknownTag
}
tags = append(tags, tg)
}
return tags, nil
}

325
vendor/gopkg.in/yaml.v2/LICENSE generated vendored
View file

@ -1,188 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2011-2014 - Canonical Inc. TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
This software is licensed under the LGPLv3, included below. 1. Definitions.
As a special exception to the GNU Lesser General Public License version 3 "License" shall mean the terms and conditions for use, reproduction,
("LGPL3"), the copyright holders of this Library give you permission to and distribution as defined by Sections 1 through 9 of this document.
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will "Licensor" shall mean the copyright owner or entity authorized by
continue to comply in full to this Library. If you modify this Library, you the copyright owner that is granting the License.
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
GNU LESSER GENERAL PUBLIC LICENSE "You" (or "Your") shall mean an individual or Legal Entity
Version 3, 29 June 2007 exercising permissions granted by this License.
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> "Source" form shall mean the preferred form for making modifications,
Everyone is permitted to copy and distribute verbatim copies including but not limited to software source code, documentation
of this license document, but changing it is not allowed. source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
This version of the GNU Lesser General Public License incorporates "Work" shall mean the work of authorship, whether in Source or
the terms and conditions of version 3 of the GNU General Public Object form, made available under the License, as indicated by a
License, supplemented by the additional permissions listed below. copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
0. Additional Definitions. "Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
As used herein, "this License" refers to version 3 of the GNU Lesser "Contribution" shall mean any work of authorship, including
General Public License, and the "GNU GPL" refers to version 3 of the GNU the original version of the Work and any modifications or additions
General Public License. to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"The Library" refers to a covered work governed by this License, "Contributor" shall mean Licensor and any individual or Legal Entity
other than an Application or a Combined Work as defined below. on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
An "Application" is any work that makes use of an interface provided 2. Grant of Copyright License. Subject to the terms and conditions of
by the Library, but which is not otherwise based on the Library. this License, each Contributor hereby grants to You a perpetual,
Defining a subclass of a class defined by the Library is deemed a mode worldwide, non-exclusive, no-charge, royalty-free, irrevocable
of using an interface provided by the Library. copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
A "Combined Work" is a work produced by combining or linking an 3. Grant of Patent License. Subject to the terms and conditions of
Application with the Library. The particular version of the Library this License, each Contributor hereby grants to You a perpetual,
with which the Combined Work was made is also called the "Linked worldwide, non-exclusive, no-charge, royalty-free, irrevocable
Version". (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
The "Minimal Corresponding Source" for a Combined Work means the 4. Redistribution. You may reproduce and distribute copies of the
Corresponding Source for the Combined Work, excluding any source code Work or Derivative Works thereof in any medium, with or without
for portions of the Combined Work that, considered in isolation, are modifications, and in Source or Object form, provided that You
based on the Application, and not on the Linked Version. meet the following conditions:
The "Corresponding Application Code" for a Combined Work means the (a) You must give any other recipients of the Work or
object code and/or source code for the Application, including any data Derivative Works a copy of this License; and
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL. (b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
You may convey a covered work under sections 3 and 4 of this License (c) You must retain, in the Source form of any Derivative Works
without being bound by section 3 of the GNU GPL. that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
2. Conveying Modified Versions. (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
If you modify a copy of the Library, and, in your modifications, a You may add Your own copyright statement to Your modifications and
facility refers to a function or data to be supplied by an Application may provide additional or different license terms and conditions
that uses the facility (other than as an argument passed when the for use, reproduction, or distribution of Your modifications, or
facility is invoked), then you may convey a copy of the modified for any such Derivative Works as a whole, provided Your use,
version: reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
a) under this License, provided that you make a good faith effort to 5. Submission of Contributions. Unless You explicitly state otherwise,
ensure that, in the event an Application does not supply the any Contribution intentionally submitted for inclusion in the Work
function or data, the facility still operates, and performs by You to the Licensor shall be under the terms and conditions of
whatever part of its purpose remains meaningful, or this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
b) under the GNU GPL, with none of the additional permissions of 6. Trademarks. This License does not grant permission to use the trade
this License applicable to that copy. names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
3. Object Code Incorporating Material from Library Header Files. 7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
The object code form of an Application may incorporate material from 8. Limitation of Liability. In no event and under no legal theory,
a header file that is part of the Library. You may convey such object whether in tort (including negligence), contract, or otherwise,
code under terms of your choice, provided that, if the incorporated unless required by applicable law (such as deliberate and grossly
material is not limited to numerical parameters, data structure negligent acts) or agreed to in writing, shall any Contributor be
layouts and accessors, or small macros, inline functions and templates liable to You for damages, including any direct, indirect, special,
(ten or fewer lines in length), you do both of the following: incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
a) Give prominent notice with each copy of the object code that the 9. Accepting Warranty or Additional Liability. While redistributing
Library is used in it and that the Library and its use are the Work or Derivative Works thereof, You may choose to offer,
covered by this License. and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
b) Accompany the object code with a copy of the GNU GPL and this license END OF TERMS AND CONDITIONS
document.
4. Combined Works. APPENDIX: How to apply the Apache License to your work.
You may convey a Combined Work under terms of your choice that, To apply the Apache License to your work, attach the following
taken together, effectively do not restrict modification of the boilerplate notice, with the fields enclosed by brackets "{}"
portions of the Library contained in the Combined Work and reverse replaced with your own identifying information. (Don't include
engineering for debugging such modifications, if you also do each of the brackets!) The text should be enclosed in the appropriate
the following: comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
a) Give prominent notice with each copy of the Combined Work that Copyright {yyyy} {name of copyright owner}
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license Licensed under the Apache License, Version 2.0 (the "License");
document. you may not use this file except in compliance with the License.
You may obtain a copy of the License at
c) For a Combined Work that displays copyright notices during http://www.apache.org/licenses/LICENSE-2.0
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following: Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
0) Convey the Minimal Corresponding Source under the terms of this WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
License, and the Corresponding Application Code in a form See the License for the specific language governing permissions and
suitable for, and under terms that permit, the user to limitations under the License.
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

13
vendor/gopkg.in/yaml.v2/NOTICE generated vendored Normal file
View file

@ -0,0 +1,13 @@
Copyright 2011-2016 Canonical Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

131
vendor/gopkg.in/yaml.v2/README.md generated vendored
View file

@ -1,131 +0,0 @@
# YAML support for the Go language
Introduction
------------
The yaml package enables Go programs to comfortably encode and decode YAML
values. It was developed within [Canonical](https://www.canonical.com) as
part of the [juju](https://juju.ubuntu.com) project, and is based on a
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
C library to parse and generate YAML data quickly and reliably.
Compatibility
-------------
The yaml package supports most of YAML 1.1 and 1.2, including support for
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
implemented, and base-60 floats from YAML 1.1 are purposefully not
supported since they're a poor design and are gone in YAML 1.2.
Installation and usage
----------------------
The import path for the package is *gopkg.in/yaml.v2*.
To install it, run:
go get gopkg.in/yaml.v2
API documentation
-----------------
If opened in a browser, the import path itself leads to the API documentation:
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
API stability
-------------
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
License
-------
The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details.
Example
-------
```Go
package main
import (
"fmt"
"log"
"gopkg.in/yaml.v2"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
t := T{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t:\n%v\n\n", t)
d, err := yaml.Marshal(&t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t dump:\n%s\n\n", string(d))
m := make(map[interface{}]interface{})
err = yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err = yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}
```
This example will generate the following output:
```
--- t:
{Easy! {2 [3 4]}}
--- t dump:
a: Easy!
b:
c: 2
d: [3, 4]
--- m:
map[a:Easy! b:map[c:2 d:[3 4]]]
--- m dump:
a: Easy!
b:
c: 2
d:
- 3
- 4
```

55
vendor/gopkg.in/yaml.v2/apic.go generated vendored
View file

@ -2,7 +2,6 @@ package yaml
import ( import (
"io" "io"
"os"
) )
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
@ -48,9 +47,9 @@ func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err
return n, nil return n, nil
} }
// File read handler. // Reader read handler.
func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
return parser.input_file.Read(buffer) return parser.input_reader.Read(buffer)
} }
// Set a string input. // Set a string input.
@ -64,12 +63,12 @@ func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
} }
// Set a file input. // Set a file input.
func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) { func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
if parser.read_handler != nil { if parser.read_handler != nil {
panic("must set the input source only once") panic("must set the input source only once")
} }
parser.read_handler = yaml_file_read_handler parser.read_handler = yaml_reader_read_handler
parser.input_file = file parser.input_reader = r
} }
// Set the source encoding. // Set the source encoding.
@ -81,14 +80,13 @@ func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
} }
// Create a new emitter object. // Create a new emitter object.
func yaml_emitter_initialize(emitter *yaml_emitter_t) bool { func yaml_emitter_initialize(emitter *yaml_emitter_t) {
*emitter = yaml_emitter_t{ *emitter = yaml_emitter_t{
buffer: make([]byte, output_buffer_size), buffer: make([]byte, output_buffer_size),
raw_buffer: make([]byte, 0, output_raw_buffer_size), raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size), events: make([]yaml_event_t, 0, initial_queue_size),
} }
return true
} }
// Destroy an emitter object. // Destroy an emitter object.
@ -102,9 +100,10 @@ func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
return nil return nil
} }
// File write handler. // yaml_writer_write_handler uses emitter.output_writer to write the
func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error { // emitted text.
_, err := emitter.output_file.Write(buffer) func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
_, err := emitter.output_writer.Write(buffer)
return err return err
} }
@ -118,12 +117,12 @@ func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]by
} }
// Set a file output. // Set a file output.
func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) { func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
if emitter.write_handler != nil { if emitter.write_handler != nil {
panic("must set the output target only once") panic("must set the output target only once")
} }
emitter.write_handler = yaml_file_write_handler emitter.write_handler = yaml_writer_write_handler
emitter.output_file = file emitter.output_writer = w
} }
// Set the output encoding. // Set the output encoding.
@ -252,41 +251,41 @@ func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
// //
// Create STREAM-START. // Create STREAM-START.
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool { func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_STREAM_START_EVENT, typ: yaml_STREAM_START_EVENT,
encoding: encoding, encoding: encoding,
} }
return true
} }
// Create STREAM-END. // Create STREAM-END.
func yaml_stream_end_event_initialize(event *yaml_event_t) bool { func yaml_stream_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_STREAM_END_EVENT, typ: yaml_STREAM_END_EVENT,
} }
return true
} }
// Create DOCUMENT-START. // Create DOCUMENT-START.
func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t, func yaml_document_start_event_initialize(
tag_directives []yaml_tag_directive_t, implicit bool) bool { event *yaml_event_t,
version_directive *yaml_version_directive_t,
tag_directives []yaml_tag_directive_t,
implicit bool,
) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_DOCUMENT_START_EVENT, typ: yaml_DOCUMENT_START_EVENT,
version_directive: version_directive, version_directive: version_directive,
tag_directives: tag_directives, tag_directives: tag_directives,
implicit: implicit, implicit: implicit,
} }
return true
} }
// Create DOCUMENT-END. // Create DOCUMENT-END.
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool { func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_DOCUMENT_END_EVENT, typ: yaml_DOCUMENT_END_EVENT,
implicit: implicit, implicit: implicit,
} }
return true
} }
///* ///*
@ -348,7 +347,7 @@ func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
} }
// Create MAPPING-START. // Create MAPPING-START.
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool { func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_MAPPING_START_EVENT, typ: yaml_MAPPING_START_EVENT,
anchor: anchor, anchor: anchor,
@ -356,15 +355,13 @@ func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte
implicit: implicit, implicit: implicit,
style: yaml_style_t(style), style: yaml_style_t(style),
} }
return true
} }
// Create MAPPING-END. // Create MAPPING-END.
func yaml_mapping_end_event_initialize(event *yaml_event_t) bool { func yaml_mapping_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_MAPPING_END_EVENT, typ: yaml_MAPPING_END_EVENT,
} }
return true
} }
// Destroy an event object. // Destroy an event object.
@ -471,7 +468,7 @@ func yaml_event_delete(event *yaml_event_t) {
// } context // } context
// tag_directive *yaml_tag_directive_t // tag_directive *yaml_tag_directive_t
// //
// context.error = YAML_NO_ERROR // Eliminate a compliler warning. // context.error = YAML_NO_ERROR // Eliminate a compiler warning.
// //
// assert(document) // Non-NULL document object is expected. // assert(document) // Non-NULL document object is expected.
// //

226
vendor/gopkg.in/yaml.v2/decode.go generated vendored
View file

@ -4,6 +4,7 @@ import (
"encoding" "encoding"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io"
"math" "math"
"reflect" "reflect"
"strconv" "strconv"
@ -22,6 +23,8 @@ type node struct {
kind int kind int
line, column int line, column int
tag string tag string
// For an alias node, alias holds the resolved alias.
alias *node
value string value string
implicit bool implicit bool
children []*node children []*node
@ -35,6 +38,7 @@ type parser struct {
parser yaml_parser_t parser yaml_parser_t
event yaml_event_t event yaml_event_t
doc *node doc *node
doneInit bool
} }
func newParser(b []byte) *parser { func newParser(b []byte) *parser {
@ -42,21 +46,30 @@ func newParser(b []byte) *parser {
if !yaml_parser_initialize(&p.parser) { if !yaml_parser_initialize(&p.parser) {
panic("failed to initialize YAML emitter") panic("failed to initialize YAML emitter")
} }
if len(b) == 0 { if len(b) == 0 {
b = []byte{'\n'} b = []byte{'\n'}
} }
yaml_parser_set_input_string(&p.parser, b) yaml_parser_set_input_string(&p.parser, b)
p.skip()
if p.event.typ != yaml_STREAM_START_EVENT {
panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
}
p.skip()
return &p return &p
} }
func newParserFromReader(r io.Reader) *parser {
p := parser{}
if !yaml_parser_initialize(&p.parser) {
panic("failed to initialize YAML emitter")
}
yaml_parser_set_input_reader(&p.parser, r)
return &p
}
func (p *parser) init() {
if p.doneInit {
return
}
p.expect(yaml_STREAM_START_EVENT)
p.doneInit = true
}
func (p *parser) destroy() { func (p *parser) destroy() {
if p.event.typ != yaml_NO_EVENT { if p.event.typ != yaml_NO_EVENT {
yaml_event_delete(&p.event) yaml_event_delete(&p.event)
@ -64,16 +77,35 @@ func (p *parser) destroy() {
yaml_parser_delete(&p.parser) yaml_parser_delete(&p.parser)
} }
func (p *parser) skip() { // expect consumes an event from the event stream and
if p.event.typ != yaml_NO_EVENT { // checks that it's of the expected type.
func (p *parser) expect(e yaml_event_type_t) {
if p.event.typ == yaml_NO_EVENT {
if !yaml_parser_parse(&p.parser, &p.event) {
p.fail()
}
}
if p.event.typ == yaml_STREAM_END_EVENT { if p.event.typ == yaml_STREAM_END_EVENT {
failf("attempted to go past the end of stream; corrupted value?") failf("attempted to go past the end of stream; corrupted value?")
} }
if p.event.typ != e {
p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
p.fail()
}
yaml_event_delete(&p.event) yaml_event_delete(&p.event)
p.event.typ = yaml_NO_EVENT
}
// peek peeks at the next event in the event stream,
// puts the results into p.event and returns the event type.
func (p *parser) peek() yaml_event_type_t {
if p.event.typ != yaml_NO_EVENT {
return p.event.typ
} }
if !yaml_parser_parse(&p.parser, &p.event) { if !yaml_parser_parse(&p.parser, &p.event) {
p.fail() p.fail()
} }
return p.event.typ
} }
func (p *parser) fail() { func (p *parser) fail() {
@ -81,6 +113,10 @@ func (p *parser) fail() {
var line int var line int
if p.parser.problem_mark.line != 0 { if p.parser.problem_mark.line != 0 {
line = p.parser.problem_mark.line line = p.parser.problem_mark.line
// Scanner errors don't iterate line before returning error
if p.parser.error == yaml_SCANNER_ERROR {
line++
}
} else if p.parser.context_mark.line != 0 { } else if p.parser.context_mark.line != 0 {
line = p.parser.context_mark.line line = p.parser.context_mark.line
} }
@ -103,7 +139,8 @@ func (p *parser) anchor(n *node, anchor []byte) {
} }
func (p *parser) parse() *node { func (p *parser) parse() *node {
switch p.event.typ { p.init()
switch p.peek() {
case yaml_SCALAR_EVENT: case yaml_SCALAR_EVENT:
return p.scalar() return p.scalar()
case yaml_ALIAS_EVENT: case yaml_ALIAS_EVENT:
@ -118,9 +155,8 @@ func (p *parser) parse() *node {
// Happens when attempting to decode an empty buffer. // Happens when attempting to decode an empty buffer.
return nil return nil
default: default:
panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ))) panic("attempted to parse unknown event: " + p.event.typ.String())
} }
panic("unreachable")
} }
func (p *parser) node(kind int) *node { func (p *parser) node(kind int) *node {
@ -135,19 +171,20 @@ func (p *parser) document() *node {
n := p.node(documentNode) n := p.node(documentNode)
n.anchors = make(map[string]*node) n.anchors = make(map[string]*node)
p.doc = n p.doc = n
p.skip() p.expect(yaml_DOCUMENT_START_EVENT)
n.children = append(n.children, p.parse()) n.children = append(n.children, p.parse())
if p.event.typ != yaml_DOCUMENT_END_EVENT { p.expect(yaml_DOCUMENT_END_EVENT)
panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
}
p.skip()
return n return n
} }
func (p *parser) alias() *node { func (p *parser) alias() *node {
n := p.node(aliasNode) n := p.node(aliasNode)
n.value = string(p.event.anchor) n.value = string(p.event.anchor)
p.skip() n.alias = p.doc.anchors[n.value]
if n.alias == nil {
failf("unknown anchor '%s' referenced", n.value)
}
p.expect(yaml_ALIAS_EVENT)
return n return n
} }
@ -157,29 +194,29 @@ func (p *parser) scalar() *node {
n.tag = string(p.event.tag) n.tag = string(p.event.tag)
n.implicit = p.event.implicit n.implicit = p.event.implicit
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_SCALAR_EVENT)
return n return n
} }
func (p *parser) sequence() *node { func (p *parser) sequence() *node {
n := p.node(sequenceNode) n := p.node(sequenceNode)
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_SEQUENCE_START_EVENT)
for p.event.typ != yaml_SEQUENCE_END_EVENT { for p.peek() != yaml_SEQUENCE_END_EVENT {
n.children = append(n.children, p.parse()) n.children = append(n.children, p.parse())
} }
p.skip() p.expect(yaml_SEQUENCE_END_EVENT)
return n return n
} }
func (p *parser) mapping() *node { func (p *parser) mapping() *node {
n := p.node(mappingNode) n := p.node(mappingNode)
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_MAPPING_START_EVENT)
for p.event.typ != yaml_MAPPING_END_EVENT { for p.peek() != yaml_MAPPING_END_EVENT {
n.children = append(n.children, p.parse(), p.parse()) n.children = append(n.children, p.parse(), p.parse())
} }
p.skip() p.expect(yaml_MAPPING_END_EVENT)
return n return n
} }
@ -188,9 +225,10 @@ func (p *parser) mapping() *node {
type decoder struct { type decoder struct {
doc *node doc *node
aliases map[string]bool aliases map[*node]bool
mapType reflect.Type mapType reflect.Type
terrors []string terrors []string
strict bool
} }
var ( var (
@ -198,11 +236,13 @@ var (
durationType = reflect.TypeOf(time.Duration(0)) durationType = reflect.TypeOf(time.Duration(0))
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
ifaceType = defaultMapType.Elem() ifaceType = defaultMapType.Elem()
timeType = reflect.TypeOf(time.Time{})
ptrTimeType = reflect.TypeOf(&time.Time{})
) )
func newDecoder() *decoder { func newDecoder(strict bool) *decoder {
d := &decoder{mapType: defaultMapType} d := &decoder{mapType: defaultMapType, strict: strict}
d.aliases = make(map[string]bool) d.aliases = make(map[*node]bool)
return d return d
} }
@ -251,7 +291,7 @@ func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
// //
// If n holds a null value, prepare returns before doing anything. // If n holds a null value, prepare returns before doing anything.
func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "") { if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
return out, false, false return out, false, false
} }
again := true again := true
@ -308,16 +348,13 @@ func (d *decoder) document(n *node, out reflect.Value) (good bool) {
} }
func (d *decoder) alias(n *node, out reflect.Value) (good bool) { func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
an, ok := d.doc.anchors[n.value] if d.aliases[n] {
if !ok { // TODO this could actually be allowed in some circumstances.
failf("unknown anchor '%s' referenced", n.value)
}
if d.aliases[n.value] {
failf("anchor '%s' value contains itself", n.value) failf("anchor '%s' value contains itself", n.value)
} }
d.aliases[n.value] = true d.aliases[n] = true
good = d.unmarshal(an, out) good = d.unmarshal(n.alias, out)
delete(d.aliases, n.value) delete(d.aliases, n)
return good return good
} }
@ -329,7 +366,7 @@ func resetMap(out reflect.Value) {
} }
} }
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { func (d *decoder) scalar(n *node, out reflect.Value) bool {
var tag string var tag string
var resolved interface{} var resolved interface{}
if n.tag == "" && !n.implicit { if n.tag == "" && !n.implicit {
@ -353,9 +390,26 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
} }
return true return true
} }
if s, ok := resolved.(string); ok && out.CanAddr() { if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { // We've resolved to exactly the type we want, so use that.
err := u.UnmarshalText([]byte(s)) out.Set(resolvedv)
return true
}
// Perhaps we can use the value as a TextUnmarshaler to
// set its value.
if out.CanAddr() {
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
if ok {
var text []byte
if tag == yaml_BINARY_TAG {
text = []byte(resolved.(string))
} else {
// We let any value be unmarshaled into TextUnmarshaler.
// That might be more lax than we'd like, but the
// TextUnmarshaler itself should bowl out any dubious values.
text = []byte(n.value)
}
err := u.UnmarshalText(text)
if err != nil { if err != nil {
fail(err) fail(err)
} }
@ -366,46 +420,54 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case reflect.String: case reflect.String:
if tag == yaml_BINARY_TAG { if tag == yaml_BINARY_TAG {
out.SetString(resolved.(string)) out.SetString(resolved.(string))
good = true return true
} else if resolved != nil { }
if resolved != nil {
out.SetString(n.value) out.SetString(n.value)
good = true return true
} }
case reflect.Interface: case reflect.Interface:
if resolved == nil { if resolved == nil {
out.Set(reflect.Zero(out.Type())) out.Set(reflect.Zero(out.Type()))
} else if tag == yaml_TIMESTAMP_TAG {
// It looks like a timestamp but for backward compatibility
// reasons we set it as a string, so that code that unmarshals
// timestamp-like values into interface{} will continue to
// see a string and not a time.Time.
// TODO(v3) Drop this.
out.Set(reflect.ValueOf(n.value))
} else { } else {
out.Set(reflect.ValueOf(resolved)) out.Set(reflect.ValueOf(resolved))
} }
good = true return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case int: case int:
if !out.OverflowInt(int64(resolved)) { if !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case int64: case int64:
if !out.OverflowInt(resolved) { if !out.OverflowInt(resolved) {
out.SetInt(resolved) out.SetInt(resolved)
good = true return true
} }
case uint64: case uint64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case float64: case float64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case string: case string:
if out.Type() == durationType { if out.Type() == durationType {
d, err := time.ParseDuration(resolved) d, err := time.ParseDuration(resolved)
if err == nil { if err == nil {
out.SetInt(int64(d)) out.SetInt(int64(d))
good = true return true
} }
} }
} }
@ -414,44 +476,49 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case int: case int:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case int64: case int64:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case uint64: case uint64:
if !out.OverflowUint(uint64(resolved)) { if !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case float64: case float64:
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
} }
case reflect.Bool: case reflect.Bool:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case bool: case bool:
out.SetBool(resolved) out.SetBool(resolved)
good = true return true
} }
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case int: case int:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case int64: case int64:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case uint64: case uint64:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case float64: case float64:
out.SetFloat(resolved) out.SetFloat(resolved)
good = true return true
}
case reflect.Struct:
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
out.Set(resolvedv)
return true
} }
case reflect.Ptr: case reflect.Ptr:
if out.Type().Elem() == reflect.TypeOf(resolved) { if out.Type().Elem() == reflect.TypeOf(resolved) {
@ -459,13 +526,11 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
elem := reflect.New(out.Type().Elem()) elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved)) elem.Elem().Set(reflect.ValueOf(resolved))
out.Set(elem) out.Set(elem)
good = true return true
} }
} }
if !good {
d.terror(n, tag, out) d.terror(n, tag, out)
} return false
return good
} }
func settableValueOf(i interface{}) reflect.Value { func settableValueOf(i interface{}) reflect.Value {
@ -482,6 +547,10 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
switch out.Kind() { switch out.Kind() {
case reflect.Slice: case reflect.Slice:
out.Set(reflect.MakeSlice(out.Type(), l, l)) out.Set(reflect.MakeSlice(out.Type(), l, l))
case reflect.Array:
if l != out.Len() {
failf("invalid array: want %d elements but got %d", out.Len(), l)
}
case reflect.Interface: case reflect.Interface:
// No type hints. Will have to use a generic sequence. // No type hints. Will have to use a generic sequence.
iface = out iface = out
@ -500,7 +569,9 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
j++ j++
} }
} }
if out.Kind() != reflect.Array {
out.Set(out.Slice(0, j)) out.Set(out.Slice(0, j))
}
if iface.IsValid() { if iface.IsValid() {
iface.Set(out) iface.Set(out)
} }
@ -561,7 +632,7 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
} }
e := reflect.New(et).Elem() e := reflect.New(et).Elem()
if d.unmarshal(n.children[i+1], e) { if d.unmarshal(n.children[i+1], e) {
out.SetMapIndex(k, e) d.setMapIndex(n.children[i+1], out, k, e)
} }
} }
} }
@ -569,6 +640,14 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
return true return true
} }
func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
if d.strict && out.MapIndex(k) != zeroValue {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
return
}
out.SetMapIndex(k, v)
}
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
outt := out.Type() outt := out.Type()
if outt.Elem() != mapItemType { if outt.Elem() != mapItemType {
@ -616,6 +695,10 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
elemType = inlineMap.Type().Elem() elemType = inlineMap.Type().Elem()
} }
var doneFields []bool
if d.strict {
doneFields = make([]bool, len(sinfo.FieldsList))
}
for i := 0; i < l; i += 2 { for i := 0; i < l; i += 2 {
ni := n.children[i] ni := n.children[i]
if isMerge(ni) { if isMerge(ni) {
@ -626,6 +709,13 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
continue continue
} }
if info, ok := sinfo.FieldsMap[name.String()]; ok { if info, ok := sinfo.FieldsMap[name.String()]; ok {
if d.strict {
if doneFields[info.Id] {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
continue
}
doneFields[info.Id] = true
}
var field reflect.Value var field reflect.Value
if info.Inline == nil { if info.Inline == nil {
field = out.Field(info.Num) field = out.Field(info.Num)
@ -639,7 +729,9 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
} }
value := reflect.New(elemType).Elem() value := reflect.New(elemType).Elem()
d.unmarshal(n.children[i+1], value) d.unmarshal(n.children[i+1], value)
inlineMap.SetMapIndex(name, value) d.setMapIndex(n.children[i+1], inlineMap, name, value)
} else if d.strict {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
} }
} }
return true return true

14
vendor/gopkg.in/yaml.v2/emitterc.go generated vendored
View file

@ -2,6 +2,7 @@ package yaml
import ( import (
"bytes" "bytes"
"fmt"
) )
// Flush the buffer if needed. // Flush the buffer if needed.
@ -664,9 +665,8 @@ func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
return yaml_emitter_emit_mapping_start(emitter, event) return yaml_emitter_emit_mapping_start(emitter, event)
default: default:
return yaml_emitter_set_emitter_error(emitter, return yaml_emitter_set_emitter_error(emitter,
"expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS") fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
} }
return false
} }
// Expect ALIAS. // Expect ALIAS.
@ -843,7 +843,7 @@ func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event
return true return true
} }
// Write an achor. // Write an anchor.
func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
if emitter.anchor_data.anchor == nil { if emitter.anchor_data.anchor == nil {
return true return true
@ -995,7 +995,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
break_space = false break_space = false
space_break = false space_break = false
preceeded_by_whitespace = false preceded_by_whitespace = false
followed_by_whitespace = false followed_by_whitespace = false
previous_space = false previous_space = false
previous_break = false previous_break = false
@ -1017,7 +1017,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
flow_indicators = true flow_indicators = true
} }
preceeded_by_whitespace = true preceded_by_whitespace = true
for i, w := 0, 0; i < len(value); i += w { for i, w := 0, 0; i < len(value); i += w {
w = width(value[i]) w = width(value[i])
followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
@ -1048,7 +1048,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
block_indicators = true block_indicators = true
} }
case '#': case '#':
if preceeded_by_whitespace { if preceded_by_whitespace {
flow_indicators = true flow_indicators = true
block_indicators = true block_indicators = true
} }
@ -1089,7 +1089,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
} }
// [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
preceeded_by_whitespace = is_blankz(value, i) preceded_by_whitespace = is_blankz(value, i)
} }
emitter.scalar_data.multiline = line_breaks emitter.scalar_data.multiline = line_breaks

132
vendor/gopkg.in/yaml.v2/encode.go generated vendored
View file

@ -3,12 +3,14 @@ package yaml
import ( import (
"encoding" "encoding"
"fmt" "fmt"
"io"
"reflect" "reflect"
"regexp" "regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode/utf8"
) )
type encoder struct { type encoder struct {
@ -16,25 +18,39 @@ type encoder struct {
event yaml_event_t event yaml_event_t
out []byte out []byte
flow bool flow bool
// doneInit holds whether the initial stream_start_event has been
// emitted.
doneInit bool
} }
func newEncoder() (e *encoder) { func newEncoder() *encoder {
e = &encoder{} e := &encoder{}
e.must(yaml_emitter_initialize(&e.emitter)) yaml_emitter_initialize(&e.emitter)
yaml_emitter_set_output_string(&e.emitter, &e.out) yaml_emitter_set_output_string(&e.emitter, &e.out)
yaml_emitter_set_unicode(&e.emitter, true) yaml_emitter_set_unicode(&e.emitter, true)
e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
e.emit()
e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
e.emit()
return e return e
} }
func (e *encoder) finish() { func newEncoderWithWriter(w io.Writer) *encoder {
e.must(yaml_document_end_event_initialize(&e.event, true)) e := &encoder{}
yaml_emitter_initialize(&e.emitter)
yaml_emitter_set_output_writer(&e.emitter, w)
yaml_emitter_set_unicode(&e.emitter, true)
return e
}
func (e *encoder) init() {
if e.doneInit {
return
}
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
e.emit() e.emit()
e.doneInit = true
}
func (e *encoder) finish() {
e.emitter.open_ended = false e.emitter.open_ended = false
e.must(yaml_stream_end_event_initialize(&e.event)) yaml_stream_end_event_initialize(&e.event)
e.emit() e.emit()
} }
@ -44,9 +60,7 @@ func (e *encoder) destroy() {
func (e *encoder) emit() { func (e *encoder) emit() {
// This will internally delete the e.event value. // This will internally delete the e.event value.
if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { e.must(yaml_emitter_emit(&e.emitter, &e.event))
e.must(false)
}
} }
func (e *encoder) must(ok bool) { func (e *encoder) must(ok bool) {
@ -59,13 +73,28 @@ func (e *encoder) must(ok bool) {
} }
} }
func (e *encoder) marshalDoc(tag string, in reflect.Value) {
e.init()
yaml_document_start_event_initialize(&e.event, nil, nil, true)
e.emit()
e.marshal(tag, in)
yaml_document_end_event_initialize(&e.event, true)
e.emit()
}
func (e *encoder) marshal(tag string, in reflect.Value) { func (e *encoder) marshal(tag string, in reflect.Value) {
if !in.IsValid() { if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
e.nilv() e.nilv()
return return
} }
iface := in.Interface() iface := in.Interface()
if m, ok := iface.(Marshaler); ok { switch m := iface.(type) {
case time.Time, *time.Time:
// Although time.Time implements TextMarshaler,
// we don't want to treat it as a string for YAML
// purposes because YAML has special support for
// timestamps.
case Marshaler:
v, err := m.MarshalYAML() v, err := m.MarshalYAML()
if err != nil { if err != nil {
fail(err) fail(err)
@ -75,31 +104,34 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
return return
} }
in = reflect.ValueOf(v) in = reflect.ValueOf(v)
} else if m, ok := iface.(encoding.TextMarshaler); ok { case encoding.TextMarshaler:
text, err := m.MarshalText() text, err := m.MarshalText()
if err != nil { if err != nil {
fail(err) fail(err)
} }
in = reflect.ValueOf(string(text)) in = reflect.ValueOf(string(text))
case nil:
e.nilv()
return
} }
switch in.Kind() { switch in.Kind() {
case reflect.Interface: case reflect.Interface:
if in.IsNil() {
e.nilv()
} else {
e.marshal(tag, in.Elem()) e.marshal(tag, in.Elem())
}
case reflect.Map: case reflect.Map:
e.mapv(tag, in) e.mapv(tag, in)
case reflect.Ptr: case reflect.Ptr:
if in.IsNil() { if in.Type() == ptrTimeType {
e.nilv() e.timev(tag, in.Elem())
} else { } else {
e.marshal(tag, in.Elem()) e.marshal(tag, in.Elem())
} }
case reflect.Struct: case reflect.Struct:
if in.Type() == timeType {
e.timev(tag, in)
} else {
e.structv(tag, in) e.structv(tag, in)
case reflect.Slice: }
case reflect.Slice, reflect.Array:
if in.Type().Elem() == mapItemType { if in.Type().Elem() == mapItemType {
e.itemsv(tag, in) e.itemsv(tag, in)
} else { } else {
@ -191,10 +223,10 @@ func (e *encoder) mappingv(tag string, f func()) {
e.flow = false e.flow = false
style = yaml_FLOW_MAPPING_STYLE style = yaml_FLOW_MAPPING_STYLE
} }
e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
e.emit() e.emit()
f() f()
e.must(yaml_mapping_end_event_initialize(&e.event)) yaml_mapping_end_event_initialize(&e.event)
e.emit() e.emit()
} }
@ -240,23 +272,36 @@ var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0
func (e *encoder) stringv(tag string, in reflect.Value) { func (e *encoder) stringv(tag string, in reflect.Value) {
var style yaml_scalar_style_t var style yaml_scalar_style_t
s := in.String() s := in.String()
rtag, rs := resolve("", s) canUsePlain := true
if rtag == yaml_BINARY_TAG { switch {
if tag == "" || tag == yaml_STR_TAG { case !utf8.ValidString(s):
tag = rtag if tag == yaml_BINARY_TAG {
s = rs.(string)
} else if tag == yaml_BINARY_TAG {
failf("explicitly tagged !!binary data must be base64-encoded") failf("explicitly tagged !!binary data must be base64-encoded")
} else { }
if tag != "" {
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
} }
// It can't be encoded directly as YAML so use a binary tag
// and encode it as base64.
tag = yaml_BINARY_TAG
s = encodeBase64(s)
case tag == "":
// Check to see if it would resolve to a specific
// tag when encoded unquoted. If it doesn't,
// there's no need to quote it.
rtag, _ := resolve("", s)
canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
} }
if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { // Note: it's possible for user code to emit invalid YAML
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE // if they explicitly specify a tag and a string containing
} else if strings.Contains(s, "\n") { // text that's incompatible with that tag.
switch {
case strings.Contains(s, "\n"):
style = yaml_LITERAL_SCALAR_STYLE style = yaml_LITERAL_SCALAR_STYLE
} else { case canUsePlain:
style = yaml_PLAIN_SCALAR_STYLE style = yaml_PLAIN_SCALAR_STYLE
default:
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
} }
e.emitScalar(s, "", tag, style) e.emitScalar(s, "", tag, style)
} }
@ -281,9 +326,20 @@ func (e *encoder) uintv(tag string, in reflect.Value) {
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
} }
func (e *encoder) timev(tag string, in reflect.Value) {
t := in.Interface().(time.Time)
s := t.Format(time.RFC3339Nano)
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) floatv(tag string, in reflect.Value) { func (e *encoder) floatv(tag string, in reflect.Value) {
// FIXME: Handle 64 bits here. // Issue #352: When formatting, use the precision of the underlying value
s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) precision := 64
if in.Kind() == reflect.Float32 {
precision = 32
}
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
switch s { switch s {
case "+Inf": case "+Inf":
s = ".inf" s = ".inf"

1
vendor/gopkg.in/yaml.v2/parserc.go generated vendored
View file

@ -166,7 +166,6 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
default: default:
panic("invalid parser state") panic("invalid parser state")
} }
return false
} }
// Parse the production: // Parse the production:

27
vendor/gopkg.in/yaml.v2/readerc.go generated vendored
View file

@ -93,9 +93,18 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
panic("read handler must be set") panic("read handler must be set")
} }
// [Go] This function was changed to guarantee the requested length size at EOF.
// The fact we need to do this is pretty awful, but the description above implies
// for that to be the case, and there are tests
// If the EOF flag is set and the raw buffer is empty, do nothing. // If the EOF flag is set and the raw buffer is empty, do nothing.
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
return true // [Go] ACTUALLY! Read the documentation of this function above.
// This is just broken. To return true, we need to have the
// given length in the buffer. Not doing that means every single
// check that calls this function to make sure the buffer has a
// given length is Go) panicking; or C) accessing invalid memory.
//return true
} }
// Return if the buffer contains enough characters. // Return if the buffer contains enough characters.
@ -247,7 +256,7 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
if parser.encoding == yaml_UTF16LE_ENCODING { if parser.encoding == yaml_UTF16LE_ENCODING {
low, high = 0, 1 low, high = 0, 1
} else { } else {
high, low = 1, 0 low, high = 1, 0
} }
// The UTF-16 encoding is not as simple as one might // The UTF-16 encoding is not as simple as one might
@ -357,23 +366,26 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
if value <= 0x7F { if value <= 0x7F {
// 0000 0000-0000 007F . 0xxxxxxx // 0000 0000-0000 007F . 0xxxxxxx
parser.buffer[buffer_len+0] = byte(value) parser.buffer[buffer_len+0] = byte(value)
buffer_len += 1
} else if value <= 0x7FF { } else if value <= 0x7FF {
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
buffer_len += 2
} else if value <= 0xFFFF { } else if value <= 0xFFFF {
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
buffer_len += 3
} else { } else {
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
buffer_len += 4
} }
buffer_len += width
parser.unread++ parser.unread++
} }
@ -386,6 +398,15 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
break break
} }
} }
// [Go] Read the documentation of this function above. To return true,
// we need to have the given length in the buffer. Not doing that means
// every single check that calls this function to make sure the buffer
// has a given length is Go) panicking; or C) accessing invalid memory.
// This happens here due to the EOF above breaking early.
for buffer_len < length {
parser.buffer[buffer_len] = 0
buffer_len++
}
parser.buffer = parser.buffer[:buffer_len] parser.buffer = parser.buffer[:buffer_len]
return true return true
} }

83
vendor/gopkg.in/yaml.v2/resolve.go generated vendored
View file

@ -3,9 +3,10 @@ package yaml
import ( import (
"encoding/base64" "encoding/base64"
"math" "math"
"regexp"
"strconv" "strconv"
"strings" "strings"
"unicode/utf8" "time"
) )
type resolveMapItem struct { type resolveMapItem struct {
@ -74,12 +75,14 @@ func longTag(tag string) string {
func resolvableTag(tag string) bool { func resolvableTag(tag string) bool {
switch tag { switch tag {
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
return true return true
} }
return false return false
} }
var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`)
func resolve(tag string, in string) (rtag string, out interface{}) { func resolve(tag string, in string) (rtag string, out interface{}) {
if !resolvableTag(tag) { if !resolvableTag(tag) {
return tag, in return tag, in
@ -89,6 +92,19 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
switch tag { switch tag {
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
return return
case yaml_FLOAT_TAG:
if rtag == yaml_INT_TAG {
switch v := out.(type) {
case int64:
rtag = yaml_FLOAT_TAG
out = float64(v)
return
case int:
rtag = yaml_FLOAT_TAG
out = float64(v)
return
}
}
} }
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
}() }()
@ -122,6 +138,15 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
case 'D', 'S': case 'D', 'S':
// Int, float, or timestamp. // Int, float, or timestamp.
// Only try values as a timestamp if the value is unquoted or there's an explicit
// !!timestamp tag.
if tag == "" || tag == yaml_TIMESTAMP_TAG {
t, ok := parseTimestamp(in)
if ok {
return yaml_TIMESTAMP_TAG, t
}
}
plain := strings.Replace(in, "_", "", -1) plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64) intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil { if err == nil {
@ -135,10 +160,12 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
if err == nil { if err == nil {
return yaml_INT_TAG, uintv return yaml_INT_TAG, uintv
} }
if yamlStyleFloat.MatchString(plain) {
floatv, err := strconv.ParseFloat(plain, 64) floatv, err := strconv.ParseFloat(plain, 64)
if err == nil { if err == nil {
return yaml_FLOAT_TAG, floatv return yaml_FLOAT_TAG, floatv
} }
}
if strings.HasPrefix(plain, "0b") { if strings.HasPrefix(plain, "0b") {
intv, err := strconv.ParseInt(plain[2:], 2, 64) intv, err := strconv.ParseInt(plain[2:], 2, 64)
if err == nil { if err == nil {
@ -153,29 +180,21 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
return yaml_INT_TAG, uintv return yaml_INT_TAG, uintv
} }
} else if strings.HasPrefix(plain, "-0b") { } else if strings.HasPrefix(plain, "-0b") {
intv, err := strconv.ParseInt(plain[3:], 2, 64) intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
if err == nil { if err == nil {
if intv == int64(int(intv)) { if true || intv == int64(int(intv)) {
return yaml_INT_TAG, -int(intv) return yaml_INT_TAG, int(intv)
} else { } else {
return yaml_INT_TAG, -intv return yaml_INT_TAG, intv
} }
} }
} }
// XXX Handle timestamps here.
default: default:
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
} }
} }
if tag == yaml_BINARY_TAG {
return yaml_BINARY_TAG, in
}
if utf8.ValidString(in) {
return yaml_STR_TAG, in return yaml_STR_TAG, in
} }
return yaml_BINARY_TAG, encodeBase64(in)
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines // encodeBase64 encodes s as base64 that is broken up into multiple lines
// as appropriate for the resulting length. // as appropriate for the resulting length.
@ -201,3 +220,39 @@ func encodeBase64(s string) string {
} }
return string(out[:k]) return string(out[:k])
} }
// This is a subset of the formats allowed by the regular expression
// defined at http://yaml.org/type/timestamp.html.
var allowedTimestampFormats = []string{
"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
"2006-1-2 15:4:5.999999999", // space separated with no time zone
"2006-1-2", // date only
// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
// from the set of examples.
}
// parseTimestamp parses s as a timestamp string and
// returns the timestamp and reports whether it succeeded.
// Timestamp formats are defined at http://yaml.org/type/timestamp.html
func parseTimestamp(s string) (time.Time, bool) {
// TODO write code to check all the formats supported by
// http://yaml.org/type/timestamp.html instead of using time.Parse.
// Quick check: all date formats start with YYYY-.
i := 0
for ; i < len(s); i++ {
if c := s[i]; c < '0' || c > '9' {
break
}
}
if i != 4 || i == len(s) || s[i] != '-' {
return time.Time{}, false
}
for _, format := range allowedTimestampFormats {
if t, err := time.Parse(format, s); err == nil {
return t, true
}
}
return time.Time{}, false
}

42
vendor/gopkg.in/yaml.v2/scannerc.go generated vendored
View file

@ -9,7 +9,7 @@ import (
// ************ // ************
// //
// The following notes assume that you are familiar with the YAML specification // The following notes assume that you are familiar with the YAML specification
// (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in // (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
// some cases we are less restrictive that it requires. // some cases we are less restrictive that it requires.
// //
// The process of transforming a YAML stream into a sequence of events is // The process of transforming a YAML stream into a sequence of events is
@ -611,7 +611,7 @@ func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, co
if directive { if directive {
context = "while parsing a %TAG directive" context = "while parsing a %TAG directive"
} }
return yaml_parser_set_scanner_error(parser, context, context_mark, "did not find URI escaped octet") return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
} }
func trace(args ...interface{}) func() { func trace(args ...interface{}) func() {
@ -871,12 +871,6 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
required := parser.flow_level == 0 && parser.indent == parser.mark.column required := parser.flow_level == 0 && parser.indent == parser.mark.column
// A simple key is required only when it is the first token in the current
// line. Therefore it is always allowed. But we add a check anyway.
if required && !parser.simple_key_allowed {
panic("should not happen")
}
// //
// If the current position may start a simple key, save it. // If the current position may start a simple key, save it.
// //
@ -1546,7 +1540,7 @@ func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool
// Unknown directive. // Unknown directive.
} else { } else {
yaml_parser_set_scanner_error(parser, "while scanning a directive", yaml_parser_set_scanner_error(parser, "while scanning a directive",
start_mark, "found uknown directive name") start_mark, "found unknown directive name")
return false return false
} }
@ -1944,7 +1938,7 @@ func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_ma
} else { } else {
// It's either the '!' tag or not really a tag handle. If it's a %TAG // It's either the '!' tag or not really a tag handle. If it's a %TAG
// directive, it's an error. If it's a tag token, it must be a part of URI. // directive, it's an error. If it's a tag token, it must be a part of URI.
if directive && !(s[0] == '!' && s[1] == 0) { if directive && string(s) != "!" {
yaml_parser_set_scanner_tag_error(parser, directive, yaml_parser_set_scanner_tag_error(parser, directive,
start_mark, "did not find expected '!'") start_mark, "did not find expected '!'")
return false return false
@ -1959,6 +1953,7 @@ func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_ma
func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
//size_t length = head ? strlen((char *)head) : 0 //size_t length = head ? strlen((char *)head) : 0
var s []byte var s []byte
hasTag := len(head) > 0
// Copy the head if needed. // Copy the head if needed.
// //
@ -2000,10 +1995,10 @@ func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false return false
} }
hasTag = true
} }
// Check if the tag is non-empty. if !hasTag {
if len(s) == 0 {
yaml_parser_set_scanner_tag_error(parser, directive, yaml_parser_set_scanner_tag_error(parser, directive,
start_mark, "did not find expected tag URI") start_mark, "did not find expected tag URI")
return false return false
@ -2474,6 +2469,10 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si
} }
} }
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false
}
// Check if we are at the end of the scalar. // Check if we are at the end of the scalar.
if single { if single {
if parser.buffer[parser.buffer_pos] == '\'' { if parser.buffer[parser.buffer_pos] == '\'' {
@ -2486,10 +2485,6 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si
} }
// Consume blank characters. // Consume blank characters.
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false
}
for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(parser.buffer, parser.buffer_pos) { if is_blank(parser.buffer, parser.buffer_pos) {
// Consume a space or a tab character. // Consume a space or a tab character.
@ -2591,19 +2586,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
// Consume non-blank characters. // Consume non-blank characters.
for !is_blankz(parser.buffer, parser.buffer_pos) { for !is_blankz(parser.buffer, parser.buffer_pos) {
// Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13".
if parser.flow_level > 0 &&
parser.buffer[parser.buffer_pos] == ':' &&
!is_blankz(parser.buffer, parser.buffer_pos+1) {
yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
start_mark, "found unexpected ':'")
return false
}
// Check for indicators that may end a plain scalar. // Check for indicators that may end a plain scalar.
if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
(parser.flow_level > 0 && (parser.flow_level > 0 &&
(parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == ':' || (parser.buffer[parser.buffer_pos] == ',' ||
parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
parser.buffer[parser.buffer_pos] == '}')) { parser.buffer[parser.buffer_pos] == '}')) {
@ -2655,10 +2641,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(parser.buffer, parser.buffer_pos) { if is_blank(parser.buffer, parser.buffer_pos) {
// Check for tab character that abuse indentation. // Check for tab characters that abuse indentation.
if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
start_mark, "found a tab character that violate indentation") start_mark, "found a tab character that violates indentation")
return false return false
} }

9
vendor/gopkg.in/yaml.v2/sorter.go generated vendored
View file

@ -51,6 +51,15 @@ func (l keyList) Less(i, j int) bool {
} }
var ai, bi int var ai, bi int
var an, bn int64 var an, bn int64
if ar[i] == '0' || br[i] == '0' {
for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
if ar[j] != '0' {
an = 1
bn = 1
break
}
}
}
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
an = an*10 + int64(ar[ai]-'0') an = an*10 + int64(ar[ai]-'0')
} }

63
vendor/gopkg.in/yaml.v2/writerc.go generated vendored
View file

@ -18,72 +18,9 @@ func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
return true return true
} }
// If the output encoding is UTF-8, we don't need to recode the buffer.
if emitter.encoding == yaml_UTF8_ENCODING {
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
} }
emitter.buffer_pos = 0 emitter.buffer_pos = 0
return true return true
} }
// Recode the buffer into the raw buffer.
var low, high int
if emitter.encoding == yaml_UTF16LE_ENCODING {
low, high = 0, 1
} else {
high, low = 1, 0
}
pos := 0
for pos < emitter.buffer_pos {
// See the "reader.c" code for more details on UTF-8 encoding. Note
// that we assume that the buffer contains a valid UTF-8 sequence.
// Read the next UTF-8 character.
octet := emitter.buffer[pos]
var w int
var value rune
switch {
case octet&0x80 == 0x00:
w, value = 1, rune(octet&0x7F)
case octet&0xE0 == 0xC0:
w, value = 2, rune(octet&0x1F)
case octet&0xF0 == 0xE0:
w, value = 3, rune(octet&0x0F)
case octet&0xF8 == 0xF0:
w, value = 4, rune(octet&0x07)
}
for k := 1; k < w; k++ {
octet = emitter.buffer[pos+k]
value = (value << 6) + (rune(octet) & 0x3F)
}
pos += w
// Write the character.
if value < 0x10000 {
var b [2]byte
b[high] = byte(value >> 8)
b[low] = byte(value & 0xFF)
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
} else {
// Write the character using a surrogate pair (check "reader.c").
var b [4]byte
value -= 0x10000
b[high] = byte(0xD8 + (value >> 18))
b[low] = byte((value >> 10) & 0xFF)
b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
b[low+2] = byte(value & 0xFF)
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
}
}
// Write the raw buffer.
if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
}
emitter.buffer_pos = 0
emitter.raw_buffer = emitter.raw_buffer[:0]
return true
}

138
vendor/gopkg.in/yaml.v2/yaml.go generated vendored
View file

@ -9,6 +9,7 @@ package yaml
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
@ -77,8 +78,65 @@ type Marshaler interface {
// supported tag options. // supported tag options.
// //
func Unmarshal(in []byte, out interface{}) (err error) { func Unmarshal(in []byte, out interface{}) (err error) {
return unmarshal(in, out, false)
}
// UnmarshalStrict is like Unmarshal except that any fields that are found
// in the data that do not have corresponding struct members, or mapping
// keys that are duplicates, will result in
// an error.
func UnmarshalStrict(in []byte, out interface{}) (err error) {
return unmarshal(in, out, true)
}
// A Decorder reads and decodes YAML values from an input stream.
type Decoder struct {
strict bool
parser *parser
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may read
// data from r beyond the YAML values requested.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
parser: newParserFromReader(r),
}
}
// SetStrict sets whether strict decoding behaviour is enabled when
// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
func (dec *Decoder) SetStrict(strict bool) {
dec.strict = strict
}
// Decode reads the next YAML-encoded value from its input
// and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about the
// conversion of YAML into a Go value.
func (dec *Decoder) Decode(v interface{}) (err error) {
d := newDecoder(dec.strict)
defer handleErr(&err) defer handleErr(&err)
d := newDecoder() node := dec.parser.parse()
if node == nil {
return io.EOF
}
out := reflect.ValueOf(v)
if out.Kind() == reflect.Ptr && !out.IsNil() {
out = out.Elem()
}
d.unmarshal(node, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
}
return nil
}
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
defer handleErr(&err)
d := newDecoder(strict)
p := newParser(in) p := newParser(in)
defer p.destroy() defer p.destroy()
node := p.parse() node := p.parse()
@ -99,8 +157,8 @@ func Unmarshal(in []byte, out interface{}) (err error) {
// of the generated document will reflect the structure of the value itself. // of the generated document will reflect the structure of the value itself.
// Maps and pointers (to struct, string, int, etc) are accepted as the in value. // Maps and pointers (to struct, string, int, etc) are accepted as the in value.
// //
// Struct fields are only unmarshalled if they are exported (have an upper case // Struct fields are only marshalled if they are exported (have an upper case
// first letter), and are unmarshalled using the field name lowercased as the // first letter), and are marshalled using the field name lowercased as the
// default key. Custom keys may be defined via the "yaml" name in the field // default key. Custom keys may be defined via the "yaml" name in the field
// tag: the content preceding the first comma is used as the key, and the // tag: the content preceding the first comma is used as the key, and the
// following comma-separated options are used to tweak the marshalling process. // following comma-separated options are used to tweak the marshalling process.
@ -114,7 +172,10 @@ func Unmarshal(in []byte, out interface{}) (err error) {
// //
// omitempty Only include the field if it's not set to the zero // omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps. // value for the type or to empty slices or maps.
// Does not apply to zero valued structs. // Zero valued structs will be omitted if all their public
// fields are zero, unless they implement an IsZero
// method (see the IsZeroer interface type), in which
// case the field will be included if that method returns true.
// //
// flow Marshal using a flow style (useful for structs, // flow Marshal using a flow style (useful for structs,
// sequences and maps). // sequences and maps).
@ -129,7 +190,7 @@ func Unmarshal(in []byte, out interface{}) (err error) {
// For example: // For example:
// //
// type T struct { // type T struct {
// F int "a,omitempty" // F int `yaml:"a,omitempty"`
// B int // B int
// } // }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
@ -139,12 +200,47 @@ func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err) defer handleErr(&err)
e := newEncoder() e := newEncoder()
defer e.destroy() defer e.destroy()
e.marshal("", reflect.ValueOf(in)) e.marshalDoc("", reflect.ValueOf(in))
e.finish() e.finish()
out = e.out out = e.out
return return
} }
// An Encoder writes YAML values to an output stream.
type Encoder struct {
encoder *encoder
}
// NewEncoder returns a new encoder that writes to w.
// The Encoder should be closed after use to flush all data
// to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
encoder: newEncoderWithWriter(w),
}
}
// Encode writes the YAML encoding of v to the stream.
// If multiple items are encoded to the stream, the
// second and subsequent document will be preceded
// with a "---" document separator, but the first will not.
//
// See the documentation for Marshal for details about the conversion of Go
// values to YAML.
func (e *Encoder) Encode(v interface{}) (err error) {
defer handleErr(&err)
e.encoder.marshalDoc("", reflect.ValueOf(v))
return nil
}
// Close closes the encoder by writing any remaining data.
// It does not write a stream terminating string "...".
func (e *Encoder) Close() (err error) {
defer handleErr(&err)
e.encoder.finish()
return nil
}
func handleErr(err *error) { func handleErr(err *error) {
if v := recover(); v != nil { if v := recover(); v != nil {
if e, ok := v.(yamlError); ok { if e, ok := v.(yamlError); ok {
@ -200,6 +296,9 @@ type fieldInfo struct {
Num int Num int
OmitEmpty bool OmitEmpty bool
Flow bool Flow bool
// Id holds the unique field identifier, so we can cheaply
// check for field duplicates without maintaining an extra map.
Id int
// Inline holds the field index if the field is part of an inlined struct. // Inline holds the field index if the field is part of an inlined struct.
Inline []int Inline []int
@ -222,7 +321,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
inlineMap := -1 inlineMap := -1
for i := 0; i != n; i++ { for i := 0; i != n; i++ {
field := st.Field(i) field := st.Field(i)
if field.PkgPath != "" { if field.PkgPath != "" && !field.Anonymous {
continue // Private field continue // Private field
} }
@ -279,6 +378,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
} else { } else {
finfo.Inline = append([]int{i}, finfo.Inline...) finfo.Inline = append([]int{i}, finfo.Inline...)
} }
finfo.Id = len(fieldsList)
fieldsMap[finfo.Key] = finfo fieldsMap[finfo.Key] = finfo
fieldsList = append(fieldsList, finfo) fieldsList = append(fieldsList, finfo)
} }
@ -300,11 +400,16 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return nil, errors.New(msg) return nil, errors.New(msg)
} }
info.Id = len(fieldsList)
fieldsList = append(fieldsList, info) fieldsList = append(fieldsList, info)
fieldsMap[info.Key] = info fieldsMap[info.Key] = info
} }
sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} sinfo = &structInfo{
FieldsMap: fieldsMap,
FieldsList: fieldsList,
InlineMap: inlineMap,
}
fieldMapMutex.Lock() fieldMapMutex.Lock()
structMap[st] = sinfo structMap[st] = sinfo
@ -312,8 +417,23 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return sinfo, nil return sinfo, nil
} }
// IsZeroer is used to check whether an object is zero to
// determine whether it should be omitted when marshaling
// with the omitempty flag. One notable implementation
// is time.Time.
type IsZeroer interface {
IsZero() bool
}
func isZero(v reflect.Value) bool { func isZero(v reflect.Value) bool {
switch v.Kind() { kind := v.Kind()
if z, ok := v.Interface().(IsZeroer); ok {
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
return true
}
return z.IsZero()
}
switch kind {
case reflect.String: case reflect.String:
return len(v.String()) == 0 return len(v.String()) == 0
case reflect.Interface, reflect.Ptr: case reflect.Interface, reflect.Ptr:

28
vendor/gopkg.in/yaml.v2/yamlh.go generated vendored
View file

@ -1,6 +1,7 @@
package yaml package yaml
import ( import (
"fmt"
"io" "io"
) )
@ -239,6 +240,27 @@ const (
yaml_MAPPING_END_EVENT // A MAPPING-END event. yaml_MAPPING_END_EVENT // A MAPPING-END event.
) )
var eventStrings = []string{
yaml_NO_EVENT: "none",
yaml_STREAM_START_EVENT: "stream start",
yaml_STREAM_END_EVENT: "stream end",
yaml_DOCUMENT_START_EVENT: "document start",
yaml_DOCUMENT_END_EVENT: "document end",
yaml_ALIAS_EVENT: "alias",
yaml_SCALAR_EVENT: "scalar",
yaml_SEQUENCE_START_EVENT: "sequence start",
yaml_SEQUENCE_END_EVENT: "sequence end",
yaml_MAPPING_START_EVENT: "mapping start",
yaml_MAPPING_END_EVENT: "mapping end",
}
func (e yaml_event_type_t) String() string {
if e < 0 || int(e) >= len(eventStrings) {
return fmt.Sprintf("unknown event %d", e)
}
return eventStrings[e]
}
// The event structure. // The event structure.
type yaml_event_t struct { type yaml_event_t struct {
@ -508,7 +530,7 @@ type yaml_parser_t struct {
problem string // Error description. problem string // Error description.
// The byte about which the problem occured. // The byte about which the problem occurred.
problem_offset int problem_offset int
problem_value int problem_value int
problem_mark yaml_mark_t problem_mark yaml_mark_t
@ -521,7 +543,7 @@ type yaml_parser_t struct {
read_handler yaml_read_handler_t // Read handler. read_handler yaml_read_handler_t // Read handler.
input_file io.Reader // File input data. input_reader io.Reader // File input data.
input []byte // String input data. input []byte // String input data.
input_pos int input_pos int
@ -632,7 +654,7 @@ type yaml_emitter_t struct {
write_handler yaml_write_handler_t // Write handler. write_handler yaml_write_handler_t // Write handler.
output_buffer *[]byte // String output data. output_buffer *[]byte // String output data.
output_file io.Writer // File output data. output_writer io.Writer // File output data.
buffer []byte // The working buffer. buffer []byte // The working buffer.
buffer_pos int // The current position of the buffer. buffer_pos int // The current position of the buffer.