cutils: add functions for IEC and SI prefixes

Extract the knowledge of IEC and SI prefixes out of size_to_str and
freq_to_str, so that it can be reused when printing statistics.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2022-05-25 15:38:48 +02:00
parent 467ef823d8
commit cfb3448922
3 changed files with 95 additions and 9 deletions

View file

@ -872,6 +872,25 @@ int parse_debug_env(const char *name, int max, int initial)
return debug;
}
const char *si_prefix(unsigned int exp10)
{
static const char *prefixes[] = {
"a", "f", "p", "n", "u", "m", "", "K", "M", "G", "T", "P", "E"
};
exp10 += 18;
assert(exp10 % 3 == 0 && exp10 / 3 < ARRAY_SIZE(prefixes));
return prefixes[exp10 / 3];
}
const char *iec_binary_prefix(unsigned int exp2)
{
static const char *prefixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
assert(exp2 % 10 == 0 && exp2 / 10 < ARRAY_SIZE(prefixes));
return prefixes[exp2 / 10];
}
/*
* Return human readable string for size @val.
* @val can be anything that uint64_t allows (no more than "16 EiB").
@ -880,7 +899,6 @@ int parse_debug_env(const char *name, int max, int initial)
*/
char *size_to_str(uint64_t val)
{
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
uint64_t div;
int i;
@ -891,25 +909,23 @@ char *size_to_str(uint64_t val)
* (see e41b509d68afb1f for more info)
*/
frexp(val / (1000.0 / 1024.0), &i);
i = (i - 1) / 10;
div = 1ULL << (i * 10);
i = (i - 1) / 10 * 10;
div = 1ULL << i;
return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]);
return g_strdup_printf("%0.3g %sB", (double)val / div, iec_binary_prefix(i));
}
char *freq_to_str(uint64_t freq_hz)
{
static const char *const suffixes[] = { "", "K", "M", "G", "T", "P", "E" };
double freq = freq_hz;
size_t idx = 0;
size_t exp10 = 0;
while (freq >= 1000.0) {
freq /= 1000.0;
idx++;
exp10 += 3;
}
assert(idx < ARRAY_SIZE(suffixes));
return g_strdup_printf("%0.3g %sHz", freq, suffixes[idx]);
return g_strdup_printf("%0.3g %sHz", freq, si_prefix(exp10));
}
int qemu_pstrcmp0(const char **str1, const char **str2)