3 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
4 ** Distributed under the terms of the NewOS License.
11 #include "fssh_errors.h"
12 #include "fssh_kernel_export.h"
18 # define TRACE(x) fssh_dprintf x
30 // TODO: the hashtable is not expanded when necessary (no load factor, nothing)
31 // resizing should be optional, though, in case the hash is used at times
32 // that forbid resizing.
35 struct hash_element
**table
;
40 int (*compare_func
)(void *e
, const void *key
);
41 uint32_t (*hash_func
)(void *e
, const void *key
, uint32_t range
);
45 #define NEXT_ADDR(t, e) ((void *)(((unsigned long)(e)) + (t)->next_ptr_offset))
46 #define NEXT(t, e) ((void *)(*(unsigned long *)NEXT_ADDR(t, e)))
47 #define PUT_IN_NEXT(t, e, val) (*(unsigned long *)NEXT_ADDR(t, e) = (long)(val))
51 next_element(hash_table
*table
, void *element
)
53 // ToDo: should we use this instead of the NEXT() macro?
54 return (void *)(*(unsigned long *)NEXT_ADDR(table
, element
));
59 hash_init(uint32_t table_size
, int next_ptr_offset
,
60 int compare_func(void *e
, const void *key
),
61 uint32_t hash_func(void *e
, const void *key
, uint32_t range
))
66 if (compare_func
== NULL
|| hash_func
== NULL
) {
67 fssh_dprintf("hash_init() called with NULL function pointer\n");
71 t
= (struct hash_table
*)malloc(sizeof(struct hash_table
));
75 t
->table
= (struct hash_element
**)malloc(sizeof(void *) * table_size
);
76 if (t
->table
== NULL
) {
81 for (i
= 0; i
< table_size
; i
++)
84 t
->table_size
= table_size
;
85 t
->next_ptr_offset
= next_ptr_offset
;
88 t
->compare_func
= compare_func
;
89 t
->hash_func
= hash_func
;
91 TRACE(("hash_init: created table %p, next_ptr_offset %d, compare_func %p, hash_func %p\n",
92 t
, next_ptr_offset
, compare_func
, hash_func
));
99 hash_uninit(struct hash_table
*table
)
101 ASSERT(table
->num_elements
== 0);
111 hash_insert(struct hash_table
*table
, void *element
)
115 ASSERT(table
!= NULL
&& element
!= NULL
);
116 TRACE(("hash_insert: table 0x%x, element 0x%x\n", table
, element
));
118 hash
= table
->hash_func(element
, NULL
, table
->table_size
);
119 PUT_IN_NEXT(table
, element
, table
->table
[hash
]);
120 table
->table
[hash
] = (struct hash_element
*)element
;
121 table
->num_elements
++;
123 // ToDo: resize hash table if it's grown too much!
130 hash_remove(struct hash_table
*table
, void *_element
)
132 uint32_t hash
= table
->hash_func(_element
, NULL
, table
->table_size
);
133 void *element
, *lastElement
= NULL
;
135 for (element
= table
->table
[hash
]; element
!= NULL
;
136 lastElement
= element
, element
= NEXT(table
, element
)) {
137 if (element
== _element
) {
138 if (lastElement
!= NULL
) {
139 // connect the previous entry with the next one
140 PUT_IN_NEXT(table
, lastElement
, NEXT(table
, element
));
142 table
->table
[hash
] = (struct hash_element
*)NEXT(table
, element
);
143 table
->num_elements
--;
154 hash_remove_current(struct hash_table
*table
, struct hash_iterator
*iterator
)
156 uint32_t index
= iterator
->bucket
;
159 if (iterator
->current
== NULL
)
160 fssh_panic("hash_remove_current() called too early.");
162 for (element
= table
->table
[index
]; index
< table
->table_size
; index
++) {
163 void *lastElement
= NULL
;
165 while (element
!= NULL
) {
166 if (element
== iterator
->current
) {
167 iterator
->current
= lastElement
;
169 if (lastElement
!= NULL
) {
170 // connect the previous entry with the next one
171 PUT_IN_NEXT(table
, lastElement
, NEXT(table
, element
));
173 table
->table
[index
] = (struct hash_element
*)NEXT(table
,
177 table
->num_elements
--;
181 element
= NEXT(table
, element
);
188 hash_remove_first(struct hash_table
*table
, uint32_t *_cookie
)
192 for (index
= _cookie
? *_cookie
: 0; index
< table
->table_size
; index
++) {
193 void *element
= table
->table
[index
];
194 if (element
!= NULL
) {
195 // remove the first element we find
196 table
->table
[index
] = (struct hash_element
*)NEXT(table
, element
);
197 table
->num_elements
--;
209 hash_find(struct hash_table
*table
, void *searchedElement
)
211 uint32_t hash
= table
->hash_func(searchedElement
, NULL
, table
->table_size
);
214 for (element
= table
->table
[hash
]; element
!= NULL
; element
= NEXT(table
, element
)) {
215 if (element
== searchedElement
)
224 hash_lookup(struct hash_table
*table
, const void *key
)
226 uint32_t hash
= table
->hash_func(NULL
, key
, table
->table_size
);
229 for (element
= table
->table
[hash
]; element
!= NULL
; element
= NEXT(table
, element
)) {
230 if (table
->compare_func(element
, key
) == 0)
238 struct hash_iterator
*
239 hash_open(struct hash_table
*table
, struct hash_iterator
*iterator
)
241 if (iterator
== NULL
) {
242 iterator
= (struct hash_iterator
*)malloc(sizeof(struct hash_iterator
));
243 if (iterator
== NULL
)
247 hash_rewind(table
, iterator
);
254 hash_close(struct hash_table
*table
, struct hash_iterator
*iterator
, bool freeIterator
)
262 hash_rewind(struct hash_table
*table
, struct hash_iterator
*iterator
)
264 iterator
->current
= NULL
;
265 iterator
->bucket
= -1;
270 hash_next(struct hash_table
*table
, struct hash_iterator
*iterator
)
275 if (iterator
->current
== NULL
) {
277 for (index
= (uint32_t)(iterator
->bucket
+ 1); index
< table
->table_size
; index
++) {
278 if (table
->table
[index
]) {
279 iterator
->bucket
= index
;
280 iterator
->current
= table
->table
[index
];
285 iterator
->current
= NEXT(table
, iterator
->current
);
286 if (!iterator
->current
)
290 return iterator
->current
;
295 hash_hash_string(const char *string
)
300 // we assume hash to be at least 32 bits
301 while ((c
= *string
++) != 0) {
310 } // namespace FSShell