10 * Given a size in bytes, allocate and return a string of the form "<N> B"
11 * for 0 <= N <= 999 or "<X> <prefix>B" where either 10 <= X <= 999 or
12 * 1.0 <= X <= 9.9 and <prefix> is "k", "M", "G", "T", "P", or "E"; and where
13 * the value returned is the largest valid value <= the provided size.
16 humansize(uint64_t size
)
23 /* Special-case for size < 1000. */
25 rc
= asprintf(&s
, "%d B", (int)size
);
27 /* Keep 10 * size / 1000^(3n) in size. */
28 for (size
/= 100, shiftcnt
= 1; size
>= 10000; shiftcnt
++)
32 * Figure out what prefix to use. Since 1 EB = 10^18 B and
33 * the maximum value of a uint64_t is 2^64 which is roughly
34 * 18.4 * 10^18, this cannot reference beyond the end of the
37 prefix
= " kMGTPE"[shiftcnt
];
39 /* Construct the string. */
41 rc
= asprintf(&s
, "%d.%d %cB", (int)size
/ 10,
42 (int)size
% 10, prefix
);
44 rc
= asprintf(&s
, "%d %cB", (int)size
/ 10, prefix
);
61 * humansize_parse(s, size):
62 * Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size in bytes.
65 humansize_parse(const char * s
, uint64_t * size
)
68 uint64_t multiplier
= 1;
79 /* We must start with at least one digit. */
80 if ((*s
< '0') || (*s
> '9')) {
87 /* We're now processing digits. */
90 /* Digit-parsing state. */
91 if (('0' <= *s
) && (*s
<= '9')) {
92 if (*size
> UINT64_MAX
/ 10)
96 if (*size
> UINT64_MAX
- (uint64_t)(*s
- '0'))
99 *size
+= (uint64_t)(*s
- '0');
105 /* We move into state 3 after an optional ' '. */
112 /* We may have one SI prefix. */
134 /* We move into state 4 after the optional prefix. */
141 /* We move into state 5 after an optional 'B'. */
148 /* We have trailing garbage. */
153 /* Move on to the next character. */
155 } while (*s
!= '\0');
157 /* Multiply by multiplier. */
158 if (*size
> UINT64_MAX
/ multiplier
)
163 /* Anything other than state -1 is success. */
164 return ((state
== -1) ? -1 : 0);
This page took 0.025384 seconds and 4 git commands to generate.