You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
11 KiB

  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$
  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. ** "new" 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 sqliteHashInit(Hash *new, int keyClass, int copyKey){
  32. assert( new!=0 );
  33. assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
  34. new->keyClass = keyClass;
  35. new->copyKey = copyKey &&
  36. (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
  37. new->first = 0;
  38. new->count = 0;
  39. new->htsize = 0;
  40. new->ht = 0;
  41. }
  42. /* Remove all entries from a hash table. Reclaim all memory.
  43. ** Call this routine to delete a hash table or to reset a hash table
  44. ** to the empty state.
  45. */
  46. void sqliteHashClear(Hash *pH){
  47. HashElem *elem; /* For looping over all elements of the table */
  48. assert( pH!=0 );
  49. elem = pH->first;
  50. pH->first = 0;
  51. if( pH->ht ) sqliteFree(pH->ht);
  52. pH->ht = 0;
  53. pH->htsize = 0;
  54. while( elem ){
  55. HashElem *next_elem = elem->next;
  56. if( pH->copyKey && elem->pKey ){
  57. sqliteFree(elem->pKey);
  58. }
  59. sqliteFree(elem);
  60. elem = next_elem;
  61. }
  62. pH->count = 0;
  63. }
  64. /*
  65. ** Hash and comparison functions when the mode is SQLITE_HASH_INT
  66. */
  67. static int intHash(const void *pKey, int nKey){
  68. return nKey ^ (nKey<<8) ^ (nKey>>8);
  69. }
  70. static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  71. return n2 - n1;
  72. }
  73. #if 0 /* NOT USED */
  74. /*
  75. ** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
  76. */
  77. static int ptrHash(const void *pKey, int nKey){
  78. uptr x = Addr(pKey);
  79. return x ^ (x<<8) ^ (x>>8);
  80. }
  81. static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  82. if( pKey1==pKey2 ) return 0;
  83. if( pKey1<pKey2 ) return -1;
  84. return 1;
  85. }
  86. #endif
  87. /*
  88. ** Hash and comparison functions when the mode is SQLITE_HASH_STRING
  89. */
  90. static int strHash(const void *pKey, int nKey){
  91. return sqliteHashNoCase((const char*)pKey, nKey);
  92. }
  93. static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  94. if( n1!=n2 ) return n2-n1;
  95. return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
  96. }
  97. /*
  98. ** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
  99. */
  100. static int binHash(const void *pKey, int nKey){
  101. int h = 0;
  102. const char *z = (const char *)pKey;
  103. while( nKey-- > 0 ){
  104. h = (h<<3) ^ h ^ *(z++);
  105. }
  106. return h & 0x7fffffff;
  107. }
  108. static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  109. if( n1!=n2 ) return n2-n1;
  110. return memcmp(pKey1,pKey2,n1);
  111. }
  112. /*
  113. ** Return a pointer to the appropriate hash function given the key class.
  114. **
  115. ** The C syntax in this function definition may be unfamilar to some
  116. ** programmers, so we provide the following additional explanation:
  117. **
  118. ** The name of the function is "hashFunction". The function takes a
  119. ** single parameter "keyClass". The return value of hashFunction()
  120. ** is a pointer to another function. Specifically, the return value
  121. ** of hashFunction() is a pointer to a function that takes two parameters
  122. ** with types "const void*" and "int" and returns an "int".
  123. */
  124. static int (*hashFunction(int keyClass))(const void*,int){
  125. switch( keyClass ){
  126. case SQLITE_HASH_INT: return &intHash;
  127. /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
  128. case SQLITE_HASH_STRING: return &strHash;
  129. case SQLITE_HASH_BINARY: return &binHash;;
  130. default: break;
  131. }
  132. return 0;
  133. }
  134. /*
  135. ** Return a pointer to the appropriate hash function given the key class.
  136. **
  137. ** For help in interpreted the obscure C code in the function definition,
  138. ** see the header comment on the previous function.
  139. */
  140. static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
  141. switch( keyClass ){
  142. case SQLITE_HASH_INT: return &intCompare;
  143. /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
  144. case SQLITE_HASH_STRING: return &strCompare;
  145. case SQLITE_HASH_BINARY: return &binCompare;
  146. default: break;
  147. }
  148. return 0;
  149. }
  150. /* Resize the hash table so that it cantains "new_size" buckets.
  151. ** "new_size" must be a power of 2. The hash table might fail
  152. ** to resize if sqliteMalloc() fails.
  153. */
  154. static void rehash(Hash *pH, int new_size){
  155. struct _ht *new_ht; /* The new hash table */
  156. HashElem *elem, *next_elem; /* For looping over existing elements */
  157. HashElem *x; /* Element being copied to new hash table */
  158. int (*xHash)(const void*,int); /* The hash function */
  159. assert( (new_size & (new_size-1))==0 );
  160. new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
  161. if( new_ht==0 ) return;
  162. if( pH->ht ) sqliteFree(pH->ht);
  163. pH->ht = new_ht;
  164. pH->htsize = new_size;
  165. xHash = hashFunction(pH->keyClass);
  166. for(elem=pH->first, pH->first=0; elem; elem = next_elem){
  167. int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
  168. next_elem = elem->next;
  169. x = new_ht[h].chain;
  170. if( x ){
  171. elem->next = x;
  172. elem->prev = x->prev;
  173. if( x->prev ) x->prev->next = elem;
  174. else pH->first = elem;
  175. x->prev = elem;
  176. }else{
  177. elem->next = pH->first;
  178. if( pH->first ) pH->first->prev = elem;
  179. elem->prev = 0;
  180. pH->first = elem;
  181. }
  182. new_ht[h].chain = elem;
  183. new_ht[h].count++;
  184. }
  185. }
  186. /* This function (for internal use only) locates an element in an
  187. ** hash table that matches the given key. The hash for this key has
  188. ** already been computed and is passed as the 4th parameter.
  189. */
  190. static HashElem *findElementGivenHash(
  191. const Hash *pH, /* The pH to be searched */
  192. const void *pKey, /* The key we are searching for */
  193. int nKey,
  194. int h /* The hash for this key. */
  195. ){
  196. HashElem *elem; /* Used to loop thru the element list */
  197. int count; /* Number of elements left to test */
  198. int (*xCompare)(const void*,int,const void*,int); /* comparison function */
  199. if( pH->ht ){
  200. elem = pH->ht[h].chain;
  201. count = pH->ht[h].count;
  202. xCompare = compareFunction(pH->keyClass);
  203. while( count-- && elem ){
  204. if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
  205. return elem;
  206. }
  207. elem = elem->next;
  208. }
  209. }
  210. return 0;
  211. }
  212. /* Remove a single entry from the hash table given a pointer to that
  213. ** element and a hash on the element's key.
  214. */
  215. static void removeElementGivenHash(
  216. Hash *pH, /* The pH containing "elem" */
  217. HashElem* elem, /* The element to be removed from the pH */
  218. int h /* Hash value for the element */
  219. ){
  220. if( elem->prev ){
  221. elem->prev->next = elem->next;
  222. }else{
  223. pH->first = elem->next;
  224. }
  225. if( elem->next ){
  226. elem->next->prev = elem->prev;
  227. }
  228. if( pH->ht[h].chain==elem ){
  229. pH->ht[h].chain = elem->next;
  230. }
  231. pH->ht[h].count--;
  232. if( pH->ht[h].count<=0 ){
  233. pH->ht[h].chain = 0;
  234. }
  235. if( pH->copyKey && elem->pKey ){
  236. sqliteFree(elem->pKey);
  237. }
  238. sqliteFree( elem );
  239. pH->count--;
  240. }
  241. /* Attempt to locate an element of the hash table pH with a key
  242. ** that matches pKey,nKey. Return the data for this element if it is
  243. ** found, or NULL if there is no match.
  244. */
  245. void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
  246. int h; /* A hash on key */
  247. HashElem *elem; /* The element that matches key */
  248. int (*xHash)(const void*,int); /* The hash function */
  249. if( pH==0 || pH->ht==0 ) return 0;
  250. xHash = hashFunction(pH->keyClass);
  251. assert( xHash!=0 );
  252. h = (*xHash)(pKey,nKey);
  253. assert( (pH->htsize & (pH->htsize-1))==0 );
  254. elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
  255. return elem ? elem->data : 0;
  256. }
  257. /* Insert an element into the hash table pH. The key is pKey,nKey
  258. ** and the data is "data".
  259. **
  260. ** If no element exists with a matching key, then a new
  261. ** element is created. A copy of the key is made if the copyKey
  262. ** flag is set. NULL is returned.
  263. **
  264. ** If another element already exists with the same key, then the
  265. ** new data replaces the old data and the old data is returned.
  266. ** The key is not copied in this instance. If a malloc fails, then
  267. ** the new data is returned and the hash table is unchanged.
  268. **
  269. ** If the "data" parameter to this function is NULL, then the
  270. ** element corresponding to "key" is removed from the hash table.
  271. */
  272. void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
  273. int hraw; /* Raw hash value of the key */
  274. int h; /* the hash of the key modulo hash table size */
  275. HashElem *elem; /* Used to loop thru the element list */
  276. HashElem *new_elem; /* New element added to the pH */
  277. int (*xHash)(const void*,int); /* The hash function */
  278. assert( pH!=0 );
  279. xHash = hashFunction(pH->keyClass);
  280. assert( xHash!=0 );
  281. hraw = (*xHash)(pKey, nKey);
  282. assert( (pH->htsize & (pH->htsize-1))==0 );
  283. h = hraw & (pH->htsize-1);
  284. elem = findElementGivenHash(pH,pKey,nKey,h);
  285. if( elem ){
  286. void *old_data = elem->data;
  287. if( data==0 ){
  288. removeElementGivenHash(pH,elem,h);
  289. }else{
  290. elem->data = data;
  291. }
  292. return old_data;
  293. }
  294. if( data==0 ) return 0;
  295. new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
  296. if( new_elem==0 ) return data;
  297. if( pH->copyKey && pKey!=0 ){
  298. new_elem->pKey = sqliteMallocRaw( nKey );
  299. if( new_elem->pKey==0 ){
  300. sqliteFree(new_elem);
  301. return data;
  302. }
  303. memcpy((void*)new_elem->pKey, pKey, nKey);
  304. }else{
  305. new_elem->pKey = (void*)pKey;
  306. }
  307. new_elem->nKey = nKey;
  308. pH->count++;
  309. if( pH->htsize==0 ) rehash(pH,8);
  310. if( pH->htsize==0 ){
  311. pH->count = 0;
  312. sqliteFree(new_elem);
  313. return data;
  314. }
  315. if( pH->count > pH->htsize ){
  316. rehash(pH,pH->htsize*2);
  317. }
  318. assert( (pH->htsize & (pH->htsize-1))==0 );
  319. h = hraw & (pH->htsize-1);
  320. elem = pH->ht[h].chain;
  321. if( elem ){
  322. new_elem->next = elem;
  323. new_elem->prev = elem->prev;
  324. if( elem->prev ){ elem->prev->next = new_elem; }
  325. else { pH->first = new_elem; }
  326. elem->prev = new_elem;
  327. }else{
  328. new_elem->next = pH->first;
  329. new_elem->prev = 0;
  330. if( pH->first ){ pH->first->prev = new_elem; }
  331. pH->first = new_elem;
  332. }
  333. pH->ht[h].count++;
  334. pH->ht[h].chain = new_elem;
  335. new_elem->data = data;
  336. return 0;
  337. }