Blender V2.61 - r43446

BLI_ghash.c

Go to the documentation of this file.
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