// hash.cpp // Author: Josh Holtrop // Date: 08/28/05 // Modified: 08/28/05 // Implements a basic hash table (u32_t -> void*) #define __HOS_CPP__ #include "hos_defines.h" #include "hash.h" #include "lang/vector.h" extern "C"{ #include "display/kout.h" #include "mm/vmm.h" } /* Hash Primes come from * http://planetmath.org/encyclopedia/GoodHashTablePrimes.html */ const u32_t hash_primes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; hash::hash() { mySizeIndex = 0; mySize = 0; myTable = new (vector *)[hash_primes[mySizeIndex]]; for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++) myTable[i] = NULL; } int hash::add(u32_t key, void *val) { kprintf("$1$"); u32_t hashed = hash_key(key); vector *vec = myTable[hashed]; kprintf("$2$"); if (!vec) myTable[hashed] = vec = new vector; for (u32_t i = 0; i < vec->size(); i++) if ( (*vec)[i]->key == key ) return -1; // key exists already kprintf("$3$"); hash_entry_t *he = (hash_entry_t *) New(hash_entry_t); kprintf("("); for (u32_t i = 0; i < vec->size(); i++) kprintf("%d,", (*vec)[i]->key); kprintf(")"); he->key = key; he->data = val; vec->add(he); mySize++; kprintf("*%d*\t", mySize); if ( mySize > (hash_primes[mySizeIndex] << 1) ) // re-hash { kprintf("*1*"); vector **oldTable = myTable; mySizeIndex++; myTable = new (vector *)[hash_primes[mySizeIndex]]; for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++) myTable[i] = NULL; mySize = 0; kprintf("*2*"); for (u32_t i = 0; i < hash_primes[mySizeIndex - 1]; i++) { if (oldTable[i]) { for (u32_t j = 0; j < oldTable[i]->size(); j++) { add( (*(oldTable[i]))[j]->key, (*(oldTable[i]))[j]->data ); kfree( (*(oldTable[i]))[j] ); } delete oldTable[i]; } } kprintf("*3*"); delete oldTable; } return 0; } void *hash::get(u32_t key) { u32_t hashed = hash_key(key); vector *vec = myTable[hashed]; if (!vec) return NULL; for (u32_t i = 0; i < vec->size(); i++) if ( (*vec)[i]->key == key ) return (*vec)[i]->data; return NULL; } int hash::remove(u32_t key) { u32_t hashed = hash_key(key); vector *vec = myTable[hashed]; if (!vec) return -1; for (u32_t i = 0; i < vec->size(); i++) if ( (*vec)[i]->key == key ) { kfree( (*vec)[i] ); vec->remove(i); // remove key mySize--; return 0; } return -1; } int hash::exists(u32_t key) { u32_t hashed = hash_key(key); vector *vec = myTable[hashed]; if (!vec) return 0; for (u32_t i = 0; i < vec->size(); i++) if ( (*vec)[i]->key == key ) return 1; // key exists return 0; } u32_t hash::hash_key(u32_t key) { return key % hash_primes[mySizeIndex]; } u32_t hash::size() { return mySize; }