pax_global_header00006660000000000000000000000064126121041360014506gustar00rootroot0000000000000052 comment=2efee857e7cfd4f3d0138cc3cbb1b4966962b93a golang-github-alecthomas-units/000077500000000000000000000000001261210413600170575ustar00rootroot00000000000000golang-github-alecthomas-units/COPYING000066400000000000000000000020371261210413600201140ustar00rootroot00000000000000Copyright (C) 2014 Alec Thomas Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-alecthomas-units/README.md000066400000000000000000000004301261210413600203330ustar00rootroot00000000000000# Units - Helpful unit multipliers and functions for Go The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package. It allows for code like this: ```go n, err := ParseBase2Bytes("1KB") // n == 1024 n = units.Mebibyte * 512 ``` golang-github-alecthomas-units/bytes.go000066400000000000000000000043371261210413600205430ustar00rootroot00000000000000package units // Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte, // etc.). type Base2Bytes int64 // Base-2 byte units. const ( Kibibyte Base2Bytes = 1024 KiB = Kibibyte Mebibyte = Kibibyte * 1024 MiB = Mebibyte Gibibyte = Mebibyte * 1024 GiB = Gibibyte Tebibyte = Gibibyte * 1024 TiB = Tebibyte Pebibyte = Tebibyte * 1024 PiB = Pebibyte Exbibyte = Pebibyte * 1024 EiB = Exbibyte ) var ( bytesUnitMap = MakeUnitMap("iB", "B", 1024) oldBytesUnitMap = MakeUnitMap("B", "B", 1024) ) // ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB // and KiB are both 1024. func ParseBase2Bytes(s string) (Base2Bytes, error) { n, err := ParseUnit(s, bytesUnitMap) if err != nil { n, err = ParseUnit(s, oldBytesUnitMap) } return Base2Bytes(n), err } func (b Base2Bytes) String() string { return ToString(int64(b), 1024, "iB", "B") } var ( metricBytesUnitMap = MakeUnitMap("B", "B", 1000) ) // MetricBytes are SI byte units (1000 bytes in a kilobyte). type MetricBytes SI // SI base-10 byte units. const ( Kilobyte MetricBytes = 1000 KB = Kilobyte Megabyte = Kilobyte * 1000 MB = Megabyte Gigabyte = Megabyte * 1000 GB = Gigabyte Terabyte = Gigabyte * 1000 TB = Terabyte Petabyte = Terabyte * 1000 PB = Petabyte Exabyte = Petabyte * 1000 EB = Exabyte ) // ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes. func ParseMetricBytes(s string) (MetricBytes, error) { n, err := ParseUnit(s, metricBytesUnitMap) return MetricBytes(n), err } func (m MetricBytes) String() string { return ToString(int64(m), 1000, "B", "B") } // ParseStrictBytes supports both iB and B suffixes for base 2 and metric, // respectively. That is, KiB represents 1024 and KB represents 1000. func ParseStrictBytes(s string) (int64, error) { n, err := ParseUnit(s, bytesUnitMap) if err != nil { n, err = ParseUnit(s, metricBytesUnitMap) } return int64(n), err } golang-github-alecthomas-units/bytes_test.go000066400000000000000000000024351261210413600215770ustar00rootroot00000000000000package units import ( "testing" "github.com/stretchr/testify/assert" ) func TestBase2BytesString(t *testing.T) { assert.Equal(t, Base2Bytes(0).String(), "0B") assert.Equal(t, Base2Bytes(1025).String(), "1KiB1B") assert.Equal(t, Base2Bytes(1048577).String(), "1MiB1B") } func TestParseBase2Bytes(t *testing.T) { n, err := ParseBase2Bytes("0B") assert.NoError(t, err) assert.Equal(t, 0, int(n)) n, err = ParseBase2Bytes("1KB") assert.NoError(t, err) assert.Equal(t, 1024, int(n)) n, err = ParseBase2Bytes("1MB1KB25B") assert.NoError(t, err) assert.Equal(t, 1049625, int(n)) n, err = ParseBase2Bytes("1.5MB") assert.NoError(t, err) assert.Equal(t, 1572864, int(n)) } func TestMetricBytesString(t *testing.T) { assert.Equal(t, MetricBytes(0).String(), "0B") assert.Equal(t, MetricBytes(1001).String(), "1KB1B") assert.Equal(t, MetricBytes(1001025).String(), "1MB1KB25B") } func TestParseMetricBytes(t *testing.T) { n, err := ParseMetricBytes("0B") assert.NoError(t, err) assert.Equal(t, 0, int(n)) n, err = ParseMetricBytes("1KB1B") assert.NoError(t, err) assert.Equal(t, 1001, int(n)) n, err = ParseMetricBytes("1MB1KB25B") assert.NoError(t, err) assert.Equal(t, 1001025, int(n)) n, err = ParseMetricBytes("1.5MB") assert.NoError(t, err) assert.Equal(t, 1500000, int(n)) } golang-github-alecthomas-units/doc.go000066400000000000000000000005341261210413600201550ustar00rootroot00000000000000// Package units provides helpful unit multipliers and functions for Go. // // The goal of this package is to have functionality similar to the time [1] package. // // // [1] http://golang.org/pkg/time/ // // It allows for code like this: // // n, err := ParseBase2Bytes("1KB") // // n == 1024 // n = units.Mebibyte * 512 package units golang-github-alecthomas-units/si.go000066400000000000000000000012121261210413600200150ustar00rootroot00000000000000package units // SI units. type SI int64 // SI unit multiples. const ( Kilo SI = 1000 Mega = Kilo * 1000 Giga = Mega * 1000 Tera = Giga * 1000 Peta = Tera * 1000 Exa = Peta * 1000 ) func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 { return map[string]float64{ shortSuffix: 1, "K" + suffix: float64(scale), "M" + suffix: float64(scale * scale), "G" + suffix: float64(scale * scale * scale), "T" + suffix: float64(scale * scale * scale * scale), "P" + suffix: float64(scale * scale * scale * scale * scale), "E" + suffix: float64(scale * scale * scale * scale * scale * scale), } } golang-github-alecthomas-units/util.go000066400000000000000000000053041261210413600203650ustar00rootroot00000000000000package units import ( "errors" "fmt" "strings" ) var ( siUnits = []string{"", "K", "M", "G", "T", "P", "E"} ) func ToString(n int64, scale int64, suffix, baseSuffix string) string { mn := len(siUnits) out := make([]string, mn) for i, m := range siUnits { if n%scale != 0 || i == 0 && n == 0 { s := suffix if i == 0 { s = baseSuffix } out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s) } n /= scale if n == 0 { break } } return strings.Join(out, "") } // Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123 var errLeadingInt = errors.New("units: bad [0-9]*") // never printed // leadingInt consumes the leading [0-9]* from s. func leadingInt(s string) (x int64, rem string, err error) { i := 0 for ; i < len(s); i++ { c := s[i] if c < '0' || c > '9' { break } if x >= (1<<63-10)/10 { // overflow return 0, "", errLeadingInt } x = x*10 + int64(c) - '0' } return x, s[i:], nil } func ParseUnit(s string, unitMap map[string]float64) (int64, error) { // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ orig := s f := float64(0) neg := false // Consume [-+]? if s != "" { c := s[0] if c == '-' || c == '+' { neg = c == '-' s = s[1:] } } // Special case: if all that is left is "0", this is zero. if s == "0" { return 0, nil } if s == "" { return 0, errors.New("units: invalid " + orig) } for s != "" { g := float64(0) // this element of the sequence var x int64 var err error // The next character must be [0-9.] if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) { return 0, errors.New("units: invalid " + orig) } // Consume [0-9]* pl := len(s) x, s, err = leadingInt(s) if err != nil { return 0, errors.New("units: invalid " + orig) } g = float64(x) pre := pl != len(s) // whether we consumed anything before a period // Consume (\.[0-9]*)? post := false if s != "" && s[0] == '.' { s = s[1:] pl := len(s) x, s, err = leadingInt(s) if err != nil { return 0, errors.New("units: invalid " + orig) } scale := 1.0 for n := pl - len(s); n > 0; n-- { scale *= 10 } g += float64(x) / scale post = pl != len(s) } if !pre && !post { // no digits (e.g. ".s" or "-.s") return 0, errors.New("units: invalid " + orig) } // Consume unit. i := 0 for ; i < len(s); i++ { c := s[i] if c == '.' || ('0' <= c && c <= '9') { break } } u := s[:i] s = s[i:] unit, ok := unitMap[u] if !ok { return 0, errors.New("units: unknown unit " + u + " in " + orig) } f += g * unit } if neg { f = -f } if f < float64(-1<<63) || f > float64(1<<63-1) { return 0, errors.New("units: overflow parsing unit") } return int64(f), nil }