bigbytes.go

  1package humanize
  2
  3import (
  4	"fmt"
  5	"math/big"
  6	"strings"
  7	"unicode"
  8)
  9
 10var (
 11	bigIECExp = big.NewInt(1024)
 12
 13	// BigByte is one byte in bit.Ints
 14	BigByte = big.NewInt(1)
 15	// BigKiByte is 1,024 bytes in bit.Ints
 16	BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp)
 17	// BigMiByte is 1,024 k bytes in bit.Ints
 18	BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp)
 19	// BigGiByte is 1,024 m bytes in bit.Ints
 20	BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp)
 21	// BigTiByte is 1,024 g bytes in bit.Ints
 22	BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp)
 23	// BigPiByte is 1,024 t bytes in bit.Ints
 24	BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp)
 25	// BigEiByte is 1,024 p bytes in bit.Ints
 26	BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp)
 27	// BigZiByte is 1,024 e bytes in bit.Ints
 28	BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp)
 29	// BigYiByte is 1,024 z bytes in bit.Ints
 30	BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp)
 31	// BigRiByte is 1,024 y bytes in bit.Ints
 32	BigRiByte = (&big.Int{}).Mul(BigYiByte, bigIECExp)
 33	// BigQiByte is 1,024 r bytes in bit.Ints
 34	BigQiByte = (&big.Int{}).Mul(BigRiByte, bigIECExp)
 35)
 36
 37var (
 38	bigSIExp = big.NewInt(1000)
 39
 40	// BigSIByte is one SI byte in big.Ints
 41	BigSIByte = big.NewInt(1)
 42	// BigKByte is 1,000 SI bytes in big.Ints
 43	BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp)
 44	// BigMByte is 1,000 SI k bytes in big.Ints
 45	BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp)
 46	// BigGByte is 1,000 SI m bytes in big.Ints
 47	BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp)
 48	// BigTByte is 1,000 SI g bytes in big.Ints
 49	BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp)
 50	// BigPByte is 1,000 SI t bytes in big.Ints
 51	BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp)
 52	// BigEByte is 1,000 SI p bytes in big.Ints
 53	BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp)
 54	// BigZByte is 1,000 SI e bytes in big.Ints
 55	BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
 56	// BigYByte is 1,000 SI z bytes in big.Ints
 57	BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
 58	// BigRByte is 1,000 SI y bytes in big.Ints
 59	BigRByte = (&big.Int{}).Mul(BigYByte, bigSIExp)
 60	// BigQByte is 1,000 SI r bytes in big.Ints
 61	BigQByte = (&big.Int{}).Mul(BigRByte, bigSIExp)
 62)
 63
 64var bigBytesSizeTable = map[string]*big.Int{
 65	"b":   BigByte,
 66	"kib": BigKiByte,
 67	"kb":  BigKByte,
 68	"mib": BigMiByte,
 69	"mb":  BigMByte,
 70	"gib": BigGiByte,
 71	"gb":  BigGByte,
 72	"tib": BigTiByte,
 73	"tb":  BigTByte,
 74	"pib": BigPiByte,
 75	"pb":  BigPByte,
 76	"eib": BigEiByte,
 77	"eb":  BigEByte,
 78	"zib": BigZiByte,
 79	"zb":  BigZByte,
 80	"yib": BigYiByte,
 81	"yb":  BigYByte,
 82	"rib": BigRiByte,
 83	"rb":  BigRByte,
 84	"qib": BigQiByte,
 85	"qb":  BigQByte,
 86	// Without suffix
 87	"":   BigByte,
 88	"ki": BigKiByte,
 89	"k":  BigKByte,
 90	"mi": BigMiByte,
 91	"m":  BigMByte,
 92	"gi": BigGiByte,
 93	"g":  BigGByte,
 94	"ti": BigTiByte,
 95	"t":  BigTByte,
 96	"pi": BigPiByte,
 97	"p":  BigPByte,
 98	"ei": BigEiByte,
 99	"e":  BigEByte,
100	"z":  BigZByte,
101	"zi": BigZiByte,
102	"y":  BigYByte,
103	"yi": BigYiByte,
104	"r":  BigRByte,
105	"ri": BigRiByte,
106	"q":  BigQByte,
107	"qi": BigQiByte,
108}
109
110var ten = big.NewInt(10)
111
112func humanateBigBytes(s, base *big.Int, sizes []string) string {
113	if s.Cmp(ten) < 0 {
114		return fmt.Sprintf("%d B", s)
115	}
116	c := (&big.Int{}).Set(s)
117	val, mag := oomm(c, base, len(sizes)-1)
118	suffix := sizes[mag]
119	f := "%.0f %s"
120	if val < 10 {
121		f = "%.1f %s"
122	}
123
124	return fmt.Sprintf(f, val, suffix)
125
126}
127
128// BigBytes produces a human readable representation of an SI size.
129//
130// See also: ParseBigBytes.
131//
132// BigBytes(82854982) -> 83 MB
133func BigBytes(s *big.Int) string {
134	sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"}
135	return humanateBigBytes(s, bigSIExp, sizes)
136}
137
138// BigIBytes produces a human readable representation of an IEC size.
139//
140// See also: ParseBigBytes.
141//
142// BigIBytes(82854982) -> 79 MiB
143func BigIBytes(s *big.Int) string {
144	sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}
145	return humanateBigBytes(s, bigIECExp, sizes)
146}
147
148// ParseBigBytes parses a string representation of bytes into the number
149// of bytes it represents.
150//
151// See also: BigBytes, BigIBytes.
152//
153// ParseBigBytes("42 MB") -> 42000000, nil
154// ParseBigBytes("42 mib") -> 44040192, nil
155func ParseBigBytes(s string) (*big.Int, error) {
156	lastDigit := 0
157	hasComma := false
158	for _, r := range s {
159		if !(unicode.IsDigit(r) || r == '.' || r == ',') {
160			break
161		}
162		if r == ',' {
163			hasComma = true
164		}
165		lastDigit++
166	}
167
168	num := s[:lastDigit]
169	if hasComma {
170		num = strings.Replace(num, ",", "", -1)
171	}
172
173	val := &big.Rat{}
174	_, err := fmt.Sscanf(num, "%f", val)
175	if err != nil {
176		return nil, err
177	}
178
179	extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
180	if m, ok := bigBytesSizeTable[extra]; ok {
181		mv := (&big.Rat{}).SetInt(m)
182		val.Mul(val, mv)
183		rv := &big.Int{}
184		rv.Div(val.Num(), val.Denom())
185		return rv, nil
186	}
187
188	return nil, fmt.Errorf("unhandled size name: %v", extra)
189}