⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lhash.pod

📁 开源的ssl算法openssl,版本0.9.8H
💻 POD
字号:
=pod=head1 NAMElh_new, lh_free, lh_insert, lh_delete, lh_retrieve, lh_doall, lh_doall_arg, lh_error - dynamic hash table=head1 SYNOPSIS #include <openssl/lhash.h> LHASH *lh_new(LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE compare); void lh_free(LHASH *table); void *lh_insert(LHASH *table, void *data); void *lh_delete(LHASH *table, void *data); void *lh_retrieve(LHASH *table, void *data); void lh_doall(LHASH *table, LHASH_DOALL_FN_TYPE func); void lh_doall_arg(LHASH *table, LHASH_DOALL_ARG_FN_TYPE func,          void *arg); int lh_error(LHASH *table); typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *); typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *); typedef void (*LHASH_DOALL_FN_TYPE)(const void *); typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, const void *);=head1 DESCRIPTIONThis library implements dynamic hash tables. The hash table entriescan be arbitrary structures. Usually they consist of key and valuefields.lh_new() creates a new B<LHASH> structure to store arbitrary dataentries, and provides the 'hash' and 'compare' callbacks to be used inorganising the table's entries.  The B<hash> callback takes a pointerto a table entry as its argument and returns an unsigned long hashvalue for its key field.  The hash value is normally truncated to apower of 2, so make sure that your hash function returns well mixedlow order bits.  The B<compare> callback takes two arguments (pointersto two hash table entries), and returns 0 if their keys are equal,non-zero otherwise.  If your hash table will contain items of someparticular type and the B<hash> and B<compare> callbacks hash/comparethese types, then the B<DECLARE_LHASH_HASH_FN> andB<IMPLEMENT_LHASH_COMP_FN> macros can be used to create callbackwrappers of the prototypes required by lh_new().  These provideper-variable casts before calling the type-specific callbacks writtenby the application author.  These macros, as well as those used forthe "doall" callbacks, are defined as; #define DECLARE_LHASH_HASH_FN(f_name,o_type) \         unsigned long f_name##_LHASH_HASH(const void *); #define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \         unsigned long f_name##_LHASH_HASH(const void *arg) { \                 o_type a = (o_type)arg; \                 return f_name(a); } #define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH #define DECLARE_LHASH_COMP_FN(f_name,o_type) \         int f_name##_LHASH_COMP(const void *, const void *); #define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \         int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \                 o_type a = (o_type)arg1; \                 o_type b = (o_type)arg2; \                 return f_name(a,b); } #define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP #define DECLARE_LHASH_DOALL_FN(f_name,o_type) \         void f_name##_LHASH_DOALL(const void *); #define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \         void f_name##_LHASH_DOALL(const void *arg) { \                 o_type a = (o_type)arg; \                 f_name(a); } #define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL #define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \         void f_name##_LHASH_DOALL_ARG(const void *, const void *); #define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \         void f_name##_LHASH_DOALL_ARG(const void *arg1, const void *arg2) { \                 o_type a = (o_type)arg1; \                 a_type b = (a_type)arg2; \                 f_name(a,b); } #define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARGAn example of a hash table storing (pointers to) structures of type 'STUFF'could be defined as follows; /* Calculates the hash value of 'tohash' (implemented elsewhere) */ unsigned long STUFF_hash(const STUFF *tohash); /* Orders 'arg1' and 'arg2' (implemented elsewhere) */ int STUFF_cmp(const STUFF *arg1, const STUFF *arg2); /* Create the type-safe wrapper functions for use in the LHASH internals */ static IMPLEMENT_LHASH_HASH_FN(STUFF_hash, const STUFF *) static IMPLEMENT_LHASH_COMP_FN(STUFF_cmp, const STUFF *); /* ... */ int main(int argc, char *argv[]) {         /* Create the new hash table using the hash/compare wrappers */         LHASH *hashtable = lh_new(LHASH_HASH_FN(STUFF_hash),                                   LHASH_COMP_FN(STUFF_cmp));	 /* ... */ }lh_free() frees the B<LHASH> structure B<table>. Allocated hash tableentries will not be freed; consider using lh_doall() to deallocate anyremaining entries in the hash table (see below).lh_insert() inserts the structure pointed to by B<data> into B<table>.If there already is an entry with the same key, the old value isreplaced. Note that lh_insert() stores pointers, the data are notcopied.lh_delete() deletes an entry from B<table>.lh_retrieve() looks up an entry in B<table>. Normally, B<data> isa structure with the key field(s) set; the function will return apointer to a fully populated structure.lh_doall() will, for every entry in the hash table, call B<func> withthe data item as its parameter.  For lh_doall() and lh_doall_arg(),function pointer casting should be avoided in the callbacks (seeB<NOTE>) - instead, either declare the callbacks to match theprototype required in lh_new() or use the declare/implement macros tocreate type-safe wrappers that cast variables prior to calling yourtype-specific callbacks.  An example of this is illustrated here wherethe callback is used to cleanup resources for items in the hash tableprior to the hashtable itself being deallocated: /* Cleans up resources belonging to 'a' (this is implemented elsewhere) */ void STUFF_cleanup(STUFF *a); /* Implement a prototype-compatible wrapper for "STUFF_cleanup" */ IMPLEMENT_LHASH_DOALL_FN(STUFF_cleanup, STUFF *)         /* ... then later in the code ... */ /* So to run "STUFF_cleanup" against all items in a hash table ... */ lh_doall(hashtable, LHASH_DOALL_FN(STUFF_cleanup)); /* Then the hash table itself can be deallocated */ lh_free(hashtable);When doing this, be careful if you delete entries from the hash tablein your callbacks: the table may decrease in size, moving the itemthat you are currently on down lower in the hash table - this couldcause some entries to be skipped during the iteration.  The secondbest solution to this problem is to set hash-E<gt>down_load=0 beforeyou start (which will stop the hash table ever decreasing in size).The best solution is probably to avoid deleting items from the hashtable inside a "doall" callback!lh_doall_arg() is the same as lh_doall() except that B<func> will becalled with B<arg> as the second argument and B<func> should be oftype B<LHASH_DOALL_ARG_FN_TYPE> (a callback prototype that is passedboth the table entry and an extra argument).  As with lh_doall(), youcan instead choose to declare your callback with a prototype matchingthe types you are dealing with and use the declare/implement macros tocreate compatible wrappers that cast variables before calling yourtype-specific callbacks.  An example of this is demonstrated here(printing all hash table entries to a BIO that is provided by thecaller): /* Prints item 'a' to 'output_bio' (this is implemented elsewhere) */ void STUFF_print(const STUFF *a, BIO *output_bio); /* Implement a prototype-compatible wrapper for "STUFF_print" */ static IMPLEMENT_LHASH_DOALL_ARG_FN(STUFF_print, const STUFF *, BIO *)         /* ... then later in the code ... */ /* Print out the entire hashtable to a particular BIO */ lh_doall_arg(hashtable, LHASH_DOALL_ARG_FN(STUFF_print), logging_bio); lh_error() can be used to determine if an error occurred in the lastoperation. lh_error() is a macro.=head1 RETURN VALUESlh_new() returns B<NULL> on error, otherwise a pointer to the newB<LHASH> structure.When a hash table entry is replaced, lh_insert() returns the valuebeing replaced. B<NULL> is returned on normal operation and on error.lh_delete() returns the entry being deleted.  B<NULL> is returned ifthere is no such value in the hash table.lh_retrieve() returns the hash table entry if it has been found,B<NULL> otherwise.lh_error() returns 1 if an error occurred in the last operation, 0otherwise.lh_free(), lh_doall() and lh_doall_arg() return no values.=head1 NOTEThe various LHASH macros and callback types exist to make it possibleto write type-safe code without resorting to function-prototypecasting - an evil that makes application code much harder toaudit/verify and also opens the window of opportunity for stackcorruption and other hard-to-find bugs.  It also, apparently, violatesANSI-C.The LHASH code regards table entries as constant data.  As such, itinternally represents lh_insert()'d items with a "const void *"pointer type.  This is why callbacks such as those used by lh_doall()and lh_doall_arg() declare their prototypes with "const", even for theparameters that pass back the table items' data pointers - forconsistency, user-provided data is "const" at all times as far as theLHASH code is concerned.  However, as callers are themselves providingthese pointers, they can choose whether they too should be treatingall such parameters as constant.As an example, a hash table may be maintained by code that, forreasons of encapsulation, has only "const" access to the data beingindexed in the hash table (ie. it is returned as "const" fromelsewhere in their code) - in this case the LHASH prototypes areappropriate as-is.  Conversely, if the caller is responsible for thelife-time of the data in question, then they may well wish to makemodifications to table item passed back in the lh_doall() orlh_doall_arg() callbacks (see the "STUFF_cleanup" example above).  Ifso, the caller can either cast the "const" away (if they're providingthe raw callbacks themselves) or use the macros to declare/implementthe wrapper functions without "const" types.Callers that only have "const" access to data they're indexing in atable, yet declare callbacks without constant types (or cast the"const" away themselves), are therefore creating their own risks/bugswithout being encouraged to do so by the API.  On a related note,those auditing code should pay special attention to any instances ofDECLARE/IMPLEMENT_LHASH_DOALL_[ARG_]_FN macros that provide typeswithout any "const" qualifiers.=head1 BUGSlh_insert() returns B<NULL> both for success and error.=head1 INTERNALSThe following description is based on the SSLeay documentation:The B<lhash> library implements a hash table described in theI<Communications of the ACM> in 1991.  What makes this hash tabledifferent is that as the table fills, the hash table is increased (ordecreased) in size via OPENSSL_realloc().  When a 'resize' is done, instead ofall hashes being redistributed over twice as many 'buckets', onebucket is split.  So when an 'expand' is done, there is only a minimalcost to redistribute some values.  Subsequent inserts will cause moresingle 'bucket' redistributions but there will never be a sudden largecost due to redistributing all the 'buckets'.The state for a particular hash table is kept in the B<LHASH> structure.The decision to increase or decrease the hash table size is madedepending on the 'load' of the hash table.  The load is the number ofitems in the hash table divided by the size of the hash table.  Thedefault values are as follows.  If (hash->up_load E<lt> load) =E<gt>expand.  if (hash-E<gt>down_load E<gt> load) =E<gt> contract.  TheB<up_load> has a default value of 1 and B<down_load> has a default valueof 2.  These numbers can be modified by the application by justplaying with the B<up_load> and B<down_load> variables.  The 'load' iskept in a form which is multiplied by 256.  Sohash-E<gt>up_load=8*256; will cause a load of 8 to be set.If you are interested in performance the field to watch isnum_comp_calls.  The hash library keeps track of the 'hash' value foreach item so when a lookup is done, the 'hashes' are compared, ifthere is a match, then a full compare is done, andhash-E<gt>num_comp_calls is incremented.  If num_comp_calls is not equalto num_delete plus num_retrieve it means that your hash function isgenerating hashes that are the same for different values.  It isprobably worth changing your hash function if this is the case becauseeven if your hash table has 10 items in a 'bucket', it can be searchedwith 10 B<unsigned long> compares and 10 linked list traverses.  Thiswill be much less expensive that 10 calls to your compare function.lh_strhash() is a demo string hashing function: unsigned long lh_strhash(const char *c);Since the B<LHASH> routines would normally be passed structures, thisroutine would not normally be passed to lh_new(), rather it would beused in the function passed to lh_new().=head1 SEE ALSOL<lh_stats(3)|lh_stats(3)>=head1 HISTORYThe B<lhash> library is available in all versions of SSLeay and OpenSSL.lh_error() was added in SSLeay 0.9.1b.This manpage is derived from the SSLeay documentation.In OpenSSL 0.9.7, all lhash functions that were passed function pointerswere changed for better type safety, and the function types LHASH_COMP_FN_TYPE,LHASH_HASH_FN_TYPE, LHASH_DOALL_FN_TYPE and LHASH_DOALL_ARG_FN_TYPE became available.=cut

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -