-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbyteconv.go
More file actions
171 lines (149 loc) · 3.39 KB
/
byteconv.go
File metadata and controls
171 lines (149 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package byteconv
import (
"fmt"
"strconv"
"strings"
"unicode"
)
const (
BYTE float64 = 1 << (10 * iota)
KiB // 1024
MiB // 1048576
GiB // 1073741824
TiB // 1099511627776 (exceeds 1 << 32)
PiB // 1125899906842624
EiB // 1152921504606846976
KB float64 = 1e3 // 1000
MB float64 = 1e6 // 1000000
GB float64 = 1e9 // 1000000000
TB float64 = 1e12 // 100000000000
PB float64 = 1e15 // 1000000000000000
EB float64 = 1e18 // 1000000000000000000
)
// BytesToBinarySize returns a human-readable IEC (binary) format string of the form 10MiB, 12.5KiB.
// History https://en.wikipedia.org/wiki/Mebibyte
// The following units are available:
// EiB: exbibyte
// PiB: pebibyte
// TiB: tebibyte
// GiB: gibibyte
// MiB: mebibyte
// KiB: kibibyte
// B: Byte
// The unit that results in the smallest number greater than or equal to 1 is always chosen.
func BytesToBinarySize(bytes float64) string {
if bytes <= 0 {
return "0"
}
var unit string
var res float64
switch {
case bytes >= EiB:
unit = "EiB"
res = bytes / EiB
case bytes >= PiB:
unit = "PiB"
res = bytes / PiB
case bytes >= TiB:
unit = "TiB"
res = bytes / TiB
case bytes >= GiB:
unit = "GiB"
res = bytes / GiB
case bytes >= MiB:
unit = "MiB"
res = bytes / MiB
case bytes >= KiB:
unit = "KiB"
res = bytes / KiB
case bytes >= BYTE:
unit = "B"
res = bytes
}
strRes := strconv.FormatFloat(res, 'f', 1, 64)
strRes = strings.TrimSuffix(strRes, ".0")
return strRes + unit
}
// StringBinaryToBytes parses a string formatted by ByteSize as bytes.
// Note binary-prefixed and SI prefixed units both mean a base-2 units
// KiB = 1024
// MiB = 1024 * K
// GiB = 1024 * M
// TiB = 1024 * G
// PiB = 1024 * T
// EiB = 1024 * P
func StringToBytes(s string) float64 {
s = strings.TrimSpace(s)
s = strings.ToUpper(s)
i := strings.IndexFunc(s, unicode.IsLetter)
if i == -1 {
return 0
}
bytesString, multiple := s[:i], s[i:]
bytes, err := strconv.ParseFloat(bytesString, 64)
if err != nil || bytes <= 0 {
return 0
}
switch multiple {
case "EIB":
return bytes * EiB
case "EB":
return bytes * EB
case "PIB":
return bytes * PiB
case "PB":
return bytes * PB
case "TIB":
return bytes * TiB
case "TB":
return bytes * TB
case "GIB":
return bytes * GiB
case "GB":
return bytes * GB
case "MIB":
return bytes * MiB
case "MB":
return bytes * MB
case "KIB":
return bytes * KiB
case "KB":
return bytes * KB
case "B":
return bytes
default:
return 0
}
}
// BytesSize returns a human-readable in 2 formats: IEC (binary) or SI (decimal)
// Binary string of the form 10MiB, 12.5KiB
// Decimal string of the form 10MB, 12.5KB
// The precision prec controls the number of digits
//The special precision -1 uses the smallest number of digits
func BytesSize(bytes float64, format string, prec int) string {
if bytes <= 0 {
return "0"
}
// Default format is decimal: MB, GB
value := 1000.0
resFormat := ""
// Binary format: MiB, GiB
if format == "binary" {
value = 1024.0
resFormat = "i"
}
if bytes < value {
strRes := strconv.FormatFloat(bytes, 'f', prec, 64)
return strings.TrimSuffix(strRes, ".0") + "B"
}
divider, exp := value, 0
for n := bytes / value; n >= value; n /= value {
divider *= value
exp++
}
strRes := strconv.FormatFloat(bytes/divider, 'f', prec, 64)
if prec == 0 {
strRes = strings.TrimSuffix(strRes, ".0")
}
return strRes + fmt.Sprintf("%c%sB", "KMGTPE"[exp], resFormat)
}