vendor: update ugorji to v1.1.2

This commit is contained in:
Sophos 2019-02-25 12:05:35 +08:00
parent 5effa154b4
commit 1adc288223
37 changed files with 6382 additions and 3269 deletions

4
go.mod
View File

@ -42,8 +42,8 @@ require (
github.com/spf13/pflag v1.0.1
github.com/stretchr/testify v1.2.2 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8
github.com/ugorji/go v1.1.1
github.com/urfave/cli v1.18.0
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43
github.com/urfave/cli v1.20.0
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2
go.etcd.io/bbolt v1.3.2
go.uber.org/atomic v1.3.2 // indirect

10
go.sum
View File

@ -86,10 +86,12 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.1 h1:gmervu+jDMvXTbcHQ0pd2wee85nEoE0BsVyEuzkfK8w=
github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/urfave/cli v1.18.0 h1:m9MfmZWX7bwr9kUcs/Asr95j0IVXzGNNc+/5ku2m26Q=
github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs=
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=

108
vendor/github.com/dustin/go-humanize/comma.go generated vendored Normal file
View File

@ -0,0 +1,108 @@
package humanize
import (
"bytes"
"math"
"math/big"
"strconv"
"strings"
)
// Comma produces a string form of the given number in base 10 with
// commas after every three orders of magnitude.
//
// e.g. Comma(834142) -> 834,142
func Comma(v int64) string {
sign := ""
// Min int64 can't be negated to a usable value, so it has to be special cased.
if v == math.MinInt64 {
return "-9,223,372,036,854,775,808"
}
if v < 0 {
sign = "-"
v = 0 - v
}
parts := []string{"", "", "", "", "", "", ""}
j := len(parts) - 1
for v > 999 {
parts[j] = strconv.FormatInt(v%1000, 10)
switch len(parts[j]) {
case 2:
parts[j] = "0" + parts[j]
case 1:
parts[j] = "00" + parts[j]
}
v = v / 1000
j--
}
parts[j] = strconv.Itoa(int(v))
return sign + strings.Join(parts[j:], ",")
}
// Commaf produces a string form of the given number in base 10 with
// commas after every three orders of magnitude.
//
// e.g. Commaf(834142.32) -> 834,142.32
func Commaf(v float64) string {
buf := &bytes.Buffer{}
if v < 0 {
buf.Write([]byte{'-'})
v = 0 - v
}
comma := []byte{','}
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
pos := 0
if len(parts[0])%3 != 0 {
pos += len(parts[0]) % 3
buf.WriteString(parts[0][:pos])
buf.Write(comma)
}
for ; pos < len(parts[0]); pos += 3 {
buf.WriteString(parts[0][pos : pos+3])
buf.Write(comma)
}
buf.Truncate(buf.Len() - 1)
if len(parts) > 1 {
buf.Write([]byte{'.'})
buf.WriteString(parts[1])
}
return buf.String()
}
// BigComma produces a string form of the given big.Int in base 10
// with commas after every three orders of magnitude.
func BigComma(b *big.Int) string {
sign := ""
if b.Sign() < 0 {
sign = "-"
b.Abs(b)
}
athousand := big.NewInt(1000)
c := (&big.Int{}).Set(b)
_, m := oom(c, athousand)
parts := make([]string, m+1)
j := len(parts) - 1
mod := &big.Int{}
for b.Cmp(athousand) >= 0 {
b.DivMod(b, athousand, mod)
parts[j] = strconv.FormatInt(mod.Int64(), 10)
switch len(parts[j]) {
case 2:
parts[j] = "0" + parts[j]
case 1:
parts[j] = "00" + parts[j]
}
j--
}
parts[j] = strconv.Itoa(int(b.Int64()))
return sign + strings.Join(parts[j:], ",")
}

40
vendor/github.com/dustin/go-humanize/commaf.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
// +build go1.6
package humanize
import (
"bytes"
"math/big"
"strings"
)
// BigCommaf produces a string form of the given big.Float in base 10
// with commas after every three orders of magnitude.
func BigCommaf(v *big.Float) string {
buf := &bytes.Buffer{}
if v.Sign() < 0 {
buf.Write([]byte{'-'})
v.Abs(v)
}
comma := []byte{','}
parts := strings.Split(v.Text('f', -1), ".")
pos := 0
if len(parts[0])%3 != 0 {
pos += len(parts[0]) % 3
buf.WriteString(parts[0][:pos])
buf.Write(comma)
}
for ; pos < len(parts[0]); pos += 3 {
buf.WriteString(parts[0][pos : pos+3])
buf.Write(comma)
}
buf.Truncate(buf.Len() - 1)
if len(parts) > 1 {
buf.Write([]byte{'.'})
buf.WriteString(parts[1])
}
return buf.String()
}

23
vendor/github.com/dustin/go-humanize/ftoa.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
package humanize
import "strconv"
func stripTrailingZeros(s string) string {
offset := len(s) - 1
for offset > 0 {
if s[offset] == '.' {
offset--
break
}
if s[offset] != '0' {
break
}
offset--
}
return s[:offset+1]
}
// Ftoa converts a float to a string with no trailing zeros.
func Ftoa(num float64) string {
return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
}

8
vendor/github.com/dustin/go-humanize/humanize.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
/*
Package humanize converts boring ugly numbers to human-friendly strings and back.
Durations can be turned into strings such as "3 days ago", numbers
representing sizes like 82854982 into useful strings like, "83 MB" or
"79 MiB" (whichever you prefer).
*/
package humanize

192
vendor/github.com/dustin/go-humanize/number.go generated vendored Normal file
View File

@ -0,0 +1,192 @@
package humanize
/*
Slightly adapted from the source to fit go-humanize.
Author: https://github.com/gorhill
Source: https://gist.github.com/gorhill/5285193
*/
import (
"math"
"strconv"
)
var (
renderFloatPrecisionMultipliers = [...]float64{
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
}
renderFloatPrecisionRounders = [...]float64{
0.5,
0.05,
0.005,
0.0005,
0.00005,
0.000005,
0.0000005,
0.00000005,
0.000000005,
0.0000000005,
}
)
// FormatFloat produces a formatted number as string based on the following user-specified criteria:
// * thousands separator
// * decimal separator
// * decimal precision
//
// Usage: s := RenderFloat(format, n)
// The format parameter tells how to render the number n.
//
// See examples: http://play.golang.org/p/LXc1Ddm1lJ
//
// Examples of format strings, given n = 12345.6789:
// "#,###.##" => "12,345.67"
// "#,###." => "12,345"
// "#,###" => "12345,678"
// "#\u202F###,##" => "12345,68"
// "#.###,###### => 12.345,678900
// "" (aka default format) => 12,345.67
//
// The highest precision allowed is 9 digits after the decimal symbol.
// There is also a version for integer number, FormatInteger(),
// which is convenient for calls within template.
func FormatFloat(format string, n float64) string {
// Special cases:
// NaN = "NaN"
// +Inf = "+Infinity"
// -Inf = "-Infinity"
if math.IsNaN(n) {
return "NaN"
}
if n > math.MaxFloat64 {
return "Infinity"
}
if n < -math.MaxFloat64 {
return "-Infinity"
}
// default format
precision := 2
decimalStr := "."
thousandStr := ","
positiveStr := ""
negativeStr := "-"
if len(format) > 0 {
format := []rune(format)
// If there is an explicit format directive,
// then default values are these:
precision = 9
thousandStr = ""
// collect indices of meaningful formatting directives
formatIndx := []int{}
for i, char := range format {
if char != '#' && char != '0' {
formatIndx = append(formatIndx, i)
}
}
if len(formatIndx) > 0 {
// Directive at index 0:
// Must be a '+'
// Raise an error if not the case
// index: 0123456789
// +0.000,000
// +000,000.0
// +0000.00
// +0000
if formatIndx[0] == 0 {
if format[formatIndx[0]] != '+' {
panic("RenderFloat(): invalid positive sign directive")
}
positiveStr = "+"
formatIndx = formatIndx[1:]
}
// Two directives:
// First is thousands separator
// Raise an error if not followed by 3-digit
// 0123456789
// 0.000,000
// 000,000.00
if len(formatIndx) == 2 {
if (formatIndx[1] - formatIndx[0]) != 4 {
panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
}
thousandStr = string(format[formatIndx[0]])
formatIndx = formatIndx[1:]
}
// One directive:
// Directive is decimal separator
// The number of digit-specifier following the separator indicates wanted precision
// 0123456789
// 0.00
// 000,0000
if len(formatIndx) == 1 {
decimalStr = string(format[formatIndx[0]])
precision = len(format) - formatIndx[0] - 1
}
}
}
// generate sign part
var signStr string
if n >= 0.000000001 {
signStr = positiveStr
} else if n <= -0.000000001 {
signStr = negativeStr
n = -n
} else {
signStr = ""
n = 0.0
}
// split number into integer and fractional parts
intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
// generate integer part string
intStr := strconv.FormatInt(int64(intf), 10)
// add thousand separator if required
if len(thousandStr) > 0 {
for i := len(intStr); i > 3; {
i -= 3
intStr = intStr[:i] + thousandStr + intStr[i:]
}
}
// no fractional part, we can leave now
if precision == 0 {
return signStr + intStr
}
// generate fractional part
fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
// may need padding
if len(fracStr) < precision {
fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
}
return signStr + intStr + decimalStr + fracStr
}
// FormatInteger produces a formatted number as string.
// See FormatFloat.
func FormatInteger(format string, n int) string {
return FormatFloat(format, float64(n))
}

25
vendor/github.com/dustin/go-humanize/ordinals.go generated vendored Normal file
View File

@ -0,0 +1,25 @@
package humanize
import "strconv"
// Ordinal gives you the input number in a rank/ordinal format.
//
// Ordinal(3) -> 3rd
func Ordinal(x int) string {
suffix := "th"
switch x % 10 {
case 1:
if x%100 != 11 {
suffix = "st"
}
case 2:
if x%100 != 12 {
suffix = "nd"
}
case 3:
if x%100 != 13 {
suffix = "rd"
}
}
return strconv.Itoa(x) + suffix
}

113
vendor/github.com/dustin/go-humanize/si.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
package humanize
import (
"errors"
"math"
"regexp"
"strconv"
)
var siPrefixTable = map[float64]string{
-24: "y", // yocto
-21: "z", // zepto
-18: "a", // atto
-15: "f", // femto
-12: "p", // pico
-9: "n", // nano
-6: "µ", // micro
-3: "m", // milli
0: "",
3: "k", // kilo
6: "M", // mega
9: "G", // giga
12: "T", // tera
15: "P", // peta
18: "E", // exa
21: "Z", // zetta
24: "Y", // yotta
}
var revSIPrefixTable = revfmap(siPrefixTable)
// revfmap reverses the map and precomputes the power multiplier
func revfmap(in map[float64]string) map[string]float64 {
rv := map[string]float64{}
for k, v := range in {
rv[v] = math.Pow(10, k)
}
return rv
}
var riParseRegex *regexp.Regexp
func init() {
ri := `^([\-0-9.]+)\s?([`
for _, v := range siPrefixTable {
ri += v
}
ri += `]?)(.*)`
riParseRegex = regexp.MustCompile(ri)
}
// ComputeSI finds the most appropriate SI prefix for the given number
// and returns the prefix along with the value adjusted to be within
// that prefix.
//
// See also: SI, ParseSI.
//
// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p")
func ComputeSI(input float64) (float64, string) {
if input == 0 {
return 0, ""
}
mag := math.Abs(input)
exponent := math.Floor(logn(mag, 10))
exponent = math.Floor(exponent/3) * 3
value := mag / math.Pow(10, exponent)
// Handle special case where value is exactly 1000.0
// Should return 1 M instead of 1000 k
if value == 1000.0 {
exponent += 3
value = mag / math.Pow(10, exponent)
}
value = math.Copysign(value, input)
prefix := siPrefixTable[exponent]
return value, prefix
}
// SI returns a string with default formatting.
//
// SI uses Ftoa to format float value, removing trailing zeros.
//
// See also: ComputeSI, ParseSI.
//
// e.g. SI(1000000, "B") -> 1 MB
// e.g. SI(2.2345e-12, "F") -> 2.2345 pF
func SI(input float64, unit string) string {
value, prefix := ComputeSI(input)
return Ftoa(value) + " " + prefix + unit
}
var errInvalid = errors.New("invalid input")
// ParseSI parses an SI string back into the number and unit.
//
// See also: SI, ComputeSI.
//
// e.g. ParseSI("2.2345 pF") -> (2.2345e-12, "F", nil)
func ParseSI(input string) (float64, string, error) {
found := riParseRegex.FindStringSubmatch(input)
if len(found) != 4 {
return 0, "", errInvalid
}
mag := revSIPrefixTable[found[2]]
unit := found[3]
base, err := strconv.ParseFloat(found[1], 64)
return base * mag, unit, err
}

117
vendor/github.com/dustin/go-humanize/times.go generated vendored Normal file
View File

@ -0,0 +1,117 @@
package humanize
import (
"fmt"
"math"
"sort"
"time"
)
// Seconds-based time units
const (
Day = 24 * time.Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
LongTime = 37 * Year
)
// Time formats a time into a relative string.
//
// Time(someT) -> "3 weeks ago"
func Time(then time.Time) string {
return RelTime(then, time.Now(), "ago", "from now")
}
// A RelTimeMagnitude struct contains a relative time point at which
// the relative format of time will switch to a new format string. A
// slice of these in ascending order by their "D" field is passed to
// CustomRelTime to format durations.
//
// The Format field is a string that may contain a "%s" which will be
// replaced with the appropriate signed label (e.g. "ago" or "from
// now") and a "%d" that will be replaced by the quantity.
//
// The DivBy field is the amount of time the time difference must be
// divided by in order to display correctly.
//
// e.g. if D is 2*time.Minute and you want to display "%d minutes %s"
// DivBy should be time.Minute so whatever the duration is will be
// expressed in minutes.
type RelTimeMagnitude struct {
D time.Duration
Format string
DivBy time.Duration
}
var defaultMagnitudes = []RelTimeMagnitude{
{time.Second, "now", time.Second},
{2 * time.Second, "1 second %s", 1},
{time.Minute, "%d seconds %s", time.Second},
{2 * time.Minute, "1 minute %s", 1},
{time.Hour, "%d minutes %s", time.Minute},
{2 * time.Hour, "1 hour %s", 1},
{Day, "%d hours %s", time.Hour},
{2 * Day, "1 day %s", 1},
{Week, "%d days %s", Day},
{2 * Week, "1 week %s", 1},
{Month, "%d weeks %s", Week},
{2 * Month, "1 month %s", 1},
{Year, "%d months %s", Month},
{18 * Month, "1 year %s", 1},
{2 * Year, "2 years %s", 1},
{LongTime, "%d years %s", Year},
{math.MaxInt64, "a long while %s", 1},
}
// RelTime formats a time into a relative string.
//
// It takes two times and two labels. In addition to the generic time
// delta string (e.g. 5 minutes), the labels are used applied so that
// the label corresponding to the smaller time is applied.
//
// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
func RelTime(a, b time.Time, albl, blbl string) string {
return CustomRelTime(a, b, albl, blbl, defaultMagnitudes)
}
// CustomRelTime formats a time into a relative string.
//
// It takes two times two labels and a table of relative time formats.
// In addition to the generic time delta string (e.g. 5 minutes), the
// labels are used applied so that the label corresponding to the
// smaller time is applied.
func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string {
lbl := albl
diff := b.Sub(a)
if a.After(b) {
lbl = blbl
diff = a.Sub(b)
}
n := sort.Search(len(magnitudes), func(i int) bool {
return magnitudes[i].D > diff
})
if n >= len(magnitudes) {
n = len(magnitudes) - 1
}
mag := magnitudes[n]
args := []interface{}{}
escaped := false
for _, ch := range mag.Format {
if escaped {
switch ch {
case 's':
args = append(args, lbl)
case 'd':
args = append(args, diff/mag.DivBy)
}
escaped = false
} else {
escaped = ch == '%'
}
}
return fmt.Sprintf(mag.Format, args...)
}

View File

@ -39,6 +39,7 @@ Rich Feature Set includes:
- Careful selected use of 'unsafe' for targeted performance gains.
100% mode exists where 'unsafe' is not used at all.
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
- In-place updates during decode, with option to zero value in maps and slices prior to decode
- Coerce types where appropriate
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
- Corner Cases:
@ -224,41 +225,3 @@ with some caveats. See Encode documentation.
*/
package codec
// TODO:
// - For Go 1.11, when mid-stack inlining is enabled,
// we should use committed functions for writeXXX and readXXX calls.
// This involves uncommenting the methods for decReaderSwitch and encWriterSwitch
// and using those (decReaderSwitch and encWriterSwitch) in all handles
// instead of encWriter and decReader.
// The benefit is that, for the (En|De)coder over []byte, the encWriter/decReader
// will be inlined, giving a performance bump for that typical case.
// However, it will only be inlined if mid-stack inlining is enabled,
// as we call panic to raise errors, and panic currently prevents inlining.
//
// PUNTED:
// - To make Handle comparable, make extHandle in BasicHandle a non-embedded pointer,
// and use overlay methods on *BasicHandle to call through to extHandle after initializing
// the "xh *extHandle" to point to a real slice.
//
// BEFORE EACH RELEASE:
// - Look through and fix padding for each type, to eliminate false sharing
// - critical shared objects that are read many times
// TypeInfos
// - pooled objects:
// decNaked, decNakedContainers, codecFner, typeInfoLoadArray,
// - small objects allocated independently, that we read/use much across threads:
// codecFn, typeInfo
// - Objects allocated independently and used a lot
// Decoder, Encoder,
// xxxHandle, xxxEncDriver, xxxDecDriver (xxx = json, msgpack, cbor, binc, simple)
// - In all above, arrange values modified together to be close to each other.
//
// For all of these, either ensure that they occupy full cache lines,
// or ensure that the things just past the cache line boundary are hardly read/written
// e.g. JsonHandle.RawBytesExt - which is copied into json(En|De)cDriver at init
//
// Occupying full cache lines means they occupy 8*N words (where N is an integer).
// Check this out by running: ./run.sh -z
// - look at those tagged ****, meaning they are not occupying full cache lines
// - look at those tagged <<<<, meaning they are larger than 32 words (something to watch)
// - Run "golint -min_confidence 0.81"

View File

@ -102,7 +102,7 @@ func bincdesc(vd, vs byte) string {
type bincEncDriver struct {
e *Encoder
h *BincHandle
w encWriter
w *encWriterSwitch
m map[string]uint16 // symbols
b [16]byte // scratch, used for encoding numbers - bigendian style
s uint16 // symbols sequencer
@ -110,6 +110,7 @@ type bincEncDriver struct {
encDriverTrackContainerWriter
noBuiltInTypes
// encNoSeparator
_ [1]uint64 // padding
}
func (e *bincEncDriver) EncodeNil() {
@ -182,7 +183,7 @@ func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8)
}
func (e *bincEncDriver) EncodeInt(v int64) {
const nbd byte = bincVdNegInt << 4
// const nbd byte = bincVdNegInt << 4
if v >= 0 {
e.encUint(bincVdPosInt<<4, true, uint64(v))
} else if v == -1 {
@ -243,18 +244,6 @@ func (e *bincEncDriver) WriteMapStart(length int) {
e.c = containerMapStart
}
func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
e.EncodeSymbol(v)
return
}
l := uint64(len(v))
e.encBytesLen(c, l)
if l > 0 {
e.w.writestr(v)
}
}
func (e *bincEncDriver) EncodeSymbol(v string) {
// if WriteSymbolsNoRefs {
// e.encodeString(cUTF8, v)
@ -319,6 +308,31 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
}
}
func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
e.EncodeSymbol(v)
return
}
l := uint64(len(v))
e.encBytesLen(c, l)
if l > 0 {
e.w.writestr(v)
}
}
func (e *bincEncDriver) EncodeStringEnc(c charEncoding, v string) {
if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
e.EncodeSymbol(v)
return
}
l := uint64(len(v))
e.encLen(bincVdString<<4, l) // e.encBytesLen(c, l)
if l > 0 {
e.w.writestr(v)
}
}
func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
if v == nil {
e.EncodeNil()
@ -331,6 +345,18 @@ func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
}
}
func (e *bincEncDriver) EncodeStringBytesRaw(v []byte) {
if v == nil {
e.EncodeNil()
return
}
l := uint64(len(v))
e.encLen(bincVdByteArray<<4, l) // e.encBytesLen(c, l)
if l > 0 {
e.w.writeb(v)
}
}
func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
//TODO: support bincUnicodeOther (for now, just use string or bytearray)
if c == cRAW {
@ -377,7 +403,7 @@ type bincDecDriver struct {
d *Decoder
h *BincHandle
r decReader
r *decReaderSwitch
br bool // bytes reader
bdRead bool
bd byte
@ -391,7 +417,7 @@ type bincDecDriver struct {
// noStreamingCodec
// decNoSeparator
b [8 * 8]byte // scratch
b [(8 + 1) * 8]byte // scratch
}
func (d *bincDecDriver) readNextBd() {
@ -452,7 +478,7 @@ func (d *bincDecDriver) DecodeTime() (t time.Time) {
d.d.errorf("cannot decode time - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
return
}
t, err := bincDecodeTime(d.r.readx(int(d.vs)))
t, err := bincDecodeTime(d.r.readx(uint(d.vs)))
if err != nil {
panic(err)
}
@ -485,7 +511,8 @@ func (d *bincDecDriver) decFloat() (f float64) {
d.decFloatPre(d.vs, 8)
f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
} else {
d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s",
msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
return
}
return
@ -507,9 +534,9 @@ func (d *bincDecDriver) decUint() (v uint64) {
d.r.readb(d.b[4:8])
v = uint64(bigen.Uint32(d.b[4:8]))
case 4, 5, 6:
lim := int(7 - d.vs)
lim := 7 - d.vs
d.r.readb(d.b[lim:8])
for i := 0; i < lim; i++ {
for i := uint8(0); i < lim; i++ {
d.b[i] = 0
}
v = uint64(bigen.Uint64(d.b[:8]))
@ -684,7 +711,7 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
slen = d.decLen()
if zerocopy {
if d.br {
bs2 = d.r.readx(slen)
bs2 = d.r.readx(uint(slen))
} else if len(bs) == 0 {
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, d.b[:])
} else {
@ -793,7 +820,7 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
d.bdRead = false
if zerocopy {
if d.br {
return d.r.readx(clen)
return d.r.readx(uint(clen))
} else if len(bs) == 0 {
bs = d.b[:]
}
@ -829,11 +856,16 @@ func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []b
d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
return
}
xbs = d.r.readx(l)
if d.br {
xbs = d.r.readx(uint(l))
} else {
xbs = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
}
} else if d.vd == bincVdByteArray {
xbs = d.DecodeBytes(nil, true)
} else {
d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s",
msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
return
}
d.bdRead = false
@ -845,7 +877,7 @@ func (d *bincDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := d.d.naked()
var decodeFurther bool
switch d.vd {
@ -878,7 +910,8 @@ func (d *bincDecDriver) DecodeNaked() {
n.v = valueTypeInt
n.i = int64(-1) // int8(-1)
default:
d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s", d.vd, d.vs, bincdesc(d.vd, d.vs))
d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s",
d.vd, d.vs, bincdesc(d.vd, d.vs))
}
case bincVdSmallInt:
n.v = valueTypeUint
@ -903,7 +936,7 @@ func (d *bincDecDriver) DecodeNaked() {
n.l = d.DecodeBytes(nil, false)
case bincVdTimestamp:
n.v = valueTypeTime
tt, err := bincDecodeTime(d.r.readx(int(d.vs)))
tt, err := bincDecodeTime(d.r.readx(uint(d.vs)))
if err != nil {
panic(err)
}
@ -912,7 +945,11 @@ func (d *bincDecDriver) DecodeNaked() {
n.v = valueTypeExt
l := d.decLen()
n.u = uint64(d.r.readn1())
n.l = d.r.readx(l)
if d.br {
n.l = d.r.readx(uint(l))
} else {
n.l = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
}
case bincVdArray:
n.v = valueTypeArray
decodeFurther = true
@ -930,7 +967,6 @@ func (d *bincDecDriver) DecodeNaked() {
n.v = valueTypeInt
n.i = int64(n.u)
}
return
}
//------------------------------------

View File

@ -33,31 +33,31 @@ const (
const (
cborBdIndefiniteBytes byte = 0x5f
cborBdIndefiniteString = 0x7f
cborBdIndefiniteArray = 0x9f
cborBdIndefiniteMap = 0xbf
cborBdBreak = 0xff
cborBdIndefiniteString byte = 0x7f
cborBdIndefiniteArray byte = 0x9f
cborBdIndefiniteMap byte = 0xbf
cborBdBreak byte = 0xff
)
// These define some in-stream descriptors for
// manual encoding e.g. when doing explicit indefinite-length
const (
CborStreamBytes byte = 0x5f
CborStreamString = 0x7f
CborStreamArray = 0x9f
CborStreamMap = 0xbf
CborStreamBreak = 0xff
CborStreamString byte = 0x7f
CborStreamArray byte = 0x9f
CborStreamMap byte = 0xbf
CborStreamBreak byte = 0xff
)
const (
cborBaseUint byte = 0x00
cborBaseNegInt = 0x20
cborBaseBytes = 0x40
cborBaseString = 0x60
cborBaseArray = 0x80
cborBaseMap = 0xa0
cborBaseTag = 0xc0
cborBaseSimple = 0xe0
cborBaseNegInt byte = 0x20
cborBaseBytes byte = 0x40
cborBaseString byte = 0x60
cborBaseArray byte = 0x80
cborBaseMap byte = 0xa0
cborBaseTag byte = 0xc0
cborBaseSimple byte = 0xe0
)
func cbordesc(bd byte) string {
@ -105,12 +105,11 @@ func cbordesc(bd byte) string {
type cborEncDriver struct {
noBuiltInTypes
encDriverNoopContainerWriter
// encNoSeparator
e *Encoder
w encWriter
w *encWriterSwitch
h *CborHandle
x [8]byte
_ [3]uint64 // padding
// _ [3]uint64 // padding
}
func (e *cborEncDriver) EncodeNil() {
@ -173,7 +172,7 @@ func (e *cborEncDriver) EncodeTime(t time.Time) {
e.EncodeNil()
} else if e.h.TimeRFC3339 {
e.encUint(0, cborBaseTag)
e.EncodeString(cUTF8, t.Format(time.RFC3339Nano))
e.EncodeStringEnc(cUTF8, t.Format(time.RFC3339Nano))
} else {
e.encUint(1, cborBaseTag)
t = t.UTC().Round(time.Microsecond)
@ -197,9 +196,11 @@ func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Enco
func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
e.encUint(uint64(re.Tag), cborBaseTag)
if false && re.Data != nil {
en.encode(re.Data)
} else if re.Value != nil {
// only encodes re.Value (never re.Data)
// if false && re.Data != nil {
// en.encode(re.Data)
// } else if re.Value != nil {
if re.Value != nil {
en.encode(re.Value)
} else {
e.EncodeNil()
@ -238,6 +239,10 @@ func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
e.encStringBytesS(cborBaseString, v)
}
func (e *cborEncDriver) EncodeStringEnc(c charEncoding, v string) {
e.encStringBytesS(cborBaseString, v)
}
func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
if v == nil {
e.EncodeNil()
@ -248,6 +253,14 @@ func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
}
}
func (e *cborEncDriver) EncodeStringBytesRaw(v []byte) {
if v == nil {
e.EncodeNil()
} else {
e.encStringBytesS(cborBaseBytes, stringView(v))
}
}
func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
if e.h.IndefiniteLength {
if bb == cborBaseBytes {
@ -255,16 +268,17 @@ func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
} else {
e.w.writen1(cborBdIndefiniteString)
}
blen := len(v) / 4
var vlen uint = uint(len(v))
blen := vlen / 4
if blen == 0 {
blen = 64
} else if blen > 1024 {
blen = 1024
}
for i := 0; i < len(v); {
for i := uint(0); i < vlen; {
var v2 string
i2 := i + blen
if i2 < len(v) {
if i2 < vlen {
v2 = v[i:i2]
} else {
v2 = v[i:]
@ -283,17 +297,16 @@ func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
// ----------------------
type cborDecDriver struct {
d *Decoder
h *CborHandle
r decReader
// b [scratchByteArrayLen]byte
d *Decoder
h *CborHandle
r *decReaderSwitch
br bool // bytes reader
bdRead bool
bd byte
noBuiltInTypes
// decNoSeparator
decDriverNoopContainerReader
_ [3]uint64 // padding
// _ [3]uint64 // padding
}
func (d *cborDecDriver) readNextBd() {
@ -382,7 +395,8 @@ func (d *cborDecDriver) decCheckInteger() (neg bool) {
} else if major == cborMajorNegInt {
neg = true
} else {
d.d.errorf("not an integer - invalid major %v from descriptor %x/%s", major, d.bd, cbordesc(d.bd))
d.d.errorf("not an integer - invalid major %v from descriptor %x/%s",
major, d.bd, cbordesc(d.bd))
return
}
return
@ -529,7 +543,7 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
d.bdRead = false
if zerocopy {
if d.br {
return d.r.readx(clen)
return d.r.readx(uint(clen))
} else if len(bs) == 0 {
bs = d.d.b[:]
}
@ -619,7 +633,7 @@ func (d *cborDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := d.d.naked()
var decodeFurther bool
switch d.bd {
@ -692,7 +706,6 @@ func (d *cborDecDriver) DecodeNaked() {
if !decodeFurther {
d.bdRead = false
}
return
}
// -------------------------

13
vendor/github.com/ugorji/go/codec/codecgen.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// +build codecgen generated
package codec
// this file is here, to set the codecgen variable to true
// when the build tag codecgen is set.
//
// this allows us do specific things e.g. skip missing fields tests,
// when running in codecgen mode.
func init() {
codecgen = true
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@ type fastpathA [0]fastpathE
func (x fastpathA) index(rtid uintptr) int { return -1 }
func (_ fastpathT) DecSliceUint8V(v []uint8, canChange bool, d *Decoder) (_ []uint8, changed bool) {
fn := d.cfer().get(uint8SliceTyp, true, true)
fn := d.h.fn(uint8SliceTyp, true, true)
d.kSlice(&fn.i, reflect.ValueOf(&v).Elem())
return v, true
}

View File

@ -1,6 +1,6 @@
/* // +build ignore */
// comment this out // + build ignore
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.
// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
@ -10,10 +10,11 @@ package codec
import (
"encoding"
"reflect"
"strconv"
)
// GenVersion is the current version of codecgen.
const GenVersion = 8
const GenVersion = 10
// This file is used to generate helper code for codecgen.
// The values here i.e. genHelper(En|De)coder are not to be used directly by
@ -49,10 +50,20 @@ type genHelperEncDriver struct {
func (x genHelperEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {}
func (x genHelperEncDriver) EncStructFieldKey(keyType valueType, s string) {
encStructFieldKey(x.encDriver, keyType, s)
var m must
if keyType == valueTypeString {
x.encDriver.EncodeStringEnc(cUTF8, s)
} else if keyType == valueTypeInt {
x.encDriver.EncodeInt(m.Int(strconv.ParseInt(s, 10, 64)))
} else if keyType == valueTypeUint {
x.encDriver.EncodeUint(m.Uint(strconv.ParseUint(s, 10, 64)))
} else if keyType == valueTypeFloat {
x.encDriver.EncodeFloat64(m.Float(strconv.ParseFloat(s, 64)))
}
// encStructFieldKey(x.encDriver, keyType, s)
}
func (x genHelperEncDriver) EncodeSymbol(s string) {
x.encDriver.EncodeString(cUTF8, s)
x.encDriver.EncodeStringEnc(cUTF8, s)
}
type genHelperDecDriver struct {
@ -124,19 +135,19 @@ func (f genHelperEncoder) EncFallback(iv interface{}) {
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
bs, fnerr := iv.MarshalText()
f.e.marshal(bs, fnerr, false, cUTF8)
f.e.marshalUtf8(bs, fnerr)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
bs, fnerr := iv.MarshalJSON()
f.e.marshal(bs, fnerr, true, cUTF8)
f.e.marshalAsis(bs, fnerr)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
bs, fnerr := iv.MarshalBinary()
f.e.marshal(bs, fnerr, false, cRAW)
f.e.marshalRaw(bs, fnerr)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@ -169,6 +180,11 @@ func (f genHelperEncoder) EncExtension(v interface{}, xfFn *extTypeTagFn) {
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) WriteStr(s string) {
f.e.w.writestr(s)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
//
// Deprecated: No longer used,

View File

@ -1,6 +1,6 @@
// +build codecgen.exec
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.
package codec
@ -88,7 +88,7 @@ if {{var "l"}} == 0 {
} {{end}}
var {{var "j"}} int
// var {{var "dn"}} bool
for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
for {{var "j"}} = 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ { // bounds-check-elimination
{{if not isArray}} if {{var "j"}} == 0 && {{var "v"}} == nil {
if {{var "hl"}} {
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})

View File

@ -41,6 +41,8 @@ import (
// However, codecgen doesn't support the following:
// - Canonical option. (codecgen IGNORES it currently)
// This is just because it has not been implemented.
// - MissingFielder implementation.
// If a type implements MissingFielder, it is completely ignored by codecgen.
//
// During encode/decode, Selfer takes precedence.
// A type implementing Selfer will know how to encode/decode itself statically.
@ -102,7 +104,9 @@ import (
// v6: removed unsafe from gen, and now uses codecgen.exec tag
// v7:
// v8: current - we now maintain compatibility with old generated code.
const genVersion = 8
// v9: skipped
// v10: modified encDriver and decDriver interfaces. Remove deprecated methods after Jan 1, 2019
const genVersion = 10
const (
genCodecPkg = "codec1978"
@ -297,7 +301,7 @@ func Gen(w io.Writer, buildTags, pkgName, uid string, noExtensions bool,
// x.out(`panic(fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v", `)
// x.linef(`%v, %sGenVersion, file))`, genVersion, x.cpfx)
x.linef("}")
x.line("if false { // reference the types, but skip this branch at build/run time")
x.line("if false { var _ byte = 0; // reference the types, but skip this branch at build/run time")
// x.line("_ = strconv.ParseInt")
var n int
// for k, t := range x.im {
@ -738,8 +742,8 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
defer func() { x.line("}") }() //end if block
if t == timeTyp {
x.linef("} else { r.EncodeTime(%s)", varname)
return
x.linef("} else if !z.EncBasicHandle().TimeNotBuiltin { r.EncodeTime(%s)", varname)
// return
}
if t == rawTyp {
x.linef("} else { z.EncRaw(%s)", varname)
@ -794,7 +798,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
case reflect.Bool:
x.line("r.EncodeBool(bool(" + varname + "))")
case reflect.String:
x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + ", string(" + varname + "))")
x.line("r.EncodeStringEnc(codecSelferCcUTF8" + x.xs + ", string(" + varname + "))")
case reflect.Chan:
x.xtraSM(varname, t, true, false)
// x.encListFallback(varname, rtid, t)
@ -808,7 +812,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
// - if elements are primitives or Selfers, call dedicated function on each member.
// - else call Encoder.encode(XXX) on it.
if rtid == uint8SliceTypId {
x.line("r.EncodeStringBytes(codecSelferCcRAW" + x.xs + ", []byte(" + varname + "))")
x.line("r.EncodeStringBytesRaw([]byte(" + varname + "))")
} else if fastpathAV.index(rtid) != -1 {
g := x.newGenV(t)
x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
@ -858,7 +862,7 @@ func (x *genRunner) encZero(t reflect.Type) {
case reflect.Bool:
x.line("r.EncodeBool(false)")
case reflect.String:
x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + `, "")`)
x.line("r.EncodeStringEnc(codecSelferCcUTF8" + x.xs + `, "")`)
default:
x.line("r.EncodeNil()")
}
@ -1047,7 +1051,7 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
}
x.line("r.WriteMapElemKey()")
// x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + ", `" + si.encName + "`)")
// x.line("r.EncodeStringEnc(codecSelferCcUTF8" + x.xs + ", `" + si.encName + "`)")
// emulate EncStructFieldKey
switch ti.keyType {
case valueTypeInt:
@ -1057,7 +1061,13 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
case valueTypeFloat:
x.linef("r.EncodeFloat64(z.M.Float(strconv.ParseFloat(`%s`, 64)))", si.encName)
default: // string
x.linef("r.EncodeString(codecSelferCcUTF8%s, `%s`)", x.xs, si.encName)
if si.encNameAsciiAlphaNum {
x.linef(`if z.IsJSONHandle() { z.WriteStr("\"%s\"") } else { `, si.encName)
}
x.linef("r.EncodeStringEnc(codecSelferCcUTF8%s, `%s`)", x.xs, si.encName)
if si.encNameAsciiAlphaNum {
x.linef("}")
}
}
// x.linef("r.EncStructFieldKey(codecSelferValueType%s%s, `%s`)", ti.keyType.String(), x.xs, si.encName)
x.line("r.WriteMapElemValue()")
@ -1084,11 +1094,11 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
func (x *genRunner) encListFallback(varname string, t reflect.Type) {
elemBytes := t.Elem().Kind() == reflect.Uint8
if t.AssignableTo(uint8SliceTyp) {
x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, []byte(%s))", x.xs, varname)
x.linef("r.EncodeStringBytesRaw([]byte(%s))", varname)
return
}
if t.Kind() == reflect.Array && elemBytes {
x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, ((*[%d]byte)(%s))[:])", x.xs, t.Len(), varname)
x.linef("r.EncodeStringBytesRaw(((*[%d]byte)(%s))[:])", t.Len(), varname)
return
}
i := x.varsfx()
@ -1108,7 +1118,7 @@ func (x *genRunner) encListFallback(varname string, t reflect.Type) {
}
// x.linef("%s = sch%s", varname, i)
if elemBytes {
x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, []byte(%s))", x.xs, "sch"+i)
x.linef("r.EncodeStringBytesRaw([]byte(%s))", "sch"+i)
x.line("}")
return
}
@ -1324,8 +1334,8 @@ func (x *genRunner) dec(varname string, t reflect.Type, isptr bool) {
addrPfx = "&"
}
if t == timeTyp {
x.linef("} else { %s%v = r.DecodeTime()", ptrPfx, varname)
return
x.linef("} else if !z.DecBasicHandle().TimeNotBuiltin { %s%v = r.DecodeTime()", ptrPfx, varname)
// return
}
if t == rawTyp {
x.linef("} else { %s%v = z.DecRaw()", ptrPfx, varname)
@ -1927,7 +1937,7 @@ func genInternalEncCommandAsString(s string, vname string) string {
case "int", "int8", "int16", "int32", "int64":
return "ee.EncodeInt(int64(" + vname + "))"
case "string":
return "ee.EncodeString(cUTF8, " + vname + ")"
return "ee.EncodeStringEnc(cUTF8, " + vname + ")"
case "float32":
return "ee.EncodeFloat32(" + vname + ")"
case "float64":

File diff suppressed because it is too large Load Diff

View File

@ -47,9 +47,9 @@ func rt2id(rt reflect.Type) uintptr {
return reflect.ValueOf(rt).Pointer()
}
func rv2rtid(rv reflect.Value) uintptr {
return reflect.ValueOf(rv.Type()).Pointer()
}
// func rv2rtid(rv reflect.Value) uintptr {
// return reflect.ValueOf(rv.Type()).Pointer()
// }
func i2rtid(i interface{}) uintptr {
return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
@ -93,23 +93,77 @@ func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) b
// return reflect.ValueOf(i).Elem()
// }
// --------------------------
type atomicClsErr struct {
v atomic.Value
}
func (x *atomicClsErr) load() (e clsErr) {
if i := x.v.Load(); i != nil {
e = i.(clsErr)
}
return
}
func (x *atomicClsErr) store(p clsErr) {
x.v.Store(p)
}
// --------------------------
type atomicTypeInfoSlice struct { // expected to be 2 words
v atomic.Value
}
func (x *atomicTypeInfoSlice) load() []rtid2ti {
i := x.v.Load()
if i == nil {
return nil
func (x *atomicTypeInfoSlice) load() (e []rtid2ti) {
if i := x.v.Load(); i != nil {
e = i.([]rtid2ti)
}
return i.([]rtid2ti)
return
}
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
x.v.Store(p)
}
// --------------------------
type atomicRtidFnSlice struct { // expected to be 2 words
v atomic.Value
}
func (x *atomicRtidFnSlice) load() (e []codecRtidFn) {
if i := x.v.Load(); i != nil {
e = i.([]codecRtidFn)
}
return
}
func (x *atomicRtidFnSlice) store(p []codecRtidFn) {
x.v.Store(p)
}
// --------------------------
func (n *decNaked) ru() reflect.Value {
return reflect.ValueOf(&n.u).Elem()
}
func (n *decNaked) ri() reflect.Value {
return reflect.ValueOf(&n.i).Elem()
}
func (n *decNaked) rf() reflect.Value {
return reflect.ValueOf(&n.f).Elem()
}
func (n *decNaked) rl() reflect.Value {
return reflect.ValueOf(&n.l).Elem()
}
func (n *decNaked) rs() reflect.Value {
return reflect.ValueOf(&n.s).Elem()
}
func (n *decNaked) rt() reflect.Value {
return reflect.ValueOf(&n.t).Elem()
}
func (n *decNaked) rb() reflect.Value {
return reflect.ValueOf(&n.b).Elem()
}
// --------------------------
func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
rv.SetBytes(d.rawBytes())
@ -194,7 +248,7 @@ func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
}
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
e.e.EncodeString(cUTF8, rv.String())
e.e.EncodeStringEnc(cUTF8, rv.String())
}
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {

View File

@ -97,9 +97,9 @@ func rt2id(rt reflect.Type) uintptr {
return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
}
func rv2rtid(rv reflect.Value) uintptr {
return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
}
// func rv2rtid(rv reflect.Value) uintptr {
// return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
// }
func i2rtid(i interface{}) uintptr {
return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
@ -176,31 +176,132 @@ func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) b
// --------------------------
// atomicTypeInfoSlice contains length and pointer to the array for a slice.
// It is expected to be 2 words.
// atomicXXX is expected to be 2 words (for symmetry with atomic.Value)
//
// Previously, we atomically loaded and stored the length and array pointer separately,
// which could lead to some races.
// We now just atomically store and load the pointer to the value directly.
// Note that we do not atomically load/store length and data pointer separately,
// as this could lead to some races. Instead, we atomically load/store cappedSlice.
//
// Note: with atomic.(Load|Store)Pointer, we MUST work with an unsafe.Pointer directly.
type atomicTypeInfoSlice struct { // expected to be 2 words
l int // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
// ----------------------
type atomicTypeInfoSlice struct {
v unsafe.Pointer // *[]rtid2ti
_ uintptr // padding (atomicXXX expected to be 2 words)
}
func (x *atomicTypeInfoSlice) load() []rtid2ti {
xp := unsafe.Pointer(x)
x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
if x2.l == 0 {
return nil
func (x *atomicTypeInfoSlice) load() (s []rtid2ti) {
x2 := atomic.LoadPointer(&x.v)
if x2 != nil {
s = *(*[]rtid2ti)(x2)
}
return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
return
}
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
s := (*unsafeSlice)(unsafe.Pointer(&p))
xp := unsafe.Pointer(x)
atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}
// --------------------------
type atomicRtidFnSlice struct {
v unsafe.Pointer // *[]codecRtidFn
_ uintptr // padding (atomicXXX expected to be 2 words)
}
func (x *atomicRtidFnSlice) load() (s []codecRtidFn) {
x2 := atomic.LoadPointer(&x.v)
if x2 != nil {
s = *(*[]codecRtidFn)(x2)
}
return
}
func (x *atomicRtidFnSlice) store(p []codecRtidFn) {
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}
// --------------------------
type atomicClsErr struct {
v unsafe.Pointer // *clsErr
_ uintptr // padding (atomicXXX expected to be 2 words)
}
func (x *atomicClsErr) load() (e clsErr) {
x2 := (*clsErr)(atomic.LoadPointer(&x.v))
if x2 != nil {
e = *x2
}
return
}
func (x *atomicClsErr) store(p clsErr) {
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}
// --------------------------
// to create a reflect.Value for each member field of decNaked,
// we first create a global decNaked, and create reflect.Value
// for them all.
// This way, we have the flags and type in the reflect.Value.
// Then, when a reflect.Value is called, we just copy it,
// update the ptr to the decNaked's, and return it.
type unsafeDecNakedWrapper struct {
decNaked
ru, ri, rf, rl, rs, rb, rt reflect.Value // mapping to the primitives above
}
func (n *unsafeDecNakedWrapper) init() {
n.ru = reflect.ValueOf(&n.u).Elem()
n.ri = reflect.ValueOf(&n.i).Elem()
n.rf = reflect.ValueOf(&n.f).Elem()
n.rl = reflect.ValueOf(&n.l).Elem()
n.rs = reflect.ValueOf(&n.s).Elem()
n.rt = reflect.ValueOf(&n.t).Elem()
n.rb = reflect.ValueOf(&n.b).Elem()
// n.rr[] = reflect.ValueOf(&n.)
}
var defUnsafeDecNakedWrapper unsafeDecNakedWrapper
func init() {
defUnsafeDecNakedWrapper.init()
}
func (n *decNaked) ru() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.ru
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.u)
return
}
func (n *decNaked) ri() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.ri
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.i)
return
}
func (n *decNaked) rf() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.rf
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.f)
return
}
func (n *decNaked) rl() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.rl
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.l)
return
}
func (n *decNaked) rs() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.rs
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.s)
return
}
func (n *decNaked) rt() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.rt
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.t)
return
}
func (n *decNaked) rb() (v reflect.Value) {
v = defUnsafeDecNakedWrapper.rb
((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.b)
return
}
// --------------------------
@ -307,7 +408,7 @@ func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
e.e.EncodeString(cUTF8, *(*string)(v.ptr))
e.e.EncodeStringEnc(cUTF8, *(*string)(v.ptr))
}
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {

View File

@ -46,8 +46,14 @@ const (
jsonLitTrue = 1
jsonLitFalseQ = 6
jsonLitFalse = 7
jsonLitNullQ = 13
jsonLitNull = 14
// jsonLitNullQ = 13
jsonLitNull = 14
)
var (
jsonLiteral4True = jsonLiterals[jsonLitTrue+1 : jsonLitTrue+4]
jsonLiteral4False = jsonLiterals[jsonLitFalse+1 : jsonLitFalse+5]
jsonLiteral4Null = jsonLiterals[jsonLitNull+1 : jsonLitNull+4]
)
const (
@ -76,14 +82,15 @@ var (
// jsonTabs and jsonSpaces are used as caches for indents
jsonTabs, jsonSpaces [jsonSpacesOrTabsLen]byte
jsonCharHtmlSafeSet bitset128
jsonCharSafeSet bitset128
jsonCharHtmlSafeSet bitset256
jsonCharSafeSet bitset256
jsonCharWhitespaceSet bitset256
jsonNumSet bitset256
)
func init() {
for i := 0; i < jsonSpacesOrTabsLen; i++ {
var i byte
for i = 0; i < jsonSpacesOrTabsLen; i++ {
jsonSpaces[i] = ' '
jsonTabs[i] = '\t'
}
@ -91,7 +98,6 @@ func init() {
// populate the safe values as true: note: ASCII control characters are (0-31)
// jsonCharSafeSet: all true except (0-31) " \
// jsonCharHtmlSafeSet: all true except (0-31) " \ < > &
var i byte
for i = 32; i < utf8.RuneSelf; i++ {
switch i {
case '"', '\\':
@ -115,8 +121,7 @@ func init() {
// ----------------
type jsonEncDriverTypical struct {
w encWriter
// w *encWriterSwitch
w *encWriterSwitch
b *[jsonScratchArrayLen]byte
tw bool // term white space
c containerState
@ -126,7 +131,6 @@ func (e *jsonEncDriverTypical) typical() {}
func (e *jsonEncDriverTypical) reset(ee *jsonEncDriver) {
e.w = ee.ew
// e.w = &ee.e.encWriterSwitch
e.b = &ee.b
e.tw = ee.h.TermWhitespace
e.c = 0
@ -205,7 +209,7 @@ func (e *jsonEncDriverTypical) atEndOfEncode() {
// ----------------
type jsonEncDriverGeneric struct {
w encWriter // encWriter // *encWriterSwitch
w *encWriterSwitch
b *[jsonScratchArrayLen]byte
c containerState
// ds string // indent string
@ -407,12 +411,13 @@ type jsonEncDriver struct {
noBuiltInTypes
e *Encoder
h *JsonHandle
ew encWriter // encWriter // *encWriterSwitch
ew *encWriterSwitch
se extWrapper
// ---- cpu cache line boundary?
bs []byte // scratch
// ---- cpu cache line boundary?
b [jsonScratchArrayLen]byte // scratch (encode time,
_ [2]uint64 // padding
}
func (e *jsonEncDriver) EncodeNil() {
@ -463,6 +468,10 @@ func (e *jsonEncDriver) EncodeString(c charEncoding, v string) {
e.quoteStr(v)
}
func (e *jsonEncDriver) EncodeStringEnc(c charEncoding, v string) {
e.quoteStr(v)
}
func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
// if encoding raw bytes and RawBytesExt is configured, use it to encode
if v == nil {
@ -475,21 +484,44 @@ func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
return
}
slen := base64.StdEncoding.EncodedLen(len(v))
if cap(e.bs) >= slen+2 {
e.bs = e.bs[:slen+2]
slen := base64.StdEncoding.EncodedLen(len(v)) + 2
if cap(e.bs) >= slen {
e.bs = e.bs[:slen]
} else {
e.bs = make([]byte, slen+2)
e.bs = make([]byte, slen)
}
e.bs[0] = '"'
base64.StdEncoding.Encode(e.bs[1:], v)
e.bs[slen+1] = '"'
e.bs[slen-1] = '"'
e.ew.writeb(e.bs)
} else {
e.quoteStr(stringView(v))
}
}
func (e *jsonEncDriver) EncodeStringBytesRaw(v []byte) {
// if encoding raw bytes and RawBytesExt is configured, use it to encode
if v == nil {
e.EncodeNil()
return
}
if e.se.InterfaceExt != nil {
e.EncodeExt(v, 0, &e.se, e.e)
return
}
slen := base64.StdEncoding.EncodedLen(len(v)) + 2
if cap(e.bs) >= slen {
e.bs = e.bs[:slen]
} else {
e.bs = make([]byte, slen)
}
e.bs[0] = '"'
base64.StdEncoding.Encode(e.bs[1:], v)
e.bs[slen-1] = '"'
e.ew.writeb(e.bs)
}
func (e *jsonEncDriver) EncodeAsis(v []byte) {
e.ew.writeb(v)
}
@ -569,7 +601,7 @@ type jsonDecDriver struct {
noBuiltInTypes
d *Decoder
h *JsonHandle
r decReader // *decReaderSwitch // decReader
r *decReaderSwitch
se extWrapper
// ---- writable fields during execution --- *try* to keep in sep cache line
@ -584,7 +616,7 @@ type jsonDecDriver struct {
b [jsonScratchArrayLen]byte // scratch 1, used for parsing strings or numbers or time.Time
b2 [jsonScratchArrayLen]byte // scratch 2, used only for readUntil, decNumBytes
_ [3]uint64 // padding
// _ [3]uint64 // padding
// n jsonNum
}
@ -707,12 +739,36 @@ func (d *jsonDecDriver) ReadMapEnd() {
d.c = containerMapEnd
}
func (d *jsonDecDriver) readLit(length, fromIdx uint8) {
bs := d.r.readx(int(length))
// func (d *jsonDecDriver) readLit(length, fromIdx uint8) {
// // length here is always less than 8 (literals are: null, true, false)
// bs := d.r.readx(int(length))
// d.tok = 0
// if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:fromIdx+length]) {
// d.d.errorf("expecting %s: got %s", jsonLiterals[fromIdx:fromIdx+length], bs)
// }
// }
func (d *jsonDecDriver) readLit4True() {
bs := d.r.readx(3)
d.tok = 0
if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:fromIdx+length]) {
d.d.errorf("expecting %s: got %s", jsonLiterals[fromIdx:fromIdx+length], bs)
return
if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4True) {
d.d.errorf("expecting %s: got %s", jsonLiteral4True, bs)
}
}
func (d *jsonDecDriver) readLit4False() {
bs := d.r.readx(4)
d.tok = 0
if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4False) {
d.d.errorf("expecting %s: got %s", jsonLiteral4False, bs)
}
}
func (d *jsonDecDriver) readLit4Null() {
bs := d.r.readx(3)
d.tok = 0
if jsonValidateSymbols && !bytes.Equal(bs, jsonLiteral4Null) {
d.d.errorf("expecting %s: got %s", jsonLiteral4Null, bs)
}
}
@ -723,7 +779,7 @@ func (d *jsonDecDriver) TryDecodeAsNil() bool {
// we shouldn't try to see if "null" was here, right?
// only the plain string: `null` denotes a nil (ie not quotes)
if d.tok == 'n' {
d.readLit(3, jsonLitNull+1) // (n)ull
d.readLit4Null()
return true
}
return false
@ -739,10 +795,10 @@ func (d *jsonDecDriver) DecodeBool() (v bool) {
}
switch d.tok {
case 'f':
d.readLit(4, jsonLitFalse+1) // (f)alse
d.readLit4False()
// v = false
case 't':
d.readLit(3, jsonLitTrue+1) // (t)rue
d.readLit4True()
v = true
default:
d.d.errorf("decode bool: got first char %c", d.tok)
@ -808,6 +864,9 @@ func (d *jsonDecDriver) decNumBytes() (bs []byte) {
func (d *jsonDecDriver) DecodeUint64() (u uint64) {
bs := d.decNumBytes()
if len(bs) == 0 {
return
}
n, neg, badsyntax, overflow := jsonParseInteger(bs)
if overflow {
d.d.errorf("overflow parsing unsigned integer: %s", bs)
@ -823,6 +882,9 @@ func (d *jsonDecDriver) DecodeUint64() (u uint64) {
func (d *jsonDecDriver) DecodeInt64() (i int64) {
const cutoff = uint64(1 << uint(64-1))
bs := d.decNumBytes()
if len(bs) == 0 {
return
}
n, neg, badsyntax, overflow := jsonParseInteger(bs)
if overflow {
d.d.errorf("overflow parsing integer: %s", bs)
@ -850,6 +912,9 @@ func (d *jsonDecDriver) DecodeInt64() (i int64) {
}
func (d *jsonDecDriver) decUint64ViaFloat(s string) (u uint64) {
if len(s) == 0 {
return
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
d.d.errorf("invalid syntax for integer: %s", s)
@ -866,6 +931,9 @@ func (d *jsonDecDriver) decUint64ViaFloat(s string) (u uint64) {
func (d *jsonDecDriver) DecodeFloat64() (f float64) {
bs := d.decNumBytes()
if len(bs) == 0 {
return
}
f, err := strconv.ParseFloat(stringView(bs), 64)
if err != nil {
d.d.errorv(err)
@ -953,15 +1021,15 @@ func (d *jsonDecDriver) appendStringAsBytes() {
// handle non-string scalar: null, true, false or a number
switch d.tok {
case 'n':
d.readLit(3, jsonLitNull+1) // (n)ull
d.readLit4Null()
d.bs = d.bs[:0]
d.fnull = true
case 'f':
d.readLit(4, jsonLitFalse+1) // (f)alse
d.readLit4False()
d.bs = d.bs[:5]
copy(d.bs, "false")
case 't':
d.readLit(3, jsonLitTrue+1) // (t)rue
d.readLit4True()
d.bs = d.bs[:4]
copy(d.bs, "true")
default:
@ -980,7 +1048,7 @@ func (d *jsonDecDriver) appendStringAsBytes() {
d.tok = 0
r := d.r
var cs = r.readUntil(d.b2[:0], '"')
var cslen = len(cs)
var cslen = uint(len(cs))
var c uint8
v := d.bs[:0]
// append on each byte seen can be expensive, so we just
@ -989,11 +1057,12 @@ func (d *jsonDecDriver) appendStringAsBytes() {
// and when we see a special byte
// e.g. end-of-slice, " or \,
// we will append the full range into the v slice before proceeding
for i, cursor := 0, 0; ; {
var i, cursor uint
for {
if i == cslen {
v = append(v, cs[cursor:]...)
cs = r.readUntil(d.b2[:0], '"')
cslen = len(cs)
cslen = uint(len(cs))
i, cursor = 0, 0
}
c = cs[i]
@ -1024,14 +1093,13 @@ func (d *jsonDecDriver) appendStringAsBytes() {
case 'u':
var r rune
var rr uint32
if len(cs) < i+4 { // may help reduce bounds-checking
if cslen < i+4 {
d.d.errorf("need at least 4 more bytes for unicode sequence")
}
// c = cs[i+4] // may help reduce bounds-checking
for j := 1; j < 5; j++ {
var j uint
for _, c = range cs[i+1 : i+5] { // bounds-check-elimination
// best to use explicit if-else
// - not a table, etc which involve memory loads, array lookup with bounds checks, etc
c = cs[i+j]
if c >= '0' && c <= '9' {
rr = rr*16 + uint32(c-jsonU4Chk2)
} else if c >= 'a' && c <= 'f' {
@ -1047,30 +1115,31 @@ func (d *jsonDecDriver) appendStringAsBytes() {
r = rune(rr)
i += 4
if utf16.IsSurrogate(r) {
if len(cs) >= i+6 && cs[i+2] == 'u' && cs[i+1] == '\\' {
i += 2
// c = cs[i+4] // may help reduce bounds-checking
var rr1 uint32
for j := 1; j < 5; j++ {
c = cs[i+j]
if c >= '0' && c <= '9' {
rr = rr*16 + uint32(c-jsonU4Chk2)
} else if c >= 'a' && c <= 'f' {
rr = rr*16 + uint32(c-jsonU4Chk1)
} else if c >= 'A' && c <= 'F' {
rr = rr*16 + uint32(c-jsonU4Chk0)
} else {
r = unicode.ReplacementChar
i += 4
goto encode_rune
if len(cs) >= int(i+6) {
var cx = cs[i+1:][:6:6] // [:6] affords bounds-check-elimination
if cx[0] == '\\' && cx[1] == 'u' {
i += 2
var rr1 uint32
for j = 2; j < 6; j++ {
c = cx[j]
if c >= '0' && c <= '9' {
rr = rr*16 + uint32(c-jsonU4Chk2)
} else if c >= 'a' && c <= 'f' {
rr = rr*16 + uint32(c-jsonU4Chk1)
} else if c >= 'A' && c <= 'F' {
rr = rr*16 + uint32(c-jsonU4Chk0)
} else {
r = unicode.ReplacementChar
i += 4
goto encode_rune
}
}
r = utf16.DecodeRune(r, rune(rr1))
i += 4
goto encode_rune
}
r = utf16.DecodeRune(r, rune(rr1))
i += 4
} else {
r = unicode.ReplacementChar
goto encode_rune
}
r = unicode.ReplacementChar
}
encode_rune:
w2 := utf8.EncodeRune(d.bstr[:], r)
@ -1086,9 +1155,23 @@ func (d *jsonDecDriver) appendStringAsBytes() {
func (d *jsonDecDriver) nakedNum(z *decNaked, bs []byte) (err error) {
const cutoff = uint64(1 << uint(64-1))
var n uint64
var neg, badsyntax, overflow bool
if len(bs) == 0 {
if d.h.PreferFloat {
z.v = valueTypeFloat
z.f = 0
} else if d.h.SignedInteger {
z.v = valueTypeInt
z.i = 0
} else {
z.v = valueTypeUint
z.u = 0
}
return
}
if d.h.PreferFloat {
goto F
}
@ -1128,7 +1211,7 @@ func (d *jsonDecDriver) bsToString() string {
}
func (d *jsonDecDriver) DecodeNaked() {
z := d.d.n
z := d.d.naked()
// var decodeFurther bool
if d.tok == 0 {
@ -1136,14 +1219,14 @@ func (d *jsonDecDriver) DecodeNaked() {
}
switch d.tok {
case 'n':
d.readLit(3, jsonLitNull+1) // (n)ull
d.readLit4Null()
z.v = valueTypeNil
case 'f':
d.readLit(4, jsonLitFalse+1) // (f)alse
d.readLit4False()
z.v = valueTypeBool
z.b = false
case 't':
d.readLit(3, jsonLitTrue+1) // (t)rue
d.readLit4True()
z.v = valueTypeBool
z.b = true
case '{':
@ -1188,7 +1271,6 @@ func (d *jsonDecDriver) DecodeNaked() {
// if decodeFurther {
// d.s.sc.retryRead()
// }
return
}
//----------------------
@ -1306,6 +1388,7 @@ func (x *jsonEncDriverTypicalImpl) reset() {
type jsonEncDriverGenericImpl struct {
jsonEncDriver
jsonEncDriverGeneric
// _ [2]uint64 // padding
}
func (x *jsonEncDriverGenericImpl) reset() {
@ -1340,7 +1423,7 @@ func (h *JsonHandle) newDecDriver(d *Decoder) decDriver {
}
func (e *jsonEncDriver) reset() {
e.ew = e.e.w // e.e.w // &e.e.encWriterSwitch
e.ew = e.e.w
e.se.InterfaceExt = e.h.RawBytesExt
if e.bs != nil {
e.bs = e.bs[:0]
@ -1348,7 +1431,7 @@ func (e *jsonEncDriver) reset() {
}
func (d *jsonDecDriver) reset() {
d.r = d.d.r // &d.d.decReaderSwitch // d.d.r
d.r = d.d.r
d.se.InterfaceExt = d.h.RawBytesExt
if d.bs != nil {
d.bs = d.bs[:0]
@ -1380,12 +1463,14 @@ func jsonFloatStrconvFmtPrec(f float64) (fmt byte, prec int) {
// custom-fitted version of strconv.Parse(Ui|I)nt.
// Also ensures we don't have to search for .eE to determine if a float or not.
// Note: s CANNOT be a zero-length slice.
func jsonParseInteger(s []byte) (n uint64, neg, badSyntax, overflow bool) {
const maxUint64 = (1<<64 - 1)
const cutoff = maxUint64/10 + 1
if len(s) == 0 {
badSyntax = true
if len(s) == 0 { // bounds-check-elimination
// treat empty string as zero value
// badSyntax = true
return
}
switch s[0] {

View File

@ -30,53 +30,53 @@ import (
const (
mpPosFixNumMin byte = 0x00
mpPosFixNumMax = 0x7f
mpFixMapMin = 0x80
mpFixMapMax = 0x8f
mpFixArrayMin = 0x90
mpFixArrayMax = 0x9f
mpFixStrMin = 0xa0
mpFixStrMax = 0xbf
mpNil = 0xc0
_ = 0xc1
mpFalse = 0xc2
mpTrue = 0xc3
mpFloat = 0xca
mpDouble = 0xcb
mpUint8 = 0xcc
mpUint16 = 0xcd
mpUint32 = 0xce
mpUint64 = 0xcf
mpInt8 = 0xd0
mpInt16 = 0xd1
mpInt32 = 0xd2
mpInt64 = 0xd3
mpPosFixNumMax byte = 0x7f
mpFixMapMin byte = 0x80
mpFixMapMax byte = 0x8f
mpFixArrayMin byte = 0x90
mpFixArrayMax byte = 0x9f
mpFixStrMin byte = 0xa0
mpFixStrMax byte = 0xbf
mpNil byte = 0xc0
_ byte = 0xc1
mpFalse byte = 0xc2
mpTrue byte = 0xc3
mpFloat byte = 0xca
mpDouble byte = 0xcb
mpUint8 byte = 0xcc
mpUint16 byte = 0xcd
mpUint32 byte = 0xce
mpUint64 byte = 0xcf
mpInt8 byte = 0xd0
mpInt16 byte = 0xd1
mpInt32 byte = 0xd2
mpInt64 byte = 0xd3
// extensions below
mpBin8 = 0xc4
mpBin16 = 0xc5
mpBin32 = 0xc6
mpExt8 = 0xc7
mpExt16 = 0xc8
mpExt32 = 0xc9
mpFixExt1 = 0xd4
mpFixExt2 = 0xd5
mpFixExt4 = 0xd6
mpFixExt8 = 0xd7
mpFixExt16 = 0xd8
mpBin8 byte = 0xc4
mpBin16 byte = 0xc5
mpBin32 byte = 0xc6
mpExt8 byte = 0xc7
mpExt16 byte = 0xc8
mpExt32 byte = 0xc9
mpFixExt1 byte = 0xd4
mpFixExt2 byte = 0xd5
mpFixExt4 byte = 0xd6
mpFixExt8 byte = 0xd7
mpFixExt16 byte = 0xd8
mpStr8 = 0xd9 // new
mpStr16 = 0xda
mpStr32 = 0xdb
mpStr8 byte = 0xd9 // new
mpStr16 byte = 0xda
mpStr32 byte = 0xdb
mpArray16 = 0xdc
mpArray32 = 0xdd
mpArray16 byte = 0xdc
mpArray32 byte = 0xdd
mpMap16 = 0xde
mpMap32 = 0xdf
mpMap16 byte = 0xde
mpMap32 byte = 0xdf
mpNegFixNumMin = 0xe0
mpNegFixNumMax = 0xff
mpNegFixNumMin byte = 0xe0
mpNegFixNumMax byte = 0xff
)
var mpTimeExtTag int8 = -1
@ -199,10 +199,10 @@ type msgpackEncDriver struct {
encDriverNoopContainerWriter
// encNoSeparator
e *Encoder
w encWriter
w *encWriterSwitch
h *MsgpackHandle
x [8]byte
_ [3]uint64 // padding
// _ [3]uint64 // padding
}
func (e *msgpackEncDriver) EncodeNil() {
@ -210,10 +210,9 @@ func (e *msgpackEncDriver) EncodeNil() {
}
func (e *msgpackEncDriver) EncodeInt(i int64) {
// if i >= 0 {
// e.EncodeUint(uint64(i))
// } else if false &&
if i > math.MaxInt8 {
if e.h.PositiveIntUnsigned && i >= 0 {
e.EncodeUint(uint64(i))
} else if i > math.MaxInt8 {
if i <= math.MaxInt16 {
e.w.writen1(mpInt16)
bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
@ -326,7 +325,7 @@ func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Enc
e.encodeExtPreamble(uint8(xtag), len(bs))
e.w.writeb(bs)
} else {
e.EncodeStringBytes(cRAW, bs)
e.EncodeStringBytesRaw(bs)
}
}
@ -380,6 +379,14 @@ func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
}
}
func (e *msgpackEncDriver) EncodeStringEnc(c charEncoding, s string) {
slen := len(s)
e.writeContainerLen(msgpackContainerStr, slen)
if slen > 0 {
e.w.writestr(s)
}
}
func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
if bs == nil {
e.EncodeNil()
@ -396,6 +403,22 @@ func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
}
}
func (e *msgpackEncDriver) EncodeStringBytesRaw(bs []byte) {
if bs == nil {
e.EncodeNil()
return
}
slen := len(bs)
if e.h.WriteExt {
e.writeContainerLen(msgpackContainerBin, slen)
} else {
e.writeContainerLen(msgpackContainerStr, slen)
}
if slen > 0 {
e.w.writeb(bs)
}
}
func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
if ct.hasFixMin && l < ct.fixCutoff {
e.w.writen1(ct.bFixMin | byte(l))
@ -414,7 +437,7 @@ func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
type msgpackDecDriver struct {
d *Decoder
r decReader // *Decoder decReader decReaderT
r *decReaderSwitch
h *MsgpackHandle
// b [scratchByteArrayLen]byte
bd byte
@ -424,7 +447,7 @@ type msgpackDecDriver struct {
// noStreamingCodec
// decNoSeparator
decDriverNoopContainerReader
_ [3]uint64 // padding
// _ [3]uint64 // padding
}
// Note: This returns either a primitive (int, bool, etc) for non-containers,
@ -437,7 +460,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
d.readNextBd()
}
bd := d.bd
n := d.d.n
n := d.d.naked()
var decodeFurther bool
switch bd {
@ -518,8 +541,10 @@ func (d *msgpackDecDriver) DecodeNaked() {
if n.u == uint64(mpTimeExtTagU) {
n.v = valueTypeTime
n.t = d.decodeTime(clen)
} else if d.br {
n.l = d.r.readx(uint(clen))
} else {
n.l = d.r.readx(clen)
n.l = decByteSlice(d.r, clen, d.d.h.MaxInitLen, d.d.b[:])
}
default:
d.d.errorf("cannot infer value: %s: Ox%x/%d/%s", msgBadDesc, bd, bd, mpdesc(bd))
@ -532,7 +557,6 @@ func (d *msgpackDecDriver) DecodeNaked() {
n.v = valueTypeInt
n.i = int64(n.u)
}
return
}
// int can be decoded from msgpack type: intXXX or uintXXX
@ -702,7 +726,7 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
}
if zerocopy {
if d.br {
return d.r.readx(clen)
return d.r.readx(uint(clen))
} else if len(bs) == 0 {
bs = d.d.b[:]
}
@ -912,7 +936,11 @@ func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs
d.d.errorf("wrong extension tag - got %b, expecting %v", xtag, tag)
return
}
xbs = d.r.readx(clen)
if d.br {
xbs = d.r.readx(uint(clen))
} else {
xbs = decByteSlice(d.r, clen, d.d.h.MaxInitLen, d.d.b[:])
}
}
d.bdRead = false
return
@ -942,6 +970,9 @@ type MsgpackHandle struct {
// a []byte or string based on the setting of RawToString.
WriteExt bool
// PositiveIntUnsigned says to encode positive integers as unsigned.
PositiveIntUnsigned bool
binaryEncodingType
noElemSeparators
@ -1023,7 +1054,7 @@ func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
}
func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
if c.isClosed() {
if cls := c.cls.load(); cls.closed {
return io.EOF
}

View File

@ -8,9 +8,10 @@ import (
"errors"
"io"
"net/rpc"
"sync"
)
var errRpcJsonNeedsTermWhitespace = errors.New("rpc requires JsonHandle with TermWhitespace=true")
// Rpc provides a rpc Server or Client Codec for rpc communication.
type Rpc interface {
ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
@ -38,12 +39,9 @@ type rpcCodec struct {
enc *Encoder
// bw *bufio.Writer
// br *bufio.Reader
mu sync.Mutex
h Handle
h Handle
cls bool
clsmu sync.RWMutex
clsErr error
cls atomicClsErr
}
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
@ -54,12 +52,12 @@ func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
// defensive: ensure that jsonH has TermWhitespace turned on.
if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
panic(errRpcJsonNeedsTermWhitespace)
}
// always ensure that we use a flusher, and always flush what was written to the connection.
// we lose nothing by using a buffered writer internally.
f, ok := w.(ioFlusher)
bh := h.getBasicHandle()
bh := basicHandle(h)
if !bh.RPCNoBuffer {
if bh.WriterBufferSize <= 0 {
if !ok {
@ -88,8 +86,11 @@ func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
}
func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
if c.isClosed() {
return c.clsErr
if c.c != nil {
cls := c.cls.load()
if cls.closed {
return cls.errClosed
}
}
err = c.enc.Encode(obj1)
if err == nil {
@ -116,8 +117,11 @@ func (c *rpcCodec) swallow(err *error) {
}
func (c *rpcCodec) read(obj interface{}) (err error) {
if c.isClosed() {
return c.clsErr
if c.c != nil {
cls := c.cls.load()
if cls.closed {
return cls.errClosed
}
}
//If nil is passed in, we should read and discard
if obj == nil {
@ -129,24 +133,18 @@ func (c *rpcCodec) read(obj interface{}) (err error) {
return c.dec.Decode(obj)
}
func (c *rpcCodec) isClosed() (b bool) {
if c.c != nil {
c.clsmu.RLock()
b = c.cls
c.clsmu.RUnlock()
}
return
}
func (c *rpcCodec) Close() error {
if c.c == nil || c.isClosed() {
return c.clsErr
if c.c == nil {
return nil
}
c.clsmu.Lock()
c.cls = true
c.clsErr = c.c.Close()
c.clsmu.Unlock()
return c.clsErr
cls := c.cls.load()
if cls.closed {
return cls.errClosed
}
cls.errClosed = c.c.Close()
cls.closed = true
c.cls.store(cls)
return cls.errClosed
}
func (c *rpcCodec) ReadResponseBody(body interface{}) error {
@ -160,15 +158,10 @@ type goRpcCodec struct {
}
func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
// Must protect for concurrent access as per API
c.mu.Lock()
defer c.mu.Unlock()
return c.write(r, body, true)
}
func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
c.mu.Lock()
defer c.mu.Unlock()
return c.write(r, body, true)
}

View File

@ -36,12 +36,12 @@ type simpleEncDriver struct {
// encNoSeparator
e *Encoder
h *SimpleHandle
w encWriter
w *encWriterSwitch
b [8]byte
// c containerState
encDriverTrackContainerWriter
// encDriverNoopContainerWriter
_ [2]uint64 // padding
_ [3]uint64 // padding
}
func (e *simpleEncDriver) EncodeNil() {
@ -157,7 +157,11 @@ func (e *simpleEncDriver) WriteMapStart(length int) {
e.encLen(simpleVdMap, length)
}
func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
// func (e *simpleEncDriver) EncodeSymbol(v string) {
// e.EncodeString(cUTF8, v)
// }
func (e *simpleEncDriver) EncodeStringEnc(c charEncoding, v string) {
if false && e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == "" {
e.EncodeNil()
return
@ -166,11 +170,15 @@ func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
e.w.writestr(v)
}
// func (e *simpleEncDriver) EncodeSymbol(v string) {
// e.EncodeString(cUTF8, v)
// }
func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
e.EncodeStringEnc(c, v)
}
func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
e.EncodeStringBytesRaw(v)
}
func (e *simpleEncDriver) EncodeStringBytesRaw(v []byte) {
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
if v == nil {
e.EncodeNil()
@ -201,7 +209,7 @@ func (e *simpleEncDriver) EncodeTime(t time.Time) {
type simpleDecDriver struct {
d *Decoder
h *SimpleHandle
r decReader
r *decReaderSwitch
bdRead bool
bd byte
br bool // a bytes reader?
@ -210,7 +218,7 @@ type simpleDecDriver struct {
noBuiltInTypes
// noStreamingCodec
decDriverNoopContainerReader
_ [3]uint64 // padding
// _ [3]uint64 // padding
}
func (d *simpleDecDriver) readNextBd() {
@ -451,7 +459,7 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
d.bdRead = false
if zerocopy {
if d.br {
return d.r.readx(clen)
return d.r.readx(uint(clen))
} else if len(bs) == 0 {
bs = d.d.b[:]
}
@ -473,7 +481,7 @@ func (d *simpleDecDriver) DecodeTime() (t time.Time) {
}
d.bdRead = false
clen := int(d.r.readn1())
b := d.r.readx(clen)
b := d.r.readx(uint(clen))
if err := (&t).UnmarshalBinary(b); err != nil {
d.d.errorv(err)
}
@ -509,7 +517,11 @@ func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs [
d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
return
}
xbs = d.r.readx(l)
if d.br {
xbs = d.r.readx(uint(l))
} else {
xbs = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
}
case simpleVdByteArray, simpleVdByteArray + 1,
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
xbs = d.DecodeBytes(nil, true)
@ -526,7 +538,7 @@ func (d *simpleDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := d.d.naked()
var decodeFurther bool
switch d.bd {
@ -570,7 +582,11 @@ func (d *simpleDecDriver) DecodeNaked() {
n.v = valueTypeExt
l := d.decLen()
n.u = uint64(d.r.readn1())
n.l = d.r.readx(l)
if d.br {
n.l = d.r.readx(uint(l))
} else {
n.l = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
}
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
simpleVdArray + 3, simpleVdArray + 4:
n.v = valueTypeArray
@ -585,7 +601,6 @@ func (d *simpleDecDriver) DecodeNaked() {
if !decodeFurther {
d.bdRead = false
}
return
}
//------------------------------------

128
vendor/github.com/urfave/cli/app.go generated vendored
View File

@ -6,9 +6,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"time"
)
@ -19,11 +17,8 @@ var (
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
errNonFuncAction = NewExitError("ERROR invalid Action type. "+
fmt.Sprintf("Must be a func of type `cli.ActionFunc`. %s", contactSysadmin)+
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
errInvalidActionSignature = NewExitError("ERROR invalid Action signature. "+
fmt.Sprintf("Must be `cli.ActionFunc`. %s", contactSysadmin)+
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
)
@ -42,6 +37,8 @@ type App struct {
ArgsUsage string
// Version of the program
Version string
// Description of the program
Description string
// List of commands to execute
Commands []Command
// List of flags to parse
@ -62,10 +59,11 @@ type App struct {
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
After AfterFunc
// The action to execute when no subcommands are specified
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
// *Note*: support for the deprecated `Action` signature will be removed in a future version
Action interface{}
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
// of deprecation period has passed, maybe?
// Execute this function if the proper command cannot be found
CommandNotFound CommandNotFoundFunc
@ -87,6 +85,12 @@ type App struct {
ErrWriter io.Writer
// Other custom info
Metadata map[string]interface{}
// Carries a function which returns app specific info.
ExtraInfo func() map[string]string
// CustomAppHelpTemplate the text template for app help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomAppHelpTemplate string
didSetup bool
}
@ -147,10 +151,6 @@ func (a *App) Setup() {
}
}
if a.EnableBashCompletion {
a.appendFlag(BashCompletionFlag)
}
if !a.HideVersion {
a.appendFlag(VersionFlag)
}
@ -160,6 +160,14 @@ func (a *App) Setup() {
a.categories = a.categories.AddCommand(command.Category, command)
}
sort.Sort(a.categories)
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
if a.Writer == nil {
a.Writer = os.Stdout
}
}
// Run is the entry point to the cli app. Parses the arguments slice and routes
@ -167,8 +175,20 @@ func (a *App) Setup() {
func (a *App) Run(arguments []string) (err error) {
a.Setup()
// handle the completion flag separately from the flagset since
// completion could be attempted after a flag, but before its value was put
// on the command line. this causes the flagset to interpret the completion
// flag name as the value of the flag before it which is undesirable
// note that we can only do this because the shell autocomplete function
// always appends the completion flag at the end of the command
shellComplete, arguments := checkShellCompleteFlag(a, arguments)
// parse flags
set := flagSet(a.Name, a.Flags)
set, err := flagSet(a.Name, a.Flags)
if err != nil {
return err
}
set.SetOutput(ioutil.Discard)
err = set.Parse(arguments[1:])
nerr := normalizeFlags(a.Flags, set)
@ -178,6 +198,7 @@ func (a *App) Run(arguments []string) (err error) {
ShowAppHelp(context)
return nerr
}
context.shellComplete = shellComplete
if checkCompletions(context) {
return nil
@ -189,7 +210,7 @@ func (a *App) Run(arguments []string) (err error) {
HandleExitCoder(err)
return err
}
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
ShowAppHelp(context)
return err
}
@ -219,7 +240,6 @@ func (a *App) Run(arguments []string) (err error) {
if a.Before != nil {
beforeErr := a.Before(context)
if beforeErr != nil {
fmt.Fprintf(a.Writer, "%v\n\n", beforeErr)
ShowAppHelp(context)
HandleExitCoder(beforeErr)
err = beforeErr
@ -236,6 +256,10 @@ func (a *App) Run(arguments []string) (err error) {
}
}
if a.Action == nil {
a.Action = helpCommand.Action
}
// Run default Action
err = HandleAction(a.Action, context)
@ -243,11 +267,12 @@ func (a *App) Run(arguments []string) (err error) {
return err
}
// DEPRECATED: Another entry point to the cli app, takes care of passing arguments and error handling
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
// to cli.App.Run. This will cause the application to exit with the given eror
// code in the cli.ExitCoder
func (a *App) RunAndExitOnError() {
fmt.Fprintf(a.errWriter(),
"DEPRECATED cli.App.RunAndExitOnError. %s See %s\n",
contactSysadmin, runAndExitOnErrorDeprecationURL)
if err := a.Run(os.Args); err != nil {
fmt.Fprintln(a.errWriter(), err)
OsExiter(1)
@ -276,13 +301,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
}
a.Commands = newCmds
// append flags
if a.EnableBashCompletion {
a.appendFlag(BashCompletionFlag)
// parse flags
set, err := flagSet(a.Name, a.Flags)
if err != nil {
return err
}
// parse flags
set := flagSet(a.Name, a.Flags)
set.SetOutput(ioutil.Discard)
err = set.Parse(ctx.Args().Tail())
nerr := normalizeFlags(a.Flags, set)
@ -309,7 +333,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
HandleExitCoder(err)
return err
}
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
ShowSubcommandHelp(context)
return err
}
@ -450,50 +474,24 @@ type Author struct {
func (a Author) String() string {
e := ""
if a.Email != "" {
e = "<" + a.Email + "> "
e = " <" + a.Email + ">"
}
return fmt.Sprintf("%v %v", a.Name, e)
return fmt.Sprintf("%v%v", a.Name, e)
}
// HandleAction uses ✧✧✧reflection✧✧✧ to figure out if the given Action is an
// ActionFunc, a func with the legacy signature for Action, or some other
// invalid thing. If it's an ActionFunc or a func with the legacy signature for
// Action, the func is run!
// HandleAction attempts to figure out which Action signature was used. If
// it's an ActionFunc or a func with the legacy signature for Action, the func
// is run!
func HandleAction(action interface{}, context *Context) (err error) {
defer func() {
if r := recover(); r != nil {
// Try to detect a known reflection error from *this scope*, rather than
// swallowing all panics that may happen when calling an Action func.
s := fmt.Sprintf("%v", r)
if strings.HasPrefix(s, "reflect: ") && strings.Contains(s, "too many input arguments") {
err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
} else {
panic(r)
}
}
}()
if reflect.TypeOf(action).Kind() != reflect.Func {
return errNonFuncAction
}
vals := reflect.ValueOf(action).Call([]reflect.Value{reflect.ValueOf(context)})
if len(vals) == 0 {
fmt.Fprintf(ErrWriter,
"DEPRECATED Action signature. Must be `cli.ActionFunc`. %s See %s\n",
contactSysadmin, appActionDeprecationURL)
if a, ok := action.(ActionFunc); ok {
return a(context)
} else if a, ok := action.(func(*Context) error); ok {
return a(context)
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
a(context)
return nil
} else {
return errInvalidActionType
}
if len(vals) > 1 {
return errInvalidActionSignature
}
if retErr, ok := vals[0].Interface().(error); vals[0].IsValid() && ok {
return retErr
}
return err
}

View File

@ -12,8 +12,11 @@
// app.Usage = "say a greeting"
// app.Action = func(c *cli.Context) error {
// println("Greetings")
// return nil
// }
//
// app.Run(os.Args)
// }
package cli
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go

View File

@ -46,6 +46,11 @@ type Command struct {
Flags []Flag
// Treat all flags as normal arguments if true
SkipFlagParsing bool
// Skip argument reordering which attempts to move flags before arguments,
// but only works if all flags appear after all arguments. This behavior was
// removed n version 2 since it only works under specific conditions so we
// backport here by exposing it as an option for compatibility.
SkipArgReorder bool
// Boolean to hide built-in help command
HideHelp bool
// Boolean to hide this command from help or completion
@ -54,6 +59,25 @@ type Command struct {
// Full name of command for help, defaults to full command name, including parent commands.
HelpName string
commandNamePath []string
// CustomHelpTemplate the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomHelpTemplate string
}
type CommandsByName []Command
func (c CommandsByName) Len() int {
return len(c)
}
func (c CommandsByName) Less(i, j int) bool {
return c[i].Name < c[j].Name
}
func (c CommandsByName) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
// FullName returns the full name of the command.
@ -82,14 +106,15 @@ func (c Command) Run(ctx *Context) (err error) {
)
}
if ctx.App.EnableBashCompletion {
c.Flags = append(c.Flags, BashCompletionFlag)
set, err := flagSet(c.Name, c.Flags)
if err != nil {
return err
}
set := flagSet(c.Name, c.Flags)
set.SetOutput(ioutil.Discard)
if !c.SkipFlagParsing {
if c.SkipFlagParsing {
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
} else if !c.SkipArgReorder {
firstFlagIndex := -1
terminatorIndex := -1
for index, arg := range ctx.Args() {
@ -122,21 +147,7 @@ func (c Command) Run(ctx *Context) (err error) {
err = set.Parse(ctx.Args().Tail())
}
} else {
if c.SkipFlagParsing {
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
}
}
if err != nil {
if c.OnUsageError != nil {
err := c.OnUsageError(ctx, err, false)
HandleExitCoder(err)
return err
}
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
return err
err = set.Parse(ctx.Args().Tail())
}
nerr := normalizeFlags(c.Flags, set)
@ -148,11 +159,23 @@ func (c Command) Run(ctx *Context) (err error) {
}
context := NewContext(ctx.App, set, ctx)
context.Command = c
if checkCommandCompletions(context, c.Name) {
return nil
}
if err != nil {
if c.OnUsageError != nil {
err := c.OnUsageError(context, err, false)
HandleExitCoder(err)
return err
}
fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
fmt.Fprintln(context.App.Writer)
ShowCommandHelp(context, c.Name)
return err
}
if checkCommandHelp(context, c.Name) {
return nil
}
@ -174,15 +197,16 @@ func (c Command) Run(ctx *Context) (err error) {
if c.Before != nil {
err = c.Before(context)
if err != nil {
fmt.Fprintln(ctx.App.Writer, err)
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
ShowCommandHelp(context, c.Name)
HandleExitCoder(err)
return err
}
}
context.Command = c
if c.Action == nil {
c.Action = helpSubcommand.Action
}
err = HandleAction(c.Action, context)
if err != nil {
@ -223,14 +247,13 @@ func (c Command) startApp(ctx *Context) error {
app.HelpName = app.Name
}
if c.Description != "" {
app.Usage = c.Description
} else {
app.Usage = c.Usage
}
app.Usage = c.Usage
app.Description = c.Description
app.ArgsUsage = c.ArgsUsage
// set CommandNotFound
app.CommandNotFound = ctx.App.CommandNotFound
app.CustomAppHelpTemplate = c.CustomHelpTemplate
// set the flags and commands
app.Commands = c.Subcommands
@ -243,6 +266,7 @@ func (c Command) startApp(ctx *Context) error {
app.Author = ctx.App.Author
app.Email = ctx.App.Email
app.Writer = ctx.App.Writer
app.ErrWriter = ctx.App.ErrWriter
app.categories = CommandCategories{}
for _, command := range c.Subcommands {
@ -265,6 +289,7 @@ func (c Command) startApp(ctx *Context) error {
} else {
app.Action = helpSubcommand.Action
}
app.OnUsageError = c.OnUsageError
for index, cc := range app.Commands {
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}

View File

@ -3,9 +3,9 @@ package cli
import (
"errors"
"flag"
"strconv"
"reflect"
"strings"
"time"
"syscall"
)
// Context is a type that is passed through to
@ -13,201 +13,23 @@ import (
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
App *App
Command Command
flagSet *flag.FlagSet
setFlags map[string]bool
globalSetFlags map[string]bool
parentContext *Context
App *App
Command Command
shellComplete bool
flagSet *flag.FlagSet
setFlags map[string]bool
parentContext *Context
}
// NewContext creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
return &Context{App: app, flagSet: set, parentContext: parentCtx}
}
c := &Context{App: app, flagSet: set, parentContext: parentCtx}
// Int looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet)
}
// Int64 looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int64(name string) int64 {
return lookupInt64(name, c.flagSet)
}
// Uint looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Uint(name string) uint {
return lookupUint(name, c.flagSet)
}
// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Uint64(name string) uint64 {
return lookupUint64(name, c.flagSet)
}
// Duration looks up the value of a local time.Duration flag, returns 0 if no
// time.Duration flag exists
func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet)
}
// Float64 looks up the value of a local float64 flag, returns 0 if no float64
// flag exists
func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet)
}
// Bool looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet)
}
// BoolT looks up the value of a local boolT flag, returns false if no bool flag exists
func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet)
}
// String looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
return lookupString(name, c.flagSet)
}
// StringSlice looks up the value of a local string slice flag, returns nil if no
// string slice flag exists
func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet)
}
// IntSlice looks up the value of a local int slice flag, returns nil if no int
// slice flag exists
func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet)
}
// Int64Slice looks up the value of a local int slice flag, returns nil if no int
// slice flag exists
func (c *Context) Int64Slice(name string) []int64 {
return lookupInt64Slice(name, c.flagSet)
}
// Generic looks up the value of a local generic flag, returns nil if no generic
// flag exists
func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet)
}
// GlobalInt looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt(name, fs)
if parentCtx != nil {
c.shellComplete = parentCtx.shellComplete
}
return 0
}
// GlobalInt64 looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt64(name string) int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64(name, fs)
}
return 0
}
// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalUint(name string) uint {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint(name, fs)
}
return 0
}
// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalUint64(name string) uint64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint64(name, fs)
}
return 0
}
// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
// if no float64 flag exists
func (c *Context) GlobalFloat64(name string) float64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupFloat64(name, fs)
}
return float64(0)
}
// GlobalDuration looks up the value of a global time.Duration flag, returns 0
// if no time.Duration flag exists
func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupDuration(name, fs)
}
return 0
}
// GlobalBool looks up the value of a global bool flag, returns false if no bool
// flag exists
func (c *Context) GlobalBool(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBool(name, fs)
}
return false
}
// GlobalBoolT looks up the value of a global bool flag, returns true if no bool
// flag exists
func (c *Context) GlobalBoolT(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBoolT(name, fs)
}
return false
}
// GlobalString looks up the value of a global string flag, returns "" if no
// string flag exists
func (c *Context) GlobalString(name string) string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupString(name, fs)
}
return ""
}
// GlobalStringSlice looks up the value of a global string slice flag, returns
// nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupStringSlice(name, fs)
}
return nil
}
// GlobalIntSlice looks up the value of a global int slice flag, returns nil if
// no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupIntSlice(name, fs)
}
return nil
}
// GlobalInt64Slice looks up the value of a global int slice flag, returns nil if
// no int slice flag exists
func (c *Context) GlobalInt64Slice(name string) []int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64Slice(name, fs)
}
return nil
}
// GlobalGeneric looks up the value of a global generic flag, returns nil if no
// generic flag exists
func (c *Context) GlobalGeneric(name string) interface{} {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupGeneric(name, fs)
}
return nil
return c
}
// NumFlags returns the number of flags set
@ -217,11 +39,13 @@ func (c *Context) NumFlags() int {
// Set sets a context flag to a value.
func (c *Context) Set(name, value string) error {
c.setFlags = nil
return c.flagSet.Set(name, value)
}
// GlobalSet sets a context flag to a value on the global flagset
func (c *Context) GlobalSet(name, value string) error {
globalContext(c).setFlags = nil
return globalContext(c).flagSet.Set(name, value)
}
@ -229,28 +53,78 @@ func (c *Context) GlobalSet(name, value string) error {
func (c *Context) IsSet(name string) bool {
if c.setFlags == nil {
c.setFlags = make(map[string]bool)
c.flagSet.Visit(func(f *flag.Flag) {
c.setFlags[f.Name] = true
})
c.flagSet.VisitAll(func(f *flag.Flag) {
if _, ok := c.setFlags[f.Name]; ok {
return
}
c.setFlags[f.Name] = false
})
// XXX hack to support IsSet for flags with EnvVar
//
// There isn't an easy way to do this with the current implementation since
// whether a flag was set via an environment variable is very difficult to
// determine here. Instead, we intend to introduce a backwards incompatible
// change in version 2 to add `IsSet` to the Flag interface to push the
// responsibility closer to where the information required to determine
// whether a flag is set by non-standard means such as environment
// variables is avaliable.
//
// See https://github.com/urfave/cli/issues/294 for additional discussion
flags := c.Command.Flags
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
if c.App != nil {
flags = c.App.Flags
}
}
for _, f := range flags {
eachName(f.GetName(), func(name string) {
if isSet, ok := c.setFlags[name]; isSet || !ok {
return
}
val := reflect.ValueOf(f)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
envVarValue := val.FieldByName("EnvVar")
if !envVarValue.IsValid() {
return
}
eachName(envVarValue.String(), func(envVar string) {
envVar = strings.TrimSpace(envVar)
if _, ok := syscall.Getenv(envVar); ok {
c.setFlags[name] = true
return
}
})
})
}
}
return c.setFlags[name] == true
return c.setFlags[name]
}
// GlobalIsSet determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
if c.globalSetFlags == nil {
c.globalSetFlags = make(map[string]bool)
ctx := c
if ctx.parentContext != nil {
ctx = ctx.parentContext
}
for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext {
ctx.flagSet.Visit(func(f *flag.Flag) {
c.globalSetFlags[f.Name] = true
})
ctx := c
if ctx.parentContext != nil {
ctx = ctx.parentContext
}
for ; ctx != nil; ctx = ctx.parentContext {
if ctx.IsSet(name) {
return true
}
}
return c.globalSetFlags[name]
return false
}
// FlagNames returns a slice of flag names used in this context.
@ -282,6 +156,11 @@ func (c *Context) Parent() *Context {
return c.parentContext
}
// value returns the value of the flag coressponding to `name`
func (c *Context) value(name string) interface{} {
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
}
// Args contains apps console arguments
type Args []string
@ -357,156 +236,6 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
return nil
}
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return int(val)
}
return 0
}
func lookupInt64(name string, set *flag.FlagSet) int64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return val
}
return 0
}
func lookupUint(name string, set *flag.FlagSet) uint {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return uint(val)
}
return 0
}
func lookupUint64(name string, set *flag.FlagSet) uint64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return val
}
return 0
}
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
f := set.Lookup(name)
if f != nil {
val, err := time.ParseDuration(f.Value.String())
if err == nil {
return val
}
}
return 0
}
func lookupFloat64(name string, set *flag.FlagSet) float64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseFloat(f.Value.String(), 64)
if err != nil {
return 0
}
return val
}
return 0
}
func lookupString(name string, set *flag.FlagSet) string {
f := set.Lookup(name)
if f != nil {
return f.Value.String()
}
return ""
}
func lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*StringSlice)).Value()
}
return nil
}
func lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*IntSlice)).Value()
}
return nil
}
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*Int64Slice)).Value()
}
return nil
}
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
f := set.Lookup(name)
if f != nil {
return f.Value
}
return nil
}
func lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return val
}
return false
}
func lookupBoolT(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseBool(f.Value.String())
if err != nil {
return true
}
return val
}
return false
}
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) {
case *StringSlice:

View File

@ -24,7 +24,7 @@ func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}
// Error implents the error interface.
// Error implements the error interface.
func (m MultiError) Error() string {
errs := make([]string, len(m.Errors))
for i, err := range m.Errors {
@ -34,6 +34,10 @@ func (m MultiError) Error() string {
return strings.Join(errs, "\n")
}
type ErrorFormatter interface {
Format(s fmt.State, verb rune)
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type ExitCoder interface {
@ -44,11 +48,11 @@ type ExitCoder interface {
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type ExitError struct {
exitCode int
message string
message interface{}
}
// NewExitError makes a new *ExitError
func NewExitError(message string, exitCode int) *ExitError {
func NewExitError(message interface{}, exitCode int) *ExitError {
return &ExitError{
exitCode: exitCode,
message: message,
@ -58,7 +62,7 @@ func NewExitError(message string, exitCode int) *ExitError {
// Error returns the string message, fulfilling the interface required by
// `error`
func (ee *ExitError) Error() string {
return ee.message
return fmt.Sprintf("%v", ee.message)
}
// ExitCode returns the exit code, fulfilling the interface required by
@ -70,7 +74,7 @@ func (ee *ExitError) ExitCode() int {
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
// given exit code. If the given error is a MultiError, then this func is
// called on all members of the Errors slice.
// called on all members of the Errors slice and calls OsExiter with the last exit code.
func HandleExitCoder(err error) {
if err == nil {
return
@ -78,15 +82,34 @@ func HandleExitCoder(err error) {
if exitErr, ok := err.(ExitCoder); ok {
if err.Error() != "" {
fmt.Fprintln(ErrWriter, err)
if _, ok := exitErr.(ErrorFormatter); ok {
fmt.Fprintf(ErrWriter, "%+v\n", err)
} else {
fmt.Fprintln(ErrWriter, err)
}
}
OsExiter(exitErr.ExitCode())
return
}
if multiErr, ok := err.(MultiError); ok {
for _, merr := range multiErr.Errors {
HandleExitCoder(merr)
}
code := handleMultiError(multiErr)
OsExiter(code)
return
}
}
func handleMultiError(multiErr MultiError) int {
code := 1
for _, merr := range multiErr.Errors {
if multiErr2, ok := merr.(MultiError); ok {
code = handleMultiError(multiErr2)
} else {
fmt.Fprintln(ErrWriter, merr)
if exitErr, ok := merr.(ExitCoder); ok {
code = exitErr.ExitCode()
}
}
}
return code
}

523
vendor/github.com/urfave/cli/flag.go generated vendored
View File

@ -3,24 +3,24 @@ package cli
import (
"flag"
"fmt"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"syscall"
"time"
)
const defaultPlaceholder = "value"
// BashCompletionFlag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{
var BashCompletionFlag Flag = BoolFlag{
Name: "generate-bash-completion",
Hidden: true,
}
// VersionFlag prints the version for the application
var VersionFlag = BoolFlag{
var VersionFlag Flag = BoolFlag{
Name: "version, v",
Usage: "print the version",
}
@ -28,7 +28,7 @@ var VersionFlag = BoolFlag{
// HelpFlag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true)
var HelpFlag = BoolFlag{
var HelpFlag Flag = BoolFlag{
Name: "help, h",
Usage: "show help",
}
@ -37,6 +37,21 @@ var HelpFlag = BoolFlag{
// to display a flag.
var FlagStringer FlagStringFunc = stringifyFlag
// FlagsByName is a slice of Flag.
type FlagsByName []Flag
func (f FlagsByName) Len() int {
return len(f)
}
func (f FlagsByName) Less(i, j int) bool {
return f[i].GetName() < f[j].GetName()
}
func (f FlagsByName) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}
// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that
// this interface be implemented.
@ -47,13 +62,29 @@ type Flag interface {
GetName() string
}
func flagSet(name string, flags []Flag) *flag.FlagSet {
// errorableFlag is an interface that allows us to return errors during apply
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors
type errorableFlag interface {
Flag
ApplyWithError(*flag.FlagSet) error
}
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
set := flag.NewFlagSet(name, flag.ContinueOnError)
for _, f := range flags {
f.Apply(set)
//TODO remove in v2 when errorableFlag is removed
if ef, ok := f.(errorableFlag); ok {
if err := ef.ApplyWithError(set); err != nil {
return nil, err
}
} else {
f.Apply(set)
}
}
return set
return set, nil
}
func eachName(longName string, fn func(string)) {
@ -70,31 +101,24 @@ type Generic interface {
String() string
}
// GenericFlag is the flag type for types implementing Generic
type GenericFlag struct {
Name string
Value Generic
Usage string
EnvVar string
Hidden bool
}
// String returns the string representation of the generic flag to display the
// help text to the user (uses the String() method of the generic flag to show
// the value)
func (f GenericFlag) String() string {
return FlagStringer(f)
}
// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
// Ignores parsing errors
func (f GenericFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
val := f.Value
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
val.Set(envVal)
if envVal, ok := syscall.Getenv(envVar); ok {
if err := val.Set(envVal); err != nil {
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
}
break
}
}
@ -103,14 +127,11 @@ func (f GenericFlag) Apply(set *flag.FlagSet) {
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
return nil
}
// GetName returns the name of a flag.
func (f GenericFlag) GetName() string {
return f.Name
}
// StringSlice is an opaque type for []string to satisfy flag.Value
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
type StringSlice []string
// Set appends the string value to the list of values
@ -129,31 +150,29 @@ func (f *StringSlice) Value() []string {
return *f
}
// StringSliceFlag is a string flag that can be specified multiple times on the
// command-line
type StringSliceFlag struct {
Name string
Value *StringSlice
Usage string
EnvVar string
Hidden bool
}
// String returns the usage
func (f StringSliceFlag) String() string {
return FlagStringer(f)
// Get returns the slice of strings set by this flag
func (f *StringSlice) Get() interface{} {
return *f
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
newVal := &StringSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
newVal.Set(s)
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
}
}
f.Value = newVal
break
@ -167,14 +186,11 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) {
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// GetName returns the name of a flag.
func (f StringSliceFlag) GetName() string {
return f.Name
}
// IntSlice is an opaque type for []int to satisfy flag.Value
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
type IntSlice []int
// Set parses the value into an integer and appends it to the list of values
@ -197,33 +213,28 @@ func (f *IntSlice) Value() []int {
return *f
}
// IntSliceFlag is an int flag that can be specified multiple times on the
// command-line
type IntSliceFlag struct {
Name string
Value *IntSlice
Usage string
EnvVar string
Hidden bool
}
// String returns the usage
func (f IntSliceFlag) String() string {
return FlagStringer(f)
// Get returns the slice of ints set by this flag
func (f *IntSlice) Get() interface{} {
return *f
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
newVal := &IntSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
err := newVal.Set(s)
if err != nil {
fmt.Fprintf(ErrWriter, err.Error())
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
}
}
f.Value = newVal
@ -238,14 +249,11 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) {
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// GetName returns the name of the flag.
func (f IntSliceFlag) GetName() string {
return f.Name
}
// Int64Slice is an opaque type for []int to satisfy flag.Value
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
type Int64Slice []int64
// Set parses the value into an integer and appends it to the list of values
@ -268,33 +276,28 @@ func (f *Int64Slice) Value() []int64 {
return *f
}
// Int64SliceFlag is an int flag that can be specified multiple times on the
// command-line
type Int64SliceFlag struct {
Name string
Value *Int64Slice
Usage string
EnvVar string
Hidden bool
}
// String returns the usage
func (f Int64SliceFlag) String() string {
return FlagStringer(f)
// Get returns the slice of ints set by this flag
func (f *Int64Slice) Get() interface{} {
return *f
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
newVal := &Int64Slice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
err := newVal.Set(s)
if err != nil {
fmt.Fprintf(ErrWriter, err.Error())
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
}
}
f.Value = newVal
@ -309,38 +312,33 @@ func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
}
set.Var(f.Value, name, f.Usage)
})
}
// GetName returns the name of the flag.
func (f Int64SliceFlag) GetName() string {
return f.Name
}
// BoolFlag is a switch that defaults to false
type BoolFlag struct {
Name string
Usage string
EnvVar string
Destination *bool
Hidden bool
}
// String returns a readable representation of this value (for usage defaults)
func (f BoolFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
val := false
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
if envVal, ok := syscall.Getenv(envVar); ok {
if envVal == "" {
val = false
break
}
envValBool, err := strconv.ParseBool(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
}
val = envValBool
break
}
}
@ -353,40 +351,35 @@ func (f BoolFlag) Apply(set *flag.FlagSet) {
}
set.Bool(name, val, f.Usage)
})
}
// GetName returns the name of the flag.
func (f BoolFlag) GetName() string {
return f.Name
}
// BoolTFlag this represents a boolean flag that is true by default, but can
// still be set to false by --some-flag=false
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Destination *bool
Hidden bool
}
// String returns a readable representation of this value (for usage defaults)
func (f BoolTFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolTFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
val := true
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
if envVal, ok := syscall.Getenv(envVar); ok {
if envVal == "" {
val = false
break
}
envValBool, err := strconv.ParseBool(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
}
val = envValBool
break
}
}
}
@ -398,34 +391,22 @@ func (f BoolTFlag) Apply(set *flag.FlagSet) {
}
set.Bool(name, val, f.Usage)
})
}
// GetName returns the name of the flag.
func (f BoolTFlag) GetName() string {
return f.Name
}
// StringFlag represents a flag that takes as string value
type StringFlag struct {
Name string
Value string
Usage string
EnvVar string
Destination *string
Hidden bool
}
// String returns the usage
func (f StringFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
f.Value = envVal
break
}
@ -439,39 +420,28 @@ func (f StringFlag) Apply(set *flag.FlagSet) {
}
set.String(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f StringFlag) GetName() string {
return f.Name
}
// IntFlag is a flag that takes an integer
type IntFlag struct {
Name string
Value int
Usage string
EnvVar string
Destination *int
Hidden bool
}
// String returns the usage
func (f IntFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err == nil {
f.Value = int(envValInt)
break
if err != nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
}
f.Value = int(envValInt)
break
}
}
}
@ -483,39 +453,29 @@ func (f IntFlag) Apply(set *flag.FlagSet) {
}
set.Int(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f IntFlag) GetName() string {
return f.Name
}
// Int64Flag is a flag that takes a 64-bit integer
type Int64Flag struct {
Name string
Value int64
Usage string
EnvVar string
Destination *int64
Hidden bool
}
// String returns the usage
func (f Int64Flag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err == nil {
f.Value = envValInt
break
if err != nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValInt
break
}
}
}
@ -527,39 +487,29 @@ func (f Int64Flag) Apply(set *flag.FlagSet) {
}
set.Int64(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f Int64Flag) GetName() string {
return f.Name
}
// UintFlag is a flag that takes an unsigned integer
type UintFlag struct {
Name string
Value uint
Usage string
EnvVar string
Destination *uint
Hidden bool
}
// String returns the usage
func (f UintFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f UintFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err == nil {
f.Value = uint(envValInt)
break
if err != nil {
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
}
f.Value = uint(envValInt)
break
}
}
}
@ -571,39 +521,29 @@ func (f UintFlag) Apply(set *flag.FlagSet) {
}
set.Uint(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f UintFlag) GetName() string {
return f.Name
}
// Uint64Flag is a flag that takes an unsigned 64-bit integer
type Uint64Flag struct {
Name string
Value uint64
Usage string
EnvVar string
Destination *uint64
Hidden bool
}
// String returns the usage
func (f Uint64Flag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Uint64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err == nil {
f.Value = uint64(envValInt)
break
if err != nil {
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
}
f.Value = uint64(envValInt)
break
}
}
}
@ -615,40 +555,29 @@ func (f Uint64Flag) Apply(set *flag.FlagSet) {
}
set.Uint64(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f Uint64Flag) GetName() string {
return f.Name
}
// DurationFlag is a flag that takes a duration specified in Go's duration
// format: https://golang.org/pkg/time/#ParseDuration
type DurationFlag struct {
Name string
Value time.Duration
Usage string
EnvVar string
Destination *time.Duration
Hidden bool
}
// String returns a readable representation of this value (for usage defaults)
func (f DurationFlag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f DurationFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValDuration, err := time.ParseDuration(envVal)
if err == nil {
f.Value = envValDuration
break
if err != nil {
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValDuration
break
}
}
}
@ -660,38 +589,29 @@ func (f DurationFlag) Apply(set *flag.FlagSet) {
}
set.Duration(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f DurationFlag) GetName() string {
return f.Name
}
// Float64Flag is a flag that takes an float value
type Float64Flag struct {
Name string
Value float64
Usage string
EnvVar string
Destination *float64
Hidden bool
}
// String returns the usage
func (f Float64Flag) String() string {
return FlagStringer(f)
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Float64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if envVal, ok := syscall.Getenv(envVar); ok {
envValFloat, err := strconv.ParseFloat(envVal, 10)
if err == nil {
f.Value = float64(envValFloat)
if err != nil {
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
}
f.Value = float64(envValFloat)
break
}
}
}
@ -703,17 +623,15 @@ func (f Float64Flag) Apply(set *flag.FlagSet) {
}
set.Float64(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f Float64Flag) GetName() string {
return f.Name
return nil
}
func visibleFlags(fl []Flag) []Flag {
visible := []Flag{}
for _, flag := range fl {
if !flagValue(flag).FieldByName("Hidden").Bool() {
field := flagValue(flag).FieldByName("Hidden")
if !field.IsValid() || !field.Bool() {
visible = append(visible, flag)
}
}
@ -806,9 +724,8 @@ func stringifyFlag(f Flag) string {
needsPlaceholder := false
defaultValueString := ""
val := fv.FieldByName("Value")
if val.IsValid() {
if val := fv.FieldByName("Value"); val.IsValid() {
needsPlaceholder = true
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())

627
vendor/github.com/urfave/cli/flag_generated.go generated vendored Normal file
View File

@ -0,0 +1,627 @@
package cli
import (
"flag"
"strconv"
"time"
)
// WARNING: This file is generated!
// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolFlag) GetName() string {
return f.Name
}
// Bool looks up the value of a local BoolFlag, returns
// false if not found
func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet)
}
// GlobalBool looks up the value of a global BoolFlag, returns
// false if not found
func (c *Context) GlobalBool(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBool(name, fs)
}
return false
}
func lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}
// BoolTFlag is a flag with type bool that is true by default
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolTFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolTFlag) GetName() string {
return f.Name
}
// BoolT looks up the value of a local BoolTFlag, returns
// false if not found
func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet)
}
// GlobalBoolT looks up the value of a global BoolTFlag, returns
// false if not found
func (c *Context) GlobalBoolT(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBoolT(name, fs)
}
return false
}
func lookupBoolT(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value time.Duration
Destination *time.Duration
}
// String returns a readable representation of this value
// (for usage defaults)
func (f DurationFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f DurationFlag) GetName() string {
return f.Name
}
// Duration looks up the value of a local DurationFlag, returns
// 0 if not found
func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet)
}
// GlobalDuration looks up the value of a global DurationFlag, returns
// 0 if not found
func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupDuration(name, fs)
}
return 0
}
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
f := set.Lookup(name)
if f != nil {
parsed, err := time.ParseDuration(f.Value.String())
if err != nil {
return 0
}
return parsed
}
return 0
}
// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value float64
Destination *float64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Float64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Float64Flag) GetName() string {
return f.Name
}
// Float64 looks up the value of a local Float64Flag, returns
// 0 if not found
func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet)
}
// GlobalFloat64 looks up the value of a global Float64Flag, returns
// 0 if not found
func (c *Context) GlobalFloat64(name string) float64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupFloat64(name, fs)
}
return 0
}
func lookupFloat64(name string, set *flag.FlagSet) float64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// GenericFlag is a flag with type Generic
type GenericFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value Generic
}
// String returns a readable representation of this value
// (for usage defaults)
func (f GenericFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f GenericFlag) GetName() string {
return f.Name
}
// Generic looks up the value of a local GenericFlag, returns
// nil if not found
func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet)
}
// GlobalGeneric looks up the value of a global GenericFlag, returns
// nil if not found
func (c *Context) GlobalGeneric(name string) interface{} {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupGeneric(name, fs)
}
return nil
}
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value, error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Int64Flag is a flag with type int64
type Int64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value int64
Destination *int64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64Flag) GetName() string {
return f.Name
}
// Int64 looks up the value of a local Int64Flag, returns
// 0 if not found
func (c *Context) Int64(name string) int64 {
return lookupInt64(name, c.flagSet)
}
// GlobalInt64 looks up the value of a global Int64Flag, returns
// 0 if not found
func (c *Context) GlobalInt64(name string) int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64(name, fs)
}
return 0
}
func lookupInt64(name string, set *flag.FlagSet) int64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// IntFlag is a flag with type int
type IntFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value int
Destination *int
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntFlag) GetName() string {
return f.Name
}
// Int looks up the value of a local IntFlag, returns
// 0 if not found
func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet)
}
// GlobalInt looks up the value of a global IntFlag, returns
// 0 if not found
func (c *Context) GlobalInt(name string) int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt(name, fs)
}
return 0
}
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return int(parsed)
}
return 0
}
// IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *IntSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntSliceFlag) GetName() string {
return f.Name
}
// IntSlice looks up the value of a local IntSliceFlag, returns
// nil if not found
func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet)
}
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
// nil if not found
func (c *Context) GlobalIntSlice(name string) []int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupIntSlice(name, fs)
}
return nil
}
func lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *Int64Slice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64SliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64SliceFlag) GetName() string {
return f.Name
}
// Int64Slice looks up the value of a local Int64SliceFlag, returns
// nil if not found
func (c *Context) Int64Slice(name string) []int64 {
return lookupInt64Slice(name, c.flagSet)
}
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
// nil if not found
func (c *Context) GlobalInt64Slice(name string) []int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64Slice(name, fs)
}
return nil
}
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// StringFlag is a flag with type string
type StringFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value string
Destination *string
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringFlag) GetName() string {
return f.Name
}
// String looks up the value of a local StringFlag, returns
// "" if not found
func (c *Context) String(name string) string {
return lookupString(name, c.flagSet)
}
// GlobalString looks up the value of a global StringFlag, returns
// "" if not found
func (c *Context) GlobalString(name string) string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupString(name, fs)
}
return ""
}
func lookupString(name string, set *flag.FlagSet) string {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value.String(), error(nil)
if err != nil {
return ""
}
return parsed
}
return ""
}
// StringSliceFlag is a flag with type *StringSlice
type StringSliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *StringSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringSliceFlag) GetName() string {
return f.Name
}
// StringSlice looks up the value of a local StringSliceFlag, returns
// nil if not found
func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet)
}
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
// nil if not found
func (c *Context) GlobalStringSlice(name string) []string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupStringSlice(name, fs)
}
return nil
}
func lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Uint64Flag is a flag with type uint64
type Uint64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value uint64
Destination *uint64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Uint64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Uint64Flag) GetName() string {
return f.Name
}
// Uint64 looks up the value of a local Uint64Flag, returns
// 0 if not found
func (c *Context) Uint64(name string) uint64 {
return lookupUint64(name, c.flagSet)
}
// GlobalUint64 looks up the value of a global Uint64Flag, returns
// 0 if not found
func (c *Context) GlobalUint64(name string) uint64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint64(name, fs)
}
return 0
}
func lookupUint64(name string, set *flag.FlagSet) uint64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// UintFlag is a flag with type uint
type UintFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value uint
Destination *uint
}
// String returns a readable representation of this value
// (for usage defaults)
func (f UintFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f UintFlag) GetName() string {
return f.Name
}
// Uint looks up the value of a local UintFlag, returns
// 0 if not found
func (c *Context) Uint(name string) uint {
return lookupUint(name, c.flagSet)
}
// GlobalUint looks up the value of a global UintFlag, returns
// 0 if not found
func (c *Context) GlobalUint(name string) uint {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint(name, fs)
}
return 0
}
func lookupUint(name string, set *flag.FlagSet) uint {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return uint(parsed)
}
return 0
}

