Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 * A general (pointer -> pointer) hash table ADT 00027 */ 00028 00033 #include <string.h> 00034 #include <stdlib.h> 00035 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 00040 00041 // #include "BLI_blenlib.h" 00042 00043 #include "BLI_mempool.h" 00044 #include "BLI_utildefines.h" 00045 #include "BLI_ghash.h" 00046 00047 #include "BLO_sys_types.h" // for intptr_t support 00048 /***/ 00049 00050 static unsigned int hashsizes[]= { 00051 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 00052 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 00053 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 00054 268435459 00055 }; 00056 00057 /***/ 00058 00059 GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) 00060 { 00061 GHash *gh= MEM_mallocN(sizeof(*gh), info); 00062 gh->hashfp= hashfp; 00063 gh->cmpfp= cmpfp; 00064 gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, FALSE, FALSE); 00065 00066 gh->cursize= 0; 00067 gh->nentries= 0; 00068 gh->nbuckets= hashsizes[gh->cursize]; 00069 00070 gh->buckets= MEM_mallocN(gh->nbuckets*sizeof(*gh->buckets), "buckets"); 00071 memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets)); 00072 00073 return gh; 00074 } 00075 00076 int BLI_ghash_size(GHash *gh) 00077 { 00078 return gh->nentries; 00079 } 00080 00081 void BLI_ghash_insert(GHash *gh, void *key, void *val) 00082 { 00083 unsigned int hash= gh->hashfp(key)%gh->nbuckets; 00084 Entry *e= (Entry*) BLI_mempool_alloc(gh->entrypool); 00085 00086 e->key= key; 00087 e->val= val; 00088 e->next= gh->buckets[hash]; 00089 gh->buckets[hash]= e; 00090 00091 if (++gh->nentries>(float)gh->nbuckets/2) { 00092 Entry **old= gh->buckets; 00093 int i, nold= gh->nbuckets; 00094 00095 gh->nbuckets= hashsizes[++gh->cursize]; 00096 gh->buckets= (Entry**)MEM_mallocN(gh->nbuckets*sizeof(*gh->buckets), "buckets"); 00097 memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets)); 00098 00099 for (i=0; i<nold; i++) { 00100 for (e= old[i]; e;) { 00101 Entry *n= e->next; 00102 00103 hash= gh->hashfp(e->key)%gh->nbuckets; 00104 e->next= gh->buckets[hash]; 00105 gh->buckets[hash]= e; 00106 00107 e= n; 00108 } 00109 } 00110 00111 MEM_freeN(old); 00112 } 00113 } 00114 00115 void *BLI_ghash_lookup(GHash *gh, const void *key) 00116 { 00117 if(gh) { 00118 unsigned int hash= gh->hashfp(key)%gh->nbuckets; 00119 Entry *e; 00120 00121 for (e= gh->buckets[hash]; e; e= e->next) 00122 if (gh->cmpfp(key, e->key)==0) 00123 return e->val; 00124 } 00125 return NULL; 00126 } 00127 00128 int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) 00129 { 00130 unsigned int hash= gh->hashfp(key)%gh->nbuckets; 00131 Entry *e; 00132 Entry *p = NULL; 00133 00134 for (e= gh->buckets[hash]; e; e= e->next) { 00135 if (gh->cmpfp(key, e->key)==0) { 00136 Entry *n= e->next; 00137 00138 if (keyfreefp) keyfreefp(e->key); 00139 if (valfreefp) valfreefp(e->val); 00140 BLI_mempool_free(gh->entrypool, e); 00141 00142 /* correct but 'e' isnt used before return */ 00143 /* e= n; */ /*UNUSED*/ 00144 if (p) 00145 p->next = n; 00146 else 00147 gh->buckets[hash] = n; 00148 00149 --gh->nentries; 00150 return 1; 00151 } 00152 p = e; 00153 } 00154 00155 return 0; 00156 } 00157 00158 int BLI_ghash_haskey(GHash *gh, void *key) 00159 { 00160 unsigned int hash= gh->hashfp(key)%gh->nbuckets; 00161 Entry *e; 00162 00163 for (e= gh->buckets[hash]; e; e= e->next) 00164 if (gh->cmpfp(key, e->key)==0) 00165 return 1; 00166 00167 return 0; 00168 } 00169 00170 void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) 00171 { 00172 int i; 00173 00174 if (keyfreefp || valfreefp) { 00175 for (i=0; i<gh->nbuckets; i++) { 00176 Entry *e; 00177 00178 for (e= gh->buckets[i]; e; ) { 00179 Entry *n= e->next; 00180 00181 if (keyfreefp) keyfreefp(e->key); 00182 if (valfreefp) valfreefp(e->val); 00183 00184 e= n; 00185 } 00186 } 00187 } 00188 00189 MEM_freeN(gh->buckets); 00190 BLI_mempool_destroy(gh->entrypool); 00191 gh->buckets = NULL; 00192 gh->nentries = 0; 00193 gh->nbuckets = 0; 00194 MEM_freeN(gh); 00195 } 00196 00197 /***/ 00198 00199 GHashIterator *BLI_ghashIterator_new(GHash *gh) 00200 { 00201 GHashIterator *ghi= MEM_mallocN(sizeof(*ghi), "ghash iterator"); 00202 ghi->gh= gh; 00203 ghi->curEntry= NULL; 00204 ghi->curBucket= -1; 00205 while (!ghi->curEntry) { 00206 ghi->curBucket++; 00207 if (ghi->curBucket==ghi->gh->nbuckets) 00208 break; 00209 ghi->curEntry= ghi->gh->buckets[ghi->curBucket]; 00210 } 00211 return ghi; 00212 } 00213 void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) 00214 { 00215 ghi->gh= gh; 00216 ghi->curEntry= NULL; 00217 ghi->curBucket= -1; 00218 while (!ghi->curEntry) { 00219 ghi->curBucket++; 00220 if (ghi->curBucket==ghi->gh->nbuckets) 00221 break; 00222 ghi->curEntry= ghi->gh->buckets[ghi->curBucket]; 00223 } 00224 } 00225 void BLI_ghashIterator_free(GHashIterator *ghi) 00226 { 00227 MEM_freeN(ghi); 00228 } 00229 00230 void *BLI_ghashIterator_getKey(GHashIterator *ghi) 00231 { 00232 return ghi->curEntry?ghi->curEntry->key:NULL; 00233 } 00234 void *BLI_ghashIterator_getValue(GHashIterator *ghi) 00235 { 00236 return ghi->curEntry?ghi->curEntry->val:NULL; 00237 } 00238 00239 void BLI_ghashIterator_step(GHashIterator *ghi) 00240 { 00241 if (ghi->curEntry) { 00242 ghi->curEntry= ghi->curEntry->next; 00243 while (!ghi->curEntry) { 00244 ghi->curBucket++; 00245 if (ghi->curBucket==ghi->gh->nbuckets) 00246 break; 00247 ghi->curEntry= ghi->gh->buckets[ghi->curBucket]; 00248 } 00249 } 00250 } 00251 int BLI_ghashIterator_isDone(GHashIterator *ghi) 00252 { 00253 return !ghi->curEntry; 00254 } 00255 00256 /***/ 00257 00258 unsigned int BLI_ghashutil_ptrhash(const void *key) 00259 { 00260 return (unsigned int)(intptr_t)key; 00261 } 00262 int BLI_ghashutil_ptrcmp(const void *a, const void *b) 00263 { 00264 if (a==b) 00265 return 0; 00266 else 00267 return (a<b)?-1:1; 00268 } 00269 00270 unsigned int BLI_ghashutil_inthash(const void *ptr) 00271 { 00272 uintptr_t key = (uintptr_t)ptr; 00273 00274 key += ~(key << 16); 00275 key ^= (key >> 5); 00276 key += (key << 3); 00277 key ^= (key >> 13); 00278 key += ~(key << 9); 00279 key ^= (key >> 17); 00280 00281 return (unsigned int)(key & 0xffffffff); 00282 } 00283 00284 int BLI_ghashutil_intcmp(const void *a, const void *b) 00285 { 00286 if (a==b) 00287 return 0; 00288 else 00289 return (a<b)?-1:1; 00290 } 00291 00292 unsigned int BLI_ghashutil_strhash(const void *ptr) 00293 { 00294 const char *s= ptr; 00295 unsigned int i= 0; 00296 unsigned char c; 00297 00298 while ( (c= *s++) ) 00299 i= i*37 + c; 00300 00301 return i; 00302 } 00303 int BLI_ghashutil_strcmp(const void *a, const void *b) 00304 { 00305 return strcmp(a, b); 00306 } 00307 00308 GHashPair *BLI_ghashutil_pairalloc(const void *first, int second) 00309 { 00310 GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair"); 00311 pair->first = first; 00312 pair->second = second; 00313 return pair; 00314 } 00315 00316 unsigned int BLI_ghashutil_pairhash(const void *ptr) 00317 { 00318 const GHashPair *pair = ptr; 00319 unsigned int hash = BLI_ghashutil_ptrhash(pair->first); 00320 return hash ^ BLI_ghashutil_inthash(SET_INT_IN_POINTER(pair->second)); 00321 } 00322 00323 int BLI_ghashutil_paircmp(const void *a, const void *b) 00324 { 00325 const GHashPair *A = a; 00326 const GHashPair *B = b; 00327 00328 int cmp = BLI_ghashutil_ptrcmp(A->first, B->first); 00329 if(cmp == 0) 00330 return BLI_ghashutil_intcmp(SET_INT_IN_POINTER(A->second), SET_INT_IN_POINTER(B->second)); 00331 return cmp; 00332 } 00333 00334 void BLI_ghashutil_pairfree(void *ptr) 00335 { 00336 MEM_freeN((void*)ptr); 00337 } 00338