00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "sqliteInt.h"
00018 #include <assert.h>
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 void sqliteHashInit(Hash *new, int keyClass, int copyKey){
00033 assert( new!=0 );
00034 assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
00035 new->keyClass = keyClass;
00036 new->copyKey = copyKey &&
00037 (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
00038 new->first = 0;
00039 new->count = 0;
00040 new->htsize = 0;
00041 new->ht = 0;
00042 }
00043
00044
00045
00046
00047
00048 void sqliteHashClear(Hash *pH){
00049 HashElem *elem;
00050
00051 assert( pH!=0 );
00052 elem = pH->first;
00053 pH->first = 0;
00054 if( pH->ht ) sqliteFree(pH->ht);
00055 pH->ht = 0;
00056 pH->htsize = 0;
00057 while( elem ){
00058 HashElem *next_elem = elem->next;
00059 if( pH->copyKey && elem->pKey ){
00060 sqliteFree(elem->pKey);
00061 }
00062 sqliteFree(elem);
00063 elem = next_elem;
00064 }
00065 pH->count = 0;
00066 }
00067
00068
00069
00070
00071 static int intHash(const void *pKey, int nKey){
00072 return nKey ^ (nKey<<8) ^ (nKey>>8);
00073 }
00074 static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
00075 return n2 - n1;
00076 }
00077
00078 #if 0
00079
00080
00081
00082 static int ptrHash(const void *pKey, int nKey){
00083 uptr x = Addr(pKey);
00084 return x ^ (x<<8) ^ (x>>8);
00085 }
00086 static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
00087 if( pKey1==pKey2 ) return 0;
00088 if( pKey1<pKey2 ) return -1;
00089 return 1;
00090 }
00091 #endif
00092
00093
00094
00095
00096 static int strHash(const void *pKey, int nKey){
00097 return sqliteHashNoCase((const char*)pKey, nKey);
00098 }
00099 static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
00100 if( n1!=n2 ) return n2-n1;
00101 return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
00102 }
00103
00104
00105
00106
00107 static int binHash(const void *pKey, int nKey){
00108 int h = 0;
00109 const char *z = (const char *)pKey;
00110 while( nKey-- > 0 ){
00111 h = (h<<3) ^ h ^ *(z++);
00112 }
00113 return h & 0x7fffffff;
00114 }
00115 static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
00116 if( n1!=n2 ) return n2-n1;
00117 return memcmp(pKey1,pKey2,n1);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static int (*hashFunction(int keyClass))(const void*,int){
00133 switch( keyClass ){
00134 case SQLITE_HASH_INT: return &intHash;
00135
00136 case SQLITE_HASH_STRING: return &strHash;
00137 case SQLITE_HASH_BINARY: return &binHash;;
00138 default: break;
00139 }
00140 return 0;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
00150 switch( keyClass ){
00151 case SQLITE_HASH_INT: return &intCompare;
00152
00153 case SQLITE_HASH_STRING: return &strCompare;
00154 case SQLITE_HASH_BINARY: return &binCompare;
00155 default: break;
00156 }
00157 return 0;
00158 }
00159
00160
00161
00162
00163
00164
00165 static void rehash(Hash *pH, int new_size){
00166 struct _ht *new_ht;
00167 HashElem *elem, *next_elem;
00168 HashElem *x;
00169 int (*xHash)(const void*,int);
00170
00171 assert( (new_size & (new_size-1))==0 );
00172 new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
00173 if( new_ht==0 ) return;
00174 if( pH->ht ) sqliteFree(pH->ht);
00175 pH->ht = new_ht;
00176 pH->htsize = new_size;
00177 xHash = hashFunction(pH->keyClass);
00178 for(elem=pH->first, pH->first=0; elem; elem = next_elem){
00179 int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
00180 next_elem = elem->next;
00181 x = new_ht[h].chain;
00182 if( x ){
00183 elem->next = x;
00184 elem->prev = x->prev;
00185 if( x->prev ) x->prev->next = elem;
00186 else pH->first = elem;
00187 x->prev = elem;
00188 }else{
00189 elem->next = pH->first;
00190 if( pH->first ) pH->first->prev = elem;
00191 elem->prev = 0;
00192 pH->first = elem;
00193 }
00194 new_ht[h].chain = elem;
00195 new_ht[h].count++;
00196 }
00197 }
00198
00199
00200
00201
00202
00203 static HashElem *findElementGivenHash(
00204 const Hash *pH,
00205 const void *pKey,
00206 int nKey,
00207 int h
00208 ){
00209 HashElem *elem;
00210 int count;
00211 int (*xCompare)(const void*,int,const void*,int);
00212
00213 if( pH->ht ){
00214 elem = pH->ht[h].chain;
00215 count = pH->ht[h].count;
00216 xCompare = compareFunction(pH->keyClass);
00217 while( count-- && elem ){
00218 if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
00219 return elem;
00220 }
00221 elem = elem->next;
00222 }
00223 }
00224 return 0;
00225 }
00226
00227
00228
00229
00230 static void removeElementGivenHash(
00231 Hash *pH,
00232 HashElem* elem,
00233 int h
00234 ){
00235 if( elem->prev ){
00236 elem->prev->next = elem->next;
00237 }else{
00238 pH->first = elem->next;
00239 }
00240 if( elem->next ){
00241 elem->next->prev = elem->prev;
00242 }
00243 if( pH->ht[h].chain==elem ){
00244 pH->ht[h].chain = elem->next;
00245 }
00246 pH->ht[h].count--;
00247 if( pH->ht[h].count<=0 ){
00248 pH->ht[h].chain = 0;
00249 }
00250 if( pH->copyKey && elem->pKey ){
00251 sqliteFree(elem->pKey);
00252 }
00253 sqliteFree( elem );
00254 pH->count--;
00255 }
00256
00257
00258
00259
00260
00261 void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
00262 int h;
00263 HashElem *elem;
00264 int (*xHash)(const void*,int);
00265
00266 if( pH==0 || pH->ht==0 ) return 0;
00267 xHash = hashFunction(pH->keyClass);
00268 assert( xHash!=0 );
00269 h = (*xHash)(pKey,nKey);
00270 assert( (pH->htsize & (pH->htsize-1))==0 );
00271 elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
00272 return elem ? elem->data : 0;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
00291 int hraw;
00292 int h;
00293 HashElem *elem;
00294 HashElem *new_elem;
00295 int (*xHash)(const void*,int);
00296
00297 assert( pH!=0 );
00298 xHash = hashFunction(pH->keyClass);
00299 assert( xHash!=0 );
00300 hraw = (*xHash)(pKey, nKey);
00301 assert( (pH->htsize & (pH->htsize-1))==0 );
00302 h = hraw & (pH->htsize-1);
00303 elem = findElementGivenHash(pH,pKey,nKey,h);
00304 if( elem ){
00305 void *old_data = elem->data;
00306 if( data==0 ){
00307 removeElementGivenHash(pH,elem,h);
00308 }else{
00309 elem->data = data;
00310 }
00311 return old_data;
00312 }
00313 if( data==0 ) return 0;
00314 new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
00315 if( new_elem==0 ) return data;
00316 if( pH->copyKey && pKey!=0 ){
00317 new_elem->pKey = sqliteMallocRaw( nKey );
00318 if( new_elem->pKey==0 ){
00319 sqliteFree(new_elem);
00320 return data;
00321 }
00322 memcpy((void*)new_elem->pKey, pKey, nKey);
00323 }else{
00324 new_elem->pKey = (void*)pKey;
00325 }
00326 new_elem->nKey = nKey;
00327 pH->count++;
00328 if( pH->htsize==0 ) rehash(pH,8);
00329 if( pH->htsize==0 ){
00330 pH->count = 0;
00331 sqliteFree(new_elem);
00332 return data;
00333 }
00334 if( pH->count > pH->htsize ){
00335 rehash(pH,pH->htsize*2);
00336 }
00337 assert( (pH->htsize & (pH->htsize-1))==0 );
00338 h = hraw & (pH->htsize-1);
00339 elem = pH->ht[h].chain;
00340 if( elem ){
00341 new_elem->next = elem;
00342 new_elem->prev = elem->prev;
00343 if( elem->prev ){ elem->prev->next = new_elem; }
00344 else { pH->first = new_elem; }
00345 elem->prev = new_elem;
00346 }else{
00347 new_elem->next = pH->first;
00348 new_elem->prev = 0;
00349 if( pH->first ){ pH->first->prev = new_elem; }
00350 pH->first = new_elem;
00351 }
00352 pH->ht[h].count++;
00353 pH->ht[h].chain = new_elem;
00354 new_elem->data = data;
00355 return 0;
00356 }