From: Michael Tremer Date: Fri, 19 Aug 2022 10:25:43 +0000 (+0000) Subject: string: Add function that parses bytes X-Git-Tag: 0.9.28~439 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=528b1f1c3d0d80b26334e33ce1cfae77dfd0d689;p=pakfire.git string: Add function that parses bytes Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/string.h b/src/libpakfire/include/pakfire/string.h index 510217ba2..a0e46d9c6 100644 --- a/src/libpakfire/include/pakfire/string.h +++ b/src/libpakfire/include/pakfire/string.h @@ -64,6 +64,8 @@ int __pakfire_strftime(char* buffer, const size_t length, int __pakfire_strftime_now(char* buffer, const size_t length, const char* format) __attribute__((format(strftime, 3, 0))); +size_t pakfire_string_parse_bytes(const char* s); + #endif #endif /* PAKFIRE_STRING_H */ diff --git a/src/libpakfire/string.c b/src/libpakfire/string.c index 527a079ae..bd0b07642 100644 --- a/src/libpakfire/string.c +++ b/src/libpakfire/string.c @@ -370,3 +370,33 @@ int __pakfire_strftime_now(char* buffer, size_t length, const char* format) { return __pakfire_strftime(buffer, length, format, t); } + +size_t pakfire_string_parse_bytes(const char* s) { + const char* units = "kMGT"; + char* unit = NULL; + + // Read the numeric value + size_t bytes = strtoul(s, &unit, 10); + + // Return bytes if there is no unit + if (!unit || !*unit) + return bytes; + + // Is the unit of the correct length? + const size_t length = strlen(unit); + if (length > 1) + goto ERROR; + + // Walk through all units and find a match + for (const char* u = units; *u; u++) { + bytes *= 1024; + + // End if the unit matches + if (*unit == *u) + return bytes; + } + +ERROR: + errno = EINVAL; + return 0; +} diff --git a/tests/libpakfire/string.c b/tests/libpakfire/string.c index c2408b91d..cfc021402 100644 --- a/tests/libpakfire/string.c +++ b/tests/libpakfire/string.c @@ -290,6 +290,34 @@ FAIL: return EXIT_FAILURE; } +static int test_parse_bytes(const struct test* t) { + // Zero without unit + ASSERT(pakfire_string_parse_bytes("0") == (size_t)0); + + // Zero with valid units + ASSERT(pakfire_string_parse_bytes("0k") == (size_t)0); + ASSERT(pakfire_string_parse_bytes("0M") == (size_t)0); + ASSERT(pakfire_string_parse_bytes("0G") == (size_t)0); + ASSERT(pakfire_string_parse_bytes("0T") == (size_t)0); + + // Zero with invalid units + ASSERT_ERRNO(pakfire_string_parse_bytes("0X") == (size_t)0, EINVAL); + ASSERT_ERRNO(pakfire_string_parse_bytes("0XX") == (size_t)0, EINVAL); + ASSERT_ERRNO(pakfire_string_parse_bytes("0MM") == (size_t)0, EINVAL); + + // One with valid units + ASSERT(pakfire_string_parse_bytes("1") == (size_t)1); + ASSERT(pakfire_string_parse_bytes("1k") == (size_t)1024); + ASSERT(pakfire_string_parse_bytes("1M") == (size_t)1024 * 1024); + ASSERT(pakfire_string_parse_bytes("1G") == (size_t)1024 * 1024 * 1024); + ASSERT(pakfire_string_parse_bytes("1T") == (size_t)1024 * 1024 * 1024 * 1024); + + return EXIT_SUCCESS; + +FAIL: + return EXIT_FAILURE; +} + int main(int argc, const char* argv[]) { testsuite_add_test(test_string_set); testsuite_add_test(test_string_startswith); @@ -300,6 +328,7 @@ int main(int argc, const char* argv[]) { testsuite_add_test(test_string_split); testsuite_add_test(test_string_join); testsuite_add_test(test_format_size); + testsuite_add_test(test_parse_bytes); return testsuite_run(argc, argv); }