diff --git a/headers/private/kernel/util/khash.h b/headers/private/kernel/util/khash.h index af0debf4e7..d130b4ed85 100644 --- a/headers/private/kernel/util/khash.h +++ b/headers/private/kernel/util/khash.h @@ -1,9 +1,16 @@ -/* -** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef _KERNEL_KHASH_H -#define _KERNEL_KHASH_H +/* + * Copyright 2002-2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_UTIL_KHASH_H +#define _KERNEL_UTIL_KHASH_H + + +#include + // can be allocated on the stack typedef struct hash_iterator { @@ -23,6 +30,7 @@ struct hash_table *hash_init(uint32 table_size, int next_ptr_offset, int hash_uninit(struct hash_table *table); status_t hash_insert(struct hash_table *table, void *_element); status_t hash_remove(struct hash_table *table, void *_element); +void hash_remove_current(struct hash_table *table, struct hash_iterator *iterator); void *hash_remove_first(struct hash_table *table, uint32 *_cookie); void *hash_find(struct hash_table *table, void *e); void *hash_lookup(struct hash_table *table, const void *key); @@ -31,17 +39,15 @@ void hash_close(struct hash_table *table, struct hash_iterator *i, bool free_ite void *hash_next(struct hash_table *table, struct hash_iterator *i); void hash_rewind(struct hash_table *table, struct hash_iterator *i); -/* function ptrs must look like this: +/* function pointers must look like this: * * uint32 hash_func(void *e, const void *key, uint32 range); * hash function should calculate hash on either e or key, - * depending on which one is not NULL + * depending on which one is not NULL - they also need + * to make sure the returned value is within range. * int compare_func(void *e, const void *key); * compare function should compare the element with * the key, returning 0 if equal, other if not - * NOTE: compare func can be null, in which case the hash - * code will compare the key pointer with the target - * ToDo: check this! */ uint32 hash_hash_string(const char *str); @@ -50,4 +56,4 @@ uint32 hash_hash_string(const char *str); } #endif -#endif /* _KERNEL_KHASH_H */ +#endif /* _KERNEL_UTIL_KHASH_H */ diff --git a/src/system/kernel/util/khash.c b/src/system/kernel/util/khash.c index bc793e9ee7..18e9846b82 100644 --- a/src/system/kernel/util/khash.c +++ b/src/system/kernel/util/khash.c @@ -1,16 +1,21 @@ -/* Generic hash table -** -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ +/* + * Copyright 2002-2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + +//! Generic hash table + #include -#include #include -#include -#include #include +#include +#include + #define TRACE_HASH 0 #if TRACE_HASH # define TRACE(x) dprintf x @@ -18,9 +23,9 @@ # define TRACE(x) ; #endif -// ToDo: the hashtable is not expanded when necessary (no load factor, no nothing) -// Could try to use pools instead of malloc() for the elements - might be -// faster than the current approach. +// TODO: the hashtable is not expanded when necessary (no load factor, nothing) +// resizing should be optional, though, in case the hash is used at times +// that forbid resizing. struct hash_table { struct hash_element **table; @@ -123,7 +128,8 @@ hash_remove(struct hash_table *table, void *_element) uint32 hash = table->hash_func(_element, NULL, table->table_size); void *element, *lastElement = NULL; - for (element = table->table[hash]; element != NULL; lastElement = element, element = NEXT(table, element)) { + for (element = table->table[hash]; element != NULL; + lastElement = element, element = NEXT(table, element)) { if (element == _element) { if (lastElement != NULL) { // connect the previous entry with the next one @@ -140,6 +146,40 @@ hash_remove(struct hash_table *table, void *_element) } +void +hash_remove_current(struct hash_table *table, struct hash_iterator *iterator) +{ + uint32 index = iterator->bucket; + void *element; + + if (iterator->current == NULL) + panic("hash_remove_current() called too early."); + + for (element = table->table[index]; index < table->table_size; index++) { + void *lastElement = NULL; + + while (element != NULL) { + if (element == iterator->current) { + iterator->current = lastElement; + + if (lastElement != NULL) { + // connect the previous entry with the next one + PUT_IN_NEXT(table, lastElement, NEXT(table, element)); + } else { + table->table[index] = (struct hash_element *)NEXT(table, + element); + } + + table->num_elements--; + return; + } + + element = NEXT(table, element); + } + } +} + + void * hash_remove_first(struct hash_table *table, uint32 *_cookie) {