Line | Source | Count |
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 | #include "includes.h" | - |
42 | | - |
43 | #ifndef HAVE_FMT_SCALED | - |
44 | | - |
45 | #include <stdio.h> | - |
46 | #include <stdlib.h> | - |
47 | #include <errno.h> | - |
48 | #include <string.h> | - |
49 | #include <ctype.h> | - |
50 | #include <limits.h> | - |
51 | | - |
52 | typedef enum { | - |
53 | NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 | - |
54 | } unit_type; | - |
55 | | - |
56 | | - |
57 | static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; | - |
58 | static char scale_chars[] = "BKMGTPE"; | - |
59 | static long long scale_factors[] = { | - |
60 | 1LL, | - |
61 | 1024LL, | - |
62 | 1024LL*1024, | - |
63 | 1024LL*1024*1024, | - |
64 | 1024LL*1024*1024*1024, | - |
65 | 1024LL*1024*1024*1024*1024, | - |
66 | 1024LL*1024*1024*1024*1024*1024, | - |
67 | }; | - |
68 | #define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) | - |
69 | | - |
70 | #define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ | - |
71 | | - |
72 | | - |
73 | | - |
74 | | - |
75 | int | - |
76 | scan_scaled(char *scaled, long long *result) | - |
77 | { | - |
78 | char *p = scaled; | - |
79 | int sign = 0; | - |
80 | unsigned int i, ndigits = 0, fract_digits = 0; | - |
81 | long long scale_fact = 1, whole = 0, fpart = 0; | - |
82 | | - |
83 | | - |
84 | while (isascii((unsigned char)*p) && isspace((unsigned char)*p))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
85 | ++p; never executed: ++p; | 0 |
86 | | - |
87 | | - |
88 | while (*p == '-' || *p == '+') {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
89 | if (*p == '-') {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
90 | if (sign) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
91 | errno = EINVAL; | - |
92 | return -1; never executed: return -1; | 0 |
93 | } | - |
94 | sign = -1; | - |
95 | ++p; | - |
96 | } else if (*p == '+') { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
97 | if (sign) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
98 | errno = EINVAL; | - |
99 | return -1; never executed: return -1; | 0 |
100 | } | - |
101 | sign = +1; | - |
102 | ++p; | - |
103 | } never executed: end of block | 0 |
104 | } never executed: end of block | 0 |
105 | | - |
106 | | - |
107 | | - |
108 | | - |
109 | | - |
110 | | - |
111 | for (; isascii((unsigned char)*p) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
112 | (isdigit((unsigned char)*p) || *p=='.'); ++p) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
113 | if (*p == '.') {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
114 | if (fract_digits > 0) { TRUE | never evaluated | FALSE | never evaluated |
| 0 |
115 | errno = EINVAL; | - |
116 | return -1; never executed: return -1; | 0 |
117 | } | - |
118 | fract_digits = 1; | - |
119 | continue; never executed: continue; | 0 |
120 | } | - |
121 | | - |
122 | i = (*p) - '0'; | - |
123 | if (fract_digits > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
124 | if (fract_digits >= MAX_DIGITS-1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
125 | | - |
126 | continue; never executed: continue; | 0 |
127 | fract_digits++; | - |
128 | if (fpart > LLONG_MAX / 10) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
129 | errno = ERANGE; | - |
130 | return -1; never executed: return -1; | 0 |
131 | } | - |
132 | fpart *= 10; | - |
133 | if (i > LLONG_MAX - fpart) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
134 | errno = ERANGE; | - |
135 | return -1; never executed: return -1; | 0 |
136 | } | - |
137 | fpart += i; | - |
138 | } else { never executed: end of block | 0 |
139 | if (++ndigits >= MAX_DIGITS) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
140 | errno = ERANGE; | - |
141 | return -1; never executed: return -1; | 0 |
142 | } | - |
143 | if (whole > LLONG_MAX / 10) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
144 | errno = ERANGE; | - |
145 | return -1; never executed: return -1; | 0 |
146 | } | - |
147 | whole *= 10; | - |
148 | if (i > LLONG_MAX - whole) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
149 | errno = ERANGE; | - |
150 | return -1; never executed: return -1; | 0 |
151 | } | - |
152 | whole += i; | - |
153 | } never executed: end of block | 0 |
154 | } | - |
155 | | - |
156 | if (sign) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
157 | whole *= sign; | - |
158 | fpart *= sign; | - |
159 | } never executed: end of block | 0 |
160 | | - |
161 | | - |
162 | if (!*p) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
163 | *result = whole; | - |
164 | return 0; never executed: return 0; | 0 |
165 | } | - |
166 | | - |
167 | | - |
168 | for (i = 0; i < SCALE_LENGTH; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
169 | | - |
170 | | - |
171 | if (*p == scale_chars[i] ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
172 | *p == tolower((unsigned char)scale_chars[i])) { never executed: end of block never executed: __res = tolower ( (unsigned char)scale_chars[i] ); never executed: __res = (*__ctype_tolower_loc ())[(int) ( (unsigned char)scale_chars[i] )]; TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
173 | | - |
174 | | - |
175 | if (isalnum((unsigned char)*(p+1))) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
176 | errno = EINVAL; | - |
177 | return -1; never executed: return -1; | 0 |
178 | } | - |
179 | scale_fact = scale_factors[i]; | - |
180 | | - |
181 | | - |
182 | if (whole > LLONG_MAX / scale_fact ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
183 | whole < LLONG_MIN / scale_fact) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
184 | errno = ERANGE; | - |
185 | return -1; never executed: return -1; | 0 |
186 | } | - |
187 | | - |
188 | | - |
189 | whole *= scale_fact; | - |
190 | | - |
191 | | - |
192 | | - |
193 | | - |
194 | while (fpart >= LLONG_MAX / scale_fact) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
195 | fpart /= 10; | - |
196 | fract_digits--; | - |
197 | } never executed: end of block | 0 |
198 | fpart *= scale_fact; | - |
199 | if (fract_digits > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
200 | for (i = 0; i < fract_digits -1; i++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
201 | fpart /= 10; never executed: fpart /= 10; | 0 |
202 | } never executed: end of block | 0 |
203 | whole += fpart; | - |
204 | *result = whole; | - |
205 | return 0; never executed: return 0; | 0 |
206 | } | - |
207 | } never executed: end of block | 0 |
208 | | - |
209 | | - |
210 | errno = EINVAL; | - |
211 | return -1; never executed: return -1; | 0 |
212 | } | - |
213 | | - |
214 | | - |
215 | | - |
216 | | - |
217 | | - |
218 | int | - |
219 | fmt_scaled(long long number, char *result) | - |
220 | { | - |
221 | long long abval, fract = 0; | - |
222 | unsigned int i; | - |
223 | unit_type unit = NONE; | - |
224 | | - |
225 | abval = llabs(number); | - |
226 | | - |
227 | | - |
228 | | - |
229 | | - |
230 | if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
231 | errno = ERANGE; | - |
232 | return -1; never executed: return -1; | 0 |
233 | } | - |
234 | | - |
235 | | - |
236 | for (i = 0; i < SCALE_LENGTH; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
237 | if (abval/1024 < scale_factors[i]) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
238 | unit = units[i]; | - |
239 | fract = (i == 0) ? 0 : abval % scale_factors[i];TRUE | never evaluated | FALSE | never evaluated |
| 0 |
240 | number /= scale_factors[i]; | - |
241 | if (i > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
242 | fract /= scale_factors[i - 1]; never executed: fract /= scale_factors[i - 1]; | 0 |
243 | break; never executed: break; | 0 |
244 | } | - |
245 | } never executed: end of block | 0 |
246 | | - |
247 | fract = (10 * fract + 512) / 1024; | - |
248 | | - |
249 | if (fract >= 10) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
250 | if (number >= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
251 | number++; never executed: number++; | 0 |
252 | else | - |
253 | number--; never executed: number--; | 0 |
254 | fract = 0; | - |
255 | } else if (fract < 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
256 | | - |
257 | fract = 0; | - |
258 | } never executed: end of block | 0 |
259 | | - |
260 | if (number == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
261 | strlcpy(result, "0B", FMT_SCALED_STRSIZE); never executed: strlcpy(result, "0B", 7); | 0 |
262 | else if (unit == NONE || number >= 100 || number <= -100) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
263 | if (fract >= 5) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
264 | if (number >= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
265 | number++; never executed: number++; | 0 |
266 | else | - |
267 | number--; never executed: number--; | 0 |
268 | } | - |
269 | (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", | - |
270 | number, scale_chars[unit]); | - |
271 | } else never executed: end of block | 0 |
272 | (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", never executed: (void)snprintf(result, 7, "%lld.%1lld%c", number, fract, scale_chars[unit]); | 0 |
273 | number, fract, scale_chars[unit]); never executed: (void)snprintf(result, 7, "%lld.%1lld%c", number, fract, scale_chars[unit]); | 0 |
274 | | - |
275 | return 0; never executed: return 0; | 0 |
276 | } | - |
277 | | - |
278 | #ifdef MAIN | - |
279 | | - |
280 | | - |
281 | | - |
282 | | - |
283 | int | - |
284 | main(int argc, char **argv) | - |
285 | { | - |
286 | char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; | - |
287 | long long ninput = 10483892, result; | - |
288 | | - |
289 | if (scan_scaled(cinput, &result) == 0) | - |
290 | printf("\"%s\" -> %lld\n", cinput, result); | - |
291 | else | - |
292 | perror(cinput); | - |
293 | | - |
294 | if (fmt_scaled(ninput, buf) == 0) | - |
295 | printf("%lld -> \"%s\"\n", ninput, buf); | - |
296 | else | - |
297 | fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); | - |
298 | | - |
299 | return 0; | - |
300 | } | - |
301 | #endif | - |
302 | | - |
303 | #endif /* HAVE_FMT_SCALED */ | - |
| | |