extensions/sqlite/sqlite-source/hash.c
changeset 1203 633c25ce6405
child 1645 27307df4d711
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/extensions/sqlite/sqlite-source/hash.c	Sun Jul 29 01:15:31 2007 +0000
     1.3 @@ -0,0 +1,397 @@
     1.4 +/*
     1.5 +** 2001 September 22
     1.6 +**
     1.7 +** The author disclaims copyright to this source code.  In place of
     1.8 +** a legal notice, here is a blessing:
     1.9 +**
    1.10 +**    May you do good and not evil.
    1.11 +**    May you find forgiveness for yourself and forgive others.
    1.12 +**    May you share freely, never taking more than you give.
    1.13 +**
    1.14 +*************************************************************************
    1.15 +** This is the implementation of generic hash-tables
    1.16 +** used in SQLite.
    1.17 +**
    1.18 +** $Id$
    1.19 +*/
    1.20 +#include "sqliteInt.h"
    1.21 +#include <assert.h>
    1.22 +
    1.23 +/* Turn bulk memory into a hash table object by initializing the
    1.24 +** fields of the Hash structure.
    1.25 +**
    1.26 +** "pNew" is a pointer to the hash table that is to be initialized.
    1.27 +** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
    1.28 +** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING.  The value of keyClass 
    1.29 +** determines what kind of key the hash table will use.  "copyKey" is
    1.30 +** true if the hash table should make its own private copy of keys and
    1.31 +** false if it should just use the supplied pointer.  CopyKey only makes
    1.32 +** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
    1.33 +** for other key classes.
    1.34 +*/
    1.35 +void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
    1.36 +  assert( pNew!=0 );
    1.37 +  assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
    1.38 +  pNew->keyClass = keyClass;
    1.39 +#if 0
    1.40 +  if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
    1.41 +#endif
    1.42 +  pNew->copyKey = copyKey;
    1.43 +  pNew->first = 0;
    1.44 +  pNew->count = 0;
    1.45 +  pNew->htsize = 0;
    1.46 +  pNew->ht = 0;
    1.47 +  pNew->xMalloc = sqlite3MallocX;
    1.48 +  pNew->xFree = sqlite3FreeX;
    1.49 +}
    1.50 +
    1.51 +/* Remove all entries from a hash table.  Reclaim all memory.
    1.52 +** Call this routine to delete a hash table or to reset a hash table
    1.53 +** to the empty state.
    1.54 +*/
    1.55 +void sqlite3HashClear(Hash *pH){
    1.56 +  HashElem *elem;         /* For looping over all elements of the table */
    1.57 +
    1.58 +  assert( pH!=0 );
    1.59 +  elem = pH->first;
    1.60 +  pH->first = 0;
    1.61 +  if( pH->ht ) pH->xFree(pH->ht);
    1.62 +  pH->ht = 0;
    1.63 +  pH->htsize = 0;
    1.64 +  while( elem ){
    1.65 +    HashElem *next_elem = elem->next;
    1.66 +    if( pH->copyKey && elem->pKey ){
    1.67 +      pH->xFree(elem->pKey);
    1.68 +    }
    1.69 +    pH->xFree(elem);
    1.70 +    elem = next_elem;
    1.71 +  }
    1.72 +  pH->count = 0;
    1.73 +}
    1.74 +
    1.75 +#if 0 /* NOT USED */
    1.76 +/*
    1.77 +** Hash and comparison functions when the mode is SQLITE_HASH_INT
    1.78 +*/
    1.79 +static int intHash(const void *pKey, int nKey){
    1.80 +  return nKey ^ (nKey<<8) ^ (nKey>>8);
    1.81 +}
    1.82 +static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
    1.83 +  return n2 - n1;
    1.84 +}
    1.85 +#endif
    1.86 +
    1.87 +#if 0 /* NOT USED */
    1.88 +/*
    1.89 +** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
    1.90 +*/
    1.91 +static int ptrHash(const void *pKey, int nKey){
    1.92 +  uptr x = Addr(pKey);
    1.93 +  return x ^ (x<<8) ^ (x>>8);
    1.94 +}
    1.95 +static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
    1.96 +  if( pKey1==pKey2 ) return 0;
    1.97 +  if( pKey1<pKey2 ) return -1;
    1.98 +  return 1;
    1.99 +}
   1.100 +#endif
   1.101 +
   1.102 +/*
   1.103 +** Hash and comparison functions when the mode is SQLITE_HASH_STRING
   1.104 +*/
   1.105 +static int strHash(const void *pKey, int nKey){
   1.106 +  const char *z = (const char *)pKey;
   1.107 +  int h = 0;
   1.108 +  if( nKey<=0 ) nKey = strlen(z);
   1.109 +  while( nKey > 0  ){
   1.110 +    h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
   1.111 +    nKey--;
   1.112 +  }
   1.113 +  return h & 0x7fffffff;
   1.114 +}
   1.115 +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
   1.116 +  if( n1!=n2 ) return 1;
   1.117 +  return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
   1.118 +}
   1.119 +
   1.120 +/*
   1.121 +** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
   1.122 +*/
   1.123 +static int binHash(const void *pKey, int nKey){
   1.124 +  int h = 0;
   1.125 +  const char *z = (const char *)pKey;
   1.126 +  while( nKey-- > 0 ){
   1.127 +    h = (h<<3) ^ h ^ *(z++);
   1.128 +  }
   1.129 +  return h & 0x7fffffff;
   1.130 +}
   1.131 +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
   1.132 +  if( n1!=n2 ) return 1;
   1.133 +  return memcmp(pKey1,pKey2,n1);
   1.134 +}
   1.135 +
   1.136 +/*
   1.137 +** Return a pointer to the appropriate hash function given the key class.
   1.138 +**
   1.139 +** The C syntax in this function definition may be unfamilar to some 
   1.140 +** programmers, so we provide the following additional explanation:
   1.141 +**
   1.142 +** The name of the function is "hashFunction".  The function takes a
   1.143 +** single parameter "keyClass".  The return value of hashFunction()
   1.144 +** is a pointer to another function.  Specifically, the return value
   1.145 +** of hashFunction() is a pointer to a function that takes two parameters
   1.146 +** with types "const void*" and "int" and returns an "int".
   1.147 +*/
   1.148 +static int (*hashFunction(int keyClass))(const void*,int){
   1.149 +#if 0  /* HASH_INT and HASH_POINTER are never used */
   1.150 +  switch( keyClass ){
   1.151 +    case SQLITE_HASH_INT:     return &intHash;
   1.152 +    case SQLITE_HASH_POINTER: return &ptrHash;
   1.153 +    case SQLITE_HASH_STRING:  return &strHash;
   1.154 +    case SQLITE_HASH_BINARY:  return &binHash;;
   1.155 +    default: break;
   1.156 +  }
   1.157 +  return 0;
   1.158 +#else
   1.159 +  if( keyClass==SQLITE_HASH_STRING ){
   1.160 +    return &strHash;
   1.161 +  }else{
   1.162 +    assert( keyClass==SQLITE_HASH_BINARY );
   1.163 +    return &binHash;
   1.164 +  }
   1.165 +#endif
   1.166 +}
   1.167 +
   1.168 +/*
   1.169 +** Return a pointer to the appropriate hash function given the key class.
   1.170 +**
   1.171 +** For help in interpreted the obscure C code in the function definition,
   1.172 +** see the header comment on the previous function.
   1.173 +*/
   1.174 +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
   1.175 +#if 0 /* HASH_INT and HASH_POINTER are never used */
   1.176 +  switch( keyClass ){
   1.177 +    case SQLITE_HASH_INT:     return &intCompare;
   1.178 +    case SQLITE_HASH_POINTER: return &ptrCompare;
   1.179 +    case SQLITE_HASH_STRING:  return &strCompare;
   1.180 +    case SQLITE_HASH_BINARY:  return &binCompare;
   1.181 +    default: break;
   1.182 +  }
   1.183 +  return 0;
   1.184 +#else
   1.185 +  if( keyClass==SQLITE_HASH_STRING ){
   1.186 +    return &strCompare;
   1.187 +  }else{
   1.188 +    assert( keyClass==SQLITE_HASH_BINARY );
   1.189 +    return &binCompare;
   1.190 +  }
   1.191 +#endif
   1.192 +}
   1.193 +
   1.194 +/* Link an element into the hash table
   1.195 +*/
   1.196 +static void insertElement(
   1.197 +  Hash *pH,              /* The complete hash table */
   1.198 +  struct _ht *pEntry,    /* The entry into which pNew is inserted */
   1.199 +  HashElem *pNew         /* The element to be inserted */
   1.200 +){
   1.201 +  HashElem *pHead;       /* First element already in pEntry */
   1.202 +  pHead = pEntry->chain;
   1.203 +  if( pHead ){
   1.204 +    pNew->next = pHead;
   1.205 +    pNew->prev = pHead->prev;
   1.206 +    if( pHead->prev ){ pHead->prev->next = pNew; }
   1.207 +    else             { pH->first = pNew; }
   1.208 +    pHead->prev = pNew;
   1.209 +  }else{
   1.210 +    pNew->next = pH->first;
   1.211 +    if( pH->first ){ pH->first->prev = pNew; }
   1.212 +    pNew->prev = 0;
   1.213 +    pH->first = pNew;
   1.214 +  }
   1.215 +  pEntry->count++;
   1.216 +  pEntry->chain = pNew;
   1.217 +}
   1.218 +
   1.219 +
   1.220 +/* Resize the hash table so that it cantains "new_size" buckets.
   1.221 +** "new_size" must be a power of 2.  The hash table might fail 
   1.222 +** to resize if sqliteMalloc() fails.
   1.223 +*/
   1.224 +static void rehash(Hash *pH, int new_size){
   1.225 +  struct _ht *new_ht;            /* The new hash table */
   1.226 +  HashElem *elem, *next_elem;    /* For looping over existing elements */
   1.227 +  int (*xHash)(const void*,int); /* The hash function */
   1.228 +
   1.229 +  assert( (new_size & (new_size-1))==0 );
   1.230 +  new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
   1.231 +  if( new_ht==0 ) return;
   1.232 +  if( pH->ht ) pH->xFree(pH->ht);
   1.233 +  pH->ht = new_ht;
   1.234 +  pH->htsize = new_size;
   1.235 +  xHash = hashFunction(pH->keyClass);
   1.236 +  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
   1.237 +    int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
   1.238 +    next_elem = elem->next;
   1.239 +    insertElement(pH, &new_ht[h], elem);
   1.240 +  }
   1.241 +}
   1.242 +
   1.243 +/* This function (for internal use only) locates an element in an
   1.244 +** hash table that matches the given key.  The hash for this key has
   1.245 +** already been computed and is passed as the 4th parameter.
   1.246 +*/
   1.247 +static HashElem *findElementGivenHash(
   1.248 +  const Hash *pH,     /* The pH to be searched */
   1.249 +  const void *pKey,   /* The key we are searching for */
   1.250 +  int nKey,
   1.251 +  int h               /* The hash for this key. */
   1.252 +){
   1.253 +  HashElem *elem;                /* Used to loop thru the element list */
   1.254 +  int count;                     /* Number of elements left to test */
   1.255 +  int (*xCompare)(const void*,int,const void*,int);  /* comparison function */
   1.256 +
   1.257 +  if( pH->ht ){
   1.258 +    struct _ht *pEntry = &pH->ht[h];
   1.259 +    elem = pEntry->chain;
   1.260 +    count = pEntry->count;
   1.261 +    xCompare = compareFunction(pH->keyClass);
   1.262 +    while( count-- && elem ){
   1.263 +      if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
   1.264 +        return elem;
   1.265 +      }
   1.266 +      elem = elem->next;
   1.267 +    }
   1.268 +  }
   1.269 +  return 0;
   1.270 +}
   1.271 +
   1.272 +/* Remove a single entry from the hash table given a pointer to that
   1.273 +** element and a hash on the element's key.
   1.274 +*/
   1.275 +static void removeElementGivenHash(
   1.276 +  Hash *pH,         /* The pH containing "elem" */
   1.277 +  HashElem* elem,   /* The element to be removed from the pH */
   1.278 +  int h             /* Hash value for the element */
   1.279 +){
   1.280 +  struct _ht *pEntry;
   1.281 +  if( elem->prev ){
   1.282 +    elem->prev->next = elem->next; 
   1.283 +  }else{
   1.284 +    pH->first = elem->next;
   1.285 +  }
   1.286 +  if( elem->next ){
   1.287 +    elem->next->prev = elem->prev;
   1.288 +  }
   1.289 +  pEntry = &pH->ht[h];
   1.290 +  if( pEntry->chain==elem ){
   1.291 +    pEntry->chain = elem->next;
   1.292 +  }
   1.293 +  pEntry->count--;
   1.294 +  if( pEntry->count<=0 ){
   1.295 +    pEntry->chain = 0;
   1.296 +  }
   1.297 +  if( pH->copyKey ){
   1.298 +    pH->xFree(elem->pKey);
   1.299 +  }
   1.300 +  pH->xFree( elem );
   1.301 +  pH->count--;
   1.302 +  if( pH->count<=0 ){
   1.303 +    assert( pH->first==0 );
   1.304 +    assert( pH->count==0 );
   1.305 +    sqlite3HashClear(pH);
   1.306 +  }
   1.307 +}
   1.308 +
   1.309 +/* Attempt to locate an element of the hash table pH with a key
   1.310 +** that matches pKey,nKey.  Return the data for this element if it is
   1.311 +** found, or NULL if there is no match.
   1.312 +*/
   1.313 +void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
   1.314 +  int h;             /* A hash on key */
   1.315 +  HashElem *elem;    /* The element that matches key */
   1.316 +  int (*xHash)(const void*,int);  /* The hash function */
   1.317 +
   1.318 +  if( pH==0 || pH->ht==0 ) return 0;
   1.319 +  xHash = hashFunction(pH->keyClass);
   1.320 +  assert( xHash!=0 );
   1.321 +  h = (*xHash)(pKey,nKey);
   1.322 +  assert( (pH->htsize & (pH->htsize-1))==0 );
   1.323 +  elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
   1.324 +  return elem ? elem->data : 0;
   1.325 +}
   1.326 +
   1.327 +/* Insert an element into the hash table pH.  The key is pKey,nKey
   1.328 +** and the data is "data".
   1.329 +**
   1.330 +** If no element exists with a matching key, then a new
   1.331 +** element is created.  A copy of the key is made if the copyKey
   1.332 +** flag is set.  NULL is returned.
   1.333 +**
   1.334 +** If another element already exists with the same key, then the
   1.335 +** new data replaces the old data and the old data is returned.
   1.336 +** The key is not copied in this instance.  If a malloc fails, then
   1.337 +** the new data is returned and the hash table is unchanged.
   1.338 +**
   1.339 +** If the "data" parameter to this function is NULL, then the
   1.340 +** element corresponding to "key" is removed from the hash table.
   1.341 +*/
   1.342 +void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
   1.343 +  int hraw;             /* Raw hash value of the key */
   1.344 +  int h;                /* the hash of the key modulo hash table size */
   1.345 +  HashElem *elem;       /* Used to loop thru the element list */
   1.346 +  HashElem *new_elem;   /* New element added to the pH */
   1.347 +  int (*xHash)(const void*,int);  /* The hash function */
   1.348 +
   1.349 +  assert( pH!=0 );
   1.350 +  xHash = hashFunction(pH->keyClass);
   1.351 +  assert( xHash!=0 );
   1.352 +  hraw = (*xHash)(pKey, nKey);
   1.353 +  assert( (pH->htsize & (pH->htsize-1))==0 );
   1.354 +  h = hraw & (pH->htsize-1);
   1.355 +  elem = findElementGivenHash(pH,pKey,nKey,h);
   1.356 +  if( elem ){
   1.357 +    void *old_data = elem->data;
   1.358 +    if( data==0 ){
   1.359 +      removeElementGivenHash(pH,elem,h);
   1.360 +    }else{
   1.361 +      elem->data = data;
   1.362 +    }
   1.363 +    return old_data;
   1.364 +  }
   1.365 +  if( data==0 ) return 0;
   1.366 +  new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
   1.367 +  if( new_elem==0 ) return data;
   1.368 +  if( pH->copyKey && pKey!=0 ){
   1.369 +    new_elem->pKey = pH->xMalloc( nKey );
   1.370 +    if( new_elem->pKey==0 ){
   1.371 +      pH->xFree(new_elem);
   1.372 +      return data;
   1.373 +    }
   1.374 +    memcpy((void*)new_elem->pKey, pKey, nKey);
   1.375 +  }else{
   1.376 +    new_elem->pKey = (void*)pKey;
   1.377 +  }
   1.378 +  new_elem->nKey = nKey;
   1.379 +  pH->count++;
   1.380 +  if( pH->htsize==0 ){
   1.381 +    rehash(pH,8);
   1.382 +    if( pH->htsize==0 ){
   1.383 +      pH->count = 0;
   1.384 +      if( pH->copyKey ){
   1.385 +        pH->xFree(new_elem->pKey);
   1.386 +      }
   1.387 +      pH->xFree(new_elem);
   1.388 +      return data;
   1.389 +    }
   1.390 +  }
   1.391 +  if( pH->count > pH->htsize ){
   1.392 +    rehash(pH,pH->htsize*2);
   1.393 +  }
   1.394 +  assert( pH->htsize>0 );
   1.395 +  assert( (pH->htsize & (pH->htsize-1))==0 );
   1.396 +  h = hraw & (pH->htsize-1);
   1.397 +  insertElement(pH, &pH->ht[h], new_elem);
   1.398 +  new_elem->data = data;
   1.399 +  return 0;
   1.400 +}