404507
From 75d7a0195b91b16116e5ad37d2cdd2374c80ef1b Mon Sep 17 00:00:00 2001
404507
Message-Id: <75d7a0195b91b16116e5ad37d2cdd2374c80ef1b@dist-git>
404507
From: Martin Kletzander <mkletzan@redhat.com>
404507
Date: Wed, 31 Jan 2018 16:32:14 +0100
404507
Subject: [PATCH] util: Introduce virBitmapNewString
404507
404507
https://bugzilla.redhat.com/show_bug.cgi?id=1289368
404507
404507
Our bitmaps can be represented as data (raw bytes for which we have
404507
virBitmapNewData() and virBitmapToData()), human representation (list
404507
of numbers in a string for which we have virBitmapParse() and
404507
virBitmapFormat()) and hexadecimal string (for which we have only
404507
virBitmapToString()).  So let's add the missing complement for the
404507
last one so that we can parse hexadecimal strings.
404507
404507
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
404507
Reviewed-by: John Ferlan <jferlan@redhat.com>
404507
(cherry picked from commit 2e5579a43b45e55d744cac9f62aaa901e2587fee)
404507
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
404507
---
404507
 src/libvirt_private.syms |  1 +
404507
 src/util/virbitmap.c     | 38 ++++++++++++++++++++++++++++++++++++++
404507
 src/util/virbitmap.h     |  4 ++++
404507
 tests/virbitmaptest.c    | 38 ++++++++++++++++++++++++++++++++++++++
404507
 4 files changed, 81 insertions(+)
404507
404507
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
404507
index f1c6786ecf..1d895a3bf6 100644
404507
--- a/src/libvirt_private.syms
404507
+++ b/src/libvirt_private.syms
404507
@@ -1372,6 +1372,7 @@ virBitmapNewCopy;
404507
 virBitmapNewData;
404507
 virBitmapNewEmpty;
404507
 virBitmapNewQuiet;
404507
+virBitmapNewString;
404507
 virBitmapNextClearBit;
404507
 virBitmapNextSetBit;
404507
 virBitmapOverlaps;
404507
diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
404507
index b1c1236fd3..47d16ee222 100644
404507
--- a/src/util/virbitmap.c
404507
+++ b/src/util/virbitmap.c
404507
@@ -36,6 +36,7 @@
404507
 #include "c-ctype.h"
404507
 #include "count-one-bits.h"
404507
 #include "virstring.h"
404507
+#include "virutil.h"
404507
 #include "virerror.h"
404507
 
404507
 #define VIR_FROM_THIS VIR_FROM_NONE
404507
@@ -1071,6 +1072,43 @@ virBitmapCountBits(virBitmapPtr bitmap)
404507
     return ret;
404507
 }
404507
 
404507
+
404507
+/**
404507
+ * virBitmapNewString:
404507
+ * @string: the string to be converted to a bitmap
404507
+ *
404507
+ * Allocate a bitmap from a string of hexadecimal data.
404507
+ *
404507
+ * Returns a pointer to the allocated bitmap or NULL if
404507
+ * memory cannot be allocated.
404507
+ */
404507
+virBitmapPtr
404507
+virBitmapNewString(const char *string)
404507
+{
404507
+    virBitmapPtr bitmap;
404507
+    size_t i = 0;
404507
+    size_t len = strlen(string);
404507
+
404507
+    if (strspn(string, "0123456789abcdefABCDEF") != len) {
404507
+        virReportError(VIR_ERR_INVALID_ARG,
404507
+                       _("Invalid hexadecimal string '%s'"), string);
404507
+        return NULL;
404507
+    }
404507
+
404507
+    bitmap = virBitmapNew(len * 4);
404507
+    if (!bitmap)
404507
+        return NULL;
404507
+
404507
+    for (i = 0; i < len; i++) {
404507
+        unsigned long nibble = virHexToBin(string[len - i - 1]);
404507
+        nibble <<= VIR_BITMAP_BIT_OFFSET(i * 4);
404507
+        bitmap->map[VIR_BITMAP_UNIT_OFFSET(i * 4)] |= nibble;
404507
+    }
404507
+
404507
+    return bitmap;
404507
+}
404507
+
404507
+
404507
 /**
404507
  * virBitmapDataFormat:
404507
  * @data: the data
404507
diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h
404507
index 02acb7519d..e964a3edc9 100644
404507
--- a/src/util/virbitmap.h
404507
+++ b/src/util/virbitmap.h
404507
@@ -80,6 +80,10 @@ bool virBitmapIsBitSet(virBitmapPtr bitmap, size_t b)
404507
 int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
404507
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK;
404507
 
404507
+virBitmapPtr
404507
+virBitmapNewString(const char *string)
404507
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
404507
+
404507
 char *virBitmapToString(virBitmapPtr bitmap, bool prefix, bool trim)
404507
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
404507
 
404507
diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
404507
index 75cdddf9a7..9daa8316f3 100644
404507
--- a/tests/virbitmaptest.c
404507
+++ b/tests/virbitmaptest.c
404507
@@ -663,6 +663,42 @@ test12(const void *opaque ATTRIBUTE_UNUSED)
404507
     return ret;
404507
 }
404507
 
404507
+
404507
+/* virBitmap(New/To)String */
404507
+static int
404507
+test13(const void *opaque ATTRIBUTE_UNUSED)
404507
+{
404507
+    virBitmapPtr map = NULL;
404507
+    const char *strings[] = { "1234feebee", "000c0fefe" };
404507
+    char *str = NULL;
404507
+    size_t i = 0;
404507
+    int ret = -1;
404507
+
404507
+    for (i = 0; i < ARRAY_CARDINALITY(strings); i++) {
404507
+        map = virBitmapNewString(strings[i]);
404507
+        str = virBitmapToString(map, false, true);
404507
+
404507
+        if (!map || !str)
404507
+            goto cleanup;
404507
+
404507
+        if (STRNEQ(strings[i], str)) {
404507
+            fprintf(stderr, "\n expected bitmap string '%s' actual string "
404507
+                    "'%s'\n", strings[i], str);
404507
+            goto cleanup;
404507
+        }
404507
+
404507
+        VIR_FREE(str);
404507
+        virBitmapFree(map);
404507
+        map = NULL;
404507
+    }
404507
+
404507
+    ret = 0;
404507
+ cleanup:
404507
+    VIR_FREE(str);
404507
+    virBitmapFree(map);
404507
+    return ret;
404507
+}
404507
+
404507
 #undef TEST_MAP
404507
 
404507
 
404507
@@ -711,6 +747,8 @@ mymain(void)
404507
 
404507
     if (virTestRun("test12", test12, NULL) < 0)
404507
         ret = -1;
404507
+    if (virTestRun("test13", test13, NULL) < 0)
404507
+        ret = -1;
404507
 
404507
     return ret;
404507
 }
404507
-- 
404507
2.16.1
404507