aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dustin
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dustin')
-rw-r--r--vendor/github.com/dustin/go-humanize/.travis.yml21
-rw-r--r--vendor/github.com/dustin/go-humanize/LICENSE21
-rw-r--r--vendor/github.com/dustin/go-humanize/README.markdown124
-rw-r--r--vendor/github.com/dustin/go-humanize/big.go31
-rw-r--r--vendor/github.com/dustin/go-humanize/bigbytes.go189
-rw-r--r--vendor/github.com/dustin/go-humanize/bytes.go143
-rw-r--r--vendor/github.com/dustin/go-humanize/comma.go116
-rw-r--r--vendor/github.com/dustin/go-humanize/commaf.go41
-rw-r--r--vendor/github.com/dustin/go-humanize/ftoa.go49
-rw-r--r--vendor/github.com/dustin/go-humanize/humanize.go8
-rw-r--r--vendor/github.com/dustin/go-humanize/number.go192
-rw-r--r--vendor/github.com/dustin/go-humanize/ordinals.go25
-rw-r--r--vendor/github.com/dustin/go-humanize/si.go127
-rw-r--r--vendor/github.com/dustin/go-humanize/times.go117
14 files changed, 1204 insertions, 0 deletions
diff --git a/vendor/github.com/dustin/go-humanize/.travis.yml b/vendor/github.com/dustin/go-humanize/.travis.yml
new file mode 100644
index 0000000..ac12e48
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/.travis.yml
@@ -0,0 +1,21 @@
1sudo: false
2language: go
3go_import_path: github.com/dustin/go-humanize
4go:
5 - 1.13.x
6 - 1.14.x
7 - 1.15.x
8 - 1.16.x
9 - stable
10 - master
11matrix:
12 allow_failures:
13 - go: master
14 fast_finish: true
15install:
16 - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
17script:
18 - diff -u <(echo -n) <(gofmt -d -s .)
19 - go vet .
20 - go install -v -race ./...
21 - go test -v -race ./...
diff --git a/vendor/github.com/dustin/go-humanize/LICENSE b/vendor/github.com/dustin/go-humanize/LICENSE
new file mode 100644
index 0000000..8d9a94a
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/LICENSE
@@ -0,0 +1,21 @@
1Copyright (c) 2005-2008 Dustin Sallings <[email protected]>
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is
8furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
20
21<http://www.opensource.org/licenses/mit-license.php>
diff --git a/vendor/github.com/dustin/go-humanize/README.markdown b/vendor/github.com/dustin/go-humanize/README.markdown
new file mode 100644
index 0000000..7d0b16b
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/README.markdown
@@ -0,0 +1,124 @@
1# Humane Units [![Build Status](https://travis-ci.org/dustin/go-humanize.svg?branch=master)](https://travis-ci.org/dustin/go-humanize) [![GoDoc](https://godoc.org/github.com/dustin/go-humanize?status.svg)](https://godoc.org/github.com/dustin/go-humanize)
2
3Just a few functions for helping humanize times and sizes.
4
5`go get` it as `github.com/dustin/go-humanize`, import it as
6`"github.com/dustin/go-humanize"`, use it as `humanize`.
7
8See [godoc](https://pkg.go.dev/github.com/dustin/go-humanize) for
9complete documentation.
10
11## Sizes
12
13This lets you take numbers like `82854982` and convert them to useful
14strings like, `83 MB` or `79 MiB` (whichever you prefer).
15
16Example:
17
18```go
19fmt.Printf("That file is %s.", humanize.Bytes(82854982)) // That file is 83 MB.
20```
21
22## Times
23
24This lets you take a `time.Time` and spit it out in relative terms.
25For example, `12 seconds ago` or `3 days from now`.
26
27Example:
28
29```go
30fmt.Printf("This was touched %s.", humanize.Time(someTimeInstance)) // This was touched 7 hours ago.
31```
32
33Thanks to Kyle Lemons for the time implementation from an IRC
34conversation one day. It's pretty neat.
35
36## Ordinals
37
38From a [mailing list discussion][odisc] where a user wanted to be able
39to label ordinals.
40
41 0 -> 0th
42 1 -> 1st
43 2 -> 2nd
44 3 -> 3rd
45 4 -> 4th
46 [...]
47
48Example:
49
50```go
51fmt.Printf("You're my %s best friend.", humanize.Ordinal(193)) // You are my 193rd best friend.
52```
53
54## Commas
55
56Want to shove commas into numbers? Be my guest.
57
58 0 -> 0
59 100 -> 100
60 1000 -> 1,000
61 1000000000 -> 1,000,000,000
62 -100000 -> -100,000
63
64Example:
65
66```go
67fmt.Printf("You owe $%s.\n", humanize.Comma(6582491)) // You owe $6,582,491.
68```
69
70## Ftoa
71
72Nicer float64 formatter that removes trailing zeros.
73
74```go
75fmt.Printf("%f", 2.24) // 2.240000
76fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24
77fmt.Printf("%f", 2.0) // 2.000000
78fmt.Printf("%s", humanize.Ftoa(2.0)) // 2
79```
80
81## SI notation
82
83Format numbers with [SI notation][sinotation].
84
85Example:
86
87```go
88humanize.SI(0.00000000223, "M") // 2.23 nM
89```
90
91## English-specific functions
92
93The following functions are in the `humanize/english` subpackage.
94
95### Plurals
96
97Simple English pluralization
98
99```go
100english.PluralWord(1, "object", "") // object
101english.PluralWord(42, "object", "") // objects
102english.PluralWord(2, "bus", "") // buses
103english.PluralWord(99, "locus", "loci") // loci
104
105english.Plural(1, "object", "") // 1 object
106english.Plural(42, "object", "") // 42 objects
107english.Plural(2, "bus", "") // 2 buses
108english.Plural(99, "locus", "loci") // 99 loci
109```
110
111### Word series
112
113Format comma-separated words lists with conjuctions:
114
115```go
116english.WordSeries([]string{"foo"}, "and") // foo
117english.WordSeries([]string{"foo", "bar"}, "and") // foo and bar
118english.WordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar and baz
119
120english.OxfordWordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar, and baz
121```
122
123[odisc]: https://groups.google.com/d/topic/golang-nuts/l8NhI74jl-4/discussion
124[sinotation]: http://en.wikipedia.org/wiki/Metric_prefix
diff --git a/vendor/github.com/dustin/go-humanize/big.go b/vendor/github.com/dustin/go-humanize/big.go
new file mode 100644
index 0000000..f49dc33
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/big.go
@@ -0,0 +1,31 @@
1package humanize
2
3import (
4 "math/big"
5)
6
7// order of magnitude (to a max order)
8func oomm(n, b *big.Int, maxmag int) (float64, int) {
9 mag := 0
10 m := &big.Int{}
11 for n.Cmp(b) >= 0 {
12 n.DivMod(n, b, m)
13 mag++
14 if mag == maxmag && maxmag >= 0 {
15 break
16 }
17 }
18 return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
19}
20
21// total order of magnitude
22// (same as above, but with no upper limit)
23func oom(n, b *big.Int) (float64, int) {
24 mag := 0
25 m := &big.Int{}
26 for n.Cmp(b) >= 0 {
27 n.DivMod(n, b, m)
28 mag++
29 }
30 return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
31}
diff --git a/vendor/github.com/dustin/go-humanize/bigbytes.go b/vendor/github.com/dustin/go-humanize/bigbytes.go
new file mode 100644
index 0000000..3b015fd
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/bigbytes.go
@@ -0,0 +1,189 @@
1package humanize
2
3import (
4 "fmt"
5 "math/big"
6 "strings"
7 "unicode"
8)
9
10var (
11 bigIECExp = big.NewInt(1024)
12
13 // BigByte is one byte in bit.Ints
14 BigByte = big.NewInt(1)
15 // BigKiByte is 1,024 bytes in bit.Ints
16 BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp)
17 // BigMiByte is 1,024 k bytes in bit.Ints
18 BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp)
19 // BigGiByte is 1,024 m bytes in bit.Ints
20 BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp)
21 // BigTiByte is 1,024 g bytes in bit.Ints
22 BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp)
23 // BigPiByte is 1,024 t bytes in bit.Ints
24 BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp)
25 // BigEiByte is 1,024 p bytes in bit.Ints
26 BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp)
27 // BigZiByte is 1,024 e bytes in bit.Ints
28 BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp)
29 // BigYiByte is 1,024 z bytes in bit.Ints
30 BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp)
31 // BigRiByte is 1,024 y bytes in bit.Ints
32 BigRiByte = (&big.Int{}).Mul(BigYiByte, bigIECExp)
33 // BigQiByte is 1,024 r bytes in bit.Ints
34 BigQiByte = (&big.Int{}).Mul(BigRiByte, bigIECExp)
35)
36
37var (
38 bigSIExp = big.NewInt(1000)
39
40 // BigSIByte is one SI byte in big.Ints
41 BigSIByte = big.NewInt(1)
42 // BigKByte is 1,000 SI bytes in big.Ints
43 BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp)
44 // BigMByte is 1,000 SI k bytes in big.Ints
45 BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp)
46 // BigGByte is 1,000 SI m bytes in big.Ints
47 BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp)
48 // BigTByte is 1,000 SI g bytes in big.Ints
49 BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp)
50 // BigPByte is 1,000 SI t bytes in big.Ints
51 BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp)
52 // BigEByte is 1,000 SI p bytes in big.Ints
53 BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp)
54 // BigZByte is 1,000 SI e bytes in big.Ints
55 BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
56 // BigYByte is 1,000 SI z bytes in big.Ints
57 BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
58 // BigRByte is 1,000 SI y bytes in big.Ints
59 BigRByte = (&big.Int{}).Mul(BigYByte, bigSIExp)
60 // BigQByte is 1,000 SI r bytes in big.Ints
61 BigQByte = (&big.Int{}).Mul(BigRByte, bigSIExp)
62)
63
64var bigBytesSizeTable = map[string]*big.Int{
65 "b": BigByte,
66 "kib": BigKiByte,
67 "kb": BigKByte,
68 "mib": BigMiByte,
69 "mb": BigMByte,
70 "gib": BigGiByte,
71 "gb": BigGByte,
72 "tib": BigTiByte,
73 "tb": BigTByte,
74 "pib": BigPiByte,
75 "pb": BigPByte,
76 "eib": BigEiByte,
77 "eb": BigEByte,
78 "zib": BigZiByte,
79 "zb": BigZByte,
80 "yib": BigYiByte,
81 "yb": BigYByte,
82 "rib": BigRiByte,
83 "rb": BigRByte,
84 "qib": BigQiByte,
85 "qb": BigQByte,
86 // Without suffix
87 "": BigByte,
88 "ki": BigKiByte,
89 "k": BigKByte,
90 "mi": BigMiByte,
91 "m": BigMByte,
92 "gi": BigGiByte,
93 "g": BigGByte,
94 "ti": BigTiByte,
95 "t": BigTByte,
96 "pi": BigPiByte,
97 "p": BigPByte,
98 "ei": BigEiByte,
99 "e": BigEByte,
100 "z": BigZByte,
101 "zi": BigZiByte,
102 "y": BigYByte,
103 "yi": BigYiByte,
104 "r": BigRByte,
105 "ri": BigRiByte,
106 "q": BigQByte,
107 "qi": BigQiByte,
108}
109
110var ten = big.NewInt(10)
111
112func humanateBigBytes(s, base *big.Int, sizes []string) string {
113 if s.Cmp(ten) < 0 {
114 return fmt.Sprintf("%d B", s)
115 }
116 c := (&big.Int{}).Set(s)
117 val, mag := oomm(c, base, len(sizes)-1)
118 suffix := sizes[mag]
119 f := "%.0f %s"
120 if val < 10 {
121 f = "%.1f %s"
122 }
123
124 return fmt.Sprintf(f, val, suffix)
125
126}
127
128// BigBytes produces a human readable representation of an SI size.
129//
130// See also: ParseBigBytes.
131//
132// BigBytes(82854982) -> 83 MB
133func BigBytes(s *big.Int) string {
134 sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"}
135 return humanateBigBytes(s, bigSIExp, sizes)
136}
137
138// BigIBytes produces a human readable representation of an IEC size.
139//
140// See also: ParseBigBytes.
141//
142// BigIBytes(82854982) -> 79 MiB
143func BigIBytes(s *big.Int) string {
144 sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}
145 return humanateBigBytes(s, bigIECExp, sizes)
146}
147
148// ParseBigBytes parses a string representation of bytes into the number
149// of bytes it represents.
150//
151// See also: BigBytes, BigIBytes.
152//
153// ParseBigBytes("42 MB") -> 42000000, nil
154// ParseBigBytes("42 mib") -> 44040192, nil
155func ParseBigBytes(s string) (*big.Int, error) {
156 lastDigit := 0
157 hasComma := false
158 for _, r := range s {
159 if !(unicode.IsDigit(r) || r == '.' || r == ',') {
160 break
161 }
162 if r == ',' {
163 hasComma = true
164 }
165 lastDigit++
166 }
167
168 num := s[:lastDigit]
169 if hasComma {
170 num = strings.Replace(num, ",", "", -1)
171 }
172
173 val := &big.Rat{}
174 _, err := fmt.Sscanf(num, "%f", val)
175 if err != nil {
176 return nil, err
177 }
178
179 extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
180 if m, ok := bigBytesSizeTable[extra]; ok {
181 mv := (&big.Rat{}).SetInt(m)
182 val.Mul(val, mv)
183 rv := &big.Int{}
184 rv.Div(val.Num(), val.Denom())
185 return rv, nil
186 }
187
188 return nil, fmt.Errorf("unhandled size name: %v", extra)
189}
diff --git a/vendor/github.com/dustin/go-humanize/bytes.go b/vendor/github.com/dustin/go-humanize/bytes.go
new file mode 100644
index 0000000..0b498f4
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/bytes.go
@@ -0,0 +1,143 @@
1package humanize
2
3import (
4 "fmt"
5 "math"
6 "strconv"
7 "strings"
8 "unicode"
9)
10
11// IEC Sizes.
12// kibis of bits
13const (
14 Byte = 1 << (iota * 10)
15 KiByte
16 MiByte
17 GiByte
18 TiByte
19 PiByte
20 EiByte
21)
22
23// SI Sizes.
24const (
25 IByte = 1
26 KByte = IByte * 1000
27 MByte = KByte * 1000
28 GByte = MByte * 1000
29 TByte = GByte * 1000
30 PByte = TByte * 1000
31 EByte = PByte * 1000
32)
33
34var bytesSizeTable = map[string]uint64{
35 "b": Byte,
36 "kib": KiByte,
37 "kb": KByte,
38 "mib": MiByte,
39 "mb": MByte,
40 "gib": GiByte,
41 "gb": GByte,
42 "tib": TiByte,
43 "tb": TByte,
44 "pib": PiByte,
45 "pb": PByte,
46 "eib": EiByte,
47 "eb": EByte,
48 // Without suffix
49 "": Byte,
50 "ki": KiByte,
51 "k": KByte,
52 "mi": MiByte,
53 "m": MByte,
54 "gi": GiByte,
55 "g": GByte,
56 "ti": TiByte,
57 "t": TByte,
58 "pi": PiByte,
59 "p": PByte,
60 "ei": EiByte,
61 "e": EByte,
62}
63
64func logn(n, b float64) float64 {
65 return math.Log(n) / math.Log(b)
66}
67
68func humanateBytes(s uint64, base float64, sizes []string) string {
69 if s < 10 {
70 return fmt.Sprintf("%d B", s)
71 }
72 e := math.Floor(logn(float64(s), base))
73 suffix := sizes[int(e)]
74 val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10
75 f := "%.0f %s"
76 if val < 10 {
77 f = "%.1f %s"
78 }
79
80 return fmt.Sprintf(f, val, suffix)
81}
82
83// Bytes produces a human readable representation of an SI size.
84//
85// See also: ParseBytes.
86//
87// Bytes(82854982) -> 83 MB
88func Bytes(s uint64) string {
89 sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"}
90 return humanateBytes(s, 1000, sizes)
91}
92
93// IBytes produces a human readable representation of an IEC size.
94//
95// See also: ParseBytes.
96//
97// IBytes(82854982) -> 79 MiB
98func IBytes(s uint64) string {
99 sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
100 return humanateBytes(s, 1024, sizes)
101}
102
103// ParseBytes parses a string representation of bytes into the number
104// of bytes it represents.
105//
106// See Also: Bytes, IBytes.
107//
108// ParseBytes("42 MB") -> 42000000, nil
109// ParseBytes("42 mib") -> 44040192, nil
110func ParseBytes(s string) (uint64, error) {
111 lastDigit := 0
112 hasComma := false
113 for _, r := range s {
114 if !(unicode.IsDigit(r) || r == '.' || r == ',') {
115 break
116 }
117 if r == ',' {
118 hasComma = true
119 }
120 lastDigit++
121 }
122
123 num := s[:lastDigit]
124 if hasComma {
125 num = strings.Replace(num, ",", "", -1)
126 }
127
128 f, err := strconv.ParseFloat(num, 64)
129 if err != nil {
130 return 0, err
131 }
132
133 extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
134 if m, ok := bytesSizeTable[extra]; ok {
135 f *= float64(m)
136 if f >= math.MaxUint64 {
137 return 0, fmt.Errorf("too large: %v", s)
138 }
139 return uint64(f), nil
140 }
141
142 return 0, fmt.Errorf("unhandled size name: %v", extra)
143}
diff --git a/vendor/github.com/dustin/go-humanize/comma.go b/vendor/github.com/dustin/go-humanize/comma.go
new file mode 100644
index 0000000..520ae3e
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/comma.go
@@ -0,0 +1,116 @@
1package humanize
2
3import (
4 "bytes"
5 "math"
6 "math/big"
7 "strconv"
8 "strings"
9)
10
11// Comma produces a string form of the given number in base 10 with
12// commas after every three orders of magnitude.
13//
14// e.g. Comma(834142) -> 834,142
15func Comma(v int64) string {
16 sign := ""
17
18 // Min int64 can't be negated to a usable value, so it has to be special cased.
19 if v == math.MinInt64 {
20 return "-9,223,372,036,854,775,808"
21 }
22
23 if v < 0 {
24 sign = "-"
25 v = 0 - v
26 }
27
28 parts := []string{"", "", "", "", "", "", ""}
29 j := len(parts) - 1
30
31 for v > 999 {
32 parts[j] = strconv.FormatInt(v%1000, 10)
33 switch len(parts[j]) {
34 case 2:
35 parts[j] = "0" + parts[j]
36 case 1:
37 parts[j] = "00" + parts[j]
38 }
39 v = v / 1000
40 j--
41 }
42 parts[j] = strconv.Itoa(int(v))
43 return sign + strings.Join(parts[j:], ",")
44}
45
46// Commaf produces a string form of the given number in base 10 with
47// commas after every three orders of magnitude.
48//
49// e.g. Commaf(834142.32) -> 834,142.32
50func Commaf(v float64) string {
51 buf := &bytes.Buffer{}
52 if v < 0 {
53 buf.Write([]byte{'-'})
54 v = 0 - v
55 }
56
57 comma := []byte{','}
58
59 parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
60 pos := 0
61 if len(parts[0])%3 != 0 {
62 pos += len(parts[0]) % 3
63 buf.WriteString(parts[0][:pos])
64 buf.Write(comma)
65 }
66 for ; pos < len(parts[0]); pos += 3 {
67 buf.WriteString(parts[0][pos : pos+3])
68 buf.Write(comma)
69 }
70 buf.Truncate(buf.Len() - 1)
71
72 if len(parts) > 1 {
73 buf.Write([]byte{'.'})
74 buf.WriteString(parts[1])
75 }
76 return buf.String()
77}
78
79// CommafWithDigits works like the Commaf but limits the resulting
80// string to the given number of decimal places.
81//
82// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
83func CommafWithDigits(f float64, decimals int) string {
84 return stripTrailingDigits(Commaf(f), decimals)
85}
86
87// BigComma produces a string form of the given big.Int in base 10
88// with commas after every three orders of magnitude.
89func BigComma(b *big.Int) string {
90 sign := ""
91 if b.Sign() < 0 {
92 sign = "-"
93 b.Abs(b)
94 }
95
96 athousand := big.NewInt(1000)
97 c := (&big.Int{}).Set(b)
98 _, m := oom(c, athousand)
99 parts := make([]string, m+1)
100 j := len(parts) - 1
101
102 mod := &big.Int{}
103 for b.Cmp(athousand) >= 0 {
104 b.DivMod(b, athousand, mod)
105 parts[j] = strconv.FormatInt(mod.Int64(), 10)
106 switch len(parts[j]) {
107 case 2:
108 parts[j] = "0" + parts[j]
109 case 1:
110 parts[j] = "00" + parts[j]
111 }
112 j--
113 }
114 parts[j] = strconv.Itoa(int(b.Int64()))
115 return sign + strings.Join(parts[j:], ",")
116}
diff --git a/vendor/github.com/dustin/go-humanize/commaf.go b/vendor/github.com/dustin/go-humanize/commaf.go
new file mode 100644
index 0000000..2bc83a0
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/commaf.go
@@ -0,0 +1,41 @@
1//go:build go1.6
2// +build go1.6
3
4package humanize
5
6import (
7 "bytes"
8 "math/big"
9 "strings"
10)
11
12// BigCommaf produces a string form of the given big.Float in base 10
13// with commas after every three orders of magnitude.
14func BigCommaf(v *big.Float) string {
15 buf := &bytes.Buffer{}
16 if v.Sign() < 0 {
17 buf.Write([]byte{'-'})
18 v.Abs(v)
19 }
20
21 comma := []byte{','}
22
23 parts := strings.Split(v.Text('f', -1), ".")
24 pos := 0
25 if len(parts[0])%3 != 0 {
26 pos += len(parts[0]) % 3
27 buf.WriteString(parts[0][:pos])
28 buf.Write(comma)
29 }
30 for ; pos < len(parts[0]); pos += 3 {
31 buf.WriteString(parts[0][pos : pos+3])
32 buf.Write(comma)
33 }
34 buf.Truncate(buf.Len() - 1)
35
36 if len(parts) > 1 {
37 buf.Write([]byte{'.'})
38 buf.WriteString(parts[1])
39 }
40 return buf.String()
41}
diff --git a/vendor/github.com/dustin/go-humanize/ftoa.go b/vendor/github.com/dustin/go-humanize/ftoa.go
new file mode 100644
index 0000000..bce923f
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/ftoa.go
@@ -0,0 +1,49 @@
1package humanize
2
3import (
4 "strconv"
5 "strings"
6)
7
8func stripTrailingZeros(s string) string {
9 if !strings.ContainsRune(s, '.') {
10 return s
11 }
12 offset := len(s) - 1
13 for offset > 0 {
14 if s[offset] == '.' {
15 offset--
16 break
17 }
18 if s[offset] != '0' {
19 break
20 }
21 offset--
22 }
23 return s[:offset+1]
24}
25
26func stripTrailingDigits(s string, digits int) string {
27 if i := strings.Index(s, "."); i >= 0 {
28 if digits <= 0 {
29 return s[:i]
30 }
31 i++
32 if i+digits >= len(s) {
33 return s
34 }
35 return s[:i+digits]
36 }
37 return s
38}
39
40// Ftoa converts a float to a string with no trailing zeros.
41func Ftoa(num float64) string {
42 return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
43}
44
45// FtoaWithDigits converts a float to a string but limits the resulting string
46// to the given number of decimal places, and no trailing zeros.
47func FtoaWithDigits(num float64, digits int) string {
48 return stripTrailingZeros(stripTrailingDigits(strconv.FormatFloat(num, 'f', 6, 64), digits))
49}
diff --git a/vendor/github.com/dustin/go-humanize/humanize.go b/vendor/github.com/dustin/go-humanize/humanize.go
new file mode 100644
index 0000000..a2c2da3
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/humanize.go
@@ -0,0 +1,8 @@
1/*
2Package humanize converts boring ugly numbers to human-friendly strings and back.
3
4Durations can be turned into strings such as "3 days ago", numbers
5representing sizes like 82854982 into useful strings like, "83 MB" or
6"79 MiB" (whichever you prefer).
7*/
8package humanize
diff --git a/vendor/github.com/dustin/go-humanize/number.go b/vendor/github.com/dustin/go-humanize/number.go
new file mode 100644
index 0000000..6470d0d
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/number.go
@@ -0,0 +1,192 @@
1package humanize
2
3/*
4Slightly adapted from the source to fit go-humanize.
5
6Author: https://github.com/gorhill
7Source: https://gist.github.com/gorhill/5285193
8
9*/
10
11import (
12 "math"
13 "strconv"
14)
15
16var (
17 renderFloatPrecisionMultipliers = [...]float64{
18 1,
19 10,
20 100,
21 1000,
22 10000,
23 100000,
24 1000000,
25 10000000,
26 100000000,
27 1000000000,
28 }
29
30 renderFloatPrecisionRounders = [...]float64{
31 0.5,
32 0.05,
33 0.005,
34 0.0005,
35 0.00005,
36 0.000005,
37 0.0000005,
38 0.00000005,
39 0.000000005,
40 0.0000000005,
41 }
42)
43
44// FormatFloat produces a formatted number as string based on the following user-specified criteria:
45// * thousands separator
46// * decimal separator
47// * decimal precision
48//
49// Usage: s := RenderFloat(format, n)
50// The format parameter tells how to render the number n.
51//
52// See examples: http://play.golang.org/p/LXc1Ddm1lJ
53//
54// Examples of format strings, given n = 12345.6789:
55// "#,###.##" => "12,345.67"
56// "#,###." => "12,345"
57// "#,###" => "12345,678"
58// "#\u202F###,##" => "12โ€ฏ345,68"
59// "#.###,###### => 12.345,678900
60// "" (aka default format) => 12,345.67
61//
62// The highest precision allowed is 9 digits after the decimal symbol.
63// There is also a version for integer number, FormatInteger(),
64// which is convenient for calls within template.
65func FormatFloat(format string, n float64) string {
66 // Special cases:
67 // NaN = "NaN"
68 // +Inf = "+Infinity"
69 // -Inf = "-Infinity"
70 if math.IsNaN(n) {
71 return "NaN"
72 }
73 if n > math.MaxFloat64 {
74 return "Infinity"
75 }
76 if n < (0.0 - math.MaxFloat64) {
77 return "-Infinity"
78 }
79
80 // default format
81 precision := 2
82 decimalStr := "."
83 thousandStr := ","
84 positiveStr := ""
85 negativeStr := "-"
86
87 if len(format) > 0 {
88 format := []rune(format)
89
90 // If there is an explicit format directive,
91 // then default values are these:
92 precision = 9
93 thousandStr = ""
94
95 // collect indices of meaningful formatting directives
96 formatIndx := []int{}
97 for i, char := range format {
98 if char != '#' && char != '0' {
99 formatIndx = append(formatIndx, i)
100 }
101 }
102
103 if len(formatIndx) > 0 {
104 // Directive at index 0:
105 // Must be a '+'
106 // Raise an error if not the case
107 // index: 0123456789
108 // +0.000,000
109 // +000,000.0
110 // +0000.00
111 // +0000
112 if formatIndx[0] == 0 {
113 if format[formatIndx[0]] != '+' {
114 panic("RenderFloat(): invalid positive sign directive")
115 }
116 positiveStr = "+"
117 formatIndx = formatIndx[1:]
118 }
119
120 // Two directives:
121 // First is thousands separator
122 // Raise an error if not followed by 3-digit
123 // 0123456789
124 // 0.000,000
125 // 000,000.00
126 if len(formatIndx) == 2 {
127 if (formatIndx[1] - formatIndx[0]) != 4 {
128 panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
129 }
130 thousandStr = string(format[formatIndx[0]])
131 formatIndx = formatIndx[1:]
132 }
133
134 // One directive:
135 // Directive is decimal separator
136 // The number of digit-specifier following the separator indicates wanted precision
137 // 0123456789
138 // 0.00
139 // 000,0000
140 if len(formatIndx) == 1 {
141 decimalStr = string(format[formatIndx[0]])
142 precision = len(format) - formatIndx[0] - 1
143 }
144 }
145 }
146
147 // generate sign part
148 var signStr string
149 if n >= 0.000000001 {
150 signStr = positiveStr
151 } else if n <= -0.000000001 {
152 signStr = negativeStr
153 n = -n
154 } else {
155 signStr = ""
156 n = 0.0
157 }
158
159 // split number into integer and fractional parts
160 intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
161
162 // generate integer part string
163 intStr := strconv.FormatInt(int64(intf), 10)
164
165 // add thousand separator if required
166 if len(thousandStr) > 0 {
167 for i := len(intStr); i > 3; {
168 i -= 3
169 intStr = intStr[:i] + thousandStr + intStr[i:]
170 }
171 }
172
173 // no fractional part, we can leave now
174 if precision == 0 {
175 return signStr + intStr
176 }
177
178 // generate fractional part
179 fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
180 // may need padding
181 if len(fracStr) < precision {
182 fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
183 }
184
185 return signStr + intStr + decimalStr + fracStr
186}
187
188// FormatInteger produces a formatted number as string.
189// See FormatFloat.
190func FormatInteger(format string, n int) string {
191 return FormatFloat(format, float64(n))
192}
diff --git a/vendor/github.com/dustin/go-humanize/ordinals.go b/vendor/github.com/dustin/go-humanize/ordinals.go
new file mode 100644
index 0000000..43d88a8
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/ordinals.go
@@ -0,0 +1,25 @@
1package humanize
2
3import "strconv"
4
5// Ordinal gives you the input number in a rank/ordinal format.
6//
7// Ordinal(3) -> 3rd
8func Ordinal(x int) string {
9 suffix := "th"
10 switch x % 10 {
11 case 1:
12 if x%100 != 11 {
13 suffix = "st"
14 }
15 case 2:
16 if x%100 != 12 {
17 suffix = "nd"
18 }
19 case 3:
20 if x%100 != 13 {
21 suffix = "rd"
22 }
23 }
24 return strconv.Itoa(x) + suffix
25}
diff --git a/vendor/github.com/dustin/go-humanize/si.go b/vendor/github.com/dustin/go-humanize/si.go
new file mode 100644
index 0000000..8b85019
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/si.go
@@ -0,0 +1,127 @@
1package humanize
2
3import (
4 "errors"
5 "math"
6 "regexp"
7 "strconv"
8)
9
10var siPrefixTable = map[float64]string{
11 -30: "q", // quecto
12 -27: "r", // ronto
13 -24: "y", // yocto
14 -21: "z", // zepto
15 -18: "a", // atto
16 -15: "f", // femto
17 -12: "p", // pico
18 -9: "n", // nano
19 -6: "ยต", // micro
20 -3: "m", // milli
21 0: "",
22 3: "k", // kilo
23 6: "M", // mega
24 9: "G", // giga
25 12: "T", // tera
26 15: "P", // peta
27 18: "E", // exa
28 21: "Z", // zetta
29 24: "Y", // yotta
30 27: "R", // ronna
31 30: "Q", // quetta
32}
33
34var revSIPrefixTable = revfmap(siPrefixTable)
35
36// revfmap reverses the map and precomputes the power multiplier
37func revfmap(in map[float64]string) map[string]float64 {
38 rv := map[string]float64{}
39 for k, v := range in {
40 rv[v] = math.Pow(10, k)
41 }
42 return rv
43}
44
45var riParseRegex *regexp.Regexp
46
47func init() {
48 ri := `^([\-0-9.]+)\s?([`
49 for _, v := range siPrefixTable {
50 ri += v
51 }
52 ri += `]?)(.*)`
53
54 riParseRegex = regexp.MustCompile(ri)
55}
56
57// ComputeSI finds the most appropriate SI prefix for the given number
58// and returns the prefix along with the value adjusted to be within
59// that prefix.
60//
61// See also: SI, ParseSI.
62//
63// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p")
64func ComputeSI(input float64) (float64, string) {
65 if input == 0 {
66 return 0, ""
67 }
68 mag := math.Abs(input)
69 exponent := math.Floor(logn(mag, 10))
70 exponent = math.Floor(exponent/3) * 3
71
72 value := mag / math.Pow(10, exponent)
73
74 // Handle special case where value is exactly 1000.0
75 // Should return 1 M instead of 1000 k
76 if value == 1000.0 {
77 exponent += 3
78 value = mag / math.Pow(10, exponent)
79 }
80
81 value = math.Copysign(value, input)
82
83 prefix := siPrefixTable[exponent]
84 return value, prefix
85}
86
87// SI returns a string with default formatting.
88//
89// SI uses Ftoa to format float value, removing trailing zeros.
90//
91// See also: ComputeSI, ParseSI.
92//
93// e.g. SI(1000000, "B") -> 1 MB
94// e.g. SI(2.2345e-12, "F") -> 2.2345 pF
95func SI(input float64, unit string) string {
96 value, prefix := ComputeSI(input)
97 return Ftoa(value) + " " + prefix + unit
98}
99
100// SIWithDigits works like SI but limits the resulting string to the
101// given number of decimal places.
102//
103// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB
104// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF
105func SIWithDigits(input float64, decimals int, unit string) string {
106 value, prefix := ComputeSI(input)
107 return FtoaWithDigits(value, decimals) + " " + prefix + unit
108}
109
110var errInvalid = errors.New("invalid input")
111
112// ParseSI parses an SI string back into the number and unit.
113//
114// See also: SI, ComputeSI.
115//
116// e.g. ParseSI("2.2345 pF") -> (2.2345e-12, "F", nil)
117func ParseSI(input string) (float64, string, error) {
118 found := riParseRegex.FindStringSubmatch(input)
119 if len(found) != 4 {
120 return 0, "", errInvalid
121 }
122 mag := revSIPrefixTable[found[2]]
123 unit := found[3]
124
125 base, err := strconv.ParseFloat(found[1], 64)
126 return base * mag, unit, err
127}
diff --git a/vendor/github.com/dustin/go-humanize/times.go b/vendor/github.com/dustin/go-humanize/times.go
new file mode 100644
index 0000000..dd3fbf5
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/times.go
@@ -0,0 +1,117 @@
1package humanize
2
3import (
4 "fmt"
5 "math"
6 "sort"
7 "time"
8)
9
10// Seconds-based time units
11const (
12 Day = 24 * time.Hour
13 Week = 7 * Day
14 Month = 30 * Day
15 Year = 12 * Month
16 LongTime = 37 * Year
17)
18
19// Time formats a time into a relative string.
20//
21// Time(someT) -> "3 weeks ago"
22func Time(then time.Time) string {
23 return RelTime(then, time.Now(), "ago", "from now")
24}
25
26// A RelTimeMagnitude struct contains a relative time point at which
27// the relative format of time will switch to a new format string. A
28// slice of these in ascending order by their "D" field is passed to
29// CustomRelTime to format durations.
30//
31// The Format field is a string that may contain a "%s" which will be
32// replaced with the appropriate signed label (e.g. "ago" or "from
33// now") and a "%d" that will be replaced by the quantity.
34//
35// The DivBy field is the amount of time the time difference must be
36// divided by in order to display correctly.
37//
38// e.g. if D is 2*time.Minute and you want to display "%d minutes %s"
39// DivBy should be time.Minute so whatever the duration is will be
40// expressed in minutes.
41type RelTimeMagnitude struct {
42 D time.Duration
43 Format string
44 DivBy time.Duration
45}
46
47var defaultMagnitudes = []RelTimeMagnitude{
48 {time.Second, "now", time.Second},
49 {2 * time.Second, "1 second %s", 1},
50 {time.Minute, "%d seconds %s", time.Second},
51 {2 * time.Minute, "1 minute %s", 1},
52 {time.Hour, "%d minutes %s", time.Minute},
53 {2 * time.Hour, "1 hour %s", 1},
54 {Day, "%d hours %s", time.Hour},
55 {2 * Day, "1 day %s", 1},
56 {Week, "%d days %s", Day},
57 {2 * Week, "1 week %s", 1},
58 {Month, "%d weeks %s", Week},
59 {2 * Month, "1 month %s", 1},
60 {Year, "%d months %s", Month},
61 {18 * Month, "1 year %s", 1},
62 {2 * Year, "2 years %s", 1},
63 {LongTime, "%d years %s", Year},
64 {math.MaxInt64, "a long while %s", 1},
65}
66
67// RelTime formats a time into a relative string.
68//
69// It takes two times and two labels. In addition to the generic time
70// delta string (e.g. 5 minutes), the labels are used applied so that
71// the label corresponding to the smaller time is applied.
72//
73// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
74func RelTime(a, b time.Time, albl, blbl string) string {
75 return CustomRelTime(a, b, albl, blbl, defaultMagnitudes)
76}
77
78// CustomRelTime formats a time into a relative string.
79//
80// It takes two times two labels and a table of relative time formats.
81// In addition to the generic time delta string (e.g. 5 minutes), the
82// labels are used applied so that the label corresponding to the
83// smaller time is applied.
84func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string {
85 lbl := albl
86 diff := b.Sub(a)
87
88 if a.After(b) {
89 lbl = blbl
90 diff = a.Sub(b)
91 }
92
93 n := sort.Search(len(magnitudes), func(i int) bool {
94 return magnitudes[i].D > diff
95 })
96
97 if n >= len(magnitudes) {
98 n = len(magnitudes) - 1
99 }
100 mag := magnitudes[n]
101 args := []interface{}{}
102 escaped := false
103 for _, ch := range mag.Format {
104 if escaped {
105 switch ch {
106 case 's':
107 args = append(args, lbl)
108 case 'd':
109 args = append(args, diff/mag.DivBy)
110 }
111 escaped = false
112 } else {
113 escaped = ch == '%'
114 }
115 }
116 return fmt.Sprintf(mag.Format, args...)
117}