# util/virbitmap.h
virBitmapClearAll;
virBitmapClearBit;
+virBitmapClearBitExpand;
virBitmapCopy;
virBitmapCountBits;
virBitmapDataToString;
virBitmapNew;
virBitmapNewCopy;
virBitmapNewData;
+virBitmapNewEmpty;
virBitmapNewQuiet;
virBitmapNextClearBit;
virBitmapNextSetBit;
virBitmapParse;
virBitmapSetAll;
virBitmapSetBit;
+virBitmapSetBitExpand;
virBitmapSize;
virBitmapString;
virBitmapSubtract;
struct _virBitmap {
size_t max_bit;
size_t map_len;
+ size_t map_alloc;
unsigned long *map;
};
bitmap->max_bit = size;
bitmap->map_len = sz;
+ bitmap->map_alloc = sz;
return bitmap;
}
}
+/**
+ * virBitmapNewEmpty:
+ *
+ * Allocate an empty bitmap. It can be used with self-expanding APIs.
+ *
+ * Returns a pointer to the allocated bitmap or NULL if memory cannot be
+ * allocated. Reports libvirt errors.
+ */
+virBitmapPtr
+virBitmapNewEmpty(void)
+{
+ virBitmapPtr ret;
+
+ ignore_value(VIR_ALLOC(ret));
+
+ return ret;
+}
+
+
/**
* virBitmapFree:
* @bitmap: previously allocated bitmap
return 0;
}
+/**
+ * virBitmapExpand:
+ * @map: Pointer to bitmap
+ * @b: bit position to include in bitmap
+ *
+ * Resizes the bitmap so that bit @b will fit into it. This shall be called only
+ * if @b would not fit into the map.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+static int virBitmapExpand(virBitmapPtr map, size_t b)
+{
+ size_t new_len = VIR_DIV_UP(b, VIR_BITMAP_BITS_PER_UNIT);
+
+ /* resize the memory if necessary */
+ if (map->map_len < new_len) {
+ if (VIR_RESIZE_N(map->map, map->map_alloc, map->map_len,
+ new_len - map->map_len) < 0)
+ return -1;
+ }
+
+ map->max_bit = b + 1;
+ map->map_len = new_len;
+
+ return 0;
+}
+
+
+/**
+ * virBitmapSetBitExpand:
+ * @bitmap: Pointer to bitmap
+ * @b: bit position to set
+ *
+ * Set bit position @b in @bitmap. Expands the bitmap as necessary so that @b is
+ * included in the map.
+ *
+ * Returns 0 on if bit is successfully set, -1 on error.
+ */
+int virBitmapSetBitExpand(virBitmapPtr bitmap, size_t b)
+{
+ if (bitmap->max_bit <= b && virBitmapExpand(bitmap, b) < 0)
+ return -1;
+
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] |= VIR_BITMAP_BIT(b);
+ return 0;
+}
+
+
/**
* virBitmapClearBit:
* @bitmap: Pointer to bitmap
return 0;
}
+
+/**
+ * virBitmapClearBitExpand:
+ * @bitmap: Pointer to bitmap
+ * @b: bit position to set
+ *
+ * Clear bit position @b in @bitmap. Expands the bitmap as necessary so that
+ * @b is included in the map.
+ *
+ * Returns 0 on if bit is successfully cleared, -1 on error.
+ */
+int virBitmapClearBitExpand(virBitmapPtr bitmap, size_t b)
+{
+ if (bitmap->max_bit <= b) {
+ if (virBitmapExpand(bitmap, b) < 0)
+ return -1;
+ } else {
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &= ~VIR_BITMAP_BIT(b);
+ }
+
+ return 0;
+}
+
+
/* Helper function. caller must ensure b < bitmap->max_bit */
static bool virBitmapIsSet(virBitmapPtr bitmap, size_t b)
{
*/
virBitmapPtr virBitmapNewQuiet(size_t size) ATTRIBUTE_RETURN_CHECK;
virBitmapPtr virBitmapNew(size_t size) ATTRIBUTE_RETURN_CHECK;
+virBitmapPtr virBitmapNewEmpty(void) ATTRIBUTE_RETURN_CHECK;
/*
* Free previously allocated bitmap
int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virBitmapSetBitExpand(virBitmapPtr bitmap, size_t b)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+
/*
* Clear bit position @b in @bitmap
*/
int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virBitmapClearBitExpand(virBitmapPtr bitmap, size_t b)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
/*
* Get bit @b in @bitmap. Returns false if b is out of range.
*/
return ret;
}
+#define TEST_MAP(sz, expect) \
+ do { \
+ char *actual; \
+ if (virBitmapSize(map) != sz) { \
+ fprintf(stderr, "\n expected bitmap size: '%d' actual size: " \
+ "'%zu'\n", sz, virBitmapSize(map)); \
+ goto cleanup; \
+ } \
+ \
+ actual = virBitmapFormat(map); \
+ \
+ if (STRNEQ_NULLABLE(expect, actual)) { \
+ fprintf(stderr, "\n expected bitmap contents '%s' actual contents "\
+ "'%s'\n", NULLSTR(expect), NULLSTR(actual)); \
+ VIR_FREE(actual); \
+ goto cleanup; \
+ } \
+ VIR_FREE(actual); \
+ } while (0)
+
+/* test self-expanding bitmap APIs */
+static int
+test12(const void *opaque ATTRIBUTE_UNUSED)
+{
+ virBitmapPtr map = NULL;
+ int ret = -1;
+
+ if (!(map = virBitmapNewEmpty()))
+ return -1;
+
+ TEST_MAP(0, "");
+
+ if (virBitmapSetBitExpand(map, 100) < 0)
+ goto cleanup;
+
+ TEST_MAP(101, "100");
+
+ if (virBitmapClearBitExpand(map, 150) < 0)
+ goto cleanup;
+
+ TEST_MAP(151, "100");
+
+ ret = 0;
+
+ cleanup:
+ virBitmapFree(map);
+ return ret;
+}
+#undef TEST_MAP
+
+
#define TESTBINARYOP(A, B, RES, FUNC) \
testBinaryOpData.a = A; \
testBinaryOpData.b = B; \
TESTBINARYOP("0-3", "0,^0", "0-3", test11);
TESTBINARYOP("0,2", "1,3", "0,2", test11);
+ if (virtTestRun("test12", test12, NULL) < 0)
+ ret = -1;
+
return ret;
}