]> git.ipfire.org Git - pakfire.git/commitdiff
string: Add function that parses bytes
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Aug 2022 10:25:43 +0000 (10:25 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Aug 2022 10:26:24 +0000 (10:26 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/string.h
src/libpakfire/string.c
tests/libpakfire/string.c

index 510217ba2b8fdd50ce59581d0aea9a538a6ace36..a0e46d9c6c1485964b9e703c06f984aee979a274 100644 (file)
@@ -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 */
index 527a079ae703833071726ded33ddcd06a2b959a9..bd0b076423db7c0efebb35e4f96e6378690f04eb 100644 (file)
@@ -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;
+}
index c2408b91d430b7b677a3a0d0307d36102d629405..cfc0214022e213c11d5aed154235a4ac44b6fbd8 100644 (file)
@@ -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);
 }