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