diff --git a/include/lib/bit/bit.h b/include/lib/bit/bit.h index 00ba076ecf9e8a726fec6e4582866de1c10650e3..575b2e846cfa363320fb46bae629cd4c8bb5f707 100644 --- a/include/lib/bit/bit.h +++ b/include/lib/bit/bit.h @@ -421,6 +421,11 @@ bit_iterator_init(struct bit_iterator *it, const void *data, size_t size, it->start = (const char *) data; it->next = it->start; it->end = it->next + size; + if (bit_unlikely(size == 0)) { + it->word = 0; + return; + } + it->word_xor = set ? 0 : (ITER_UINT) -1; it->word_base = 0; diff --git a/include/lib/bitset/index.h b/include/lib/bitset/index.h index fd1ed792b7dba5d5e299342a02091213b6445dc1..c35407494fdac6a2436c665dc1e59fc67176ca45 100644 --- a/include/lib/bitset/index.h +++ b/include/lib/bitset/index.h @@ -154,8 +154,7 @@ bitset_index_destroy(struct bitset_index *index); /** * @brief Insert (\a key, \a value) pair into \a index. - * Only one pair with a given value can exist in the index. - * If a pair with the same \a value exists, it is updated quietly. + * \a value must be unique in the index. * This method is atomic, i.e. \a index will be in a consistent * state after a return even in case of error. * diff --git a/src/lib/bitset/index.c b/src/lib/bitset/index.c index 541ac65a92ac9b5bdd4f60a30565bd11309fc286..ff51fe9ec0a67ddae1b303aebc7edd542845ac4d 100644 --- a/src/lib/bitset/index.c +++ b/src/lib/bitset/index.c @@ -162,7 +162,10 @@ bitset_index_insert(struct bitset_index *index, const void *key, if (rc < 0) return -1; - /* if 1 then the value is new in the index */ + assert(rc == 0); /* if 1 then the value is already exist in the index */ + if (key_size == 0) /* optimization for empty key */ + return 0; + index->rollback_buf[0] = (char) rc; /* @@ -188,23 +191,6 @@ bitset_index_insert(struct bitset_index *index, const void *key, index->rollback_buf[b] = (char) rc; } - /* Finish here if the value is new in the index */ - if (index->rollback_buf[0] == 0) - return 0; - - /* - * Step 3: Iterate over 'unset' bits and cleanup other bitsets - * This step is needed if the value was already existed in the index. - * Nothing can fail here because current implementation of - * bitset_clear never fails. - */ - bit_iterator_init(&bit_it, key, key_size, false); - while ((pos = bit_iterator_next(&bit_it)) != SIZE_MAX) { - size_t b = pos + 1; - rc = bitset_clear(index->bitsets[b], value); - assert(rc >= 0); /* bitset_clear never fails */ - } - return 0; rollback: @@ -308,6 +294,9 @@ bitset_index_expr_all_set(struct bitset_expr *expr, const void *key, if (bitset_expr_add_conj(expr) != 0) return -1; + if (key_size == 0) + return 0; /* optimization for empty key */ + struct bit_iterator bit_it; bit_iterator_init(&bit_it, key, key_size, true); size_t pos; @@ -326,6 +315,9 @@ bitset_index_expr_any_set(struct bitset_expr *expr, const void *key, { bitset_expr_clear(expr); + if (key_size == 0) + return 0; /* optimization for empty key */ + struct bit_iterator bit_it; bit_iterator_init(&bit_it, key, key_size, true); size_t pos; @@ -351,6 +343,9 @@ bitset_index_expr_all_not_set(struct bitset_expr *expr, const void *key, if (bitset_expr_add_param(expr, 0, false) != 0) return -1; + if (key_size == 0) + return 0; /* optimization for empty key */ + struct bit_iterator bit_it; bit_iterator_init(&bit_it, key, key_size, true); size_t pos; diff --git a/test/unit/bit.c b/test/unit/bit.c index a7cce03672e5333f53edf8bbc3ad26a64ca4b54e..d3eadbea19dd8c6b2ec411bb68dab063229e40a8 100644 --- a/test/unit/bit.c +++ b/test/unit/bit.c @@ -190,6 +190,22 @@ test_bit_iter(void) footer(); } +static void +test_bit_iter_empty(void) +{ + header(); + + struct bit_iterator it; + + bit_iterator_init(&it, NULL, 0, true); + fail_unless(bit_iterator_next(&it) == SIZE_MAX); + + bit_iterator_init(&it, NULL, 0, false); + fail_unless(bit_iterator_next(&it) == SIZE_MAX); + + footer(); +} + int main(void) { @@ -199,4 +215,5 @@ main(void) test_bswap(); test_index(); test_bit_iter(); + test_bit_iter_empty(); } diff --git a/test/unit/bit.result b/test/unit/bit.result index 1817985feff4c0af154ccbe468735f9bd74e057a..37d5f60b3f0e7afe9ecf96a99037409730048f64 100644 --- a/test/unit/bit.result +++ b/test/unit/bit.result @@ -889,4 +889,6 @@ bit_index_u64(18446744073709551615, *, -1) => 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Set: 3, 9, 11, 16, 17, 18, 22, 24, 25, 27, 29, 64, 65, 68, 69, 72, 73, 76, 77, Clear: 0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 19, 20, 21, 23, 26, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 66, 67, 70, 71, 74, 75, 78, 79, *** test_bit_iter: done *** + *** test_bit_iter_empty *** + *** test_bit_iter_empty: done *** \ No newline at end of file