diff --git a/src/lib/bitset/expr.c b/src/lib/bitset/expr.c index 860066899fb7e53011cd1c876bf66aa4a746cc1f..8c004c56073fe6ec894ecad2e0923424deb3727d 100644 --- a/src/lib/bitset/expr.c +++ b/src/lib/bitset/expr.c @@ -48,11 +48,17 @@ void bitset_expr_destroy(struct bitset_expr *expr) { for (size_t c = 0; c < expr->size; c++) { + if (expr->conjs[c].capacity == 0) + continue; + expr->realloc(expr->conjs[c].bitset_ids, 0); expr->realloc(expr->conjs[c].pre_nots, 0); - memset(&expr->conjs[c], 0, sizeof(expr->conjs[c])); } - expr->realloc(expr->conjs, 0); + + if (expr->capacity > 0) { + expr->realloc(expr->conjs, 0); + } + memset(expr, 0, sizeof(*expr)); } diff --git a/src/lib/bitset/iterator.c b/src/lib/bitset/iterator.c index 6e21f670484c738a52f9542b16a7bf3d48a51ce8..db56fd9ab2945ead6145af3e720bb9888ffaede1 100644 --- a/src/lib/bitset/iterator.c +++ b/src/lib/bitset/iterator.c @@ -67,16 +67,28 @@ void bitset_iterator_destroy(struct bitset_iterator *it) { for (size_t c = 0; c < it->size; c++) { + if (it->conjs[c].capacity == 0) + continue; + it->realloc(it->conjs[c].bitsets, 0); it->realloc(it->conjs[c].pre_nots, 0); it->realloc(it->conjs[c].pages, 0); } - it->realloc(it->conjs, 0); - bitset_page_destroy(it->page); - bitset_page_destroy(it->page_tmp); - it->realloc(it->page, 0); - it->realloc(it->page_tmp, 0); + if (it->capacity > 0) { + it->realloc(it->conjs, 0); + } + + if (it->page != NULL) { + bitset_page_destroy(it->page); + it->realloc(it->page, 0); + } + + if (it->page != NULL) { + bitset_page_destroy(it->page_tmp); + it->realloc(it->page_tmp, 0); + } + memset(it, 0, sizeof(*it)); } @@ -165,20 +177,27 @@ bitset_iterator_init(struct bitset_iterator *it, struct bitset_expr *expr, { assert(it != NULL); assert(expr != NULL); - assert(p_bitsets != NULL); - assert(expr->size > 0); + if (bitsets_size > 0) { + assert(p_bitsets != NULL); + } size_t page_alloc_size = bitset_page_alloc_size(it->realloc); - it->page = it->realloc(NULL, page_alloc_size); - it->page_tmp = it->realloc(NULL, page_alloc_size); - - if (it->page == NULL || it->page_tmp == NULL) { - it->realloc(it->page, 0); - it->realloc(it->page_tmp, 0); - return -1; + if (it->page != NULL) { + bitset_page_destroy(it->page); + } else { + it->page = it->realloc(NULL, page_alloc_size); } bitset_page_create(it->page); + + if (it->page_tmp != NULL) { + bitset_page_destroy(it->page_tmp); + } else { + it->page_tmp = it->realloc(NULL, page_alloc_size); + if (it->page_tmp == NULL) + return -1; + } + bitset_page_create(it->page_tmp); if (bitset_iterator_reserve(it, expr->size) != 0) @@ -187,7 +206,6 @@ bitset_iterator_init(struct bitset_iterator *it, struct bitset_expr *expr, for (size_t c = 0; c < expr->size; c++) { struct bitset_expr_conj *exconj = &expr->conjs[c]; struct bitset_iterator_conj *itconj = &it->conjs[c]; - assert(exconj->size > 0); if (bitset_iterator_conj_reserve(it, itconj, exconj->size) != 0) return -1; @@ -216,9 +234,13 @@ bitset_iterator_conj_rewind(struct bitset_iterator_conj *conj, size_t pos) { assert(conj != NULL); assert(pos % (BITSET_PAGE_DATA_SIZE * CHAR_BIT) == 0); - assert(conj->size > 0); assert(conj->page_first_pos <= pos); + if (conj->size == 0) { + conj->page_first_pos = SIZE_MAX; + return; + } + struct bitset_page key; key.first_pos = pos; @@ -312,7 +334,11 @@ bitset_iterator_prepare_page(struct bitset_iterator *it) bitset_iterator_conj_cmp); bitset_page_set_zeros(it->page); - it->page->first_pos = it->conjs[0].page_first_pos; + if (it->size > 0) { + it->page->first_pos = it->conjs[0].page_first_pos; + } else { + it->page->first_pos = SIZE_MAX; + } /* There is no more conjunctions that can be ORed */ if (it->page->first_pos == SIZE_MAX) diff --git a/test/unit/bitset_iterator.c b/test/unit/bitset_iterator.c index bebf1bf31dd6b867e7111fa25f5cf91a1b3b8cc5..37f25e9babdbcd7c6f773c132741e6de4e4de16b 100644 --- a/test/unit/bitset_iterator.c +++ b/test/unit/bitset_iterator.c @@ -78,7 +78,88 @@ nums_shuffle(size_t *nums, size_t size) } static -void test_empty() +void test_empty_expr(void) +{ + header(); + + struct bitset_expr expr; + bitset_expr_create(&expr, realloc); + struct bitset_iterator it; + bitset_iterator_create(&it, realloc); + + fail_unless(bitset_iterator_init(&it, &expr, NULL, 0) == 0); + bitset_expr_destroy(&expr); + + size_t pos = bitset_iterator_next(&it); + fail_unless(pos == SIZE_MAX); + + bitset_iterator_destroy(&it); + + footer(); +} + +static +void test_empty_expr_conj1(void) +{ + header(); + + struct bitset_expr expr; + bitset_expr_create(&expr, realloc); + struct bitset_iterator it; + bitset_iterator_create(&it, realloc); + + fail_unless(bitset_expr_add_conj(&expr) == 0); + + fail_unless(bitset_iterator_init(&it, &expr, NULL, 0) == 0); + bitset_expr_destroy(&expr); + + size_t pos = bitset_iterator_next(&it); + fail_unless(pos == SIZE_MAX); + + bitset_iterator_destroy(&it); + + footer(); +} + +static +void test_empty_expr_conj2(void) +{ + header(); + + size_t big_i = (size_t) 1 << 15; + struct bitset **bitsets = bitsets_create(2); + bitset_set(bitsets[0], 1); + bitset_set(bitsets[0], big_i); + + struct bitset_expr expr; + bitset_expr_create(&expr, realloc); + struct bitset_iterator it; + bitset_iterator_create(&it, realloc); + + fail_unless(bitset_expr_add_conj(&expr) == 0); + fail_unless(bitset_expr_add_conj(&expr) == 0); + fail_unless(bitset_expr_add_conj(&expr) == 0); + + fail_unless(bitset_expr_add_param(&expr, 0, false) == 0); + fail_unless(bitset_expr_add_param(&expr, 1, true) == 0); + fail_unless(bitset_expr_add_conj(&expr) == 0); + fail_unless(bitset_expr_add_conj(&expr) == 0); + + fail_unless(bitset_iterator_init(&it, &expr, bitsets, 2) == 0); + bitset_expr_destroy(&expr); + + fail_unless(bitset_iterator_next(&it) == 1); + fail_unless(bitset_iterator_next(&it) == big_i); + fail_unless(bitset_iterator_next(&it) == SIZE_MAX); + + bitset_iterator_destroy(&it); + bitsets_destroy(bitsets, 2); + + footer(); +} + +static +void test_empty_result(void) { header(); @@ -123,7 +204,7 @@ void test_empty() } static -void test_first() +void test_first_result(void) { header(); @@ -398,8 +479,11 @@ int main(void) setbuf(stdout, NULL); nums_fill(NUMS, NUMS_SIZE); - test_empty(); - test_first(); + test_empty_expr(); + test_empty_expr_conj1(); + test_empty_expr_conj2(); + test_empty_result(); + test_first_result(); test_simple(); test_big(); test_not_empty(); diff --git a/test/unit/bitset_iterator.result b/test/unit/bitset_iterator.result index 9d6a699aad43228f187a82d52c4427b4907dfe70..fd1e666d10fcff833d46b0ab0cae81908cfc3a6f 100644 --- a/test/unit/bitset_iterator.result +++ b/test/unit/bitset_iterator.result @@ -1,7 +1,13 @@ - *** test_empty *** - *** test_empty: done *** - *** test_first *** - *** test_first: done *** + *** test_empty_expr *** + *** test_empty_expr: done *** + *** test_empty_expr_conj1 *** + *** test_empty_expr_conj1: done *** + *** test_empty_expr_conj2 *** + *** test_empty_expr_conj2: done *** + *** test_empty_result *** + *** test_empty_result: done *** + *** test_first_result *** + *** test_first_result: done *** *** test_simple *** *** test_simple: done *** *** test_big ***