[Libguestfs] [PATCH libnbd 3/5] common: Combine human-size.h headers into one

Richard W.M. Jones
Sun, 03 Sep 2023 15:23:23 -0000

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