hashLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:21k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* hashLib.c - generic hashing library */
  2. /* Copyright 1990-1993 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01l,12feb93,kdl  changed hashLibInit() to handle multiple invocations.
  8. 01k,04jul92,jcf  scalable/ANSI/cleanup effort.
  9. 01j,26may92,rrr  the tree shuffle
  10. 01i,19nov91,rrr  shut up some ansi warnings.
  11. 01h,04oct91,rrr  passed through the ansification filter
  12.                   -changed functions to ansi style
  13.   -changed includes to have absolute path from h/
  14.   -changed VOID to void
  15.   -changed copyright notice
  16. 01g,01oct90,jcf   fixed hashTblEach() to traverse table correctly.
  17. 01f,28sep90,jcf   documentation.
  18. 01e,17jul90,dnw   changed call to objAlloc() to objAllocExtra()
  19. 01d,05jul90,jcf   documentation.
  20. 01c,23jun90,jcf   changed ffs to ffsMsb.
  21. 01b,22apr90,jcf   removed hashTblShow to indepent show routine library.
  22. 01a,17nov89,jcf   written.
  23. */
  24. /*
  25. DESCRIPTION
  26. This subroutine library supports the creation and maintenance of a
  27. chained hash table.  Hash tables efficiently store hash nodes for fast access.
  28. They are frequently used for symbol tables, or other name to identifier
  29. functions.  A chained hash table is an array of singly linked list heads,
  30. with one list head per element of the hash table.  During creation a hash table
  31. is passed two user-definable functions, the hashing function, and the hash node
  32. comparator.
  33. HASH NODES
  34. A hash node is a structure used for chaining nodes together in the table.
  35. The defined structure HASH_NODE is not complete because it contains no field
  36. for the key for referencing, and no place to store data.  The user completes
  37. the hash node by including a HASH_NODE in a structure containing the necessary
  38. key and data fields.  This flexibility allows hash tables to better suit
  39. varying data representations of the key and data fields.  The hashing function
  40. and the hash node comparator determine the full hash node representation.  Refer
  41. to the defined structures H_NODE_INT and H_NODE_STRING for examples of the
  42. general purpose hash nodes used by the hashing functions and hash node
  43. comparators defined in this library.
  44. HASHING FUNCTIONS
  45. One function, called the hashing function, controls the distribution of nodes
  46. in the table.  This library provides a number of standard hashing functions,
  47. but applications can specify their own.  Desirable properties of a hashing
  48. function are that they execute quickly, and evenly distribute the nodes
  49. throughout the table.  The worst hashing function imaginable would be:
  50. h(k) = 0.  This function would put all nodes in list associated with the
  51. zero element in the hash table.  Most hashing functions find their origin
  52. in random number generators.
  53. Hashing functions must return an index between zero and (elements - 1).  They
  54. take the following form:
  55. .CS
  56. int hashFuncXXX (elements, pHashNode, keyArg)
  57.     int elements; /@ number of elements in hash table        @/
  58.     HASH_NODE *pHashNode; /@ hash node to pass through hash function @/
  59.     int keyArg; /@ optional argument to hash function      @/
  60. .CE
  61. HASH NODE COMPARATOR FUNCTIONS
  62. The second function required is a key comparator.  Different hash tables may
  63. choose to compare hash nodes in different ways.  For example, the hash node
  64. could contain a key which is a pointer to a string, or simply an integer.
  65. The comparator compares the hash node on the basis of some criteria, and
  66. returns a boolean as to the nodes equivalence.  Additionally, the key
  67. comparator can use the keyCmpArg for additional information to the comparator.
  68. The keyCmpArg is passed from all the hashLib functions which use the the
  69. comparator.  The keyCmpArg is usually not needed except for advanced
  70. hash table queurying.
  71. symLib is a good example of the utilization of the keyCmpArg parameter.
  72. symLib hashes the name of the symbol.  It finds the id based on the
  73. name using hashTblFind(), but for the purposes of putting and removing
  74. symbols from the symbol's hash table, an additional comparison restriction
  75. applies.  Symbols have types, and while symbols of equivalent names can exist,
  76. no symbols of equivalent name and type can exist.  So symLib utilizes the
  77. keyCmpArg as a flag to denote the which operation being performed on the hash
  78. table: symbol name matching, or complete symbol name and type matching.
  79. Key comparator functions must return a boolean.  They take the following form:
  80. .CS
  81. int hashKeyCmpXXX (pMatchNode, pHashNode, keyCmpArg)
  82.     HASH_NODE *pMatchNode; /@ hash node to match                        @/
  83.     HASH_NODE *pHashNode; /@ hash node in table being compared to      @/
  84.     int keyCmpArg; /@ parameter passed to hashTblFind (2)       @/
  85. .CE
  86. HASHING COLLISIONS
  87. Hashing collisions occur when the hashing function returns the same index when
  88. given two unique keys.  This is unavoidable in cases where there are more nodes
  89. in the hash table then there are elements in the hash table.  In a chained
  90. hash table, collisions are resolved by treating each element of the table as
  91. the head of a linked list.  Nodes are simply added to appropriate list
  92. regardless of other nodes already in the list.  The list is not sorted, but
  93. new nodes are added at the head of the list because newer entries are usually
  94. searched for before older entries.  When nodes are removed or searched for,
  95. the list is traversed from the head until a match is found.
  96. STRUCTURE
  97. .CS
  98.    HASH_HEAD 0           HASH_NODE         HASH_NODE
  99.    ---------             --------          --------
  100.    | head--------------->| next----------->| next---------
  101.    |       |             |......|          |......|      |
  102.    | tail------          | key  |          | key  |      |
  103.    |       |  |          | data |          | data |      v
  104.    ---------  |          --------          --------     ---
  105.               |                             ^            -
  106.               |                             |
  107.               -------------------------------
  108.    HASH_HEAD 1           HASH_NODE
  109.    ---------             --------
  110.    | head--------------->| next---------
  111.    |       |             |......|      |
  112.    | tail------          | key  |      |
  113.    |       |  |          | data |      v
  114.    ---------  |          --------     ---
  115.               |           ^            -
  116.               |           |
  117.               -------------
  118.     ...
  119.     ...
  120.    HASH_HEAD N
  121.    ---------
  122.    | head-----------------
  123.    |       |             |
  124.    | tail---------       |
  125.    |       |     |       v
  126.    ---------    ---     ---
  127.  -  -
  128. .CE
  129. CAVEATS
  130. Hash tables must have a number of elements equal to a power of two.
  131. INCLUDE FILE: hashLib.h
  132. */
  133. #include "vxWorks.h"
  134. #include "errno.h"
  135. #include "hashLib.h"
  136. #include "string.h"
  137. #include "private/classLibP.h"
  138. #include "private/objLibP.h"
  139. IMPORT int ffsMsb (int bitfield);
  140. /* locals */
  141. LOCAL OBJ_CLASS hashClass;
  142. LOCAL BOOL hashLibInstalled = FALSE;  /* protect from multiple inits */
  143. /* globals */
  144. CLASS_ID hashClassId = &hashClass;
  145. /*******************************************************************************
  146. *
  147. * hashLibInit - initialize hash table library
  148. *
  149. * This routine initializes the hash table package.
  150. */
  151. STATUS hashLibInit (void)
  152.     {
  153.     if (!hashLibInstalled &&(classInit (hashClassId, sizeof (HASH_TBL), 
  154.               OFFSET(HASH_TBL,objCore),
  155.               (FUNCPTR) hashTblCreate, 
  156. (FUNCPTR) hashTblInit,
  157.               (FUNCPTR) hashTblDestroy) == OK))
  158. {
  159. hashLibInstalled = TRUE;
  160. }
  161.     return ((hashLibInstalled) ? OK : ERROR);
  162.     }
  163. /*******************************************************************************
  164. *
  165. * hashTblCreate - create a hash table
  166. *
  167. * This rountine creates a hash table 2^sizeLog2 number of elements.  The hash
  168. * table is carved from the system memory pool via malloc (2).  To accomidate
  169. * the list structures associated with the table, the actual amout of memory
  170. * alocated will be roughly eight times the number of elements requested.
  171. * Additionallly, two routines must be specified to dictate the behavior of the
  172. * hashing table.  The first routine is the hashing function.
  173. *
  174. * The hashing function's role is to disperse the hash nodes added to the table
  175. * as evenly throughout the table as possible.  The hashing function receives as
  176. * its parameters; the number of elements in the table, a pointer to the
  177. * HASH_NODE structure, and finally the keyArg parameter passed to this
  178. * routine.  The keyArg may be used to seed the hashing function.  The hash
  179. * function returns an index between 0 and (elements - 1).  Standard hashing
  180. * functions are available in this library.
  181. *
  182. * The keyCmpRtn parameter specifies the other function required by the hash
  183. * table.  This routine tests for equivalence of two HASH_NODES.  It returns a
  184. * boolean, TRUE if the keys match, and FALSE if they differ.  As an example,
  185. * a hash node may contain a HASH_NODE followed by a key which is an unsigned
  186. * integer identifiers, or a pointer to a string, depending on the application.
  187. * Standard hash node comparators are available in this library.
  188. *
  189. * RETURNS: HASH_ID, or NULL if hash table could not be created.
  190. *
  191. * SEE ALSO: hashFuncIterScale(), hashFuncModulo(), hashFuncMultiply()
  192. *      hashKeyCmp(), hashKeyStrCmp()
  193. */
  194. HASH_ID hashTblCreate
  195.     (
  196.     int         sizeLog2,       /* number of elements in hash table log 2 */
  197.     FUNCPTR     keyCmpRtn,      /* function to test keys for equivalence */
  198.     FUNCPTR     keyRtn,         /* hashing function to generate hash from key */
  199.     int         keyArg          /* argument to hashing function */
  200.     )
  201.     {
  202.     unsigned extra  = (1 << sizeLog2) * sizeof (SL_LIST);
  203.     HASH_ID hashId;
  204.     SL_LIST *pList;
  205.     hashId  = (HASH_ID) objAllocExtra (hashClassId, extra, (void **) &pList);
  206.     if (hashId != NULL)
  207. hashTblInit (hashId, pList, sizeLog2, keyCmpRtn, keyRtn, keyArg);
  208.     return (hashId); /* return the hash id */
  209.     }
  210. /*******************************************************************************
  211. *
  212. * hashTblInit - initialize a hash table
  213. *
  214. * This routine initializes a hash table.
  215. *
  216. * RETURNS: OK
  217. */
  218. STATUS hashTblInit
  219.     (
  220.     HASH_TBL    *pHashTbl,      /* pointer to hash table to initialize */
  221.     SL_LIST     *pTblMem,       /* pointer to memory of sizeLog2 SL_LISTs */
  222.     int         sizeLog2,       /* number of elements in hash table log 2 */
  223.     FUNCPTR     keyCmpRtn,      /* function to test keys for equivalence */
  224.     FUNCPTR     keyRtn,         /* hashing function to generate hash from key */
  225.     int         keyArg          /* argument to hashing function */
  226.     )
  227.     {
  228.     FAST int ix;
  229.     pHashTbl->elements = 1 << sizeLog2; /* store number of elements */
  230.     pHashTbl->keyCmpRtn = keyCmpRtn; /* store comparator routine */
  231.     pHashTbl->keyRtn = keyRtn; /* store hashing function */
  232.     pHashTbl->keyArg = keyArg; /* store hashing function arg */
  233.     pHashTbl->pHashTbl = pTblMem;
  234.     /* initialize all of the linked list heads in the table */
  235.     for (ix = 0; ix < pHashTbl->elements; ix++)
  236. sllInit (&pHashTbl->pHashTbl [ix]);
  237.     objCoreInit (&pHashTbl->objCore, hashClassId); /* initialize core */
  238.     return (OK);
  239.     }
  240. /*******************************************************************************
  241. *
  242. * hashTblDelete - delete a hash table
  243. *
  244. * This routine deletes the specified hash table and frees the
  245. * associated memory.  The hash table is marked as invalid.
  246. *
  247. * RETURNS: OK, or ERROR if hashId is invalid.
  248. */
  249. STATUS hashTblDelete
  250.     (
  251.     HASH_ID hashId              /* id of hash table to delete */
  252.     )
  253.     {
  254.     return (hashTblDestroy (hashId, TRUE)); /* delete the hash table */
  255.     }
  256. /*******************************************************************************
  257. *
  258. * hashTblTerminate - terminate a hash table
  259. *
  260. * This routine terminates the specified hash table.  The hash table is marked
  261. * as invalid.
  262. *
  263. * RETURNS: OK, or ERROR if hashId is invalid.
  264. */
  265. STATUS hashTblTerminate
  266.     (
  267.     HASH_ID hashId              /* id of hash table to terminate */
  268.     )
  269.     {
  270.     return (hashTblDestroy (hashId, FALSE)); /* terminate the hash table */
  271.     }
  272. /*******************************************************************************
  273. *
  274. * hashTblDestroy - destroy a hash table
  275. *
  276. * This routine destroys the specified hash table and optionally frees the
  277. * associated memory.  The hash table is marked as invalid.
  278. *
  279. * RETURNS: OK, or ERROR if hashId is invalid.
  280. */
  281. STATUS hashTblDestroy
  282.     (
  283.     HASH_ID hashId,             /* id of hash table to destroy */
  284.     BOOL    dealloc             /* deallocate associated memory */
  285.     )
  286.     {
  287.     if (OBJ_VERIFY (hashId, hashClassId) != OK)
  288. return (ERROR); /* invalid hash id */
  289.     objCoreTerminate (&hashId->objCore); /* terminate core */
  290.     if (dealloc)
  291. return (objFree (hashClassId, (char *) hashId));
  292.     return (OK);
  293.     }
  294. /*******************************************************************************
  295. *
  296. * hashTblPut - put a hash node into the specified hash table
  297. *
  298. * This routine puts the specified hash node in the specified hash table.
  299. * Identical nodes will be kept in FIFO order in the hash table.
  300. *
  301. * RETURNS: OK, or ERROR if hashId is invalid.
  302. *
  303. * SEE ALSO: hashTblRemove()
  304. */
  305. STATUS hashTblPut
  306.     (
  307.     HASH_ID     hashId,         /* id of hash table in which to put node */
  308.     HASH_NODE   *pHashNode      /* pointer to hash node to put in hash table */
  309.     )
  310.     {
  311.     int index;
  312.     if (OBJ_VERIFY (hashId, hashClassId) != OK)
  313. return (ERROR); /* invalid hash id */
  314.     /* invoke hash table's hashing routine to get index into table */
  315.     index = (* hashId->keyRtn) (hashId->elements, pHashNode, hashId->keyArg);
  316.     /* add hash node to head of linked list */
  317.     sllPutAtHead (&hashId->pHashTbl [index], pHashNode);
  318.     return (OK);
  319.     }
  320. /*******************************************************************************
  321. *
  322. * hashTblFind - find a hash node that matches the specified key
  323. *
  324. * This routine finds the hash node that matches the specified key.
  325. *
  326. * RETURNS: pointer to HASH_NODE, or NULL if no matching hash node is found.
  327. */
  328. HASH_NODE *hashTblFind
  329.     (
  330.     FAST HASH_ID hashId,        /* id of hash table from which to find node */
  331.     HASH_NODE    *pMatchNode,   /* pointer to hash node to match */
  332.     int          keyCmpArg      /* parameter to be passed to key comparator */
  333.     )
  334.     {
  335.     FAST HASH_NODE *pHNode;
  336.     int             ix;
  337.     if (OBJ_VERIFY (hashId, hashClassId) != OK)
  338. return (NULL); /* invalid hash node */
  339.     /* invoke hash table's hashing routine to get index into table */
  340.     ix = (* hashId->keyRtn) (hashId->elements, pMatchNode, hashId->keyArg);
  341.     /* search linked list for above hash index and return matching hash node */
  342.     pHNode = (HASH_NODE *) SLL_FIRST (&hashId->pHashTbl [ix]);
  343.     while ((pHNode != NULL) &&
  344.    !((* hashId->keyCmpRtn) (pMatchNode, pHNode, keyCmpArg)))
  345. pHNode = (HASH_NODE *) SLL_NEXT (pHNode);
  346.     return (pHNode);
  347.     }
  348. /*******************************************************************************
  349. *
  350. * hashTblRemove - remove a hash node from a hash table
  351. *
  352. * This routine removes the hash node that matches the specified key.
  353. *
  354. * RETURNS: OK, or ERROR if hashId is invalid or no matching hash node is found.
  355. */
  356. STATUS hashTblRemove
  357.     (
  358.     HASH_ID     hashId,         /* id of hash table to to remove node from */
  359.     HASH_NODE   *pHashNode      /* pointer to hash node to remove */
  360.     )
  361.     {
  362.     HASH_NODE *pPrevNode;
  363.     int       ix;
  364.     if (OBJ_VERIFY (hashId, hashClassId) != OK)
  365. return (ERROR); /* invalid hash node */
  366.     /* invoke hash table's hashing routine to get index into table */
  367.     ix = (* hashId->keyRtn) (hashId->elements, pHashNode, hashId->keyArg);
  368.     pPrevNode = sllPrevious (&hashId->pHashTbl [ix], pHashNode);
  369.     sllRemove (&hashId->pHashTbl [ix], pHashNode, pPrevNode);
  370.     return (OK);
  371.     }
  372. /*******************************************************************************
  373. *
  374. * hashTblEach - call a routine for each node in a hash table
  375. *
  376. * This routine calls a user-supplied routine once for each node in the
  377. * hash table.  The routine should be declared as follows:
  378. * .CS
  379. *  BOOL routine (pNode, arg)
  380. *      HASH_NODE *pNode; /@ pointer to a hash table node     @/
  381. *      int   arg; /@ arbitrary user-supplied argument @/
  382. * .CE
  383. * The user-supplied routine should return TRUE if hashTblEach() is to
  384. * continue calling it with the remaining nodes, or FALSE if it is done and
  385. * hashTblEach() can exit.
  386. *
  387. * RETURNS: NULL if traversed whole hash table, or pointer to HASH_NODE that
  388. *          hashTblEach ended with.
  389. */
  390. HASH_NODE *hashTblEach
  391.     (
  392.     HASH_ID     hashId,         /* hash table to call routine for */
  393.     FUNCPTR     routine,        /* the routine to call for each hash node */
  394.     int         routineArg      /* arbitrary user-supplied argument */
  395.     )
  396.     {
  397.     FAST int  ix;
  398.     HASH_NODE *pNode = NULL;
  399.     if (OBJ_VERIFY (hashId, hashClassId) != OK)
  400. return (NULL); /* invalid hash id */
  401.     for (ix = 0; (ix < hashId->elements) && (pNode == NULL); ix++)
  402. pNode = (HASH_NODE *)sllEach (&hashId->pHashTbl[ix],routine,routineArg);
  403.     return (pNode); /* return node we ended with */
  404.     }
  405. /*******************************************************************************
  406. *
  407. * hashFuncIterScale - interative scaling hashing function for strings
  408. *
  409. * This hashing function interprets the key as a pointer to a null terminated
  410. * string.  A seed of 13 or 27 appears to work well.  It calculates the hash as
  411. * follows:
  412. *
  413. * .CS
  414. *
  415. *  for (tkey = pHNode->string; *tkey != ''; tkey++)
  416. * hash = hash * seed + (unsigned int) *tkey;
  417. *
  418. *  hash &= (elements - 1);
  419. *
  420. * .CE
  421. *
  422. * RETURNS: integer between 0 and (elements - 1)
  423. */
  424. int hashFuncIterScale
  425.     (
  426.     int                 elements,       /* number of elements in hash table */
  427.     H_NODE_STRING       *pHNode,        /* pointer to string keyed hash node */
  428.     int                 seed            /* seed to be used as scalar */
  429.     )
  430.     {
  431.     FAST char *tkey;
  432.     FAST int hash = 0;
  433.     /* Compute string signature (sparse 32-bit hash value) */
  434.     for (tkey = pHNode->string; *tkey != ''; tkey++)
  435. hash = hash * seed + (unsigned int) *tkey;
  436.     return (hash & (elements - 1)); /* mask hash to (0, elements - 1) */
  437.     }
  438. /*******************************************************************************
  439. *
  440. * hashFuncModulo - hashing function using remainder technique
  441. *
  442. * This hashing function interprets the key as a 32 bit quantity and applies the
  443. * standard hashing function: h (k) = K mod D.  Where D is the passed divisor.
  444. * The result of the hash function is masked to the appropriate number of bits
  445. * to ensure the hash is not greater than (elements - 1).
  446. *
  447. * RETURNS: integer between 0 and (elements - 1)
  448. */
  449. int hashFuncModulo
  450.     (
  451.     int         elements,       /* number of elements in hash table */
  452.     H_NODE_INT  *pHNode,        /* pointer to integer keyed hash node */
  453.     int         divisor         /* divisor */
  454.     )
  455.     {
  456.     FAST int hash;
  457.     hash = pHNode->key % divisor; /* modulo hashing function */
  458.     return (hash & (elements - 1)); /* mask hash to (0,elements-1)*/
  459.     }
  460. /*******************************************************************************
  461. *
  462. * hashFuncMultiply - multiplicative hashing function
  463. *
  464. * This hashing function interprets the key as a unsigned integer quantity and
  465. * applies the standard hashing function: h (k) = leading N bits of (B * K).
  466. * Where N is the appropriate number of bits such that the hash is not greater
  467. * than (elements - 1).  The overflow of B * K is discarded.  The value of B is
  468. * passed as an argument.  The choice of B is similar to that of the seed to a
  469. * linear congruential random number generator.  Namely, B's value should take
  470. * on a large number (roughly 9 digits base 10) and end in ...x21 where x is an
  471. * even number.  (Don't ask... it involves statistics mumbo jumbo)
  472. *
  473. * RETURNS: integer between 0 and (elements - 1)
  474. */
  475. int hashFuncMultiply
  476.     (
  477.     int         elements,       /* number of elements in hash table */
  478.     H_NODE_INT  *pHNode,        /* pointer to integer keyed hash node */
  479.     int         multiplier      /* multiplier */
  480.     )
  481.     {
  482.     FAST int hash;
  483.     hash = pHNode->key * multiplier; /* multiplicative hash func */
  484.     hash = hash >> (33 - ffsMsb (elements)); /* take only the leading bits */
  485.     return (hash & (elements - 1)); /* mask hash to (0,elements-1)*/
  486.     }
  487. /*******************************************************************************
  488. *
  489. * hashKeyCmp - compare keys as 32 bit identifiers
  490. *
  491. * This routine compares hash node keys as 32 bit identifiers.
  492. * The argument keyCmpArg is unneeded by this comparator.
  493. *
  494. * RETURNS: TRUE if keys match or, FALSE if keys do not match.
  495. *
  496. *ARGSUSED
  497. */
  498. BOOL hashKeyCmp
  499.     (
  500.     H_NODE_INT  *pMatchHNode,   /* hash node to match */
  501.     H_NODE_INT  *pHNode,        /* hash node in table to compare to */
  502.     int         keyCmpArg       /* argument ingnored */
  503.     )
  504.     {
  505.     if (pMatchHNode->key == pHNode->key) /* simple comparison */
  506. return (TRUE);
  507.     else
  508. return (FALSE);
  509.     }
  510. /*******************************************************************************
  511. *
  512. * hashKeyStrCmp - compare keys based on strings they point to
  513. *
  514. * This routine compares keys based on the strings they point to.  The strings
  515. * must be null terminated.  The routine strcmp() is used to compare keys.
  516. * The argument keyCmpArg is unneeded by this comparator.
  517. *
  518. * RETURNS: TRUE if keys match or, FALSE if keys do not match.
  519. *
  520. *ARGSUSED
  521. */
  522. BOOL hashKeyStrCmp
  523.     (
  524.     H_NODE_STRING       *pMatchHNode,   /* hash node to match */
  525.     H_NODE_STRING       *pHNode,        /* hash node in table to compare to */
  526.     int                 keyCmpArg       /* argument ingnored */
  527.     )
  528.     {
  529.     if (strcmp (pMatchHNode->string, pHNode->string) == 0)
  530. return (TRUE);
  531.     else
  532. return (FALSE);
  533.     }