void SuperHashTable::doDeleteElement(unsigned v) { #ifdef HASHSIZE_POWER2 unsigned hm = (tablesize - 1); #endif unsigned hs = tablesize; unsigned vn = v; table[v] = NULL; while (1) { vn++; if (vn==hs) vn = 0; void *et2 = table[vn]; if (!et2) break; #ifdef HASHSIZE_POWER2 unsigned vm = getHashFromElement(et2) & hm; if (((vn+hs-vm) & hm)>=((vn+hs-v) & hm)) // diff(vn,vm)>=diff(vn,v) #else unsigned vm = getHashFromElement(et2) % hs; if (((vn+hs-vm) % hs)>=((vn+hs-v) % hs)) // diff(vn,vm)>=diff(vn,v) #endif { table[v] = et2; v = vn; table[v] = NULL; } } tablecount--; }
void SuperHashTable::expand(unsigned newsize) { if (newsize < tablesize) throw MakeStringException(0, "HashTable expanded beyond 2^32 items"); void * *newtable = (void * *) checked_malloc(newsize*sizeof(void *),-603); memset(newtable,0,newsize*sizeof(void *)); void * *oldtable = table; unsigned i; for (i = 0; i < tablesize; i++) { void *et = oldtable[i]; if (et) { #ifdef HASHSIZE_POWER2 unsigned v = getHashFromElement(et) & (newsize - 1); #else unsigned v = getHashFromElement(et) % newsize; #endif while (newtable[v]) { v++; if (v==newsize) v = 0; } newtable[v] = et; } } free(table); table = newtable; tablesize = newsize; }
unsigned SuperHashTable::doFindExact(const void *et) const { unsigned i = cache; if (i>=tablesize || table[i]!=et) { #ifdef HASHSIZE_POWER2 i = getHashFromElement(et) & (tablesize - 1); #else i = getHashFromElement(et) % tablesize; #endif unsigned is = i; for (;;) { const void * cur = table[i]; if (!cur || cur == et) break; i++; if (i==tablesize) i = 0; if (i==is) break; } setCache(i); } return i; }
bool SuperHashTable::doAdd(void * donor, bool replace) { unsigned vs = getHashFromElement(donor); unsigned vm = doFind(vs, getFindParam(donor)); void *et = table[vm]; if (et) { if (replace) { onRemove(et); table[vm] = donor; onAdd(donor); return true; } else return false; } else { unsigned tablelim = getTableLimit(tablesize); if (tablecount>=tablelim) { expand(); vm = doFind(vs, getFindParam(donor)); } tablecount++; table[vm] = donor; onAdd(donor); } return true; }
unsigned SuperHashTable::doFindExact(const void *et) const { unsigned i = cache; if (i>=tablesize || table[i]!=et) { #ifdef HASHSIZE_POWER2 i = getHashFromElement(et) & (tablesize - 1); #else i = getHashFromElement(et) % tablesize; #endif unsigned is = i; while (table[i]!=et) { i++; if (i==tablesize) i = 0; if (!table[i] || i==is) break; } } return i; }
void *SuperHashTable::addOrFind(void * donor) { unsigned vs = getHashFromElement(donor); unsigned vm = doFind(vs, getFindParam(donor)); void *et = table[vm]; if(!et) { unsigned tablelim = getTableLimit(tablesize); if (tablecount>=tablelim) { expand(); vm = doFind(vs, getFindParam(donor)); } tablecount++; table[vm] = donor; onAdd(donor); return donor; } return et; }
void *SuperHashTable::findElement(const void * findEt) const { unsigned vm = doFindElement(getHashFromElement(findEt), findEt); void *et = table[vm]; return et; }
void SuperHashTable::addNew(void * donor) { addNew(donor, getHashFromElement(donor)); }