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