Skip to content

Commit 6655090

Browse files
Andre Muezeriedavid-marchand
Andre Muezerie
authored andcommitted
eal: add human readable size formatter
It's common to use %' in the printf format specifier to make large numbers more easily readable by having the thousands grouped. However, this grouping does not work on Windows. Therefore, a function is needed to make uint64_t numbers more easily readable. Signed-off-by: Andre Muezerie <[email protected]> Acked-by: Morten Brørup <[email protected]> Acked-by: Bruce Richardson <[email protected]>
1 parent b6ae9ae commit 6655090

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

lib/eal/common/eal_common_string_fns.c

+54
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <ctype.h>
66
#include <errno.h>
7+
#include <inttypes.h>
78
#include <stdio.h>
89
#include <stdlib.h>
910

@@ -91,6 +92,12 @@ rte_str_to_size(const char *str)
9192
endptr++; /* allow 1 space gap */
9293

9394
switch (*endptr) {
95+
case 'E': case 'e':
96+
size *= 1024; /* fall-through */
97+
case 'P': case 'p':
98+
size *= 1024; /* fall-through */
99+
case 'T': case 't':
100+
size *= 1024; /* fall-through */
94101
case 'G': case 'g':
95102
size *= 1024; /* fall-through */
96103
case 'M': case 'm':
@@ -102,3 +109,50 @@ rte_str_to_size(const char *str)
102109
}
103110
return size;
104111
}
112+
113+
RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_size_to_str, 25.07)
114+
char *
115+
rte_size_to_str(char *buf, int buf_size, uint64_t count, bool use_iec, const char *unit)
116+
{
117+
/* https://en.wikipedia.org/wiki/International_System_of_Units */
118+
const char *prefix = "kMGTPE";
119+
const unsigned int base = use_iec ? 1024 : 1000;
120+
uint64_t powi = 1;
121+
uint16_t powj = 1;
122+
uint8_t precision = 2;
123+
int result;
124+
125+
if (count < base) {
126+
if (unit != NULL && *unit != '\0')
127+
result = snprintf(buf, buf_size, "%"PRIu64" %s", count, unit);
128+
else
129+
result = snprintf(buf, buf_size, "%"PRIu64, count);
130+
131+
return result < buf_size ? buf : NULL;
132+
}
133+
134+
/* increase value by a factor of 1000/1024 and store
135+
* if result is something a human can read
136+
*/
137+
for (;;) {
138+
powi *= base;
139+
if (count / powi < base)
140+
break;
141+
142+
if (prefix[1] == '\0')
143+
break;
144+
++prefix;
145+
}
146+
147+
/* try to guess a good number of digits for precision */
148+
for (; precision > 0; precision--) {
149+
powj *= 10;
150+
if (count / powi < powj)
151+
break;
152+
}
153+
154+
result = snprintf(buf, buf_size, "%.*f %c%s%s", precision,
155+
(double)count / powi, *prefix, use_iec ? "i" : "",
156+
(unit != NULL) ? unit : "");
157+
return result < buf_size ? buf : NULL;
158+
}

lib/eal/include/rte_common.h

+37
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
#include <assert.h>
1616
#include <limits.h>
17+
#include <stdbool.h>
1718
#include <stdint.h>
1819
#include <stdalign.h>
1920

21+
#include <rte_compat.h>
2022
#include <rte_config.h>
2123

2224
/* OS specific include */
@@ -887,6 +889,41 @@ __extension__ typedef uint64_t RTE_MARKER64[0];
887889
uint64_t
888890
rte_str_to_size(const char *str);
889891

892+
/**
893+
* @warning
894+
* @b EXPERIMENTAL: this API may change without prior notice.
895+
*
896+
* Converts the uint64_t value provided to a human-readable string.
897+
* It null-terminates the string, truncating the data if needed.
898+
* An optional unit (like "B") can be provided as a string. It will be
899+
* appended to the number, and a space will be inserted before the unit if needed.
900+
*
901+
* Sample outputs: (1) "use_iec" disabled, (2) "use_iec" enabled,
902+
* (3) "use_iec" enabled and "B" as unit.
903+
* 0 : "0", "0", "0 B"
904+
* 700 : "700", "700", "700 B"
905+
* 1000 : "1.00 k", "1000", "1000 B"
906+
* 1024 : "1.02 k", "1.00 ki", "1.00 kiB"
907+
* 21474836480 : "21.5 G", "20.0 Gi", "20.0 GiB"
908+
* 109951162777600 : "110 T", "100 Ti", "100 TiB"
909+
*
910+
* @param buf
911+
* Buffer to write the string to.
912+
* @param buf_size
913+
* Size of the buffer.
914+
* @param count
915+
* Number to convert.
916+
* @param use_iec
917+
* If true, use IEC units (1024-based), otherwise use SI units (1000-based).
918+
* @param unit
919+
* Unit to append to the string (Like "B" for bytes). Can be NULL.
920+
* @return
921+
* buf on success, NULL if the buffer is too small.
922+
*/
923+
__rte_experimental
924+
char *
925+
rte_size_to_str(char *buf, int buf_size, uint64_t count, bool use_iec, const char *unit);
926+
890927
/**
891928
* Function to terminate the application immediately, printing an error
892929
* message and returning the exit_code back to the shell.

0 commit comments

Comments
 (0)