00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00041 #include "pipe/p_compiler.h"
00042 #include "pipe/p_debug.h"
00043
00044 #include "cso_cache/cso_hash.h"
00045
00046 #include "util/u_memory.h"
00047 #include "util/u_hash_table.h"
00048
00049
00050 struct hash_table
00051 {
00052 struct cso_hash *cso;
00053
00055 unsigned (*hash)(void *key);
00056
00058 int (*compare)(void *key1, void *key2);
00059
00060
00061 };
00062
00063
00064 struct hash_table_item
00065 {
00066 void *key;
00067 void *value;
00068 };
00069
00070
00071 static INLINE struct hash_table_item *
00072 hash_table_item(struct cso_hash_iter iter)
00073 {
00074 return (struct hash_table_item *)cso_hash_iter_data(iter);
00075 }
00076
00077
00078 struct hash_table *
00079 hash_table_create(unsigned (*hash)(void *key),
00080 int (*compare)(void *key1, void *key2))
00081 {
00082 struct hash_table *ht;
00083
00084 ht = MALLOC_STRUCT(hash_table);
00085 if(!ht)
00086 return NULL;
00087
00088 ht->cso = cso_hash_create();
00089 if(!ht->cso) {
00090 FREE(ht);
00091 return NULL;
00092 }
00093
00094 ht->hash = hash;
00095 ht->compare = compare;
00096
00097 return ht;
00098 }
00099
00100
00101 static INLINE struct cso_hash_iter
00102 hash_table_find_iter(struct hash_table *ht,
00103 void *key,
00104 unsigned key_hash)
00105 {
00106 struct cso_hash_iter iter;
00107 struct hash_table_item *item;
00108
00109 iter = cso_hash_find(ht->cso, key_hash);
00110 while (!cso_hash_iter_is_null(iter)) {
00111 item = (struct hash_table_item *)cso_hash_iter_data(iter);
00112 if (!ht->compare(item->key, key))
00113 break;
00114 iter = cso_hash_iter_next(iter);
00115 }
00116
00117 return iter;
00118 }
00119
00120
00121 static INLINE struct hash_table_item *
00122 hash_table_find_item(struct hash_table *ht,
00123 void *key,
00124 unsigned key_hash)
00125 {
00126 struct cso_hash_iter iter;
00127 struct hash_table_item *item;
00128
00129 iter = cso_hash_find(ht->cso, key_hash);
00130 while (!cso_hash_iter_is_null(iter)) {
00131 item = (struct hash_table_item *)cso_hash_iter_data(iter);
00132 if (!ht->compare(item->key, key))
00133 return item;
00134 iter = cso_hash_iter_next(iter);
00135 }
00136
00137 return NULL;
00138 }
00139
00140
00141 enum pipe_error
00142 hash_table_set(struct hash_table *ht,
00143 void *key,
00144 void *value)
00145 {
00146 unsigned key_hash;
00147 struct hash_table_item *item;
00148 struct cso_hash_iter iter;
00149
00150 assert(ht);
00151
00152 key_hash = ht->hash(key);
00153
00154 item = hash_table_find_item(ht, key, key_hash);
00155 if(item) {
00156
00157 item->value = value;
00158 return PIPE_OK;
00159 }
00160
00161 item = MALLOC_STRUCT(hash_table_item);
00162 if(!item)
00163 return PIPE_ERROR_OUT_OF_MEMORY;
00164
00165 item->key = key;
00166 item->value = value;
00167
00168 iter = cso_hash_insert(ht->cso, key_hash, item);
00169 if(cso_hash_iter_is_null(iter)) {
00170 FREE(item);
00171 return PIPE_ERROR_OUT_OF_MEMORY;
00172 }
00173
00174 return PIPE_OK;
00175 }
00176
00177
00178 void *
00179 hash_table_get(struct hash_table *ht,
00180 void *key)
00181 {
00182 unsigned key_hash;
00183 struct hash_table_item *item;
00184
00185 assert(ht);
00186
00187 key_hash = ht->hash(key);
00188
00189 item = hash_table_find_item(ht, key, key_hash);
00190 if(!item)
00191 return NULL;
00192
00193 return item->value;
00194 }
00195
00196
00197 void
00198 hash_table_remove(struct hash_table *ht,
00199 void *key)
00200 {
00201 unsigned key_hash;
00202 struct cso_hash_iter iter;
00203 struct hash_table_item *item;
00204
00205 assert(ht);
00206
00207 key_hash = ht->hash(key);
00208
00209 iter = hash_table_find_iter(ht, key, key_hash);
00210 if(cso_hash_iter_is_null(iter))
00211 return;
00212
00213 item = hash_table_item(iter);
00214 assert(item);
00215 FREE(item);
00216
00217 cso_hash_erase(ht->cso, iter);
00218 }
00219
00220
00221 void
00222 hash_table_clear(struct hash_table *ht)
00223 {
00224 struct cso_hash_iter iter;
00225 struct hash_table_item *item;
00226
00227 assert(ht);
00228
00229 iter = cso_hash_first_node(ht->cso);
00230 while (!cso_hash_iter_is_null(iter)) {
00231 item = (struct hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter));
00232 FREE(item);
00233 iter = cso_hash_first_node(ht->cso);
00234 }
00235 }
00236
00237
00238 enum pipe_error
00239 hash_table_foreach(struct hash_table *ht,
00240 enum pipe_error (*callback)(void *key, void *value, void *data),
00241 void *data)
00242 {
00243 struct cso_hash_iter iter;
00244 struct hash_table_item *item;
00245 enum pipe_error result;
00246
00247 assert(ht);
00248
00249 iter = cso_hash_first_node(ht->cso);
00250 while (!cso_hash_iter_is_null(iter)) {
00251 item = (struct hash_table_item *)cso_hash_iter_data(iter);
00252 result = callback(item->key, item->value, data);
00253 if(result != PIPE_OK)
00254 return result;
00255 iter = cso_hash_iter_next(iter);
00256 }
00257
00258 return PIPE_OK;
00259 }
00260
00261
00262 void
00263 hash_table_destroy(struct hash_table *ht)
00264 {
00265 struct cso_hash_iter iter;
00266 struct hash_table_item *item;
00267
00268 assert(ht);
00269
00270 iter = cso_hash_first_node(ht->cso);
00271 while (!cso_hash_iter_is_null(iter)) {
00272 item = (struct hash_table_item *)cso_hash_iter_data(iter);
00273 FREE(item);
00274 iter = cso_hash_iter_next(iter);
00275 }
00276
00277 cso_hash_delete(ht->cso);
00278
00279 FREE(ht);
00280 }