Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix removing items from hashset

Change-Id: I76bf80eac5797b9ddde1dfa9815c97c2469a35dc
Reviewed-on: http://review.couchbase.org/14798
Tested-by: Sergey Avseyev <sergey.avseyev@gmail.com>
Reviewed-by: Trond Norbye <trond.norbye@gmail.com>
  • Loading branch information...
commit 64f246c963d60cc70adbb2344f3026655f3468df 1 parent ec21e22
@avsej avsej authored trondn committed
Showing with 51 additions and 6 deletions.
  1. +10 −4 src/hashset.c
  2. +4 −1 src/hashset.h
  3. +37 −1 tests/hashset-test.c
View
14 src/hashset.c
@@ -27,7 +27,7 @@ hashset_t hashset_create()
if (set == NULL) {
return NULL;
}
- set->nbits = 2;
+ set->nbits = 3;
set->capacity = 1 << set->nbits;
set->mask = set->capacity - 1;
set->items = calloc(set->capacity, sizeof(size_t));
@@ -55,9 +55,15 @@ void hashset_destroy(hashset_t set)
static int hashset_add_member(hashset_t set, void *item)
{
size_t value = (size_t)item;
- size_t ii = set->mask & (prime_1 * value);
+ size_t ii;
- while (set->items[ii] != 0) {
+ if (value == 0 || value == 1) {
+ return -1;
+ }
+
+ ii = set->mask & (prime_1 * value);
+
+ while (set->items[ii] != 0 && set->items[ii] != 1) {
if (set->items[ii] == value) {
return 0;
} else {
@@ -106,7 +112,7 @@ int hashset_remove(hashset_t set, void *item)
while (set->items[ii] != 0) {
if (set->items[ii] == value) {
- set->items[ii] = 0;
+ set->items[ii] = 1;
set->nitems--;
return 1;
} else {
View
5 src/hashset.h
@@ -36,7 +36,10 @@ void hashset_destroy(hashset_t set);
size_t hashset_num_items(hashset_t set);
-/* add item into the hashset
+/* add item into the hashset.
+ *
+ * @note 0 and 1 is special values, meaning nil and deleted items. the
+ * function will return -1 indicating error.
*
* returns zero if the item already in the set and non-zero otherwise
*/
View
38 tests/hashset-test.c
@@ -52,12 +52,48 @@ static void trivial(void)
hashset_destroy(set);
}
+static void test_gaps(void)
+{
+ hashset_t set = hashset_create();
+
+ /* fill the hashset */
+ hashset_add(set, (void *)0xbabe);
+ hashset_add(set, (void *)0xbeef);
+ hashset_add(set, (void *)0xbad);
+ hashset_add(set, (void *)0xf00d);
+ /* 0xf00d (nil) (nil) (nil) (nil) 0xbad 0xbabe 0xbeef */
+
+ /* make a gap */
+ hashset_remove(set, (void *)0xbeef);
+ /* 0xf00d (nil) (nil) (nil) (nil) 0xbad 0xbabe 0x1 */
+
+ /* check that 0xf00d is still reachable */
+ assert(hashset_is_member(set, (void *)0xf00d));
+
+ /* add 0xbeef back */
+ hashset_add(set, (void *)0xbeef);
+ /* 0xf00d (nil) (nil) (nil) (nil) 0xbad 0xbabe 0xbeef */
+
+ /* verify */
+ assert(hashset_is_member(set, (void *)0xbeef));
+ assert(hashset_is_member(set, (void *)0xf00d));
+}
+
+static void test_exceptions(void)
+{
+ hashset_t set = hashset_create();
+
+ assert(hashset_add(set, (void *)0) == -1);
+ assert(hashset_add(set, (void *)1) == -1);
+}
+
int main(int argc, char *argv[])
{
trivial();
+ test_gaps();
+ test_exceptions();
(void)argc;
(void)argv;
return 0;
}
-
Please sign in to comment.
Something went wrong with that request. Please try again.