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) 32 33var ( 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 56var 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 94var ten = big.NewInt(10) 95 96func humanateBigBytes(s, base *big.Int, sizes []string) string { 97 if s.Cmp(ten) < 0 { 98 return fmt.Sprintf("%d B", 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// See also: ParseBigBytes. 115// 116// BigBytes(82854982) -> 83 MB 117func BigBytes(s *big.Int) string { 118 sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} 119 return humanateBigBytes(s, bigSIExp, sizes) 120} 121 122// BigIBytes produces a human readable representation of an IEC size. 123// 124// See also: ParseBigBytes. 125// 126// BigIBytes(82854982) -> 79 MiB 127func BigIBytes(s *big.Int) string { 128 sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} 129 return humanateBigBytes(s, bigIECExp, sizes) 130} 131 132// ParseBigBytes parses a string representation of bytes into the number 133// of bytes it represents. 134// 135// See also: BigBytes, BigIBytes. 136// 137// ParseBigBytes("42 MB") -> 42000000, nil 138// ParseBigBytes("42 mib") -> 44040192, nil 139func ParseBigBytes(s string) (*big.Int, error) { 140 lastDigit := 0 141 hasComma := false 142 for _, r := range s { 143 if !(unicode.IsDigit(r) || r == '.' || r == ',') { 144 break 145 } 146 if r == ',' { 147 hasComma = true 148 } 149 lastDigit++ 150 } 151 152 num := s[:lastDigit] 153 if hasComma { 154 num = strings.Replace(num, ",", "", -1) 155 } 156 157 val := &big.Rat{} 158 _, err := fmt.Sscanf(num, "%f", val) 159 if err != nil { 160 return nil, err 161 } 162 163 extra := strings.ToLower(strings.TrimSpace(s[lastDigit:])) 164 if m, ok := bigBytesSizeTable[extra]; ok { 165 mv := (&big.Rat{}).SetInt(m) 166 val.Mul(val, mv) 167 rv := &big.Int{} 168 rv.Div(val.Num(), val.Denom()) 169 return rv, nil 170 } 171 172 return nil, fmt.Errorf("unhandled size name: %v", extra) 173} 174