Copy the human_size() function from common/utils/ into the new human-size.h header in common/include/. Remove human-size.c and combine the tests into one. --- common/include/human-size.h | 51 ++++++++++++++++++ common/include/test-human-size.c | 79 +++++++++++++++++++++++++--- common/utils/Makefile.am | 10 +--- common/utils/human-size.c | 56 -------------------- common/utils/human-size.h | 49 ------------------ common/utils/test-human-size.c | 89 -------------------------------- 6 files changed, 126 insertions(+), 208 deletions(-)
diff --git a/common/include/human-size.h b/common/include/human-size.h index 788dbd7ba5..47729c3c58 100644 --- a/common/include/human-size.h +++ b/common/include/human-size.h @@ -134,4 +134,55 @@ human_size_parse (const char *str, return size * scale; } +/* If you allocate a buffer of at least this length in bytes and pass + * it as the first parameter to human_size, then it will not overrun. + */ +#define HUMAN_SIZE_LONGEST 64 + +/* Convert bytes to a human-readable string. + * + * This is roughly the opposite of nbdkit_parse_size. It will convert + * multiples of powers of 1024 to the appropriate human size with the + * right extension like 'M' or 'G'. Anything that cannot be converted + * is returned as bytes. The *human flag is set to true if the output + * was abbreviated to a human-readable size, or false if it is just + * bytes. + * + * If buf == NULL, a buffer is allocated and returned. In this case + * the returned buffer must be freed. + * + * buf may also be allocated by the caller, in which case it must be + * at least HUMAN_SIZE_LONGEST bytes. + * + * On error the function returns an error and sets errno. + */ +static inline char * +human_size (char *buf, uint64_t bytes, bool *human) +{ + static const char ext[][2] = { "E", "P", "T", "G", "M", "K", "" }; + size_t i; + + if (buf == NULL) { + buf = malloc (HUMAN_SIZE_LONGEST); + if (buf == NULL) + return NULL; + } + + /* Work out which extension to use, if any. */ + i = 6; + if (bytes != 0) { + while ((bytes & 1023) == 0) { + bytes >>= 10; + i--; + } + } + + /* Set the flag to true if we're going to add a human-readable extension. */ + if (human) + *human = ext[i][0] != '\0'; + + snprintf (buf, HUMAN_SIZE_LONGEST, "%" PRIu64 "%s", bytes, ext[i]); + return buf; +} + #endif /* NBDKIT_HUMAN_SIZE_H */ diff --git a/common/include/test-human-size.c b/common/include/test-human-size.c index e8cbe7f413..d56186b9da 100644 --- a/common/include/test-human-size.c +++ b/common/include/test-human-size.c @@ -36,15 +36,18 @@ #include <stdlib.h> #include <stdbool.h> #include <stdint.h> +#include <string.h> #include "array-size.h" #include "human-size.h" -int -main (void) +static unsigned errors = 0; + +/* Test the human_size_parse function. */ +static void +test1 (void) { size_t i; - bool pass = true; struct pair { const char *str; int64_t res; @@ -119,15 +122,79 @@ main (void) fprintf (stderr, "Wrong parse for %s, got %" PRId64 ", expected %" PRId64 "\n", pairs[i].str, r, pairs[i].res); - pass = false; + errors++; } if (r == -1) { if (error == NULL || pstr == NULL) { fprintf (stderr, "Wrong error message handling for %s\n", pairs[i].str); - pass = false; + errors++; } } } +} + +/* Test the human_size function. */ +static void +test2_run (uint64_t bytes, const char *expected, bool expected_human_flag) +{ + char actual[HUMAN_SIZE_LONGEST]; + bool actual_human_flag; + + human_size (actual, bytes, &actual_human_flag); + + if (strcmp (actual, expected) == 0 && + actual_human_flag == expected_human_flag) { + printf ("test-human-size: %" PRIu64 " -> \"%s\" (%s) OK\n", + bytes, actual, actual_human_flag ? "true" : "false"); + fflush (stdout); + } + else { + fprintf (stderr, + "test-human-size: error: test case %" PRIu64 " " + "expected \"%s\" (%s) " + "but returned \"%s\" (%s)\n", + bytes, + expected, expected_human_flag ? "true" : "false", + actual, actual_human_flag ? "true" : "false"); + errors++; + } +} + +static void +test2 (void) +{ + test2_run (0, "0", false); + test2_run (1, "1", false); + test2_run (512, "512", false); + test2_run (1023, "1023", false); + test2_run (1024, "1K", true); + test2_run (1025, "1025", false); + test2_run (2047, "2047", false); + test2_run (2048, "2K", true); + test2_run (3 * 1024, "3K", true); + + test2_run (1023 * 1024, "1023K", true); + test2_run (1048575, "1048575", false); + test2_run (1048576, "1M", true); + test2_run (1048577, "1048577", false); + + test2_run (UINT64_C (1073741824), "1G", true); + + test2_run (UINT64_C (1099511627776), "1T", true); + test2_run (UINT64_C (1099511627777), "1099511627777", false); + test2_run (UINT64_C (1099511627776) + 1024, "1073741825K", true); + + test2_run (UINT64_C (1125899906842624), "1P", true); + + test2_run ((uint64_t)INT64_MAX+1, "8E", true); + test2_run (UINT64_MAX-1023, "18014398509481983K", true); + test2_run (UINT64_MAX, "18446744073709551615", false); +} - exit (pass ? EXIT_SUCCESS : EXIT_FAILURE); +int +main (int argc, char *argv[]) +{ + test1 (); + test2 (); + exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/common/utils/Makefile.am b/common/utils/Makefile.am index a1602fbb58..901d12ad2e 100644 --- a/common/utils/Makefile.am +++ b/common/utils/Makefile.am @@ -35,8 +35,6 @@ noinst_LTLIBRARIES = libutils.la libutils_la_SOURCES = \ const-string-vector.h \ - human-size.c \ - human-size.h \ nbdkit-string.h \ string-vector.h \ vector.c \ @@ -56,12 +54,8 @@ libutils_la_LIBADD = \ # Unit tests. -TESTS = test-human-size test-vector -check_PROGRAMS = test-human-size test-vector - -test_human_size_SOURCES = test-human-size.c human-size.c human-size.h -test_human_size_CPPFLAGS = -I$(srcdir) -test_human_size_CFLAGS = $(WARNINGS_CFLAGS) +TESTS = test-vector +check_PROGRAMS = test-vector test_vector_SOURCES = test-vector.c vector.c vector.h bench.h test_vector_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)/common/include diff --git a/common/utils/human-size.c b/common/utils/human-size.c deleted file mode 100644 index 14d6801318..0000000000 --- a/common/utils/human-size.c +++ /dev/null @@ -1,56 +0,0 @@ -/* nbd client library in userspace - * Copyright Red Hat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <stdint.h> -#include <inttypes.h> - -#include "human-size.h" - -char * -human_size (char *buf, uint64_t bytes, bool *human) -{ - static const char ext[][2] = { "E", "P", "T", "G", "M", "K", "" }; - size_t i; - - if (buf == NULL) { - buf = malloc (HUMAN_SIZE_LONGEST); - if (buf == NULL) - return NULL; - } - - /* Work out which extension to use, if any. */ - i = 6; - if (bytes != 0) { - while ((bytes & 1023) == 0) { - bytes >>= 10; - i--; - } - } - - /* Set the flag to true if we're going to add a human-readable extension. */ - if (human) - *human = ext[i][0] != '\0'; - - snprintf (buf, HUMAN_SIZE_LONGEST, "%" PRIu64 "%s", bytes, ext[i]); - return buf; -} diff --git a/common/utils/human-size.h b/common/utils/human-size.h deleted file mode 100644 index 5ab90a0fa3..0000000000 --- a/common/utils/human-size.h +++ /dev/null @@ -1,49 +0,0 @@ -/* nbd client library in userspace - * Copyright Red Hat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBNBD_HUMAN_SIZE_H -#define LIBNBD_HUMAN_SIZE_H - -#include <stdbool.h> -#include <stdint.h> - -/* If you allocate a buffer of at least this length in bytes and pass - * it as the first parameter to human_size, then it will not overrun. - */ -#define HUMAN_SIZE_LONGEST 64 - -/* Convert bytes to a human-readable string. - * - * This is roughly the opposite of nbdkit_parse_size. It will convert - * multiples of powers of 1024 to the appropriate human size with the - * right extension like 'M' or 'G'. Anything that cannot be converted - * is returned as bytes. The *human flag is set to true if the output - * was abbreviated to a human-readable size, or false if it is just - * bytes. - * - * If buf == NULL, a buffer is allocated and returned. In this case - * the returned buffer must be freed. - * - * buf may also be allocated by the caller, in which case it must be - * at least HUMAN_SIZE_LONGEST bytes. - * - * On error the function returns an error and sets errno. - */ -extern char *human_size (char *buf, uint64_t bytes, bool *human); - -#endif /* LIBNBD_HUMAN_SIZE_H */ diff --git a/common/utils/test-human-size.c b/common/utils/test-human-size.c deleted file mode 100644 index 94210e85f2..0000000000 --- a/common/utils/test-human-size.c +++ /dev/null @@ -1,89 +0,0 @@ -/* nbd client library in userspace - * Copyright Red Hat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <stdint.h> -#include <inttypes.h> -#include <string.h> - -#include "human-size.h" - -static unsigned errors = 0; - -static void -test (uint64_t bytes, const char *expected, bool expected_human_flag) -{ - char actual[HUMAN_SIZE_LONGEST]; - bool actual_human_flag; - - human_size (actual, bytes, &actual_human_flag); - - if (strcmp (actual, expected) == 0 && - actual_human_flag == expected_human_flag) { - printf ("test-human-size: %" PRIu64 " -> \"%s\" (%s) OK\n", - bytes, actual, actual_human_flag ? "true" : "false"); - fflush (stdout); - } - else { - fprintf (stderr, - "test-human-size: error: test case %" PRIu64 " " - "expected \"%s\" (%s) " - "but returned \"%s\" (%s)\n", - bytes, - expected, expected_human_flag ? "true" : "false", - actual, actual_human_flag ? "true" : "false"); - errors++; - } -} - -int -main (int argc, char *argv[]) -{ - test (0, "0", false); - test (1, "1", false); - test (512, "512", false); - test (1023, "1023", false); - test (1024, "1K", true); - test (1025, "1025", false); - test (2047, "2047", false); - test (2048, "2K", true); - test (3 * 1024, "3K", true); - - test (1023 * 1024, "1023K", true); - test (1048575, "1048575", false); - test (1048576, "1M", true); - test (1048577, "1048577", false); - - test (UINT64_C (1073741824), "1G", true); - - test (UINT64_C (1099511627776), "1T", true); - test (UINT64_C (1099511627777), "1099511627777", false); - test (UINT64_C (1099511627776) + 1024, "1073741825K", true); - - test (UINT64_C (1125899906842624), "1P", true); - - test ((uint64_t)INT64_MAX+1, "8E", true); - test (UINT64_MAX-1023, "18014398509481983K", true); - test (UINT64_MAX, "18446744073709551615", false); - - exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); -} -- 2.41.0 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs