For parsing a bitmap of an unknown size.
---
src/libvirt_private.syms | 1 +
src/util/virbitmap.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virbitmap.h | 4 ++
tests/virbitmaptest.c | 7 +++
4 files changed, 124 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a88a3d1..a2f699b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1207,6 +1207,7 @@ virBitmapNextSetBit;
virBitmapOverlaps;
virBitmapParse;
virBitmapParseSeparator;
+virBitmapParseUnlimited;
virBitmapSetAll;
virBitmapSetBit;
virBitmapSetBitExpand;
diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
index 3381a3d..3276763 100644
--- a/src/util/virbitmap.c
+++ b/src/util/virbitmap.c
@@ -543,6 +543,118 @@ virBitmapParse(const char *str,
}
/**
+ * virBitmapParseUnlimited:
+ * @str: points to a string representing a human-readable bitmap
+ * @bitmap: a bitmap created from @str
+ *
+ * This function is the counterpart of virBitmapFormat. This function creates
+ * a bitmap, in which bits are set according to the content of @str.
+ *
+ * The bitmap is expanded to accomodate all the bits.
+ *
+ * @str is a comma separated string of fields N, which means a number of bit
+ * to set, and ^N, which means to unset the bit, and N-M for ranges of bits
+ * to set.
+ *
+ * Returns 0 on success, or -1 in case of error.
+ */
+int
+virBitmapParseUnlimited(const char *str,
+ virBitmapPtr *bitmap)
+{
+ bool neg = false;
+ const char *cur = str;
+ char *tmp;
+ size_t i;
+ int start, last;
+
+ if (!(*bitmap = virBitmapNewEmpty()))
+ return -1;
+
+ if (!str)
+ goto error;
+
+ virSkipSpaces(&cur);
+
+ if (*cur == '\0')
+ goto error;
+
+ while (*cur != 0) {
+ /*
+ * 3 constructs are allowed:
+ * - N : a single CPU number
+ * - N-M : a range of CPU numbers with N < M
+ * - ^N : remove a single CPU number from the current set
+ */
+ if (*cur == '^') {
+ cur++;
+ neg = true;
+ }
+
+ if (!c_isdigit(*cur))
+ goto error;
+
+ if (virStrToLong_i(cur, &tmp, 10, &start) < 0)
+ goto error;
+ if (start < 0)
+ goto error;
+
+ cur = tmp;
+
+ virSkipSpaces(&cur);
+
+ if (*cur == ',' || *cur == 0) {
+ if (neg) {
+ if (virBitmapClearBitExpand(*bitmap, start) < 0)
+ goto error;
+ } else {
+ if (virBitmapSetBitExpand(*bitmap, start) < 0)
+ goto error;
+ }
+ } else if (*cur == '-') {
+ if (neg)
+ goto error;
+
+ cur++;
+ virSkipSpaces(&cur);
+
+ if (virStrToLong_i(cur, &tmp, 10, &last) < 0)
+ goto error;
+ if (last < start)
+ goto error;
+
+ cur = tmp;
+
+ for (i = start; i <= last; i++) {
+ if (virBitmapSetBitExpand(*bitmap, i) < 0)
+ goto error;
+ }
+
+ virSkipSpaces(&cur);
+ }
+
+ if (*cur == ',') {
+ cur++;
+ virSkipSpaces(&cur);
+ neg = false;
+ } else if (*cur == 0) {
+ break;
+ } else {
+ goto error;
+ }
+ }
+
+ return 0;
+
+ error:
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Failed to parse bitmap '%s'"), str);
+ virBitmapFree(*bitmap);
+ *bitmap = NULL;
+ return -1;
+}
+
+/**
* virBitmapNewCopy:
* @src: the source bitmap.
*
diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h
index 3356e1e..5984b80 100644
--- a/src/util/virbitmap.h
+++ b/src/util/virbitmap.h
@@ -94,6 +94,10 @@ virBitmapParseSeparator(const char *str,
char terminator,
virBitmapPtr *bitmap,
size_t bitmapSize);
+int
+virBitmapParseUnlimited(const char *str,
+ virBitmapPtr *bitmap)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
virBitmapPtr virBitmapNewCopy(virBitmapPtr src) ATTRIBUTE_NONNULL(1);
diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
index 89c41d0..009fa0d 100644
--- a/tests/virbitmaptest.c
+++ b/tests/virbitmaptest.c
@@ -632,12 +632,19 @@ test12(const void *opaque ATTRIBUTE_UNUSED)
TEST_MAP(151, "100");
+ virBitmapFree(map);
+ if (virBitmapParseUnlimited("34,1023", &map) < 0)
+ goto cleanup;
+
+ TEST_MAP(1024, "34,1023");
+
ret = 0;
cleanup:
virBitmapFree(map);
return ret;
}
+
#undef TEST_MAP
--
2.7.3