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