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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list