@cryptotaxi247 / kubo / commits / 74767f004

Revert "godeps: drop go-humanize"

shareness needs the go-random/random utility. Godep doesnt know that.

Henry committed Feb 27, 2015 at 13:34 UTC 74767f004fe9a11fb896c6effca7043a37db6273
23 files changed +1471 -2
Godeps/Godeps.json
+4
@@ -78,6 +78,10 @@
78 "ImportPath": "github.com/crowdmob/goamz/s3",
79 "Rev": "82345796204222aa56be89cf930c316b1297f906"
80 },
81 + {
82 + "ImportPath": "github.com/dustin/go-humanize",
83 + "Rev": "b198514c204f20799b91c93b6ffd8b26be04c2c9"
84 + },
85 {
86 "ImportPath": "github.com/facebookgo/atomicfile",
87 "Rev": "6f117f2e7f224fb03eb5e5fba370eade6e2b90c8"
Godeps/_workspace/src/github.com/dustin/go-humanize/.gitignore new
+6
@@ -0,0 +1,6 @@
1 +#*
2 +*.[568]
3 +*.a
4 +*~
5 +[568].out
6 +_*
Godeps/_workspace/src/github.com/dustin/go-humanize/LICENSE new
+21
@@ -0,0 +1,21 @@
1 +Copyright (c) 2005-2008 Dustin Sallings <dustin@spy.net>
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 +SOFTWARE.
20 +
21 +<http://www.opensource.org/licenses/mit-license.php>
Godeps/_workspace/src/github.com/dustin/go-humanize/README.markdown new
+78
@@ -0,0 +1,78 @@
1 +# Humane Units
2 +
3 +Just 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 +
8 +## Sizes
9 +
10 +This lets you take numbers like `82854982` and convert them to useful
11 +strings like, `83MB` or `79MiB` (whichever you prefer).
12 +
13 +Example:
14 +
15 + fmt.Printf("That file is %s.", humanize.Bytes(82854982))
16 +
17 +## Times
18 +
19 +This lets you take a `time.Time` and spit it out in relative terms.
20 +For example, `12 seconds ago` or `3 days from now`.
21 +
22 +Example:
23 +
24 + fmt.Printf("This was touched %s", humanize.Time(someTimeInstance))
25 +
26 +Thanks to Kyle Lemons for the time implementation from an IRC
27 +conversation one day. It's pretty neat.
28 +
29 +## Ordinals
30 +
31 +From a [mailing list discussion][odisc] where a user wanted to be able
32 +to label ordinals.
33 +
34 + 0 -> 0th
35 + 1 -> 1st
36 + 2 -> 2nd
37 + 3 -> 3rd
38 + 4 -> 4th
39 + [...]
40 +
41 +Example:
42 +
43 + fmt.Printf("You're my %s best friend.", humanize.Ordinal(193))
44 +
45 +## Commas
46 +
47 +Want to shove commas into numbers? Be my guest.
48 +
49 + 0 -> 0
50 + 100 -> 100
51 + 1000 -> 1,000
52 + 1000000000 -> 1,000,000,000
53 + -100000 -> -100,000
54 +
55 +Example:
56 +
57 + fmt.Printf("You owe $%s.\n", humanize.Comma(6582491))
58 +
59 +## Ftoa
60 +
61 +Nicer float64 formatter that removes trailing zeros.
62 +
63 + fmt.Printf("%f", 2.24) // 2.240000
64 + fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24
65 + fmt.Printf("%f", 2.0) // 2.000000
66 + fmt.Printf("%s", humanize.Ftoa(2.0)) // 2
67 +
68 +## SI notation
69 +
70 +Format numbers with [SI notation][sinotation].
71 +
72 +Example:
73 +
74 + humanize.SI(0.00000000223, "M") // 2.23nM
75 +
76 +
77 +[odisc]: https://groups.google.com/d/topic/golang-nuts/l8NhI74jl-4/discussion
78 +[sinotation]: http://en.wikipedia.org/wiki/Metric_prefix
Godeps/_workspace/src/github.com/dustin/go-humanize/big.go new
+31
@@ -0,0 +1,31 @@
1 +package humanize
2 +
3 +import (
4 + "math/big"
5 +)
6 +
7 +// order of magnitude (to a max order)
8 +func 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)
23 +func 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 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/bigbytes.go new
+158
@@ -0,0 +1,158 @@
1 +package humanize
2 +
3 +import (
4 + "fmt"
5 + "math/big"
6 + "strings"
7 + "unicode"
8 +)
9 +
10 +var (
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 +)
32 +
33 +var (
34 + bigSIExp = big.NewInt(1000)
35 +
36 + // BigSIByte is one SI byte in big.Ints
37 + BigSIByte = big.NewInt(1)
38 + // BigKByte is 1,000 SI bytes in big.Ints
39 + BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp)
40 + // BigMByte is 1,000 SI k bytes in big.Ints
41 + BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp)
42 + // BigGByte is 1,000 SI m bytes in big.Ints
43 + BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp)
44 + // BigTByte is 1,000 SI g bytes in big.Ints
45 + BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp)
46 + // BigPByte is 1,000 SI t bytes in big.Ints
47 + BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp)
48 + // BigEByte is 1,000 SI p bytes in big.Ints
49 + BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp)
50 + // BigZByte is 1,000 SI e bytes in big.Ints
51 + BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
52 + // BigYByte is 1,000 SI z bytes in big.Ints
53 + BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
54 +)
55 +
56 +var bigBytesSizeTable = map[string]*big.Int{
57 + "b": BigByte,
58 + "kib": BigKiByte,
59 + "kb": BigKByte,
60 + "mib": BigMiByte,
61 + "mb": BigMByte,
62 + "gib": BigGiByte,
63 + "gb": BigGByte,
64 + "tib": BigTiByte,
65 + "tb": BigTByte,
66 + "pib": BigPiByte,
67 + "pb": BigPByte,
68 + "eib": BigEiByte,
69 + "eb": BigEByte,
70 + "zib": BigZiByte,
71 + "zb": BigZByte,
72 + "yib": BigYiByte,
73 + "yb": BigYByte,
74 + // Without suffix
75 + "": BigByte,
76 + "ki": BigKiByte,
77 + "k": BigKByte,
78 + "mi": BigMiByte,
79 + "m": BigMByte,
80 + "gi": BigGiByte,
81 + "g": BigGByte,
82 + "ti": BigTiByte,
83 + "t": BigTByte,
84 + "pi": BigPiByte,
85 + "p": BigPByte,
86 + "ei": BigEiByte,
87 + "e": BigEByte,
88 + "z": BigZByte,
89 + "zi": BigZiByte,
90 + "y": BigYByte,
91 + "yi": BigYiByte,
92 +}
93 +
94 +var ten = big.NewInt(10)
95 +
96 +func humanateBigBytes(s, base *big.Int, sizes []string) string {
97 + if s.Cmp(ten) < 0 {
98 + return fmt.Sprintf("%dB", s)
99 + }
100 + c := (&big.Int{}).Set(s)
101 + val, mag := oomm(c, base, len(sizes)-1)
102 + suffix := sizes[mag]
103 + f := "%.0f%s"
104 + if val < 10 {
105 + f = "%.1f%s"
106 + }
107 +
108 + return fmt.Sprintf(f, val, suffix)
109 +
110 +}
111 +
112 +// BigBytes produces a human readable representation of an SI size.
113 +//
114 +// BigBytes(82854982) -> 83MB
115 +func BigBytes(s *big.Int) string {
116 + sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
117 + return humanateBigBytes(s, bigSIExp, sizes)
118 +}
119 +
120 +// BigIBytes produces a human readable representation of an IEC size.
121 +//
122 +// BigIBytes(82854982) -> 79MiB
123 +func BigIBytes(s *big.Int) string {
124 + sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
125 + return humanateBigBytes(s, bigIECExp, sizes)
126 +}
127 +
128 +// ParseBigBytes parses a string representation of bytes into the number
129 +// of bytes it represents.
130 +//
131 +// ParseBigBytes("42MB") -> 42000000, nil
132 +// ParseBigBytes("42mib") -> 44040192, nil
133 +func ParseBigBytes(s string) (*big.Int, error) {
134 + lastDigit := 0
135 + for _, r := range s {
136 + if !(unicode.IsDigit(r) || r == '.') {
137 + break
138 + }
139 + lastDigit++
140 + }
141 +
142 + val := &big.Rat{}
143 + _, err := fmt.Sscanf(s[:lastDigit], "%f", val)
144 + if err != nil {
145 + return nil, err
146 + }
147 +
148 + extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
149 + if m, ok := bigBytesSizeTable[extra]; ok {
150 + mv := (&big.Rat{}).SetInt(m)
151 + val.Mul(val, mv)
152 + rv := &big.Int{}
153 + rv.Div(val.Num(), val.Denom())
154 + return rv, nil
155 + }
156 +
157 + return nil, fmt.Errorf("unhandled size name: %v", extra)
158 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/bigbytes_test.go new
+219
@@ -0,0 +1,219 @@
1 +package humanize
2 +
3 +import (
4 + "math/big"
5 + "testing"
6 +)
7 +
8 +func TestBigByteParsing(t *testing.T) {
9 + tests := []struct {
10 + in string
11 + exp uint64
12 + }{
13 + {"42", 42},
14 + {"42MB", 42000000},
15 + {"42MiB", 44040192},
16 + {"42mb", 42000000},
17 + {"42mib", 44040192},
18 + {"42MIB", 44040192},
19 + {"42 MB", 42000000},
20 + {"42 MiB", 44040192},
21 + {"42 mb", 42000000},
22 + {"42 mib", 44040192},
23 + {"42 MIB", 44040192},
24 + {"42.5MB", 42500000},
25 + {"42.5MiB", 44564480},
26 + {"42.5 MB", 42500000},
27 + {"42.5 MiB", 44564480},
28 + // No need to say B
29 + {"42M", 42000000},
30 + {"42Mi", 44040192},
31 + {"42m", 42000000},
32 + {"42mi", 44040192},
33 + {"42MI", 44040192},
34 + {"42 M", 42000000},
35 + {"42 Mi", 44040192},
36 + {"42 m", 42000000},
37 + {"42 mi", 44040192},
38 + {"42 MI", 44040192},
39 + {"42.5M", 42500000},
40 + {"42.5Mi", 44564480},
41 + {"42.5 M", 42500000},
42 + {"42.5 Mi", 44564480},
43 + // Large testing, breaks when too much larger than
44 + // this.
45 + {"12.5 EB", uint64(12.5 * float64(EByte))},
46 + {"12.5 E", uint64(12.5 * float64(EByte))},
47 + {"12.5 EiB", uint64(12.5 * float64(EiByte))},
48 + }
49 +
50 + for _, p := range tests {
51 + got, err := ParseBigBytes(p.in)
52 + if err != nil {
53 + t.Errorf("Couldn't parse %v: %v", p.in, err)
54 + } else {
55 + if got.Uint64() != p.exp {
56 + t.Errorf("Expected %v for %v, got %v",
57 + p.exp, p.in, got)
58 + }
59 + }
60 + }
61 +}
62 +
63 +func TestBigByteErrors(t *testing.T) {
64 + got, err := ParseBigBytes("84 JB")
65 + if err == nil {
66 + t.Errorf("Expected error, got %v", got)
67 + }
68 + got, err = ParseBigBytes("")
69 + if err == nil {
70 + t.Errorf("Expected error parsing nothing")
71 + }
72 +}
73 +
74 +func bbyte(in uint64) string {
75 + return BigBytes((&big.Int{}).SetUint64(in))
76 +}
77 +
78 +func bibyte(in uint64) string {
79 + return BigIBytes((&big.Int{}).SetUint64(in))
80 +}
81 +
82 +func TestBigBytes(t *testing.T) {
83 + testList{
84 + {"bytes(0)", bbyte(0), "0B"},
85 + {"bytes(1)", bbyte(1), "1B"},
86 + {"bytes(803)", bbyte(803), "803B"},
87 + {"bytes(999)", bbyte(999), "999B"},
88 +
89 + {"bytes(1024)", bbyte(1024), "1.0KB"},
90 + {"bytes(1MB - 1)", bbyte(MByte - Byte), "1000KB"},
91 +
92 + {"bytes(1MB)", bbyte(1024 * 1024), "1.0MB"},
93 + {"bytes(1GB - 1K)", bbyte(GByte - KByte), "1000MB"},
94 +
95 + {"bytes(1GB)", bbyte(GByte), "1.0GB"},
96 + {"bytes(1TB - 1M)", bbyte(TByte - MByte), "1000GB"},
97 +
98 + {"bytes(1TB)", bbyte(TByte), "1.0TB"},
99 + {"bytes(1PB - 1T)", bbyte(PByte - TByte), "999TB"},
100 +
101 + {"bytes(1PB)", bbyte(PByte), "1.0PB"},
102 + {"bytes(1PB - 1T)", bbyte(EByte - PByte), "999PB"},
103 +
104 + {"bytes(1EB)", bbyte(EByte), "1.0EB"},
105 + // Overflows.
106 + // {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
107 +
108 + {"bytes(0)", bibyte(0), "0B"},
109 + {"bytes(1)", bibyte(1), "1B"},
110 + {"bytes(803)", bibyte(803), "803B"},
111 + {"bytes(1023)", bibyte(1023), "1023B"},
112 +
113 + {"bytes(1024)", bibyte(1024), "1.0KiB"},
114 + {"bytes(1MB - 1)", bibyte(MiByte - IByte), "1024KiB"},
115 +
116 + {"bytes(1MB)", bibyte(1024 * 1024), "1.0MiB"},
117 + {"bytes(1GB - 1K)", bibyte(GiByte - KiByte), "1024MiB"},
118 +
119 + {"bytes(1GB)", bibyte(GiByte), "1.0GiB"},
120 + {"bytes(1TB - 1M)", bibyte(TiByte - MiByte), "1024GiB"},
121 +
122 + {"bytes(1TB)", bibyte(TiByte), "1.0TiB"},
123 + {"bytes(1PB - 1T)", bibyte(PiByte - TiByte), "1023TiB"},
124 +
125 + {"bytes(1PB)", bibyte(PiByte), "1.0PiB"},
126 + {"bytes(1PB - 1T)", bibyte(EiByte - PiByte), "1023PiB"},
127 +
128 + {"bytes(1EiB)", bibyte(EiByte), "1.0EiB"},
129 + // Overflows.
130 + // {"bytes(1EB - 1P)", bibyte((KIByte*EIByte)-PiByte), "1023EB"},
131 +
132 + {"bytes(5.5GiB)", bibyte(5.5 * GiByte), "5.5GiB"},
133 +
134 + {"bytes(5.5GB)", bbyte(5.5 * GByte), "5.5GB"},
135 + }.validate(t)
136 +}
137 +
138 +func TestVeryBigBytes(t *testing.T) {
139 + b, _ := (&big.Int{}).SetString("15347691069326346944512", 10)
140 + s := BigBytes(b)
141 + if s != "15ZB" {
142 + t.Errorf("Expected 15ZB, got %v", s)
143 + }
144 + s = BigIBytes(b)
145 + if s != "13ZiB" {
146 + t.Errorf("Expected 13ZiB, got %v", s)
147 + }
148 +
149 + b, _ = (&big.Int{}).SetString("15716035654990179271180288", 10)
150 + s = BigBytes(b)
151 + if s != "16YB" {
152 + t.Errorf("Expected 16YB, got %v", s)
153 + }
154 + s = BigIBytes(b)
155 + if s != "13YiB" {
156 + t.Errorf("Expected 13YiB, got %v", s)
157 + }
158 +}
159 +
160 +func TestVeryVeryBigBytes(t *testing.T) {
161 + b, _ := (&big.Int{}).SetString("16093220510709943573688614912", 10)
162 + s := BigBytes(b)
163 + if s != "16093YB" {
164 + t.Errorf("Expected 16093YB, got %v", s)
165 + }
166 + s = BigIBytes(b)
167 + if s != "13312YiB" {
168 + t.Errorf("Expected 13312YiB, got %v", s)
169 + }
170 +}
171 +
172 +func TestParseVeryBig(t *testing.T) {
173 + tests := []struct {
174 + in string
175 + out string
176 + }{
177 + {"16ZB", "16000000000000000000000"},
178 + {"16ZiB", "18889465931478580854784"},
179 + {"16.5ZB", "16500000000000000000000"},
180 + {"16.5ZiB", "19479761741837286506496"},
181 + {"16Z", "16000000000000000000000"},
182 + {"16Zi", "18889465931478580854784"},
183 + {"16.5Z", "16500000000000000000000"},
184 + {"16.5Zi", "19479761741837286506496"},
185 +
186 + {"16YB", "16000000000000000000000000"},
187 + {"16YiB", "19342813113834066795298816"},
188 + {"16.5YB", "16500000000000000000000000"},
189 + {"16.5YiB", "19947276023641381382651904"},
190 + {"16Y", "16000000000000000000000000"},
191 + {"16Yi", "19342813113834066795298816"},
192 + {"16.5Y", "16500000000000000000000000"},
193 + {"16.5Yi", "19947276023641381382651904"},
194 + }
195 +
196 + for _, test := range tests {
197 + x, err := ParseBigBytes(test.in)
198 + if err != nil {
199 + t.Errorf("Error parsing %q: %v", test.in, err)
200 + continue
201 + }
202 +
203 + if x.String() != test.out {
204 + t.Errorf("Expected %q for %q, got %v", test.out, test.in, x)
205 + }
206 + }
207 +}
208 +
209 +func BenchmarkParseBigBytes(b *testing.B) {
210 + for i := 0; i < b.N; i++ {
211 + ParseBigBytes("16.5Z")
212 + }
213 +}
214 +
215 +func BenchmarkBigBytes(b *testing.B) {
216 + for i := 0; i < b.N; i++ {
217 + bibyte(16.5 * GByte)
218 + }
219 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/bytes.go new
+128
@@ -0,0 +1,128 @@
1 +package humanize
2 +
3 +import (
4 + "fmt"
5 + "math"
6 + "strconv"
7 + "strings"
8 + "unicode"
9 +)
10 +
11 +// IEC Sizes.
12 +// kibis of bits
13 +const (
14 + Byte = 1 << (iota * 10)
15 + KiByte
16 + MiByte
17 + GiByte
18 + TiByte
19 + PiByte
20 + EiByte
21 +)
22 +
23 +// SI Sizes.
24 +const (
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 +
34 +var 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 +
64 +func logn(n, b float64) float64 {
65 + return math.Log(n) / math.Log(b)
66 +}
67 +
68 +func humanateBytes(s uint64, base float64, sizes []string) string {
69 + if s < 10 {
70 + return fmt.Sprintf("%dB", 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 +// Bytes(82854982) -> 83MB
86 +func Bytes(s uint64) string {
87 + sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
88 + return humanateBytes(s, 1000, sizes)
89 +}
90 +
91 +// IBytes produces a human readable representation of an IEC size.
92 +//
93 +// IBytes(82854982) -> 79MiB
94 +func IBytes(s uint64) string {
95 + sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
96 + return humanateBytes(s, 1024, sizes)
97 +}
98 +
99 +// ParseBytes parses a string representation of bytes into the number
100 +// of bytes it represents.
101 +//
102 +// ParseBytes("42MB") -> 42000000, nil
103 +// ParseBytes("42mib") -> 44040192, nil
104 +func ParseBytes(s string) (uint64, error) {
105 + lastDigit := 0
106 + for _, r := range s {
107 + if !(unicode.IsDigit(r) || r == '.') {
108 + break
109 + }
110 + lastDigit++
111 + }
112 +
113 + f, err := strconv.ParseFloat(s[:lastDigit], 64)
114 + if err != nil {
115 + return 0, err
116 + }
117 +
118 + extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
119 + if m, ok := bytesSizeTable[extra]; ok {
120 + f *= float64(m)
121 + if f >= math.MaxUint64 {
122 + return 0, fmt.Errorf("too large: %v", s)
123 + }
124 + return uint64(f), nil
125 + }
126 +
127 + return 0, fmt.Errorf("unhandled size name: %v", extra)
128 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/bytes_test.go new
+144
@@ -0,0 +1,144 @@
1 +package humanize
2 +
3 +import (
4 + "testing"
5 +)
6 +
7 +func TestByteParsing(t *testing.T) {
8 + tests := []struct {
9 + in string
10 + exp uint64
11 + }{
12 + {"42", 42},
13 + {"42MB", 42000000},
14 + {"42MiB", 44040192},
15 + {"42mb", 42000000},
16 + {"42mib", 44040192},
17 + {"42MIB", 44040192},
18 + {"42 MB", 42000000},
19 + {"42 MiB", 44040192},
20 + {"42 mb", 42000000},
21 + {"42 mib", 44040192},
22 + {"42 MIB", 44040192},
23 + {"42.5MB", 42500000},
24 + {"42.5MiB", 44564480},
25 + {"42.5 MB", 42500000},
26 + {"42.5 MiB", 44564480},
27 + // No need to say B
28 + {"42M", 42000000},
29 + {"42Mi", 44040192},
30 + {"42m", 42000000},
31 + {"42mi", 44040192},
32 + {"42MI", 44040192},
33 + {"42 M", 42000000},
34 + {"42 Mi", 44040192},
35 + {"42 m", 42000000},
36 + {"42 mi", 44040192},
37 + {"42 MI", 44040192},
38 + {"42.5M", 42500000},
39 + {"42.5Mi", 44564480},
40 + {"42.5 M", 42500000},
41 + {"42.5 Mi", 44564480},
42 + // Large testing, breaks when too much larger than
43 + // this.
44 + {"12.5 EB", uint64(12.5 * float64(EByte))},
45 + {"12.5 E", uint64(12.5 * float64(EByte))},
46 + {"12.5 EiB", uint64(12.5 * float64(EiByte))},
47 + }
48 +
49 + for _, p := range tests {
50 + got, err := ParseBytes(p.in)
51 + if err != nil {
52 + t.Errorf("Couldn't parse %v: %v", p.in, err)
53 + }
54 + if got != p.exp {
55 + t.Errorf("Expected %v for %v, got %v",
56 + p.exp, p.in, got)
57 + }
58 + }
59 +}
60 +
61 +func TestByteErrors(t *testing.T) {
62 + got, err := ParseBytes("84 JB")
63 + if err == nil {
64 + t.Errorf("Expected error, got %v", got)
65 + }
66 + got, err = ParseBytes("")
67 + if err == nil {
68 + t.Errorf("Expected error parsing nothing")
69 + }
70 + got, err = ParseBytes("16 EiB")
71 + if err == nil {
72 + t.Errorf("Expected error, got %v", got)
73 + }
74 +}
75 +
76 +func TestBytes(t *testing.T) {
77 + testList{
78 + {"bytes(0)", Bytes(0), "0B"},
79 + {"bytes(1)", Bytes(1), "1B"},
80 + {"bytes(803)", Bytes(803), "803B"},
81 + {"bytes(999)", Bytes(999), "999B"},
82 +
83 + {"bytes(1024)", Bytes(1024), "1.0KB"},
84 + {"bytes(9999)", Bytes(9999), "10KB"},
85 + {"bytes(1MB - 1)", Bytes(MByte - Byte), "1000KB"},
86 +
87 + {"bytes(1MB)", Bytes(1024 * 1024), "1.0MB"},
88 + {"bytes(1GB - 1K)", Bytes(GByte - KByte), "1000MB"},
89 +
90 + {"bytes(1GB)", Bytes(GByte), "1.0GB"},
91 + {"bytes(1TB - 1M)", Bytes(TByte - MByte), "1000GB"},
92 + {"bytes(10MB)", Bytes(9999 * 1000), "10MB"},
93 +
94 + {"bytes(1TB)", Bytes(TByte), "1.0TB"},
95 + {"bytes(1PB - 1T)", Bytes(PByte - TByte), "999TB"},
96 +
97 + {"bytes(1PB)", Bytes(PByte), "1.0PB"},
98 + {"bytes(1PB - 1T)", Bytes(EByte - PByte), "999PB"},
99 +
100 + {"bytes(1EB)", Bytes(EByte), "1.0EB"},
101 + // Overflows.
102 + // {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
103 +
104 + {"bytes(0)", IBytes(0), "0B"},
105 + {"bytes(1)", IBytes(1), "1B"},
106 + {"bytes(803)", IBytes(803), "803B"},
107 + {"bytes(1023)", IBytes(1023), "1023B"},
108 +
109 + {"bytes(1024)", IBytes(1024), "1.0KiB"},
110 + {"bytes(1MB - 1)", IBytes(MiByte - IByte), "1024KiB"},
111 +
112 + {"bytes(1MB)", IBytes(1024 * 1024), "1.0MiB"},
113 + {"bytes(1GB - 1K)", IBytes(GiByte - KiByte), "1024MiB"},
114 +
115 + {"bytes(1GB)", IBytes(GiByte), "1.0GiB"},
116 + {"bytes(1TB - 1M)", IBytes(TiByte - MiByte), "1024GiB"},
117 +
118 + {"bytes(1TB)", IBytes(TiByte), "1.0TiB"},
119 + {"bytes(1PB - 1T)", IBytes(PiByte - TiByte), "1023TiB"},
120 +
121 + {"bytes(1PB)", IBytes(PiByte), "1.0PiB"},
122 + {"bytes(1PB - 1T)", IBytes(EiByte - PiByte), "1023PiB"},
123 +
124 + {"bytes(1EiB)", IBytes(EiByte), "1.0EiB"},
125 + // Overflows.
126 + // {"bytes(1EB - 1P)", IBytes((KIByte*EIByte)-PiByte), "1023EB"},
127 +
128 + {"bytes(5.5GiB)", IBytes(5.5 * GiByte), "5.5GiB"},
129 +
130 + {"bytes(5.5GB)", Bytes(5.5 * GByte), "5.5GB"},
131 + }.validate(t)
132 +}
133 +
134 +func BenchmarkParseBytes(b *testing.B) {
135 + for i := 0; i < b.N; i++ {
136 + ParseBytes("16.5GB")
137 + }
138 +}
139 +
140 +func BenchmarkBytes(b *testing.B) {
141 + for i := 0; i < b.N; i++ {
142 + Bytes(16.5 * GByte)
143 + }
144 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/comma.go new
+67
@@ -0,0 +1,67 @@
1 +package humanize
2 +
3 +import (
4 + "math/big"
5 + "strconv"
6 + "strings"
7 +)
8 +
9 +// Comma produces a string form of the given number in base 10 with
10 +// commas after every three orders of magnitude.
11 +//
12 +// e.g. Comma(834142) -> 834,142
13 +func Comma(v int64) string {
14 + sign := ""
15 + if v < 0 {
16 + sign = "-"
17 + v = 0 - v
18 + }
19 +
20 + parts := []string{"", "", "", "", "", "", "", ""}
21 + j := len(parts) - 1
22 +
23 + for v > 999 {
24 + parts[j] = strconv.FormatInt(v%1000, 10)
25 + switch len(parts[j]) {
26 + case 2:
27 + parts[j] = "0" + parts[j]
28 + case 1:
29 + parts[j] = "00" + parts[j]
30 + }
31 + v = v / 1000
32 + j--
33 + }
34 + parts[j] = strconv.Itoa(int(v))
35 + return sign + strings.Join(parts[j:len(parts)], ",")
36 +}
37 +
38 +// BigComma produces a string form of the given big.Int in base 10
39 +// with commas after every three orders of magnitude.
40 +func BigComma(b *big.Int) string {
41 + sign := ""
42 + if b.Sign() < 0 {
43 + sign = "-"
44 + b.Abs(b)
45 + }
46 +
47 + athousand := big.NewInt(1000)
48 + c := (&big.Int{}).Set(b)
49 + _, m := oom(c, athousand)
50 + parts := make([]string, m+1)
51 + j := len(parts) - 1
52 +
53 + mod := &big.Int{}
54 + for b.Cmp(athousand) >= 0 {
55 + b.DivMod(b, athousand, mod)
56 + parts[j] = strconv.FormatInt(mod.Int64(), 10)
57 + switch len(parts[j]) {
58 + case 2:
59 + parts[j] = "0" + parts[j]
60 + case 1:
61 + parts[j] = "00" + parts[j]
62 + }
63 + j--
64 + }
65 + parts[j] = strconv.Itoa(int(b.Int64()))
66 + return sign + strings.Join(parts[j:len(parts)], ",")
67 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/comma_test.go new
+98
@@ -0,0 +1,98 @@
1 +package humanize
2 +
3 +import (
4 + "math/big"
5 + "testing"
6 +)
7 +
8 +func TestCommas(t *testing.T) {
9 + testList{
10 + {"0", Comma(0), "0"},
11 + {"10", Comma(10), "10"},
12 + {"100", Comma(100), "100"},
13 + {"1,000", Comma(1000), "1,000"},
14 + {"10,000", Comma(10000), "10,000"},
15 + {"100,000", Comma(100000), "100,000"},
16 + {"10,000,000", Comma(10000000), "10,000,000"},
17 + {"10,100,000", Comma(10100000), "10,100,000"},
18 + {"10,010,000", Comma(10010000), "10,010,000"},
19 + {"10,001,000", Comma(10001000), "10,001,000"},
20 + {"123,456,789", Comma(123456789), "123,456,789"},
21 + {"maxint", Comma(9.223372e+18), "9,223,372,000,000,000,000"},
22 + {"minint", Comma(-9.223372e+18), "-9,223,372,000,000,000,000"},
23 + {"-123,456,789", Comma(-123456789), "-123,456,789"},
24 + {"-10,100,000", Comma(-10100000), "-10,100,000"},
25 + {"-10,010,000", Comma(-10010000), "-10,010,000"},
26 + {"-10,001,000", Comma(-10001000), "-10,001,000"},
27 + {"-10,000,000", Comma(-10000000), "-10,000,000"},
28 + {"-100,000", Comma(-100000), "-100,000"},
29 + {"-10,000", Comma(-10000), "-10,000"},
30 + {"-1,000", Comma(-1000), "-1,000"},
31 + {"-100", Comma(-100), "-100"},
32 + {"-10", Comma(-10), "-10"},
33 + }.validate(t)
34 +}
35 +
36 +func BenchmarkCommas(b *testing.B) {
37 + for i := 0; i < b.N; i++ {
38 + Comma(1234567890)
39 + }
40 +}
41 +
42 +func BenchmarkBigCommas(b *testing.B) {
43 + for i := 0; i < b.N; i++ {
44 + BigComma(big.NewInt(1234567890))
45 + }
46 +}
47 +
48 +func bigComma(i int64) string {
49 + return BigComma(big.NewInt(i))
50 +}
51 +
52 +func TestBigCommas(t *testing.T) {
53 + testList{
54 + {"0", bigComma(0), "0"},
55 + {"10", bigComma(10), "10"},
56 + {"100", bigComma(100), "100"},
57 + {"1,000", bigComma(1000), "1,000"},
58 + {"10,000", bigComma(10000), "10,000"},
59 + {"100,000", bigComma(100000), "100,000"},
60 + {"10,000,000", bigComma(10000000), "10,000,000"},
61 + {"10,100,000", bigComma(10100000), "10,100,000"},
62 + {"10,010,000", bigComma(10010000), "10,010,000"},
63 + {"10,001,000", bigComma(10001000), "10,001,000"},
64 + {"123,456,789", bigComma(123456789), "123,456,789"},
65 + {"maxint", bigComma(9.223372e+18), "9,223,372,000,000,000,000"},
66 + {"minint", bigComma(-9.223372e+18), "-9,223,372,000,000,000,000"},
67 + {"-123,456,789", bigComma(-123456789), "-123,456,789"},
68 + {"-10,100,000", bigComma(-10100000), "-10,100,000"},
69 + {"-10,010,000", bigComma(-10010000), "-10,010,000"},
70 + {"-10,001,000", bigComma(-10001000), "-10,001,000"},
71 + {"-10,000,000", bigComma(-10000000), "-10,000,000"},
72 + {"-100,000", bigComma(-100000), "-100,000"},
73 + {"-10,000", bigComma(-10000), "-10,000"},
74 + {"-1,000", bigComma(-1000), "-1,000"},
75 + {"-100", bigComma(-100), "-100"},
76 + {"-10", bigComma(-10), "-10"},
77 + }.validate(t)
78 +}
79 +
80 +func TestVeryBigCommas(t *testing.T) {
81 + tests := []struct{ in, exp string }{
82 + {
83 + "84889279597249724975972597249849757294578485",
84 + "84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
85 + },
86 + {
87 + "-84889279597249724975972597249849757294578485",
88 + "-84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
89 + },
90 + }
91 + for _, test := range tests {
92 + n, _ := (&big.Int{}).SetString(test.in, 10)
93 + got := BigComma(n)
94 + if test.exp != got {
95 + t.Errorf("Expected %q, got %q", test.exp, got)
96 + }
97 + }
98 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/common_test.go new
+18
@@ -0,0 +1,18 @@
1 +package humanize
2 +
3 +import (
4 + "testing"
5 +)
6 +
7 +type testList []struct {
8 + name, got, exp string
9 +}
10 +
11 +func (tl testList) validate(t *testing.T) {
12 + for _, test := range tl {
13 + if test.got != test.exp {
14 + t.Errorf("On %v, expected '%v', but got '%v'",
15 + test.name, test.exp, test.got)
16 + }
17 + }
18 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/ftoa.go new
+23
@@ -0,0 +1,23 @@
1 +package humanize
2 +
3 +import "strconv"
4 +
5 +func stripTrailingZeros(s string) string {
6 + offset := len(s) - 1
7 + for offset > 0 {
8 + if s[offset] == '.' {
9 + offset--
10 + break
11 + }
12 + if s[offset] != '0' {
13 + break
14 + }
15 + offset--
16 + }
17 + return s[:offset+1]
18 +}
19 +
20 +// Ftoa converts a float to a string with no trailing zeros.
21 +func Ftoa(num float64) string {
22 + return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64))
23 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/ftoa_test.go new
+55
@@ -0,0 +1,55 @@
1 +package humanize
2 +
3 +import (
4 + "fmt"
5 + "regexp"
6 + "strconv"
7 + "testing"
8 +)
9 +
10 +func TestFtoa(t *testing.T) {
11 + testList{
12 + {"200", Ftoa(200), "200"},
13 + {"2", Ftoa(2), "2"},
14 + {"2.2", Ftoa(2.2), "2.2"},
15 + {"2.02", Ftoa(2.02), "2.02"},
16 + {"200.02", Ftoa(200.02), "200.02"},
17 + }.validate(t)
18 +}
19 +
20 +func BenchmarkFtoaRegexTrailing(b *testing.B) {
21 + trailingZerosRegex := regexp.MustCompile(`\.?0+$`)
22 +
23 + b.ResetTimer()
24 + for i := 0; i < b.N; i++ {
25 + trailingZerosRegex.ReplaceAllString("2.00000", "")
26 + trailingZerosRegex.ReplaceAllString("2.0000", "")
27 + trailingZerosRegex.ReplaceAllString("2.000", "")
28 + trailingZerosRegex.ReplaceAllString("2.00", "")
29 + trailingZerosRegex.ReplaceAllString("2.0", "")
30 + trailingZerosRegex.ReplaceAllString("2", "")
31 + }
32 +}
33 +
34 +func BenchmarkFtoaFunc(b *testing.B) {
35 + for i := 0; i < b.N; i++ {
36 + stripTrailingZeros("2.00000")
37 + stripTrailingZeros("2.0000")
38 + stripTrailingZeros("2.000")
39 + stripTrailingZeros("2.00")
40 + stripTrailingZeros("2.0")
41 + stripTrailingZeros("2")
42 + }
43 +}
44 +
45 +func BenchmarkFmtF(b *testing.B) {
46 + for i := 0; i < b.N; i++ {
47 + fmt.Sprintf("%f", 2.03584)
48 + }
49 +}
50 +
51 +func BenchmarkStrconvF(b *testing.B) {
52 + for i := 0; i < b.N; i++ {
53 + strconv.FormatFloat(2.03584, 'f', 6, 64)
54 + }
55 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/humanize.go new
+8
@@ -0,0 +1,8 @@
1 +/*
2 +Package humanize converts boring ugly numbers to human-friendly strings.
3 +
4 +Durations can be turned into strings such as "3 days ago", numbers
5 +representing sizes like 82854982 into useful strings like, "83MB" or
6 +"79MiB" (whichever you prefer).
7 +*/
8 +package humanize
Godeps/_workspace/src/github.com/dustin/go-humanize/ordinals.go new
+25
@@ -0,0 +1,25 @@
1 +package humanize
2 +
3 +import "strconv"
4 +
5 +// Ordinal gives you the input number in a rank/ordinal format.
6 +//
7 +// Ordinal(3) -> 3rd
8 +func 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 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/ordinals_test.go new
+22
@@ -0,0 +1,22 @@
1 +package humanize
2 +
3 +import (
4 + "testing"
5 +)
6 +
7 +func TestOrdinals(t *testing.T) {
8 + testList{
9 + {"0", Ordinal(0), "0th"},
10 + {"1", Ordinal(1), "1st"},
11 + {"2", Ordinal(2), "2nd"},
12 + {"3", Ordinal(3), "3rd"},
13 + {"4", Ordinal(4), "4th"},
14 + {"10", Ordinal(10), "10th"},
15 + {"11", Ordinal(11), "11th"},
16 + {"12", Ordinal(12), "12th"},
17 + {"13", Ordinal(13), "13th"},
18 + {"101", Ordinal(101), "101st"},
19 + {"102", Ordinal(102), "102nd"},
20 + {"103", Ordinal(103), "103rd"},
21 + }.validate(t)
22 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/si.go new
+104
@@ -0,0 +1,104 @@
1 +package humanize
2 +
3 +import (
4 + "errors"
5 + "math"
6 + "regexp"
7 + "strconv"
8 +)
9 +
10 +var siPrefixTable = map[float64]string{
11 + -24: "y", // yocto
12 + -21: "z", // zepto
13 + -18: "a", // atto
14 + -15: "f", // femto
15 + -12: "p", // pico
16 + -9: "n", // nano
17 + -6: "µ", // micro
18 + -3: "m", // milli
19 + 0: "",
20 + 3: "k", // kilo
21 + 6: "M", // mega
22 + 9: "G", // giga
23 + 12: "T", // tera
24 + 15: "P", // peta
25 + 18: "E", // exa
26 + 21: "Z", // zetta
27 + 24: "Y", // yotta
28 +}
29 +
30 +var revSIPrefixTable = revfmap(siPrefixTable)
31 +
32 +// revfmap reverses the map and precomputes the power multiplier
33 +func revfmap(in map[float64]string) map[string]float64 {
34 + rv := map[string]float64{}
35 + for k, v := range in {
36 + rv[v] = math.Pow(10, k)
37 + }
38 + return rv
39 +}
40 +
41 +var riParseRegex *regexp.Regexp
42 +
43 +func init() {
44 + ri := `^([0-9.]+)([`
45 + for _, v := range siPrefixTable {
46 + ri += v
47 + }
48 + ri += `]?)(.*)`
49 +
50 + riParseRegex = regexp.MustCompile(ri)
51 +}
52 +
53 +// ComputeSI finds the most appropriate SI prefix for the given number
54 +// and returns the prefix along with the value adjusted to be within
55 +// that prefix.
56 +//
57 +// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p")
58 +func ComputeSI(input float64) (float64, string) {
59 + if input == 0 {
60 + return 0, ""
61 + }
62 + exponent := math.Floor(logn(input, 10))
63 + exponent = math.Floor(exponent/3) * 3
64 +
65 + value := input / math.Pow(10, exponent)
66 +
67 + // Handle special case where value is exactly 1000.0
68 + // Should return 1M instead of 1000k
69 + if value == 1000.0 {
70 + exponent += 3
71 + value = input / math.Pow(10, exponent)
72 + }
73 +
74 + prefix := siPrefixTable[exponent]
75 + return value, prefix
76 +}
77 +
78 +// SI returns a string with default formatting.
79 +//
80 +// SI uses Ftoa to format float value, removing trailing zeros.
81 +//
82 +// e.g. SI(1000000, B) -> 1MB
83 +// e.g. SI(2.2345e-12, "F") -> 2.2345pF
84 +func SI(input float64, unit string) string {
85 + value, prefix := ComputeSI(input)
86 + return Ftoa(value) + prefix + unit
87 +}
88 +
89 +var errInvalid = errors.New("invalid input")
90 +
91 +// ParseSI parses an SI string back into the number and unit.
92 +//
93 +// e.g. ParseSI(2.2345pF) -> (2.2345e-12, "F", nil)
94 +func ParseSI(input string) (float64, string, error) {
95 + found := riParseRegex.FindStringSubmatch(input)
96 + if len(found) != 4 {
97 + return 0, "", errInvalid
98 + }
99 + mag := revSIPrefixTable[found[2]]
100 + unit := found[3]
101 +
102 + base, err := strconv.ParseFloat(found[1], 64)
103 + return base * mag, unit, err
104 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/si_test.go new
+98
@@ -0,0 +1,98 @@
1 +package humanize
2 +
3 +import (
4 + "math"
5 + "testing"
6 +)
7 +
8 +func TestSI(t *testing.T) {
9 + tests := []struct {
10 + name string
11 + num float64
12 + formatted string
13 + }{
14 + {"e-24", 1e-24, "1yF"},
15 + {"e-21", 1e-21, "1zF"},
16 + {"e-18", 1e-18, "1aF"},
17 + {"e-15", 1e-15, "1fF"},
18 + {"e-12", 1e-12, "1pF"},
19 + {"e-12", 2.2345e-12, "2.2345pF"},
20 + {"e-12", 2.23e-12, "2.23pF"},
21 + {"e-11", 2.23e-11, "22.3pF"},
22 + {"e-10", 2.2e-10, "220pF"},
23 + {"e-9", 2.2e-9, "2.2nF"},
24 + {"e-8", 2.2e-8, "22nF"},
25 + {"e-7", 2.2e-7, "220nF"},
26 + {"e-6", 2.2e-6, "2.2µF"},
27 + {"e-6", 1e-6, "1µF"},
28 + {"e-5", 2.2e-5, "22µF"},
29 + {"e-4", 2.2e-4, "220µF"},
30 + {"e-3", 2.2e-3, "2.2mF"},
31 + {"e-2", 2.2e-2, "22mF"},
32 + {"e-1", 2.2e-1, "220mF"},
33 + {"e+0", 2.2e-0, "2.2F"},
34 + {"e+0", 2.2, "2.2F"},
35 + {"e+1", 2.2e+1, "22F"},
36 + {"0", 0, "0F"},
37 + {"e+1", 22, "22F"},
38 + {"e+2", 2.2e+2, "220F"},
39 + {"e+2", 220, "220F"},
40 + {"e+3", 2.2e+3, "2.2kF"},
41 + {"e+3", 2200, "2.2kF"},
42 + {"e+4", 2.2e+4, "22kF"},
43 + {"e+4", 22000, "22kF"},
44 + {"e+5", 2.2e+5, "220kF"},
45 + {"e+6", 2.2e+6, "2.2MF"},
46 + {"e+6", 1e+6, "1MF"},
47 + {"e+7", 2.2e+7, "22MF"},
48 + {"e+8", 2.2e+8, "220MF"},
49 + {"e+9", 2.2e+9, "2.2GF"},
50 + {"e+10", 2.2e+10, "22GF"},
51 + {"e+11", 2.2e+11, "220GF"},
52 + {"e+12", 2.2e+12, "2.2TF"},
53 + {"e+15", 2.2e+15, "2.2PF"},
54 + {"e+18", 2.2e+18, "2.2EF"},
55 + {"e+21", 2.2e+21, "2.2ZF"},
56 + {"e+24", 2.2e+24, "2.2YF"},
57 +
58 + // special case
59 + {"1F", 1000 * 1000, "1MF"},
60 + {"1F", 1e6, "1MF"},
61 + }
62 +
63 + for _, test := range tests {
64 + got := SI(test.num, "F")
65 + if got != test.formatted {
66 + t.Errorf("On %v (%v), got %v, wanted %v",
67 + test.name, test.num, got, test.formatted)
68 + }
69 +
70 + gotf, gotu, err := ParseSI(test.formatted)
71 + if err != nil {
72 + t.Errorf("Error parsing %v (%v): %v", test.name, test.formatted, err)
73 + continue
74 + }
75 +
76 + if math.Abs(1-(gotf/test.num)) > 0.01 {
77 + t.Errorf("On %v (%v), got %v, wanted %v (±%v)",
78 + test.name, test.formatted, gotf, test.num,
79 + math.Abs(1-(gotf/test.num)))
80 + }
81 + if gotu != "F" {
82 + t.Errorf("On %v (%v), expected unit F, got %v",
83 + test.name, test.formatted, gotu)
84 + }
85 + }
86 +
87 + // Parse error
88 + gotf, gotu, err := ParseSI("x1.21JW") // 1.21 jigga whats
89 + if err == nil {
90 + t.Errorf("Expected error on x1.21JW, got %v %v", gotf, gotu)
91 + }
92 +}
93 +
94 +func BenchmarkParseSI(b *testing.B) {
95 + for i := 0; i < b.N; i++ {
96 + ParseSI("2.2346ZB")
97 + }
98 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/times.go new
+91
@@ -0,0 +1,91 @@
1 +package humanize
2 +
3 +import (
4 + "fmt"
5 + "math"
6 + "sort"
7 + "time"
8 +)
9 +
10 +// Seconds-based time units
11 +const (
12 + Minute = 60
13 + Hour = 60 * Minute
14 + Day = 24 * Hour
15 + Week = 7 * Day
16 + Month = 30 * Day
17 + Year = 12 * Month
18 + LongTime = 37 * Year
19 +)
20 +
21 +// Time formats a time into a relative string.
22 +//
23 +// Time(someT) -> "3 weeks ago"
24 +func Time(then time.Time) string {
25 + return RelTime(then, time.Now(), "ago", "from now")
26 +}
27 +
28 +var magnitudes = []struct {
29 + d int64
30 + format string
31 + divby int64
32 +}{
33 + {1, "now", 1},
34 + {2, "1 second %s", 1},
35 + {Minute, "%d seconds %s", 1},
36 + {2 * Minute, "1 minute %s", 1},
37 + {Hour, "%d minutes %s", Minute},
38 + {2 * Hour, "1 hour %s", 1},
39 + {Day, "%d hours %s", Hour},
40 + {2 * Day, "1 day %s", 1},
41 + {Week, "%d days %s", Day},
42 + {2 * Week, "1 week %s", 1},
43 + {Month, "%d weeks %s", Week},
44 + {2 * Month, "1 month %s", 1},
45 + {Year, "%d months %s", Month},
46 + {18 * Month, "1 year %s", 1},
47 + {2 * Year, "2 years %s", 1},
48 + {LongTime, "%d years %s", Year},
49 + {math.MaxInt64, "a long while %s", 1},
50 +}
51 +
52 +// RelTime formats a time into a relative string.
53 +//
54 +// It takes two times and two labels. In addition to the generic time
55 +// delta string (e.g. 5 minutes), the labels are used applied so that
56 +// the label corresponding to the smaller time is applied.
57 +//
58 +// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
59 +func RelTime(a, b time.Time, albl, blbl string) string {
60 + lbl := albl
61 + diff := b.Unix() - a.Unix()
62 +
63 + after := a.After(b)
64 + if after {
65 + lbl = blbl
66 + diff = a.Unix() - b.Unix()
67 + }
68 +
69 + n := sort.Search(len(magnitudes), func(i int) bool {
70 + return magnitudes[i].d > diff
71 + })
72 +
73 + mag := magnitudes[n]
74 + args := []interface{}{}
75 + escaped := false
76 + for _, ch := range mag.format {
77 + if escaped {
78 + switch ch {
79 + case '%':
80 + case 's':
81 + args = append(args, lbl)
82 + case 'd':
83 + args = append(args, diff/mag.divby)
84 + }
85 + escaped = false
86 + } else {
87 + escaped = ch == '%'
88 + }
89 + }
90 + return fmt.Sprintf(mag.format, args...)
91 +}
Godeps/_workspace/src/github.com/dustin/go-humanize/times_test.go new
+71
@@ -0,0 +1,71 @@
1 +package humanize
2 +
3 +import (
4 + "math"
5 + "testing"
6 + "time"
7 +)
8 +
9 +func TestPast(t *testing.T) {
10 + now := time.Now().Unix()
11 + testList{
12 + {"now", Time(time.Unix(now, 0)), "now"},
13 + {"1 second ago", Time(time.Unix(now-1, 0)), "1 second ago"},
14 + {"12 seconds ago", Time(time.Unix(now-12, 0)), "12 seconds ago"},
15 + {"30 seconds ago", Time(time.Unix(now-30, 0)), "30 seconds ago"},
16 + {"45 seconds ago", Time(time.Unix(now-45, 0)), "45 seconds ago"},
17 + {"1 minute ago", Time(time.Unix(now-63, 0)), "1 minute ago"},
18 + {"15 minutes ago", Time(time.Unix(now-15*Minute, 0)), "15 minutes ago"},
19 + {"1 hour ago", Time(time.Unix(now-63*Minute, 0)), "1 hour ago"},
20 + {"2 hours ago", Time(time.Unix(now-2*Hour, 0)), "2 hours ago"},
21 + {"21 hours ago", Time(time.Unix(now-21*Hour, 0)), "21 hours ago"},
22 + {"1 day ago", Time(time.Unix(now-26*Hour, 0)), "1 day ago"},
23 + {"2 days ago", Time(time.Unix(now-49*Hour, 0)), "2 days ago"},
24 + {"3 days ago", Time(time.Unix(now-3*Day, 0)), "3 days ago"},
25 + {"1 week ago (1)", Time(time.Unix(now-7*Day, 0)), "1 week ago"},
26 + {"1 week ago (2)", Time(time.Unix(now-12*Day, 0)), "1 week ago"},
27 + {"2 weeks ago", Time(time.Unix(now-15*Day, 0)), "2 weeks ago"},
28 + {"1 month ago", Time(time.Unix(now-39*Day, 0)), "1 month ago"},
29 + {"3 months ago", Time(time.Unix(now-99*Day, 0)), "3 months ago"},
30 + {"1 year ago (1)", Time(time.Unix(now-365*Day, 0)), "1 year ago"},
31 + {"1 year ago (1)", Time(time.Unix(now-400*Day, 0)), "1 year ago"},
32 + {"2 years ago (1)", Time(time.Unix(now-548*Day, 0)), "2 years ago"},
33 + {"2 years ago (2)", Time(time.Unix(now-725*Day, 0)), "2 years ago"},
34 + {"2 years ago (3)", Time(time.Unix(now-800*Day, 0)), "2 years ago"},
35 + {"3 years ago", Time(time.Unix(now-3*Year, 0)), "3 years ago"},
36 + {"long ago", Time(time.Unix(now-LongTime, 0)), "a long while ago"},
37 + }.validate(t)
38 +}
39 +
40 +func TestFuture(t *testing.T) {
41 + now := time.Now().Unix()
42 + testList{
43 + {"now", Time(time.Unix(now, 0)), "now"},
44 + {"1 second from now", Time(time.Unix(now+1, 0)), "1 second from now"},
45 + {"12 seconds from now", Time(time.Unix(now+12, 0)), "12 seconds from now"},
46 + {"30 seconds from now", Time(time.Unix(now+30, 0)), "30 seconds from now"},
47 + {"45 seconds from now", Time(time.Unix(now+45, 0)), "45 seconds from now"},
48 + {"15 minutes from now", Time(time.Unix(now+15*Minute, 0)), "15 minutes from now"},
49 + {"2 hours from now", Time(time.Unix(now+2*Hour, 0)), "2 hours from now"},
50 + {"21 hours from now", Time(time.Unix(now+21*Hour, 0)), "21 hours from now"},
51 + {"1 day from now", Time(time.Unix(now+26*Hour, 0)), "1 day from now"},
52 + {"2 days from now", Time(time.Unix(now+49*Hour, 0)), "2 days from now"},
53 + {"3 days from now", Time(time.Unix(now+3*Day, 0)), "3 days from now"},
54 + {"1 week from now (1)", Time(time.Unix(now+7*Day, 0)), "1 week from now"},
55 + {"1 week from now (2)", Time(time.Unix(now+12*Day, 0)), "1 week from now"},
56 + {"2 weeks from now", Time(time.Unix(now+15*Day, 0)), "2 weeks from now"},
57 + {"1 month from now", Time(time.Unix(now+30*Day, 0)), "1 month from now"},
58 + {"1 year from now", Time(time.Unix(now+365*Day, 0)), "1 year from now"},
59 + {"2 years from now", Time(time.Unix(now+2*Year, 0)), "2 years from now"},
60 + {"a while from now", Time(time.Unix(now+LongTime, 0)), "a long while from now"},
61 + }.validate(t)
62 +}
63 +
64 +func TestRange(t *testing.T) {
65 + start := time.Time{}
66 + end := time.Unix(math.MaxInt64, math.MaxInt64)
67 + x := RelTime(start, end, "ago", "from now")
68 + if x != "a long while from now" {
69 + t.Errorf("Expected a long while from now, got %q", x)
70 + }
71 +}
Godeps/_workspace/src/github.com/h2so5/utp/benchmark/main.go
+1 -1
@@ -12,7 +12,7 @@ import (
12 "time"
13
14 "github.com/davecheney/profile"
15 - "github.com/dustin/go-humanize"
15 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"
16 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/h2so5/utp"
17 )
18
Godeps/_workspace/src/github.com/jbenet/go-random/random/random.go
+1 -1
@@ -5,7 +5,7 @@ import (
5 "os"
6 "strconv"
7
8 - "github.com/dustin/go-humanize"
8 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"
9 random "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-random"
10 )
11