]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
bitmap: add way to find next clear bit
authorEric Blake <eblake@redhat.com>
Sat, 2 Feb 2013 00:33:18 +0000 (17:33 -0700)
committerEric Blake <eblake@redhat.com>
Tue, 5 Feb 2013 23:23:14 +0000 (16:23 -0700)
We had an easy way to iterate set bits, but not for iterating
cleared bits.

* src/util/virbitmap.h (virBitmapNextClearBit): New prototype.
* src/util/virbitmap.c (virBitmapNextClearBit): Implement it.
* src/libvirt_private.syms (bitmap.h): Export it.
* tests/virbitmaptest.c (test4): Test it.

src/libvirt_private.syms
src/util/virbitmap.c
src/util/virbitmap.h
tests/virbitmaptest.c

index 0d3481778f3d1bd679a0f66b1f36d4bab087f0ea..57e3eb4188178316b7f10853ed839aa0d2c11c80 100644 (file)
@@ -18,6 +18,7 @@ virBitmapIsAllSet;
 virBitmapNew;
 virBitmapNewCopy;
 virBitmapNewData;
+virBitmapNextClearBit;
 virBitmapNextSetBit;
 virBitmapParse;
 virBitmapSetAll;
index 2cfe03a9d5b8d7d87ac6f19ff429f7fe5029f6aa..21509ac3966338e6ac94269a77d3af42043a759a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virbitmap.h: Simple bitmap operations
  *
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2010 Novell, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -595,13 +595,14 @@ bool virBitmapIsAllSet(virBitmapPtr bitmap)
  * @bitmap: the bitmap
  * @pos: the position after which to search for a set bit
  *
- * search the first set bit after position @pos in bitmap @bitmap.
+ * Search for the first set bit after position @pos in bitmap @bitmap.
  * @pos can be -1 to search for the first set bit. Position starts
  * at 0.
  *
- * returns the position of the found bit, or -1 if no bit found.
+ * Returns the position of the found bit, or -1 if no bit found.
  */
-ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos)
+ssize_t
+virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos)
 {
     size_t nl;
     size_t nb;
@@ -630,6 +631,54 @@ ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos)
     return ffsl(bits) - 1 + nl * VIR_BITMAP_BITS_PER_UNIT;
 }
 
+/**
+ * virBitmapNextClearBit:
+ * @bitmap: the bitmap
+ * @pos: the position after which to search for a clear bit
+ *
+ * Search for the first clear bit after position @pos in bitmap @bitmap.
+ * @pos can be -1 to search for the first set bit. Position starts
+ * at 0.
+ *
+ * Returns the position of the found bit, or -1 if no bit found.
+ */
+ssize_t
+virBitmapNextClearBit(virBitmapPtr bitmap, ssize_t pos)
+{
+    size_t nl;
+    size_t nb;
+    unsigned long bits;
+
+    if (pos < 0)
+        pos = -1;
+
+    pos++;
+
+    if (pos >= bitmap->max_bit)
+        return -1;
+
+    nl = pos / VIR_BITMAP_BITS_PER_UNIT;
+    nb = pos % VIR_BITMAP_BITS_PER_UNIT;
+
+    bits = ~bitmap->map[nl] & ~((1UL << nb) - 1);
+
+    while (bits == 0 && ++nl < bitmap->map_len) {
+        bits = ~bitmap->map[nl];
+    }
+
+    if (nl == bitmap->map_len - 1) {
+        /* Ensure tail bits are ignored.  */
+        int tail = bitmap->max_bit % VIR_BITMAP_BITS_PER_UNIT;
+
+        if (tail)
+            bits &= -1UL >> (VIR_BITMAP_BITS_PER_UNIT - tail);
+    }
+    if (bits == 0)
+        return -1;
+
+    return ffsl(bits) - 1 + nl * VIR_BITMAP_BITS_PER_UNIT;
+}
+
 /* Return the number of bits currently set in the map.  */
 size_t
 virBitmapCountBits(virBitmapPtr bitmap)
