Skip to content

Commit 3477202

Browse files
committed
feat: implement roaring64_bitmap_overwrite
1 parent 8746674 commit 3477202

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

include/roaring/roaring64.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ void roaring64_bitmap_free(roaring64_bitmap_t *r);
5050
*/
5151
roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r);
5252

53+
/**
54+
* Copies a bitmap from src to dest. It is assumed that the pointer dest
55+
* is to an already allocated bitmap. The content of the dest bitmap is
56+
* freed/deleted.
57+
*
58+
* It might be preferable and simpler to call roaring64_bitmap_copy except
59+
* that roaring64_bitmap_overwrite can save on memory allocations.
60+
*
61+
*/
62+
void roaring64_bitmap_overwrite(roaring64_bitmap_t *dest,
63+
const roaring64_bitmap_t *src);
64+
5365
/**
5466
* Creates a new bitmap of a pointer to N 64-bit integers.
5567
*/

src/roaring64.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,42 @@ roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r) {
273273
return result;
274274
}
275275

276+
void roaring64_bitmap_overwrite(roaring64_bitmap_t *dest,
277+
const roaring64_bitmap_t *src) {
278+
if (dest == src) {
279+
return;
280+
}
281+
282+
// Free dest's containers.
283+
art_iterator_t it = art_init_iterator(&dest->art, /*first=*/true);
284+
while (it.value != NULL) {
285+
leaf_t leaf = (leaf_t)*it.value;
286+
container_free(get_container(dest, leaf), get_typecode(leaf));
287+
art_iterator_next(&it);
288+
}
289+
art_free(&dest->art);
290+
roaring_free(dest->containers);
291+
292+
// Reinitialize dest.
293+
art_init_cleared(&dest->art);
294+
dest->flags = 0;
295+
dest->first_free = 0;
296+
dest->capacity = 0;
297+
dest->containers = NULL;
298+
299+
// Copy src's containers into dest.
300+
it = art_init_iterator((art_t *)&src->art, /*first=*/true);
301+
while (it.value != NULL) {
302+
leaf_t leaf = (leaf_t)*it.value;
303+
uint8_t typecode = get_typecode(leaf);
304+
container_t *container = get_copy_of_container(
305+
get_container(src, leaf), &typecode, /*copy_on_write=*/false);
306+
leaf_t dest_leaf = add_container(dest, container, typecode);
307+
art_insert(&dest->art, it.key, (art_val_t)dest_leaf);
308+
art_iterator_next(&it);
309+
}
310+
}
311+
276312
/**
277313
* Steal the containers from a 32-bit bitmap and insert them into a 64-bit
278314
* bitmap (with an offset)

tests/roaring64_unit.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,45 @@ DEFINE_TEST(test_copy) {
114114
roaring64_bitmap_free(r2);
115115
}
116116

117+
DEFINE_TEST(test_overwrite) {
118+
roaring64_bitmap_t* r1 = roaring64_bitmap_create();
119+
roaring64_bitmap_add(r1, 0);
120+
roaring64_bitmap_add(r1, 10000);
121+
roaring64_bitmap_add(r1, 200000);
122+
123+
roaring64_bitmap_t* r2 = roaring64_bitmap_create();
124+
roaring64_bitmap_add(r2, 123);
125+
126+
roaring64_bitmap_overwrite(r2, r1);
127+
assert_r64_valid(r2);
128+
assert_true(roaring64_bitmap_contains(r2, 0));
129+
assert_true(roaring64_bitmap_contains(r2, 10000));
130+
assert_true(roaring64_bitmap_contains(r2, 200000));
131+
assert_false(roaring64_bitmap_contains(r2, 123));
132+
133+
// Modifying src after overwrite does not affect dest.
134+
roaring64_bitmap_remove(r1, 200000);
135+
roaring64_bitmap_add(r1, 300000);
136+
assert_r64_valid(r1);
137+
assert_true(roaring64_bitmap_contains(r2, 200000));
138+
assert_false(roaring64_bitmap_contains(r2, 300000));
139+
140+
// Overwriting with an empty bitmap clears dest.
141+
roaring64_bitmap_t* empty = roaring64_bitmap_create();
142+
roaring64_bitmap_overwrite(r2, empty);
143+
assert_r64_valid(r2);
144+
assert_true(roaring64_bitmap_is_empty(r2));
145+
146+
// Self-overwrite is a no-op.
147+
roaring64_bitmap_overwrite(r1, r1);
148+
assert_r64_valid(r1);
149+
assert_true(roaring64_bitmap_contains(r1, 300000));
150+
151+
roaring64_bitmap_free(empty);
152+
roaring64_bitmap_free(r1);
153+
roaring64_bitmap_free(r2);
154+
}
155+
117156
DEFINE_TEST(test_move_from_roaring32) {
118157
{
119158
// Empty bitmap
@@ -2336,6 +2375,7 @@ int main() {
23362375
cmocka_unit_test(test_remove_many_issue_742B),
23372376
cmocka_unit_test(fuzz_deserializer),
23382377
cmocka_unit_test(test_copy),
2378+
cmocka_unit_test(test_overwrite),
23392379
cmocka_unit_test(test_from_range),
23402380
cmocka_unit_test(test_move_from_roaring32),
23412381
cmocka_unit_test(test_of_ptr),

0 commit comments

Comments
 (0)