hash.c
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:13k
源码类别:

数据库系统

开发平台:

C/C++

  1. /*
  2. ** 2001 September 22
  3. **
  4. ** The author disclaims copyright to this source code.  In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. **    May you do good and not evil.
  8. **    May you find forgiveness for yourself and forgive others.
  9. **    May you share freely, never taking more than you give.
  10. **
  11. *************************************************************************
  12. ** This is the implementation of generic hash-tables
  13. ** used in SQLite.
  14. **
  15. ** $Id: hash.c,v 1.27 2008/04/02 18:33:08 drh Exp $
  16. */
  17. #include "sqliteInt.h"
  18. #include <assert.h>
  19. /* Turn bulk memory into a hash table object by initializing the
  20. ** fields of the Hash structure.
  21. **
  22. ** "pNew" is a pointer to the hash table that is to be initialized.
  23. ** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
  24. ** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING.  The value of keyClass 
  25. ** determines what kind of key the hash table will use.  "copyKey" is
  26. ** true if the hash table should make its own private copy of keys and
  27. ** false if it should just use the supplied pointer.  CopyKey only makes
  28. ** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
  29. ** for other key classes.
  30. */
  31. void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
  32.   assert( pNew!=0 );
  33.   assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
  34.   pNew->keyClass = keyClass;
  35. #if 0
  36.   if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
  37. #endif
  38.   pNew->copyKey = copyKey;
  39.   pNew->first = 0;
  40.   pNew->count = 0;
  41.   pNew->htsize = 0;
  42.   pNew->ht = 0;
  43. }
  44. /* Remove all entries from a hash table.  Reclaim all memory.
  45. ** Call this routine to delete a hash table or to reset a hash table
  46. ** to the empty state.
  47. */
  48. void sqlite3HashClear(Hash *pH){
  49.   HashElem *elem;         /* For looping over all elements of the table */
  50.   assert( pH!=0 );
  51.   elem = pH->first;
  52.   pH->first = 0;
  53.   sqlite3_free(pH->ht);
  54.   pH->ht = 0;
  55.   pH->htsize = 0;
  56.   while( elem ){
  57.     HashElem *next_elem = elem->next;
  58.     if( pH->copyKey && elem->pKey ){
  59.       sqlite3_free(elem->pKey);
  60.     }
  61.     sqlite3_free(elem);
  62.     elem = next_elem;
  63.   }
  64.   pH->count = 0;
  65. }
  66. #if 0 /* NOT USED */
  67. /*
  68. ** Hash and comparison functions when the mode is SQLITE_HASH_INT
  69. */
  70. static int intHash(const void *pKey, int nKey){
  71.   return nKey ^ (nKey<<8) ^ (nKey>>8);
  72. }
  73. static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  74.   return n2 - n1;
  75. }
  76. #endif
  77. #if 0 /* NOT USED */
  78. /*
  79. ** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
  80. */
  81. static int ptrHash(const void *pKey, int nKey){
  82.   uptr x = Addr(pKey);
  83.   return x ^ (x<<8) ^ (x>>8);
  84. }
  85. static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  86.   if( pKey1==pKey2 ) return 0;
  87.   if( pKey1<pKey2 ) return -1;
  88.   return 1;
  89. }
  90. #endif
  91. /*
  92. ** Hash and comparison functions when the mode is SQLITE_HASH_STRING
  93. */
  94. static int strHash(const void *pKey, int nKey){
  95.   const char *z = (const char *)pKey;
  96.   int h = 0;
  97.   if( nKey<=0 ) nKey = strlen(z);
  98.   while( nKey > 0  ){
  99.     h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
  100.     nKey--;
  101.   }
  102.   return h & 0x7fffffff;
  103. }
  104. static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  105.   if( n1!=n2 ) return 1;
  106.   return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
  107. }
  108. /*
  109. ** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
  110. */
  111. static int binHash(const void *pKey, int nKey){
  112.   int h = 0;
  113.   const char *z = (const char *)pKey;
  114.   while( nKey-- > 0 ){
  115.     h = (h<<3) ^ h ^ *(z++);
  116.   }
  117.   return h & 0x7fffffff;
  118. }
  119. static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  120.   if( n1!=n2 ) return 1;
  121.   return memcmp(pKey1,pKey2,n1);
  122. }
  123. /*
  124. ** Return a pointer to the appropriate hash function given the key class.
  125. **
  126. ** The C syntax in this function definition may be unfamilar to some 
  127. ** programmers, so we provide the following additional explanation:
  128. **
  129. ** The name of the function is "hashFunction".  The function takes a
  130. ** single parameter "keyClass".  The return value of hashFunction()
  131. ** is a pointer to another function.  Specifically, the return value
  132. ** of hashFunction() is a pointer to a function that takes two parameters
  133. ** with types "const void*" and "int" and returns an "int".
  134. */
  135. static int (*hashFunction(int keyClass))(const void*,int){
  136. #if 0  /* HASH_INT and HASH_POINTER are never used */
  137.   switch( keyClass ){
  138.     case SQLITE_HASH_INT:     return &intHash;
  139.     case SQLITE_HASH_POINTER: return &ptrHash;
  140.     case SQLITE_HASH_STRING:  return &strHash;
  141.     case SQLITE_HASH_BINARY:  return &binHash;;
  142.     default: break;
  143.   }
  144.   return 0;
  145. #else
  146.   if( keyClass==SQLITE_HASH_STRING ){
  147.     return &strHash;
  148.   }else{
  149.     assert( keyClass==SQLITE_HASH_BINARY );
  150.     return &binHash;
  151.   }
  152. #endif
  153. }
  154. /*
  155. ** Return a pointer to the appropriate hash function given the key class.
  156. **
  157. ** For help in interpreted the obscure C code in the function definition,
  158. ** see the header comment on the previous function.
  159. */
  160. static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
  161. #if 0 /* HASH_INT and HASH_POINTER are never used */
  162.   switch( keyClass ){
  163.     case SQLITE_HASH_INT:     return &intCompare;
  164.     case SQLITE_HASH_POINTER: return &ptrCompare;
  165.     case SQLITE_HASH_STRING:  return &strCompare;
  166.     case SQLITE_HASH_BINARY:  return &binCompare;
  167.     default: break;
  168.   }
  169.   return 0;
  170. #else
  171.   if( keyClass==SQLITE_HASH_STRING ){
  172.     return &strCompare;
  173.   }else{
  174.     assert( keyClass==SQLITE_HASH_BINARY );
  175.     return &binCompare;
  176.   }
  177. #endif
  178. }
  179. /* Link an element into the hash table
  180. */
  181. static void insertElement(
  182.   Hash *pH,              /* The complete hash table */
  183.   struct _ht *pEntry,    /* The entry into which pNew is inserted */
  184.   HashElem *pNew         /* The element to be inserted */
  185. ){
  186.   HashElem *pHead;       /* First element already in pEntry */
  187.   pHead = pEntry->chain;
  188.   if( pHead ){
  189.     pNew->next = pHead;
  190.     pNew->prev = pHead->prev;
  191.     if( pHead->prev ){ pHead->prev->next = pNew; }
  192.     else             { pH->first = pNew; }
  193.     pHead->prev = pNew;
  194.   }else{
  195.     pNew->next = pH->first;
  196.     if( pH->first ){ pH->first->prev = pNew; }
  197.     pNew->prev = 0;
  198.     pH->first = pNew;
  199.   }
  200.   pEntry->count++;
  201.   pEntry->chain = pNew;
  202. }
  203. /* Resize the hash table so that it cantains "new_size" buckets.
  204. ** "new_size" must be a power of 2.  The hash table might fail 
  205. ** to resize if sqlite3_malloc() fails.
  206. */
  207. static void rehash(Hash *pH, int new_size){
  208.   struct _ht *new_ht;            /* The new hash table */
  209.   HashElem *elem, *next_elem;    /* For looping over existing elements */
  210.   int (*xHash)(const void*,int); /* The hash function */
  211. #ifdef SQLITE_MALLOC_SOFT_LIMIT
  212.   if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
  213.     new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
  214.   }
  215.   if( new_size==pH->htsize ) return;
  216. #endif
  217.   /* There is a call to sqlite3_malloc() inside rehash(). If there is
  218.   ** already an allocation at pH->ht, then if this malloc() fails it
  219.   ** is benign (since failing to resize a hash table is a performance
  220.   ** hit only, not a fatal error).
  221.   */
  222.   sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pH->htsize>0);
  223.   new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
  224.   sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
  225.   if( new_ht==0 ) return;
  226.   sqlite3_free(pH->ht);
  227.   pH->ht = new_ht;
  228.   pH->htsize = new_size;
  229.   xHash = hashFunction(pH->keyClass);
  230.   for(elem=pH->first, pH->first=0; elem; elem = next_elem){
  231.     int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
  232.     next_elem = elem->next;
  233.     insertElement(pH, &new_ht[h], elem);
  234.   }
  235. }
  236. /* This function (for internal use only) locates an element in an
  237. ** hash table that matches the given key.  The hash for this key has
  238. ** already been computed and is passed as the 4th parameter.
  239. */
  240. static HashElem *findElementGivenHash(
  241.   const Hash *pH,     /* The pH to be searched */
  242.   const void *pKey,   /* The key we are searching for */
  243.   int nKey,
  244.   int h               /* The hash for this key. */
  245. ){
  246.   HashElem *elem;                /* Used to loop thru the element list */
  247.   int count;                     /* Number of elements left to test */
  248.   int (*xCompare)(const void*,int,const void*,int);  /* comparison function */
  249.   if( pH->ht ){
  250.     struct _ht *pEntry = &pH->ht[h];
  251.     elem = pEntry->chain;
  252.     count = pEntry->count;
  253.     xCompare = compareFunction(pH->keyClass);
  254.     while( count-- && elem ){
  255.       if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
  256.         return elem;
  257.       }
  258.       elem = elem->next;
  259.     }
  260.   }
  261.   return 0;
  262. }
  263. /* Remove a single entry from the hash table given a pointer to that
  264. ** element and a hash on the element's key.
  265. */
  266. static void removeElementGivenHash(
  267.   Hash *pH,         /* The pH containing "elem" */
  268.   HashElem* elem,   /* The element to be removed from the pH */
  269.   int h             /* Hash value for the element */
  270. ){
  271.   struct _ht *pEntry;
  272.   if( elem->prev ){
  273.     elem->prev->next = elem->next; 
  274.   }else{
  275.     pH->first = elem->next;
  276.   }
  277.   if( elem->next ){
  278.     elem->next->prev = elem->prev;
  279.   }
  280.   pEntry = &pH->ht[h];
  281.   if( pEntry->chain==elem ){
  282.     pEntry->chain = elem->next;
  283.   }
  284.   pEntry->count--;
  285.   if( pEntry->count<=0 ){
  286.     pEntry->chain = 0;
  287.   }
  288.   if( pH->copyKey ){
  289.     sqlite3_free(elem->pKey);
  290.   }
  291.   sqlite3_free( elem );
  292.   pH->count--;
  293.   if( pH->count<=0 ){
  294.     assert( pH->first==0 );
  295.     assert( pH->count==0 );
  296.     sqlite3HashClear(pH);
  297.   }
  298. }
  299. /* Attempt to locate an element of the hash table pH with a key
  300. ** that matches pKey,nKey.  Return a pointer to the corresponding 
  301. ** HashElem structure for this element if it is found, or NULL
  302. ** otherwise.
  303. */
  304. HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){
  305.   int h;             /* A hash on key */
  306.   HashElem *elem;    /* The element that matches key */
  307.   int (*xHash)(const void*,int);  /* The hash function */
  308.   if( pH==0 || pH->ht==0 ) return 0;
  309.   xHash = hashFunction(pH->keyClass);
  310.   assert( xHash!=0 );
  311.   h = (*xHash)(pKey,nKey);
  312.   elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize);
  313.   return elem;
  314. }
  315. /* Attempt to locate an element of the hash table pH with a key
  316. ** that matches pKey,nKey.  Return the data for this element if it is
  317. ** found, or NULL if there is no match.
  318. */
  319. void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
  320.   HashElem *elem;    /* The element that matches key */
  321.   elem = sqlite3HashFindElem(pH, pKey, nKey);
  322.   return elem ? elem->data : 0;
  323. }
  324. /* Insert an element into the hash table pH.  The key is pKey,nKey
  325. ** and the data is "data".
  326. **
  327. ** If no element exists with a matching key, then a new
  328. ** element is created.  A copy of the key is made if the copyKey
  329. ** flag is set.  NULL is returned.
  330. **
  331. ** If another element already exists with the same key, then the
  332. ** new data replaces the old data and the old data is returned.
  333. ** The key is not copied in this instance.  If a malloc fails, then
  334. ** the new data is returned and the hash table is unchanged.
  335. **
  336. ** If the "data" parameter to this function is NULL, then the
  337. ** element corresponding to "key" is removed from the hash table.
  338. */
  339. void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
  340.   int hraw;             /* Raw hash value of the key */
  341.   int h;                /* the hash of the key modulo hash table size */
  342.   HashElem *elem;       /* Used to loop thru the element list */
  343.   HashElem *new_elem;   /* New element added to the pH */
  344.   int (*xHash)(const void*,int);  /* The hash function */
  345.   assert( pH!=0 );
  346.   xHash = hashFunction(pH->keyClass);
  347.   assert( xHash!=0 );
  348.   hraw = (*xHash)(pKey, nKey);
  349.   if( pH->htsize ){
  350.     h = hraw % pH->htsize;
  351.     elem = findElementGivenHash(pH,pKey,nKey,h);
  352.     if( elem ){
  353.       void *old_data = elem->data;
  354.       if( data==0 ){
  355.         removeElementGivenHash(pH,elem,h);
  356.       }else{
  357.         elem->data = data;
  358.         if( !pH->copyKey ){
  359.           elem->pKey = (void *)pKey;
  360.         }
  361.         assert(nKey==elem->nKey);
  362.       }
  363.       return old_data;
  364.     }
  365.   }
  366.   if( data==0 ) return 0;
  367.   new_elem = (HashElem*)sqlite3_malloc( sizeof(HashElem) );
  368.   if( new_elem==0 ) return data;
  369.   if( pH->copyKey && pKey!=0 ){
  370.     new_elem->pKey = sqlite3_malloc( nKey );
  371.     if( new_elem->pKey==0 ){
  372.       sqlite3_free(new_elem);
  373.       return data;
  374.     }
  375.     memcpy((void*)new_elem->pKey, pKey, nKey);
  376.   }else{
  377.     new_elem->pKey = (void*)pKey;
  378.   }
  379.   new_elem->nKey = nKey;
  380.   pH->count++;
  381.   if( pH->htsize==0 ){
  382.     rehash(pH, 128/sizeof(pH->ht[0]));
  383.     if( pH->htsize==0 ){
  384.       pH->count = 0;
  385.       if( pH->copyKey ){
  386.         sqlite3_free(new_elem->pKey);
  387.       }
  388.       sqlite3_free(new_elem);
  389.       return data;
  390.     }
  391.   }
  392.   if( pH->count > pH->htsize ){
  393.     rehash(pH,pH->htsize*2);
  394.   }
  395.   assert( pH->htsize>0 );
  396.   h = hraw % pH->htsize;
  397.   insertElement(pH, &pH->ht[h], new_elem);
  398.   new_elem->data = data;
  399.   return 0;
  400. }