source: mainline/kernel/generic/src/adt/hash_table.c@ 1c85bae

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1c85bae was 1c85bae, checked in by Jakub Jermar <jakub@…>, 8 years ago

Add hash_table_remove_item()

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genericadt
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Implementation of generic chained hash table.
36 *
37 * This file contains implementation of generic chained hash table.
38 */
39
40#include <adt/hash_table.h>
41#include <adt/list.h>
42#include <assert.h>
43#include <typedefs.h>
44#include <mm/slab.h>
45#include <mem.h>
46
47/** Create chained hash table.
48 *
49 * @param h Hash table structure. Will be initialized by this call.
50 * @param m Number of slots in the hash table.
51 * @param max_keys Maximal number of keys needed to identify an item.
52 * @param op Hash table operations structure.
53 */
54void hash_table_create(hash_table_t *h, size_t m, size_t max_keys, hash_table_operations_t *op)
55{
56 size_t i;
57
58 assert(h);
59 assert(op);
60 assert(op->hash);
61 assert(op->compare);
62 assert(max_keys > 0);
63
64 h->entry = (list_t *) malloc(m * sizeof(list_t), 0);
65 if (!h->entry)
66 panic("Cannot allocate memory for hash table.");
67
68 memsetb(h->entry, m * sizeof(list_t), 0);
69
70 for (i = 0; i < m; i++)
71 list_initialize(&h->entry[i]);
72
73 h->entries = m;
74 h->max_keys = max_keys;
75 h->op = op;
76}
77
78/** Insert item into hash table.
79 *
80 * @param h Hash table.
81 * @param key Array of all keys necessary to compute hash index.
82 * @param item Item to be inserted into the hash table.
83 */
84void hash_table_insert(hash_table_t *h, sysarg_t key[], link_t *item)
85{
86 size_t chain;
87
88 assert(item);
89 assert(h);
90 assert(h->op);
91 assert(h->op->hash);
92 assert(h->op->compare);
93
94 chain = h->op->hash(key);
95 assert(chain < h->entries);
96
97 list_append(item, &h->entry[chain]);
98}
99
100/** Search hash table for an item matching keys.
101 *
102 * @param h Hash table.
103 * @param key Array of all keys needed to compute hash index.
104 *
105 * @return Matching item on success, NULL if there is no such item.
106 */
107link_t *hash_table_find(hash_table_t *h, sysarg_t key[])
108{
109 size_t chain;
110
111 assert(h);
112 assert(h->op);
113 assert(h->op->hash);
114 assert(h->op->compare);
115
116 chain = h->op->hash(key);
117 assert(chain < h->entries);
118
119 link_t *cur = list_first(&h->entry[chain]);
120 while (cur != NULL) {
121 if (h->op->compare(key, h->max_keys, cur)) {
122 /*
123 * The entry is there.
124 */
125 return cur;
126 }
127 cur = list_next(cur, &h->entry[chain]);
128 }
129
130 return NULL;
131}
132
133/** Remove all matching items from hash table.
134 *
135 * For each removed item, h->remove_callback() is called (if not NULL).
136 *
137 * @param h Hash table.
138 * @param key Array of keys that will be compared against items of the hash table.
139 * @param keys Number of keys in the key array.
140 */
141void hash_table_remove(hash_table_t *h, sysarg_t key[], size_t keys)
142{
143 size_t chain;
144
145 assert(h);
146 assert(h->op);
147 assert(h->op->hash);
148 assert(h->op->compare);
149 assert(keys <= h->max_keys);
150
151
152 if (keys == h->max_keys) {
153 link_t *cur;
154
155 /*
156 * All keys are known, hash_table_find() can be used to find the entry.
157 */
158
159 cur = hash_table_find(h, key);
160 if (cur) {
161 list_remove(cur);
162 if (h->op->remove_callback)
163 h->op->remove_callback(cur);
164 }
165 return;
166 }
167
168 /*
169 * Fewer keys were passed.
170 * Any partially matching entries are to be removed.
171 */
172 for (chain = 0; chain < h->entries; chain++) {
173 link_t *cur;
174 for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
175 cur = cur->next) {
176 if (h->op->compare(key, keys, cur)) {
177 link_t *hlp;
178
179 hlp = cur;
180 cur = cur->prev;
181
182 list_remove(hlp);
183 if (h->op->remove_callback)
184 h->op->remove_callback(hlp);
185
186 continue;
187 }
188 }
189 }
190}
191
192/** Remove an existing item from hash table.
193 *
194 * @param h Hash table.
195 * @param item Item to remove from the hash table.
196 */
197void hash_table_remove_item(hash_table_t *h, link_t *item)
198{
199 assert(h);
200 assert(h->op);
201
202 list_remove(item);
203 if (h->op->remove_callback)
204 h->op->remove_callback(item);
205}
206
207/** @}
208 */
Note: See TracBrowser for help on using the repository browser.