00001 /* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */ 00002 /* 00003 * Copyright (c) 2002, Christopher Clark 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * * Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the distribution. 00016 * 00017 * * Neither the name of the original author; nor the names of any contributors 00018 * may be used to endorse or promote products derived from this software 00019 * without specific prior written permission. 00020 * 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00025 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00026 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00027 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00028 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00029 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00030 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00031 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 00035 #ifndef __HASHTABLE_CWC22_H__ 00036 #define __HASHTABLE_CWC22_H__ 00037 00038 struct hashtable; 00039 00040 /* Example of use: 00041 * 00042 * struct hashtable *h; 00043 * struct some_key *k; 00044 * struct some_value *v; 00045 * 00046 * static unsigned int hash_from_key_fn( void *k ); 00047 * static int keys_equal_fn ( void *key1, void *key2 ); 00048 * 00049 * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); 00050 * k = (struct some_key *) MALLOC(sizeof(struct some_key)); 00051 * v = (struct some_value *) MALLOC(sizeof(struct some_value)); 00052 * 00053 * (initialise k and v to suitable values) 00054 * 00055 * if (! hashtable_insert(h,k,v) ) 00056 * { exit(-1); } 00057 * 00058 * if (NULL == (found = hashtable_search(h,k) )) 00059 * { printf("not found!"); } 00060 * 00061 * if (NULL == (found = hashtable_remove(h,k) )) 00062 * { printf("Not found\n"); } 00063 * 00064 */ 00065 00066 /* Macros may be used to define type-safe(r) hashtable access functions, with 00067 * methods specialized to take known key and value types as parameters. 00068 * 00069 * Example: 00070 * 00071 * Insert this at the start of your file: 00072 * 00073 * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); 00074 * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); 00075 * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); 00076 * 00077 * This defines the functions 'insert_some', 'search_some' and 'remove_some'. 00078 * These operate just like hashtable_insert etc., with the same parameters, 00079 * but their function signatures have 'struct some_key *' rather than 00080 * 'void *', and hence can generate compile time errors if your program is 00081 * supplying incorrect data as a key (and similarly for value). 00082 * 00083 * Note that the hash and key equality functions passed to create_hashtable 00084 * still take 'void *' parameters instead of 'some key *'. This shouldn't be 00085 * a difficult issue as they're only defined and passed once, and the other 00086 * functions will ensure that only valid keys are supplied to them. 00087 * 00088 * The cost for this checking is increased code size and runtime overhead 00089 * - if performance is important, it may be worth switching back to the 00090 * unsafe methods once your program has been debugged with the safe methods. 00091 * This just requires switching to some simple alternative defines - eg: 00092 * #define insert_some hashtable_insert 00093 * 00094 */ 00095 00096 /***************************************************************************** 00097 * create_hashtable 00098 00099 * @name create_hashtable 00100 * @param minsize minimum initial size of hashtable 00101 * @param hashfunction function for hashing keys 00102 * @param key_eq_fn function for determining key equality 00103 * @return newly created hashtable or NULL on failure 00104 */ 00105 00106 struct hashtable * 00107 create_hashtable(unsigned int minsize, 00108 unsigned int (*hashfunction) (void*), 00109 int (*key_eq_fn) (void*,void*)); 00110 00111 /***************************************************************************** 00112 * hashtable_insert 00113 00114 * @name hashtable_insert 00115 * @param h the hashtable to insert into 00116 * @param k the key - hashtable claims ownership and will free on removal 00117 * @param v the value - does not claim ownership 00118 * @return non-zero for successful insertion 00119 * 00120 * This function will cause the table to expand if the insertion would take 00121 * the ratio of entries to table size over the maximum load factor. 00122 * 00123 * This function does not check for repeated insertions with a duplicate key. 00124 * The value returned when using a duplicate key is undefined -- when 00125 * the hashtable changes size, the order of retrieval of duplicate key 00126 * entries is reversed. 00127 * If in doubt, remove before insert. 00128 */ 00129 00130 int hashtable_insert(struct hashtable *h, void *k, void *v); 00131 00132 #define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ 00133 int fnname (struct hashtable *h, keytype *k, valuetype *v) \ 00134 { \ 00135 return hashtable_insert(h,k,v); \ 00136 } 00137 00138 /***************************************************************************** 00139 * hashtable_search 00140 00141 * @name hashtable_search 00142 * @param h the hashtable to search 00143 * @param k the key to search for - does not claim ownership 00144 * @return the value associated with the key, or NULL if none found 00145 */ 00146 00147 void * 00148 hashtable_search(struct hashtable *h, void *k); 00149 00150 #define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ 00151 valuetype * fnname (struct hashtable *h, keytype *k) \ 00152 { \ 00153 return (valuetype *) (hashtable_search(h,k)); \ 00154 } 00155 00156 /***************************************************************************** 00157 * hashtable_remove 00158 00159 * @name hashtable_remove 00160 * @param h the hashtable to remove the item from 00161 * @param k the key to search for - does not claim ownership 00162 * @return the value associated with the key, or NULL if none found 00163 */ 00164 00165 void * /* returns value */ 00166 hashtable_remove(struct hashtable *h, void *k); 00167 00168 #define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ 00169 valuetype * fnname (struct hashtable *h, keytype *k) \ 00170 { \ 00171 return (valuetype *) (hashtable_remove(h,k)); \ 00172 } 00173 00174 00175 /***************************************************************************** 00176 * hashtable_count 00177 00178 * @name hashtable_count 00179 * @param h the hashtable 00180 * @return the number of items stored in the hashtable 00181 */ 00182 unsigned int hashtable_count(struct hashtable *h); 00183 00184 00185 /***************************************************************************** 00186 * hashtable_destroy 00187 00188 * @name hashtable_destroy 00189 * @param h the hashtable 00190 * @param free_values whether to call 'free' on the remaining values 00191 */ 00192 00193 void hashtable_destroy(struct hashtable *h, int free_values); 00194 00195 #endif /* __HASHTABLE_CWC22_H__ */ 00196
1.5.1