u_hash_table.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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    /* TODO: key, value destructors? */
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       /* TODO: key/value destruction? */
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 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4