bigbytes.go (4850B)
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 // 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 37 var ( 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 64 var 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 110 var ten = big.NewInt(10) 111 112 func 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 133 func 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 143 func 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 155 func 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 }