hbitmap_iter_next(&hbi);
}
+static void test_hbitmap_next_zero_check(TestHBitmapData *data, int64_t start)
+{
+ int64_t ret1 = hbitmap_next_zero(data->hb, start);
+ int64_t ret2 = start;
+ for ( ; ret2 < data->size && hbitmap_get(data->hb, ret2); ret2++) {
+ ;
+ }
+ if (ret2 == data->size) {
+ ret2 = -1;
+ }
+
+ g_assert_cmpint(ret1, ==, ret2);
+}
+
+static void test_hbitmap_next_zero_do(TestHBitmapData *data, int granularity)
+{
+ hbitmap_test_init(data, L3, granularity);
+ test_hbitmap_next_zero_check(data, 0);
+ test_hbitmap_next_zero_check(data, L3 - 1);
+
+ hbitmap_set(data->hb, L2, 1);
+ test_hbitmap_next_zero_check(data, 0);
+ test_hbitmap_next_zero_check(data, L2 - 1);
+ test_hbitmap_next_zero_check(data, L2);
+ test_hbitmap_next_zero_check(data, L2 + 1);
+
+ hbitmap_set(data->hb, L2 + 5, L1);
+ test_hbitmap_next_zero_check(data, 0);
+ test_hbitmap_next_zero_check(data, L2 + 1);
+ test_hbitmap_next_zero_check(data, L2 + 2);
+ test_hbitmap_next_zero_check(data, L2 + 5);
+ test_hbitmap_next_zero_check(data, L2 + L1 - 1);
+ test_hbitmap_next_zero_check(data, L2 + L1);
+
+ hbitmap_set(data->hb, L2 * 2, L3 - L2 * 2);
+ test_hbitmap_next_zero_check(data, L2 * 2 - L1);
+ test_hbitmap_next_zero_check(data, L2 * 2 - 2);
+ test_hbitmap_next_zero_check(data, L2 * 2 - 1);
+ test_hbitmap_next_zero_check(data, L2 * 2);
+ test_hbitmap_next_zero_check(data, L3 - 1);
+
+ hbitmap_set(data->hb, 0, L3);
+ test_hbitmap_next_zero_check(data, 0);
+}
+
+static void test_hbitmap_next_zero_0(TestHBitmapData *data, const void *unused)
+{
+ test_hbitmap_next_zero_do(data, 0);
+}
+
+static void test_hbitmap_next_zero_4(TestHBitmapData *data, const void *unused)
+{
+ test_hbitmap_next_zero_do(data, 4);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
hbitmap_test_add("/hbitmap/iter/iter_and_reset",
test_hbitmap_iter_and_reset);
+
+ hbitmap_test_add("/hbitmap/next_zero/next_zero_0",
+ test_hbitmap_next_zero_0);
+ hbitmap_test_add("/hbitmap/next_zero/next_zero_4",
+ test_hbitmap_next_zero_4);
+
g_test_run();
return 0;
}
}
+int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start)
+{
+ size_t pos = (start >> hb->granularity) >> BITS_PER_LEVEL;
+ unsigned long *last_lev = hb->levels[HBITMAP_LEVELS - 1];
+ uint64_t sz = hb->sizes[HBITMAP_LEVELS - 1];
+ unsigned long cur = last_lev[pos];
+ unsigned start_bit_offset =
+ (start >> hb->granularity) & (BITS_PER_LONG - 1);
+ int64_t res;
+
+ cur |= (1UL << start_bit_offset) - 1;
+ assert((start >> hb->granularity) < hb->size);
+
+ if (cur == (unsigned long)-1) {
+ do {
+ pos++;
+ } while (pos < sz && last_lev[pos] == (unsigned long)-1);
+
+ if (pos >= sz) {
+ return -1;
+ }
+
+ cur = last_lev[pos];
+ }
+
+ res = (pos << BITS_PER_LEVEL) + ctol(cur);
+ if (res >= hb->size) {
+ return -1;
+ }
+
+ res = res << hb->granularity;
+ if (res < start) {
+ assert(((start - res) >> hb->granularity) == 0);
+ return start;
+ }
+
+ return res;
+}
+
bool hbitmap_empty(const HBitmap *hb)
{
return hb->count == 0;