From f33c86be1df7356fe6ef257769f52981528311a7 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 6 Dec 2021 16:28:44 +0100 Subject: [PATCH] util: bitmap: Unify parsing of bitmaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were two separate instances of string->virBitmap code: virBitmapParseInternal and virBitmapParseUnlimited. By adding a flag to switch to expanding APIs we can merge the two implementations into one. Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- src/util/virbitmap.c | 115 ++++++++++--------------------------------- 1 file changed, 26 insertions(+), 89 deletions(-) diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index 4047870e04..5b9204cbd7 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -367,6 +367,7 @@ virBitmapFormat(virBitmap *bitmap) * virBitmapParseInternal: * @str: points to a string representing a human-readable bitmap * @bitmap: a bitmap populated from @str + * @limited: Don't use self-expanding APIs, report error if bit exceeds bitmap size * * This function is the counterpart of virBitmapFormat. This function creates * a bitmap, in which bits are set according to the content of @str. @@ -379,7 +380,8 @@ virBitmapFormat(virBitmap *bitmap) */ static int virBitmapParseInternal(const char *str, - virBitmap *bitmap) + virBitmap *bitmap, + bool limited) { bool neg = false; const char *cur = str; @@ -421,11 +423,19 @@ virBitmapParseInternal(const char *str, if (*cur == ',' || *cur == 0) { if (neg) { - if (virBitmapClearBit(bitmap, start) < 0) - goto error; + if (limited) { + if (virBitmapClearBit(bitmap, start) < 0) + goto error; + } else { + virBitmapClearBitExpand(bitmap, start); + } } else { - if (virBitmapSetBit(bitmap, start) < 0) - goto error; + if (limited) { + if (virBitmapSetBit(bitmap, start) < 0) + goto error; + } else { + virBitmapSetBitExpand(bitmap, start); + } } } else if (*cur == '-') { if (neg) @@ -442,8 +452,12 @@ virBitmapParseInternal(const char *str, cur = tmp; for (i = start; i <= last; i++) { - if (virBitmapSetBit(bitmap, i) < 0) - goto error; + if (limited) { + if (virBitmapSetBit(bitmap, i) < 0) + goto error; + } else { + virBitmapSetBitExpand(bitmap, i); + } } virSkipSpaces(&cur); @@ -491,7 +505,7 @@ virBitmapParse(const char *str, { g_autoptr(virBitmap) tmp = virBitmapNew(bitmapSize); - if (virBitmapParseInternal(str, tmp) < 0) + if (virBitmapParseInternal(str, tmp, true) < 0) return -1; *bitmap = g_steal_pointer(&tmp); @@ -518,89 +532,12 @@ virBitmapParse(const char *str, virBitmap * virBitmapParseUnlimited(const char *str) { - virBitmap *bitmap = virBitmapNew(0); - bool neg = false; - const char *cur = str; - char *tmp; - size_t i; - int start, last; + g_autoptr(virBitmap) tmp = virBitmapNew(0); - if (!str) - goto error; + if (virBitmapParseInternal(str, tmp, false) < 0) + return NULL; - 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 (!g_ascii_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) { - virBitmapClearBitExpand(bitmap, start); - } else { - virBitmapSetBitExpand(bitmap, start); - } - } 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++) - virBitmapSetBitExpand(bitmap, i); - - virSkipSpaces(&cur); - } - - if (*cur == ',') { - cur++; - virSkipSpaces(&cur); - neg = false; - } else if (*cur == 0) { - break; - } else { - goto error; - } - } - - return bitmap; - - error: - virReportError(VIR_ERR_INVALID_ARG, - _("Failed to parse bitmap '%s'"), NULLSTR(str)); - virBitmapFree(bitmap); - return NULL; + return g_steal_pointer(&tmp); }