From d2460f85d3648607bf6119ee36a5d40546876d38 Mon Sep 17 00:00:00 2001 From: Chen Fan Date: Tue, 4 Nov 2014 10:44:39 +0800 Subject: [PATCH] bitmap: add virBitmapLastSetBit for finding the last bit position of bitmap Signed-off-by: Chen Fan --- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 45 ++++++++++++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ tests/virbitmaptest.c | 13 +++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e7e8df526c..840d93bcae 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1011,6 +1011,7 @@ virBitmapFree; virBitmapGetBit; virBitmapIsAllClear; virBitmapIsAllSet; +virBitmapLastSetBit; virBitmapNew; virBitmapNewCopy; virBitmapNewData; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index b6bd074cf4..04a2388049 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -650,6 +650,51 @@ virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) return ffsl(bits) - 1 + nl * VIR_BITMAP_BITS_PER_UNIT; } +/** + * virBitmapLastSetBit: + * @bitmap: the bitmap + * + * Search for the last set bit in bitmap @bitmap. + * + * Returns the position of the found bit, or -1 if no bit is set. + */ +ssize_t +virBitmapLastSetBit(virBitmapPtr bitmap) +{ + ssize_t i; + int unusedBits; + ssize_t sz; + unsigned long bits; + + unusedBits = bitmap->map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap->max_bit; + + sz = bitmap->map_len - 1; + if (unusedBits > 0) { + bits = bitmap->map[sz] & (VIR_BITMAP_BIT(VIR_BITMAP_BITS_PER_UNIT - unusedBits) - 1); + if (bits != 0) + goto found; + + sz--; + } + + for (; sz >= 0; sz--) { + bits = bitmap->map[sz]; + if (bits != 0) + goto found; + } + + if (bits == 0) + return -1; + + found: + for (i = VIR_BITMAP_BITS_PER_UNIT - 1; i >= 0; i--) { + if (bits & 1UL << i) + return i + sz * VIR_BITMAP_BITS_PER_UNIT; + } + + return -1; +} + /** * virBitmapNextClearBit: * @bitmap: the bitmap diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 4493cc94ba..565264cc4c 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -105,6 +105,9 @@ bool virBitmapIsAllClear(virBitmapPtr bitmap) ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); +ssize_t virBitmapLastSetBit(virBitmapPtr bitmap) + ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextClearBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c index ea832ad7f3..ac5f2987d7 100644 --- a/tests/virbitmaptest.c +++ b/tests/virbitmaptest.c @@ -171,7 +171,7 @@ test3(const void *data ATTRIBUTE_UNUSED) return ret; } -/* test for virBitmapNextSetBit, virBitmapNextClearBit */ +/* test for virBitmapNextSetBit, virBitmapLastSetBit, virBitmapNextClearBit */ static int test4(const void *data ATTRIBUTE_UNUSED) { @@ -200,6 +200,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, -1) != -1) goto error; + if (virBitmapLastSetBit(bitmap) != -1) + goto error; + for (i = 0; i < size; i++) { if (virBitmapNextClearBit(bitmap, i - 1) != i) goto error; @@ -232,6 +235,11 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; + j = sizeof(bitsPos)/sizeof(int) - 1; + + if (virBitmapLastSetBit(bitmap) != bitsPos[j]) + goto error; + j = 0; i = -1; @@ -255,6 +263,9 @@ test4(const void *data ATTRIBUTE_UNUSED) if (virBitmapNextSetBit(bitmap, i) != -1) goto error; + if (virBitmapLastSetBit(bitmap) != size - 1) + goto error; + if (virBitmapNextClearBit(bitmap, -1) != -1) goto error; -- GitLab