[PATCH v2 08/17] virstring: Introduce virStringIsNull()

Michal Privoznik mprivozn at redhat.com
Tue Jul 7 19:46:26 UTC 2020


This function will be used to detect zero buffers (which are
going to be interpreted as hole in virStream later).

I shamelessly took inspiration from coreutils.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/util/virstring.c     | 38 ++++++++++++++++++++++++++++++++
 src/util/virstring.h     |  2 ++
 tests/virstringtest.c    | 47 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ae0e253ab9..1d80aeb833 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3197,6 +3197,7 @@ virStringHasChars;
 virStringHasControlChars;
 virStringHasSuffix;
 virStringIsEmpty;
+virStringIsNull;
 virStringIsPrintable;
 virStringListAdd;
 virStringListAutoFree;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index e9e792f3bf..c26bc770d4 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -1404,3 +1404,41 @@ int virStringParseYesNo(const char *str, bool *result)
 
     return 0;
 }
+
+
+/**
+ * virStringIsNull:
+ * @buf: buffer to check
+ * @len: the length of the buffer
+ *
+ * For given buffer @buf and its size @len determine whether
+ * it contains only zero bytes (NUL) or not.
+ *
+ * Returns: true if buffer is full of zero bytes,
+ *          false otherwise.
+ */
+bool virStringIsNull(const char *buf, size_t len)
+{
+    const char *p = buf;
+
+    if (!len)
+        return true;
+
+    /* Check up to 16 first bytes. */
+    for (;;) {
+        if (*p)
+            return false;
+
+        p++;
+        len--;
+
+        if (!len)
+            return true;
+
+        if ((len & 0xf) == 0)
+            break;
+    }
+
+    /* Now we know first 16 bytes are NUL, memcmp with self.  */
+    return memcmp(buf, p, len) == 0;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 360c68395c..d0e54358ac 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -185,6 +185,8 @@ int virStringParsePort(const char *str,
 int virStringParseYesNo(const char *str,
                         bool *result)
     G_GNUC_WARN_UNUSED_RESULT;
+bool virStringIsNull(const char *buf, size_t len);
+
 /**
  * VIR_AUTOSTRINGLIST:
  *
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index bee49e6cb6..5838a57574 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -649,6 +649,27 @@ static int testFilterChars(const void *args)
     return ret;
 }
 
+struct testIsNulData {
+    const char *buf;
+    size_t len;
+    bool nul;
+};
+
+static int
+testIsNul(const void *args)
+{
+    const struct testIsNulData *data = args;
+    int rc;
+
+    rc = virStringIsNull(data->buf, data->len);
+    if (rc != data->nul) {
+        fprintf(stderr, "Returned %d, expected %d\n", rc, data->nul);
+        return -1;
+    }
+
+    return 0;
+}
+
 static int
 mymain(void)
 {
@@ -977,6 +998,32 @@ mymain(void)
     TEST_FILTER_CHARS(NULL, NULL, NULL);
     TEST_FILTER_CHARS("hello 123 hello", "helo", "hellohello");
 
+#define TEST_IS_NUL(expect, ...) \
+    do { \
+        const char buf[] = {__VA_ARGS__ }; \
+        struct testIsNulData isNulData = { \
+            .buf = buf, \
+            .len = G_N_ELEMENTS(buf), \
+            .nul = expect \
+        }; \
+        if (virTestRun("isNul check", \
+                       testIsNul, &isNulData) < 0) \
+            ret = -1; \
+    } while (0)
+
+    TEST_IS_NUL(true);
+    TEST_IS_NUL(true,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+    TEST_IS_NUL(false, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
+    TEST_IS_NUL(false,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
+    TEST_IS_NUL(false,
+                0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                0x00);
+
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-- 
2.26.2




More information about the libvir-list mailing list