Introduce virBitmapParseUnlimited

For parsing a bitmap of an unknown size.
This commit is contained in:
Ján Tomko 2016-06-17 15:12:02 +02:00
parent ff52e9d43a
commit dc56b3a7ce
4 changed files with 124 additions and 0 deletions

View File

@ -1208,6 +1208,7 @@ virBitmapNextSetBit;
virBitmapOverlaps;
virBitmapParse;
virBitmapParseSeparator;
virBitmapParseUnlimited;
virBitmapSetAll;
virBitmapSetBit;
virBitmapSetBitExpand;

View File

@ -542,6 +542,118 @@ virBitmapParse(const char *str,
return virBitmapParseSeparator(str, '\0', bitmap, bitmapSize);
}
/**
* 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.

View File

@ -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);

View File

@ -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