Implemented hash_remove_current() which removes the current iterator position
from the hash - not yet tested. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20368 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,9 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2002-2007, Haiku Inc. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*
|
||||||
#ifndef _KERNEL_KHASH_H
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
#define _KERNEL_KHASH_H
|
* Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_UTIL_KHASH_H
|
||||||
|
#define _KERNEL_UTIL_KHASH_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
// can be allocated on the stack
|
// can be allocated on the stack
|
||||||
typedef struct hash_iterator {
|
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);
|
int hash_uninit(struct hash_table *table);
|
||||||
status_t hash_insert(struct hash_table *table, void *_element);
|
status_t hash_insert(struct hash_table *table, void *_element);
|
||||||
status_t hash_remove(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_remove_first(struct hash_table *table, uint32 *_cookie);
|
||||||
void *hash_find(struct hash_table *table, void *e);
|
void *hash_find(struct hash_table *table, void *e);
|
||||||
void *hash_lookup(struct hash_table *table, const void *key);
|
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_next(struct hash_table *table, struct hash_iterator *i);
|
||||||
void hash_rewind(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);
|
* uint32 hash_func(void *e, const void *key, uint32 range);
|
||||||
* hash function should calculate hash on either e or key,
|
* 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);
|
* int compare_func(void *e, const void *key);
|
||||||
* compare function should compare the element with
|
* compare function should compare the element with
|
||||||
* the key, returning 0 if equal, other if not
|
* 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);
|
uint32 hash_hash_string(const char *str);
|
||||||
@@ -50,4 +56,4 @@ uint32 hash_hash_string(const char *str);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _KERNEL_KHASH_H */
|
#endif /* _KERNEL_UTIL_KHASH_H */
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
/* Generic hash table
|
/*
|
||||||
**
|
* Copyright 2002-2007, Haiku Inc. All rights reserved.
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
* Distributed under the terms of the MIT License.
|
||||||
** Distributed under the terms of the NewOS License.
|
*
|
||||||
*/
|
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
|
* Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! Generic hash table
|
||||||
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <Errors.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <util/khash.h>
|
#include <util/khash.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define TRACE_HASH 0
|
#define TRACE_HASH 0
|
||||||
#if TRACE_HASH
|
#if TRACE_HASH
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
@@ -18,9 +23,9 @@
|
|||||||
# define TRACE(x) ;
|
# define TRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ToDo: the hashtable is not expanded when necessary (no load factor, no nothing)
|
// TODO: the hashtable is not expanded when necessary (no load factor, nothing)
|
||||||
// Could try to use pools instead of malloc() for the elements - might be
|
// resizing should be optional, though, in case the hash is used at times
|
||||||
// faster than the current approach.
|
// that forbid resizing.
|
||||||
|
|
||||||
struct hash_table {
|
struct hash_table {
|
||||||
struct hash_element **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);
|
uint32 hash = table->hash_func(_element, NULL, table->table_size);
|
||||||
void *element, *lastElement = NULL;
|
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 (element == _element) {
|
||||||
if (lastElement != NULL) {
|
if (lastElement != NULL) {
|
||||||
// connect the previous entry with the next one
|
// 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 *
|
void *
|
||||||
hash_remove_first(struct hash_table *table, uint32 *_cookie)
|
hash_remove_first(struct hash_table *table, uint32 *_cookie)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user