mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
4.2 KiB
173 lines
4.2 KiB
package humanize |
|
|
|
import ( |
|
"fmt" |
|
"math/big" |
|
"strings" |
|
"unicode" |
|
) |
|
|
|
var ( |
|
bigIECExp = big.NewInt(1024) |
|
|
|
// BigByte is one byte in bit.Ints |
|
BigByte = big.NewInt(1) |
|
// BigKiByte is 1,024 bytes in bit.Ints |
|
BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp) |
|
// BigMiByte is 1,024 k bytes in bit.Ints |
|
BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp) |
|
// BigGiByte is 1,024 m bytes in bit.Ints |
|
BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp) |
|
// BigTiByte is 1,024 g bytes in bit.Ints |
|
BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp) |
|
// BigPiByte is 1,024 t bytes in bit.Ints |
|
BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp) |
|
// BigEiByte is 1,024 p bytes in bit.Ints |
|
BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp) |
|
// BigZiByte is 1,024 e bytes in bit.Ints |
|
BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp) |
|
// BigYiByte is 1,024 z bytes in bit.Ints |
|
BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp) |
|
) |
|
|
|
var ( |
|
bigSIExp = big.NewInt(1000) |
|
|
|
// BigSIByte is one SI byte in big.Ints |
|
BigSIByte = big.NewInt(1) |
|
// BigKByte is 1,000 SI bytes in big.Ints |
|
BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp) |
|
// BigMByte is 1,000 SI k bytes in big.Ints |
|
BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp) |
|
// BigGByte is 1,000 SI m bytes in big.Ints |
|
BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp) |
|
// BigTByte is 1,000 SI g bytes in big.Ints |
|
BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp) |
|
// BigPByte is 1,000 SI t bytes in big.Ints |
|
BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp) |
|
// BigEByte is 1,000 SI p bytes in big.Ints |
|
BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp) |
|
// BigZByte is 1,000 SI e bytes in big.Ints |
|
BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp) |
|
// BigYByte is 1,000 SI z bytes in big.Ints |
|
BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp) |
|
) |
|
|
|
var bigBytesSizeTable = map[string]*big.Int{ |
|
"b": BigByte, |
|
"kib": BigKiByte, |
|
"kb": BigKByte, |
|
"mib": BigMiByte, |
|
"mb": BigMByte, |
|
"gib": BigGiByte, |
|
"gb": BigGByte, |
|
"tib": BigTiByte, |
|
"tb": BigTByte, |
|
"pib": BigPiByte, |
|
"pb": BigPByte, |
|
"eib": BigEiByte, |
|
"eb": BigEByte, |
|
"zib": BigZiByte, |
|
"zb": BigZByte, |
|
"yib": BigYiByte, |
|
"yb": BigYByte, |
|
// Without suffix |
|
"": BigByte, |
|
"ki": BigKiByte, |
|
"k": BigKByte, |
|
"mi": BigMiByte, |
|
"m": BigMByte, |
|
"gi": BigGiByte, |
|
"g": BigGByte, |
|
"ti": BigTiByte, |
|
"t": BigTByte, |
|
"pi": BigPiByte, |
|
"p": BigPByte, |
|
"ei": BigEiByte, |
|
"e": BigEByte, |
|
"z": BigZByte, |
|
"zi": BigZiByte, |
|
"y": BigYByte, |
|
"yi": BigYiByte, |
|
} |
|
|
|
var ten = big.NewInt(10) |
|
|
|
func humanateBigBytes(s, base *big.Int, sizes []string) string { |
|
if s.Cmp(ten) < 0 { |
|
return fmt.Sprintf("%d B", s) |
|
} |
|
c := (&big.Int{}).Set(s) |
|
val, mag := oomm(c, base, len(sizes)-1) |
|
suffix := sizes[mag] |
|
f := "%.0f %s" |
|
if val < 10 { |
|
f = "%.1f %s" |
|
} |
|
|
|
return fmt.Sprintf(f, val, suffix) |
|
|
|
} |
|
|
|
// BigBytes produces a human readable representation of an SI size. |
|
// |
|
// See also: ParseBigBytes. |
|
// |
|
// BigBytes(82854982) -> 83 MB |
|
func BigBytes(s *big.Int) string { |
|
sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} |
|
return humanateBigBytes(s, bigSIExp, sizes) |
|
} |
|
|
|
// BigIBytes produces a human readable representation of an IEC size. |
|
// |
|
// See also: ParseBigBytes. |
|
// |
|
// BigIBytes(82854982) -> 79 MiB |
|
func BigIBytes(s *big.Int) string { |
|
sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} |
|
return humanateBigBytes(s, bigIECExp, sizes) |
|
} |
|
|
|
// ParseBigBytes parses a string representation of bytes into the number |
|
// of bytes it represents. |
|
// |
|
// See also: BigBytes, BigIBytes. |
|
// |
|
// ParseBigBytes("42 MB") -> 42000000, nil |
|
// ParseBigBytes("42 mib") -> 44040192, nil |
|
func ParseBigBytes(s string) (*big.Int, error) { |
|
lastDigit := 0 |
|
hasComma := false |
|
for _, r := range s { |
|
if !(unicode.IsDigit(r) || r == '.' || r == ',') { |
|
break |
|
} |
|
if r == ',' { |
|
hasComma = true |
|
} |
|
lastDigit++ |
|
} |
|
|
|
num := s[:lastDigit] |
|
if hasComma { |
|
num = strings.Replace(num, ",", "", -1) |
|
} |
|
|
|
val := &big.Rat{} |
|
_, err := fmt.Sscanf(num, "%f", val) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
extra := strings.ToLower(strings.TrimSpace(s[lastDigit:])) |
|
if m, ok := bigBytesSizeTable[extra]; ok { |
|
mv := (&big.Rat{}).SetInt(m) |
|
val.Mul(val, mv) |
|
rv := &big.Int{} |
|
rv.Div(val.Num(), val.Denom()) |
|
return rv, nil |
|
} |
|
|
|
return nil, fmt.Errorf("unhandled size name: %v", extra) |
|
}
|
|
|