141
vendor/github.com/urfave/cli/help.go generated vendored
View File

@ -13,27 +13,31 @@ import (
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var AppHelpTemplate = `NAME:
{{.Name}} - {{.Usage}}
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
{{if .Version}}{{if not .HideVersion}}
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}
{{end}}{{end}}{{if len .Authors}}
AUTHOR(S):
{{range .Authors}}{{.}}{{end}}
{{end}}{{if .VisibleCommands}}
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{end}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
{{end}}{{end}}{{if .VisibleFlags}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}{{if .Copyright}}
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}
{{end}}
{{.Copyright}}{{end}}
`
// CommandHelpTemplate is the text template for the command help topic.
@ -43,7 +47,7 @@ var CommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}}
USAGE:
{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
CATEGORY:
{{.Category}}{{end}}{{if .Description}}
@ -60,10 +64,10 @@ OPTIONS:
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var SubcommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}}
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
USAGE:
{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{end}}{{range .VisibleCommands}}
@ -108,17 +112,42 @@ var helpSubcommand = Command{
// Prints help for the App or Command
type helpPrinter func(w io.Writer, templ string, data interface{})
// Prints help for the App or Command with custom template function.
type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{})
// HelpPrinter is a function that writes the help output. If not set a default
// is used. The function signature is:
// func(w io.Writer, templ string, data interface{})
var HelpPrinter helpPrinter = printHelp
// HelpPrinterCustom is same as HelpPrinter but
// takes a custom function for template function map.
var HelpPrinterCustom helpPrinterCustom = printHelpCustom
// VersionPrinter prints the version for the App
var VersionPrinter = printVersion
// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code.
func ShowAppHelpAndExit(c *Context, exitCode int) {
ShowAppHelp(c)
os.Exit(exitCode)
}
// ShowAppHelp is an action that displays the help.
func ShowAppHelp(c *Context) error {
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
func ShowAppHelp(c *Context) (err error) {
if c.App.CustomAppHelpTemplate == "" {
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
return
}
customAppData := func() map[string]interface{} {
if c.App.ExtraInfo == nil {
return nil
}
return map[string]interface{}{
"ExtraInfo": c.App.ExtraInfo,
}
}
HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData())
return nil
}
@ -134,6 +163,12 @@ func DefaultAppComplete(c *Context) {
}
}
// ShowCommandHelpAndExit - exits with code after showing help
func ShowCommandHelpAndExit(c *Context, command string, code int) {
ShowCommandHelp(c, command)
os.Exit(code)
}
// ShowCommandHelp prints help for the given command
func ShowCommandHelp(ctx *Context, command string) error {
// show the subcommand help for a command with subcommands
@ -144,7 +179,11 @@ func ShowCommandHelp(ctx *Context, command string) error {
for _, c := range ctx.App.Commands {
if c.HasName(command) {
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
if c.CustomHelpTemplate != "" {
HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil)
} else {
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
}
return nil
}
}
@ -187,10 +226,15 @@ func ShowCommandCompletions(ctx *Context, command string) {
}
}
func printHelp(out io.Writer, templ string, data interface{}) {
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
funcMap := template.FuncMap{
"join": strings.Join,
}
if customFunc != nil {
for key, value := range customFunc {
funcMap[key] = value
}
}
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
@ -206,10 +250,14 @@ func printHelp(out io.Writer, templ string, data interface{}) {
w.Flush()
}
func printHelp(out io.Writer, templ string, data interface{}) {
printHelpCustom(out, templ, data, nil)
}
func checkVersion(c *Context) bool {
found := false
if VersionFlag.Name != "" {
eachName(VersionFlag.Name, func(name string) {
if VersionFlag.GetName() != "" {
eachName(VersionFlag.GetName(), func(name string) {
if c.GlobalBool(name) || c.Bool(name) {
found = true
}
@ -220,8 +268,8 @@ func checkVersion(c *Context) bool {
func checkHelp(c *Context) bool {
found := false
if HelpFlag.Name != "" {
eachName(HelpFlag.Name, func(name string) {
if HelpFlag.GetName() != "" {
eachName(HelpFlag.GetName(), func(name string) {
if c.GlobalBool(name) || c.Bool(name) {
found = true
}
@ -240,7 +288,7 @@ func checkCommandHelp(c *Context, name string) bool {
}
func checkSubcommandHelp(c *Context) bool {
if c.GlobalBool("h") || c.GlobalBool("help") {
if c.Bool("h") || c.Bool("help") {
ShowSubcommandHelp(c)
return true
}
@ -248,20 +296,43 @@ func checkSubcommandHelp(c *Context) bool {
return false
}
func checkCompletions(c *Context) bool {
if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
ShowCompletions(c)
return true
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
if !a.EnableBashCompletion {
return false, arguments
}
return false
pos := len(arguments) - 1
lastArg := arguments[pos]
if lastArg != "--"+BashCompletionFlag.GetName() {
return false, arguments
}
return true, arguments[:pos]
}
func checkCompletions(c *Context) bool {
if !c.shellComplete {
return false
}
if args := c.Args(); args.Present() {
name := args.First()
if cmd := c.App.Command(name); cmd != nil {
// let the command handle the completion
return false
}
}
ShowCompletions(c)
return true
}
func checkCommandCompletions(c *Context, name string) bool {
if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
ShowCommandCompletions(c, name)
return true
if !c.shellComplete {
return false
}
return false
ShowCommandCompletions(c, name)
return true
}