index 0f68b791adcbe573c718b226ecfc1076aac285df..044c7a65fcf70a328279fefcaabcee4f58314b04 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virbitmap.h: Simple bitmap operations
  *
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012-2013 Red Hat, Inc.
  * Copyright (C) 2010 Novell, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -103,6 +103,9 @@ bool virBitmapIsAllSet(virBitmapPtr bitmap)
 ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos)
     ATTRIBUTE_NONNULL(1);
 
+ssize_t virBitmapNextClearBit(virBitmapPtr bitmap, ssize_t pos)
+    ATTRIBUTE_NONNULL(1);
+
 size_t virBitmapCountBits(virBitmapPtr bitmap)
     ATTRIBUTE_NONNULL(1);
 
index 66ffd1b49d312f7e1d628305b0ad23d7bca4d4c2..95d010a11348466b2aeb589ac6cd83899bebaf3c 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2013 Red Hat, Inc.
  * Copyright (C) 2012 Fujitsu.
  *
  * This library is free software; you can redistribute it and/or
@@ -160,7 +161,7 @@ error:
     return ret;
 }
 
-/* test for virBitmapNextSetBit */
+/* test for virBitmapNextSetBit, virBitmapNextClearBit */
 static int test4(const void *data ATTRIBUTE_UNUSED)
 {
     const char *bitsString = "0, 2-4, 6-10, 12, 14-18, 20, 22, 25";
@@ -169,17 +170,30 @@ static int test4(const void *data ATTRIBUTE_UNUSED)
         0,  2,  3,  4,  6,  7,  8,  9, 10, 12,
         14, 15, 16, 17, 18, 20, 22, 25
     };
-    int npos = 18;
+    int bitsPosInv[] = {
+        1, 5, 11, 13, 19, 21, 23, 24, 26, 27,
+        28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
+    };
     virBitmapPtr bitmap = NULL;
     int i, j;
 
+    if (ARRAY_CARDINALITY(bitsPos) + ARRAY_CARDINALITY(bitsPosInv) != size)
+        goto error;
+
     /* 1. zero set */
 
     bitmap = virBitmapNew(size);
     if (!bitmap)
         goto error;
 
-    if (virBitmapNextSetBit(bitmap, -1) >= 0)
+    if (virBitmapNextSetBit(bitmap, -1) != -1)
+        goto error;
+
+    for (i = 0; i < size; i++) {
+        if (virBitmapNextClearBit(bitmap, i - 1) != i)
+            goto error;
+    }
+    if (virBitmapNextClearBit(bitmap, i) != -1)
         goto error;
 
     virBitmapFree(bitmap);
@@ -195,27 +209,39 @@ static int test4(const void *data ATTRIBUTE_UNUSED)
     j = 0;
     i = -1;
 
-    while (j < npos) {
+    while (j < ARRAY_CARDINALITY(bitsPos)) {
         i = virBitmapNextSetBit(bitmap, i);
         if (i != bitsPos[j++])
             goto error;
     }
 
-    if (virBitmapNextSetBit(bitmap, i) > 0)
+    if (virBitmapNextSetBit(bitmap, i) != -1)
+        goto error;
+
+    j = 0;
+    i = -1;
+
+    while (j < ARRAY_CARDINALITY(bitsPosInv)) {
+        i = virBitmapNextClearBit(bitmap, i);
+        if (i != bitsPosInv[j++])
+            goto error;
+    }
+
+    if (virBitmapNextClearBit(bitmap, i) != -1)
         goto error;
 
     /* 3. full set */
 
-    i = -1;
     virBitmapSetAll(bitmap);
 
-    for (j = 0; j < size; j++) {
-        i = virBitmapNextSetBit(bitmap, i);
-        if (i != j)
+    for (i = 0; i < size; i++) {
+        if (virBitmapNextSetBit(bitmap, i - 1) != i)
             goto error;
     }
+    if (virBitmapNextSetBit(bitmap, i) != -1)
+        goto error;
 
-    if (virBitmapNextSetBit(bitmap, i) > 0)
+    if (virBitmapNextClearBit(bitmap, -1) != -1)
         goto error;
 
     virBitmapFree(bitmap);