1
2
3
4
5
6
7
8
9
10
11 package psiprobe.tools;
12
13 import java.text.NumberFormat;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16
17
18
19
20 public final class SizeExpression {
21
22
23 public static final long MULTIPLIER_2 = 1024;
24
25
26 public static final long MULTIPLIER_10 = 1000;
27
28
29 public static final String UNIT_BASE = "B";
30
31
32 public static final char PREFIX_KILO = 'K';
33
34
35 public static final char PREFIX_MEGA = 'M';
36
37
38 public static final char PREFIX_GIGA = 'G';
39
40
41 public static final char PREFIX_TERA = 'T';
42
43
44 public static final char PREFIX_PETA = 'P';
45
46
47
48
49 private SizeExpression() {
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 public static long parse(String expression) {
113 String prefixClass =
114 "[" + PREFIX_KILO + PREFIX_MEGA + PREFIX_GIGA + PREFIX_TERA + PREFIX_PETA + "]";
115 Pattern expPattern =
116 Pattern.compile("(\\d+|\\d*\\.\\d+)\\s*(" + prefixClass + ")?(" + UNIT_BASE + ")?",
117 Pattern.CASE_INSENSITIVE);
118 Matcher expMatcher = expPattern.matcher(expression);
119 if (expMatcher.matches()) {
120 String value = expMatcher.group(1);
121 String unitPrefix = expMatcher.group(2);
122 String unitBase = expMatcher.group(3);
123 double multiplier = 1;
124 if (unitPrefix != null) {
125 multiplier = multiplier(unitPrefix.charAt(0), unitBase != null);
126 }
127 double rawValue = Double.parseDouble(value);
128 return (long) (rawValue * multiplier);
129 }
130 throw new NumberFormatException("Invalid expression format: " + expression);
131 }
132
133
134
135
136
137
138
139
140
141
142
143 public static String format(long value, int decimalPlaces, boolean base2) {
144 NumberFormat nf = NumberFormat.getInstance();
145 nf.setMinimumFractionDigits(decimalPlaces);
146
147 double doubleResult;
148 String unit = base2 ? UNIT_BASE : "";
149 double multiplierKilo = multiplier(PREFIX_KILO, base2);
150 double multiplierMega = multiplier(PREFIX_MEGA, base2);
151 double multiplierGiga = multiplier(PREFIX_GIGA, base2);
152 double multiplierTera = multiplier(PREFIX_TERA, base2);
153 double multiplierPeta = multiplier(PREFIX_PETA, base2);
154 if (value < multiplierKilo) {
155 doubleResult = value;
156 nf.setMinimumFractionDigits(0);
157 } else if (value < multiplierMega) {
158 doubleResult = round(value / multiplierKilo, decimalPlaces);
159 unit = PREFIX_KILO + unit;
160 } else if (value < multiplierGiga) {
161 doubleResult = round(value / multiplierMega, decimalPlaces);
162 unit = PREFIX_MEGA + unit;
163 } else if (value < multiplierTera) {
164 doubleResult = round(value / multiplierGiga, decimalPlaces);
165 unit = PREFIX_GIGA + unit;
166 } else if (value < multiplierPeta) {
167 doubleResult = round(value / multiplierTera, decimalPlaces);
168 unit = PREFIX_TERA + unit;
169 } else {
170 doubleResult = round(value / multiplierPeta, decimalPlaces);
171 unit = PREFIX_PETA + unit;
172 }
173 return nf.format(doubleResult) + (base2 ? " " : "") + unit;
174 }
175
176
177
178
179
180
181
182
183
184 private static double round(double value, int decimalPlaces) {
185 return Math.round(value * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
186 }
187
188
189
190
191
192
193
194
195
196
197 private static double multiplier(char unitPrefix, boolean base2) {
198 long result;
199 long multiplier = base2 ? MULTIPLIER_2 : MULTIPLIER_10;
200 switch (Character.toUpperCase(unitPrefix)) {
201 case PREFIX_KILO:
202 result = multiplier;
203 break;
204 case PREFIX_MEGA:
205 result = multiplier * multiplier;
206 break;
207 case PREFIX_GIGA:
208 result = multiplier * multiplier * multiplier;
209 break;
210 case PREFIX_TERA:
211 result = multiplier * multiplier * multiplier * multiplier;
212 break;
213 case PREFIX_PETA:
214 result = multiplier * multiplier * multiplier * multiplier * multiplier;
215 break;
216 default:
217 throw new IllegalArgumentException("Invalid unit prefix: " + unitPrefix);
218 }
219 return result;
220 }
221
222 }