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:
parent
467ef823d8
commit
cfb3448922
@ -1,6 +1,24 @@
|
||||
#ifndef QEMU_CUTILS_H
|
||||
#define QEMU_CUTILS_H
|
||||
|
||||
/*
|
||||
* si_prefix:
|
||||
* @exp10: exponent of 10, a multiple of 3 between -18 and 18 inclusive.
|
||||
*
|
||||
* Return a SI prefix (n, u, m, K, M, etc.) corresponding
|
||||
* to the given exponent of 10.
|
||||
*/
|
||||
const char *si_prefix(unsigned int exp10);
|
||||
|
||||
/*
|
||||
* iec_binary_prefix:
|
||||
* @exp2: exponent of 2, a multiple of 10 between 0 and 60 inclusive.
|
||||
*
|
||||
* Return an IEC binary prefix (Ki, Mi, etc.) corresponding
|
||||
* to the given exponent of 2.
|
||||
*/
|
||||
const char *iec_binary_prefix(unsigned int exp2);
|
||||
|
||||
/**
|
||||
* pstrcpy:
|
||||
* @buf: buffer to copy string into
|
||||
|
@ -2450,6 +2450,50 @@ static void test_qemu_strtosz_metric(void)
|
||||
g_assert(endptr == str + 7);
|
||||
}
|
||||
|
||||
static void test_freq_to_str(void)
|
||||
{
|
||||
g_assert_cmpstr(freq_to_str(999), ==, "999 Hz");
|
||||
g_assert_cmpstr(freq_to_str(1000), ==, "1 KHz");
|
||||
g_assert_cmpstr(freq_to_str(1010), ==, "1.01 KHz");
|
||||
}
|
||||
|
||||
static void test_size_to_str(void)
|
||||
{
|
||||
g_assert_cmpstr(size_to_str(0), ==, "0 B");
|
||||
g_assert_cmpstr(size_to_str(1), ==, "1 B");
|
||||
g_assert_cmpstr(size_to_str(1016), ==, "0.992 KiB");
|
||||
g_assert_cmpstr(size_to_str(1024), ==, "1 KiB");
|
||||
g_assert_cmpstr(size_to_str(512ull << 20), ==, "512 MiB");
|
||||
}
|
||||
|
||||
static void test_iec_binary_prefix(void)
|
||||
{
|
||||
g_assert_cmpstr(iec_binary_prefix(0), ==, "");
|
||||
g_assert_cmpstr(iec_binary_prefix(10), ==, "Ki");
|
||||
g_assert_cmpstr(iec_binary_prefix(20), ==, "Mi");
|
||||
g_assert_cmpstr(iec_binary_prefix(30), ==, "Gi");
|
||||
g_assert_cmpstr(iec_binary_prefix(40), ==, "Ti");
|
||||
g_assert_cmpstr(iec_binary_prefix(50), ==, "Pi");
|
||||
g_assert_cmpstr(iec_binary_prefix(60), ==, "Ei");
|
||||
}
|
||||
|
||||
static void test_si_prefix(void)
|
||||
{
|
||||
g_assert_cmpstr(si_prefix(-18), ==, "a");
|
||||
g_assert_cmpstr(si_prefix(-15), ==, "f");
|
||||
g_assert_cmpstr(si_prefix(-12), ==, "p");
|
||||
g_assert_cmpstr(si_prefix(-9), ==, "n");
|
||||
g_assert_cmpstr(si_prefix(-6), ==, "u");
|
||||
g_assert_cmpstr(si_prefix(-3), ==, "m");
|
||||
g_assert_cmpstr(si_prefix(0), ==, "");
|
||||
g_assert_cmpstr(si_prefix(3), ==, "K");
|
||||
g_assert_cmpstr(si_prefix(6), ==, "M");
|
||||
g_assert_cmpstr(si_prefix(9), ==, "G");
|
||||
g_assert_cmpstr(si_prefix(12), ==, "T");
|
||||
g_assert_cmpstr(si_prefix(15), ==, "P");
|
||||
g_assert_cmpstr(si_prefix(18), ==, "E");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
@ -2729,5 +2773,13 @@ int main(int argc, char **argv)
|
||||
g_test_add_func("/cutils/strtosz/metric",
|
||||
test_qemu_strtosz_metric);
|
||||
|
||||
g_test_add_func("/cutils/size_to_str",
|
||||
test_size_to_str);
|
||||
g_test_add_func("/cutils/freq_to_str",
|
||||
test_freq_to_str);
|
||||
g_test_add_func("/cutils/iec_binary_prefix",
|
||||
test_iec_binary_prefix);
|
||||
g_test_add_func("/cutils/si_prefix",
|
||||
test_si_prefix);
|
||||
return g_test_run();
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user