| OLD | NEW |
| 1 =pod | 1 =pod |
| 2 | 2 |
| 3 =head1 NAME | 3 =head1 NAME |
| 4 | 4 |
| 5 lh_new, lh_free, lh_insert, lh_delete, lh_retrieve, lh_doall, lh_doall_arg, lh_e
rror - dynamic hash table | 5 lh_new, lh_free, lh_insert, lh_delete, lh_retrieve, lh_doall, lh_doall_arg, lh_e
rror - dynamic hash table |
| 6 | 6 |
| 7 =head1 SYNOPSIS | 7 =head1 SYNOPSIS |
| 8 | 8 |
| 9 #include <openssl/lhash.h> | 9 #include <openssl/lhash.h> |
| 10 | 10 |
| 11 LHASH *lh_new(LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE compare); | 11 DECLARE_LHASH_OF(<type>); |
| 12 void lh_free(LHASH *table); | |
| 13 | 12 |
| 14 void *lh_insert(LHASH *table, void *data); | 13 LHASH *lh_<type>_new(); |
| 15 void *lh_delete(LHASH *table, void *data); | 14 void lh_<type>_free(LHASH_OF(<type> *table); |
| 16 void *lh_retrieve(LHASH *table, void *data); | |
| 17 | 15 |
| 18 void lh_doall(LHASH *table, LHASH_DOALL_FN_TYPE func); | 16 <type> *lh_<type>_insert(LHASH_OF(<type> *table, <type> *data); |
| 19 void lh_doall_arg(LHASH *table, LHASH_DOALL_ARG_FN_TYPE func, | 17 <type> *lh_<type>_delete(LHASH_OF(<type> *table, <type> *data); |
| 20 void *arg); | 18 <type> *lh_retrieve(LHASH_OF<type> *table, <type> *data); |
| 21 | 19 |
| 22 int lh_error(LHASH *table); | 20 void lh_<type>_doall(LHASH_OF(<type> *table, LHASH_DOALL_FN_TYPE func); |
| 21 void lh_<type>_doall_arg(LHASH_OF(<type> *table, LHASH_DOALL_ARG_FN_TYPE func, |
| 22 <type2>, <type2> *arg); |
| 23 |
| 24 int lh_<type>_error(LHASH_OF(<type> *table); |
| 23 | 25 |
| 24 typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *); | 26 typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *); |
| 25 typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *); | 27 typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *); |
| 26 typedef void (*LHASH_DOALL_FN_TYPE)(const void *); | 28 typedef void (*LHASH_DOALL_FN_TYPE)(const void *); |
| 27 typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, const void *); | 29 typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, const void *); |
| 28 | 30 |
| 29 =head1 DESCRIPTION | 31 =head1 DESCRIPTION |
| 30 | 32 |
| 31 This library implements dynamic hash tables. The hash table entries | 33 This library implements type-checked dynamic hash tables. The hash |
| 32 can be arbitrary structures. Usually they consist of key and value | 34 table entries can be arbitrary structures. Usually they consist of key |
| 33 fields. | 35 and value fields. |
| 34 | 36 |
| 35 lh_new() creates a new B<LHASH> structure to store arbitrary data | 37 lh_<type>_new() creates a new B<LHASH_OF(<type>> structure to store |
| 36 entries, and provides the 'hash' and 'compare' callbacks to be used in | 38 arbitrary data entries, and provides the 'hash' and 'compare' |
| 37 organising the table's entries. The B<hash> callback takes a pointer | 39 callbacks to be used in organising the table's entries. The B<hash> |
| 38 to a table entry as its argument and returns an unsigned long hash | 40 callback takes a pointer to a table entry as its argument and returns |
| 39 value for its key field. The hash value is normally truncated to a | 41 an unsigned long hash value for its key field. The hash value is |
| 40 power of 2, so make sure that your hash function returns well mixed | 42 normally truncated to a power of 2, so make sure that your hash |
| 41 low order bits. The B<compare> callback takes two arguments (pointers | 43 function returns well mixed low order bits. The B<compare> callback |
| 42 to two hash table entries), and returns 0 if their keys are equal, | 44 takes two arguments (pointers to two hash table entries), and returns |
| 43 non-zero otherwise. If your hash table will contain items of some | 45 0 if their keys are equal, non-zero otherwise. If your hash table |
| 44 particular type and the B<hash> and B<compare> callbacks hash/compare | 46 will contain items of some particular type and the B<hash> and |
| 45 these types, then the B<DECLARE_LHASH_HASH_FN> and | 47 B<compare> callbacks hash/compare these types, then the |
| 46 B<IMPLEMENT_LHASH_COMP_FN> macros can be used to create callback | 48 B<DECLARE_LHASH_HASH_FN> and B<IMPLEMENT_LHASH_COMP_FN> macros can be |
| 47 wrappers of the prototypes required by lh_new(). These provide | 49 used to create callback wrappers of the prototypes required by |
| 48 per-variable casts before calling the type-specific callbacks written | 50 lh_<type>_new(). These provide per-variable casts before calling the |
| 49 by the application author. These macros, as well as those used for | 51 type-specific callbacks written by the application author. These |
| 50 the "doall" callbacks, are defined as; | 52 macros, as well as those used for the "doall" callbacks, are defined |
| 53 as; |
| 51 | 54 |
| 52 #define DECLARE_LHASH_HASH_FN(f_name,o_type) \ | 55 #define DECLARE_LHASH_HASH_FN(name, o_type) \ |
| 53 unsigned long f_name##_LHASH_HASH(const void *); | 56 » unsigned long name##_LHASH_HASH(const void *); |
| 54 #define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \ | 57 #define IMPLEMENT_LHASH_HASH_FN(name, o_type) \ |
| 55 unsigned long f_name##_LHASH_HASH(const void *arg) { \ | 58 » unsigned long name##_LHASH_HASH(const void *arg) { \ |
| 56 o_type a = (o_type)arg; \ | 59 » » const o_type *a = arg; \ |
| 57 return f_name(a); } | 60 » » return name##_hash(a); } |
| 58 #define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH | 61 #define LHASH_HASH_FN(name) name##_LHASH_HASH |
| 59 | 62 |
| 60 #define DECLARE_LHASH_COMP_FN(f_name,o_type) \ | 63 #define DECLARE_LHASH_COMP_FN(name, o_type) \ |
| 61 int f_name##_LHASH_COMP(const void *, const void *); | 64 » int name##_LHASH_COMP(const void *, const void *); |
| 62 #define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \ | 65 #define IMPLEMENT_LHASH_COMP_FN(name, o_type) \ |
| 63 int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \ | 66 » int name##_LHASH_COMP(const void *arg1, const void *arg2) { \ |
| 64 o_type a = (o_type)arg1; \ | 67 » » const o_type *a = arg1;» » \ |
| 65 o_type b = (o_type)arg2; \ | 68 » » const o_type *b = arg2; \ |
| 66 return f_name(a,b); } | 69 » » return name##_cmp(a,b); } |
| 67 #define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP | 70 #define LHASH_COMP_FN(name) name##_LHASH_COMP |
| 68 | 71 |
| 69 #define DECLARE_LHASH_DOALL_FN(f_name,o_type) \ | 72 #define DECLARE_LHASH_DOALL_FN(name, o_type) \ |
| 70 void f_name##_LHASH_DOALL(const void *); | 73 » void name##_LHASH_DOALL(void *); |
| 71 #define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \ | 74 #define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \ |
| 72 void f_name##_LHASH_DOALL(const void *arg) { \ | 75 » void name##_LHASH_DOALL(void *arg) { \ |
| 73 o_type a = (o_type)arg; \ | 76 » » o_type *a = arg; \ |
| 74 f_name(a); } | 77 » » name##_doall(a); } |
| 75 #define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL | 78 #define LHASH_DOALL_FN(name) name##_LHASH_DOALL |
| 76 | 79 |
| 77 #define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \ | 80 #define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ |
| 78 void f_name##_LHASH_DOALL_ARG(const void *, const void *); | 81 » void name##_LHASH_DOALL_ARG(void *, void *); |
| 79 #define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \ | 82 #define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ |
| 80 void f_name##_LHASH_DOALL_ARG(const void *arg1, const void *arg2) { \ | 83 » void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ |
| 81 o_type a = (o_type)arg1; \ | 84 » » o_type *a = arg1; \ |
| 82 a_type b = (a_type)arg2; \ | 85 » » a_type *b = arg2; \ |
| 83 f_name(a,b); } | 86 » » name##_doall_arg(a, b); } |
| 84 #define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG | 87 #define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG |
| 85 | 88 |
| 86 An example of a hash table storing (pointers to) structures of type 'STUFF' | 89 An example of a hash table storing (pointers to) structures of type 'STUFF' |
| 87 could be defined as follows; | 90 could be defined as follows; |
| 88 | 91 |
| 89 /* Calculates the hash value of 'tohash' (implemented elsewhere) */ | 92 /* Calculates the hash value of 'tohash' (implemented elsewhere) */ |
| 90 unsigned long STUFF_hash(const STUFF *tohash); | 93 unsigned long STUFF_hash(const STUFF *tohash); |
| 91 /* Orders 'arg1' and 'arg2' (implemented elsewhere) */ | 94 /* Orders 'arg1' and 'arg2' (implemented elsewhere) */ |
| 92 int STUFF_cmp(const STUFF *arg1, const STUFF *arg2); | 95 int stuff_cmp(const STUFF *arg1, const STUFF *arg2); |
| 93 /* Create the type-safe wrapper functions for use in the LHASH internals */ | 96 /* Create the type-safe wrapper functions for use in the LHASH internals */ |
| 94 static IMPLEMENT_LHASH_HASH_FN(STUFF_hash, const STUFF *) | 97 static IMPLEMENT_LHASH_HASH_FN(stuff, STUFF); |
| 95 static IMPLEMENT_LHASH_COMP_FN(STUFF_cmp, const STUFF *); | 98 static IMPLEMENT_LHASH_COMP_FN(stuff, STUFF); |
| 96 /* ... */ | 99 /* ... */ |
| 97 int main(int argc, char *argv[]) { | 100 int main(int argc, char *argv[]) { |
| 98 /* Create the new hash table using the hash/compare wrappers */ | 101 /* Create the new hash table using the hash/compare wrappers */ |
| 99 LHASH *hashtable = lh_new(LHASH_HASH_FN(STUFF_hash), | 102 LHASH_OF(STUFF) *hashtable = lh_STUFF_new(LHASH_HASH_FN(STUFF_hash), |
| 100 LHASH_COMP_FN(STUFF_cmp)); | 103 LHASH_COMP_FN(STUFF_cmp)); |
| 101 /* ... */ | 104 /* ... */ |
| 102 } | 105 } |
| 103 | 106 |
| 104 lh_free() frees the B<LHASH> structure B<table>. Allocated hash table | 107 lh_<type>_free() frees the B<LHASH_OF(<type>> structure |
| 105 entries will not be freed; consider using lh_doall() to deallocate any | 108 B<table>. Allocated hash table entries will not be freed; consider |
| 106 remaining entries in the hash table (see below). | 109 using lh_<type>_doall() to deallocate any remaining entries in the |
| 110 hash table (see below). |
| 107 | 111 |
| 108 lh_insert() inserts the structure pointed to by B<data> into B<table>. | 112 lh_<type>_insert() inserts the structure pointed to by B<data> into |
| 109 If there already is an entry with the same key, the old value is | 113 B<table>. If there already is an entry with the same key, the old |
| 110 replaced. Note that lh_insert() stores pointers, the data are not | 114 value is replaced. Note that lh_<type>_insert() stores pointers, the |
| 111 copied. | 115 data are not copied. |
| 112 | 116 |
| 113 lh_delete() deletes an entry from B<table>. | 117 lh_<type>_delete() deletes an entry from B<table>. |
| 114 | 118 |
| 115 lh_retrieve() looks up an entry in B<table>. Normally, B<data> is | 119 lh_<type>_retrieve() looks up an entry in B<table>. Normally, B<data> |
| 116 a structure with the key field(s) set; the function will return a | 120 is a structure with the key field(s) set; the function will return a |
| 117 pointer to a fully populated structure. | 121 pointer to a fully populated structure. |
| 118 | 122 |
| 119 lh_doall() will, for every entry in the hash table, call B<func> with | 123 lh_<type>_doall() will, for every entry in the hash table, call |
| 120 the data item as its parameter. For lh_doall() and lh_doall_arg(), | 124 B<func> with the data item as its parameter. For lh_<type>_doall() |
| 121 function pointer casting should be avoided in the callbacks (see | 125 and lh_<type>_doall_arg(), function pointer casting should be avoided |
| 122 B<NOTE>) - instead, either declare the callbacks to match the | 126 in the callbacks (see B<NOTE>) - instead use the declare/implement |
| 123 prototype required in lh_new() or use the declare/implement macros to | 127 macros to create type-checked wrappers that cast variables prior to |
| 124 create type-safe wrappers that cast variables prior to calling your | 128 calling your type-specific callbacks. An example of this is |
| 125 type-specific callbacks. An example of this is illustrated here where | 129 illustrated here where the callback is used to cleanup resources for |
| 126 the callback is used to cleanup resources for items in the hash table | 130 items in the hash table prior to the hashtable itself being |
| 127 prior to the hashtable itself being deallocated: | 131 deallocated: |
| 128 | 132 |
| 129 /* Cleans up resources belonging to 'a' (this is implemented elsewhere) */ | 133 /* Cleans up resources belonging to 'a' (this is implemented elsewhere) */ |
| 130 void STUFF_cleanup(STUFF *a); | 134 void STUFF_cleanup_doall(STUFF *a); |
| 131 /* Implement a prototype-compatible wrapper for "STUFF_cleanup" */ | 135 /* Implement a prototype-compatible wrapper for "STUFF_cleanup" */ |
| 132 IMPLEMENT_LHASH_DOALL_FN(STUFF_cleanup, STUFF *) | 136 IMPLEMENT_LHASH_DOALL_FN(STUFF_cleanup, STUFF) |
| 133 /* ... then later in the code ... */ | 137 /* ... then later in the code ... */ |
| 134 /* So to run "STUFF_cleanup" against all items in a hash table ... */ | 138 /* So to run "STUFF_cleanup" against all items in a hash table ... */ |
| 135 lh_doall(hashtable, LHASH_DOALL_FN(STUFF_cleanup)); | 139 lh_STUFF_doall(hashtable, LHASH_DOALL_FN(STUFF_cleanup)); |
| 136 /* Then the hash table itself can be deallocated */ | 140 /* Then the hash table itself can be deallocated */ |
| 137 lh_free(hashtable); | 141 lh_STUFF_free(hashtable); |
| 138 | 142 |
| 139 When doing this, be careful if you delete entries from the hash table | 143 When doing this, be careful if you delete entries from the hash table |
| 140 in your callbacks: the table may decrease in size, moving the item | 144 in your callbacks: the table may decrease in size, moving the item |
| 141 that you are currently on down lower in the hash table - this could | 145 that you are currently on down lower in the hash table - this could |
| 142 cause some entries to be skipped during the iteration. The second | 146 cause some entries to be skipped during the iteration. The second |
| 143 best solution to this problem is to set hash-E<gt>down_load=0 before | 147 best solution to this problem is to set hash-E<gt>down_load=0 before |
| 144 you start (which will stop the hash table ever decreasing in size). | 148 you start (which will stop the hash table ever decreasing in size). |
| 145 The best solution is probably to avoid deleting items from the hash | 149 The best solution is probably to avoid deleting items from the hash |
| 146 table inside a "doall" callback! | 150 table inside a "doall" callback! |
| 147 | 151 |
| 148 lh_doall_arg() is the same as lh_doall() except that B<func> will be | 152 lh_<type>_doall_arg() is the same as lh_<type>_doall() except that |
| 149 called with B<arg> as the second argument and B<func> should be of | 153 B<func> will be called with B<arg> as the second argument and B<func> |
| 150 type B<LHASH_DOALL_ARG_FN_TYPE> (a callback prototype that is passed | 154 should be of type B<LHASH_DOALL_ARG_FN_TYPE> (a callback prototype |
| 151 both the table entry and an extra argument). As with lh_doall(), you | 155 that is passed both the table entry and an extra argument). As with |
| 152 can instead choose to declare your callback with a prototype matching | 156 lh_doall(), you can instead choose to declare your callback with a |
| 153 the types you are dealing with and use the declare/implement macros to | 157 prototype matching the types you are dealing with and use the |
| 154 create compatible wrappers that cast variables before calling your | 158 declare/implement macros to create compatible wrappers that cast |
| 155 type-specific callbacks. An example of this is demonstrated here | 159 variables before calling your type-specific callbacks. An example of |
| 156 (printing all hash table entries to a BIO that is provided by the | 160 this is demonstrated here (printing all hash table entries to a BIO |
| 157 caller): | 161 that is provided by the caller): |
| 158 | 162 |
| 159 /* Prints item 'a' to 'output_bio' (this is implemented elsewhere) */ | 163 /* Prints item 'a' to 'output_bio' (this is implemented elsewhere) */ |
| 160 void STUFF_print(const STUFF *a, BIO *output_bio); | 164 void STUFF_print_doall_arg(const STUFF *a, BIO *output_bio); |
| 161 /* Implement a prototype-compatible wrapper for "STUFF_print" */ | 165 /* Implement a prototype-compatible wrapper for "STUFF_print" */ |
| 162 static IMPLEMENT_LHASH_DOALL_ARG_FN(STUFF_print, const STUFF *, BIO *) | 166 static IMPLEMENT_LHASH_DOALL_ARG_FN(STUFF, const STUFF, BIO) |
| 163 /* ... then later in the code ... */ | 167 /* ... then later in the code ... */ |
| 164 /* Print out the entire hashtable to a particular BIO */ | 168 /* Print out the entire hashtable to a particular BIO */ |
| 165 lh_doall_arg(hashtable, LHASH_DOALL_ARG_FN(STUFF_print), logging_bio); | 169 lh_STUFF_doall_arg(hashtable, LHASH_DOALL_ARG_FN(STUFF_print), BIO, |
| 170 logging_bio); |
| 166 | 171 |
| 167 lh_error() can be used to determine if an error occurred in the last | 172 lh_<type>_error() can be used to determine if an error occurred in the last |
| 168 operation. lh_error() is a macro. | 173 operation. lh_<type>_error() is a macro. |
| 169 | 174 |
| 170 =head1 RETURN VALUES | 175 =head1 RETURN VALUES |
| 171 | 176 |
| 172 lh_new() returns B<NULL> on error, otherwise a pointer to the new | 177 lh_<type>_new() returns B<NULL> on error, otherwise a pointer to the new |
| 173 B<LHASH> structure. | 178 B<LHASH> structure. |
| 174 | 179 |
| 175 When a hash table entry is replaced, lh_insert() returns the value | 180 When a hash table entry is replaced, lh_<type>_insert() returns the value |
| 176 being replaced. B<NULL> is returned on normal operation and on error. | 181 being replaced. B<NULL> is returned on normal operation and on error. |
| 177 | 182 |
| 178 lh_delete() returns the entry being deleted. B<NULL> is returned if | 183 lh_<type>_delete() returns the entry being deleted. B<NULL> is returned if |
| 179 there is no such value in the hash table. | 184 there is no such value in the hash table. |
| 180 | 185 |
| 181 lh_retrieve() returns the hash table entry if it has been found, | 186 lh_<type>_retrieve() returns the hash table entry if it has been found, |
| 182 B<NULL> otherwise. | 187 B<NULL> otherwise. |
| 183 | 188 |
| 184 lh_error() returns 1 if an error occurred in the last operation, 0 | 189 lh_<type>_error() returns 1 if an error occurred in the last operation, 0 |
| 185 otherwise. | 190 otherwise. |
| 186 | 191 |
| 187 lh_free(), lh_doall() and lh_doall_arg() return no values. | 192 lh_<type>_free(), lh_<type>_doall() and lh_<type>_doall_arg() return no values. |
| 188 | 193 |
| 189 =head1 NOTE | 194 =head1 NOTE |
| 190 | 195 |
| 191 The various LHASH macros and callback types exist to make it possible | 196 The various LHASH macros and callback types exist to make it possible |
| 192 to write type-safe code without resorting to function-prototype | 197 to write type-checked code without resorting to function-prototype |
| 193 casting - an evil that makes application code much harder to | 198 casting - an evil that makes application code much harder to |
| 194 audit/verify and also opens the window of opportunity for stack | 199 audit/verify and also opens the window of opportunity for stack |
| 195 corruption and other hard-to-find bugs. It also, apparently, violates | 200 corruption and other hard-to-find bugs. It also, apparently, violates |
| 196 ANSI-C. | 201 ANSI-C. |
| 197 | 202 |
| 198 The LHASH code regards table entries as constant data. As such, it | 203 The LHASH code regards table entries as constant data. As such, it |
| 199 internally represents lh_insert()'d items with a "const void *" | 204 internally represents lh_insert()'d items with a "const void *" |
| 200 pointer type. This is why callbacks such as those used by lh_doall() | 205 pointer type. This is why callbacks such as those used by lh_doall() |
| 201 and lh_doall_arg() declare their prototypes with "const", even for the | 206 and lh_doall_arg() declare their prototypes with "const", even for the |
| 202 parameters that pass back the table items' data pointers - for | 207 parameters that pass back the table items' data pointers - for |
| (...skipping 17 matching lines...) Expand all Loading... |
| 220 Callers that only have "const" access to data they're indexing in a | 225 Callers that only have "const" access to data they're indexing in a |
| 221 table, yet declare callbacks without constant types (or cast the | 226 table, yet declare callbacks without constant types (or cast the |
| 222 "const" away themselves), are therefore creating their own risks/bugs | 227 "const" away themselves), are therefore creating their own risks/bugs |
| 223 without being encouraged to do so by the API. On a related note, | 228 without being encouraged to do so by the API. On a related note, |
| 224 those auditing code should pay special attention to any instances of | 229 those auditing code should pay special attention to any instances of |
| 225 DECLARE/IMPLEMENT_LHASH_DOALL_[ARG_]_FN macros that provide types | 230 DECLARE/IMPLEMENT_LHASH_DOALL_[ARG_]_FN macros that provide types |
| 226 without any "const" qualifiers. | 231 without any "const" qualifiers. |
| 227 | 232 |
| 228 =head1 BUGS | 233 =head1 BUGS |
| 229 | 234 |
| 230 lh_insert() returns B<NULL> both for success and error. | 235 lh_<type>_insert() returns B<NULL> both for success and error. |
| 231 | 236 |
| 232 =head1 INTERNALS | 237 =head1 INTERNALS |
| 233 | 238 |
| 234 The following description is based on the SSLeay documentation: | 239 The following description is based on the SSLeay documentation: |
| 235 | 240 |
| 236 The B<lhash> library implements a hash table described in the | 241 The B<lhash> library implements a hash table described in the |
| 237 I<Communications of the ACM> in 1991. What makes this hash table | 242 I<Communications of the ACM> in 1991. What makes this hash table |
| 238 different is that as the table fills, the hash table is increased (or | 243 different is that as the table fills, the hash table is increased (or |
| 239 decreased) in size via OPENSSL_realloc(). When a 'resize' is done, instead of | 244 decreased) in size via OPENSSL_realloc(). When a 'resize' is done, instead of |
| 240 all hashes being redistributed over twice as many 'buckets', one | 245 all hashes being redistributed over twice as many 'buckets', one |
| (...skipping 24 matching lines...) Expand all Loading... |
| 265 probably worth changing your hash function if this is the case because | 270 probably worth changing your hash function if this is the case because |
| 266 even if your hash table has 10 items in a 'bucket', it can be searched | 271 even if your hash table has 10 items in a 'bucket', it can be searched |
| 267 with 10 B<unsigned long> compares and 10 linked list traverses. This | 272 with 10 B<unsigned long> compares and 10 linked list traverses. This |
| 268 will be much less expensive that 10 calls to your compare function. | 273 will be much less expensive that 10 calls to your compare function. |
| 269 | 274 |
| 270 lh_strhash() is a demo string hashing function: | 275 lh_strhash() is a demo string hashing function: |
| 271 | 276 |
| 272 unsigned long lh_strhash(const char *c); | 277 unsigned long lh_strhash(const char *c); |
| 273 | 278 |
| 274 Since the B<LHASH> routines would normally be passed structures, this | 279 Since the B<LHASH> routines would normally be passed structures, this |
| 275 routine would not normally be passed to lh_new(), rather it would be | 280 routine would not normally be passed to lh_<type>_new(), rather it would be |
| 276 used in the function passed to lh_new(). | 281 used in the function passed to lh_<type>_new(). |
| 277 | 282 |
| 278 =head1 SEE ALSO | 283 =head1 SEE ALSO |
| 279 | 284 |
| 280 L<lh_stats(3)|lh_stats(3)> | 285 L<lh_stats(3)|lh_stats(3)> |
| 281 | 286 |
| 282 =head1 HISTORY | 287 =head1 HISTORY |
| 283 | 288 |
| 284 The B<lhash> library is available in all versions of SSLeay and OpenSSL. | 289 The B<lhash> library is available in all versions of SSLeay and OpenSSL. |
| 285 lh_error() was added in SSLeay 0.9.1b. | 290 lh_error() was added in SSLeay 0.9.1b. |
| 286 | 291 |
| 287 This manpage is derived from the SSLeay documentation. | 292 This manpage is derived from the SSLeay documentation. |
| 288 | 293 |
| 289 In OpenSSL 0.9.7, all lhash functions that were passed function pointers | 294 In OpenSSL 0.9.7, all lhash functions that were passed function pointers |
| 290 were changed for better type safety, and the function types LHASH_COMP_FN_TYPE, | 295 were changed for better type safety, and the function types LHASH_COMP_FN_TYPE, |
| 291 LHASH_HASH_FN_TYPE, LHASH_DOALL_FN_TYPE and LHASH_DOALL_ARG_FN_TYPE | 296 LHASH_HASH_FN_TYPE, LHASH_DOALL_FN_TYPE and LHASH_DOALL_ARG_FN_TYPE |
| 292 became available. | 297 became available. |
| 293 | 298 |
| 299 In OpenSSL 1.0.0, the lhash interface was revamped for even better |
| 300 type checking. |
| 301 |
| 294 =cut | 302 =cut |
| OLD | NEW |