// 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; for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++) myTable.add(vector()); } int hash::add(u32_t key, void *val) { u32_t hashed = hash_key(key); for (u32_t i = 0; i < myTable[hashed].size(); i++) if ( myTable[hashed][i].key == key ) return -1; // key exists already kprintf("hash.cpp: %d (slot %d) -> %d\n", key, hashed, val); hash_entry_t he = {key, val}; kprintf("hash.cpp: going to add {%d, %d} to vector %d\n", he.key, he.data, hashed); myTable[hashed].add(he); kprintf("hash.cpp: finished adding %d -> %d\n", myTable[hashed][myTable[hashed].size()-1].key, myTable[hashed][myTable[hashed].size()-1].data); mySize++; if ( mySize > (hash_primes[mySizeIndex] << 1) ) // re-hash { kprintf("re-hashing\n"); vector< vector > oldTable = myTable; mySizeIndex++; myTable = vector< vector >(); for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++) myTable.add(vector()); mySize = 0; for (u32_t i = 0; i < hash_primes[mySizeIndex - 1]; i++) { for (u32_t j = 0; j < oldTable[i].size(); j++) { add( oldTable[i][j].key, oldTable[i][j].data ); } } } return 0; } void *hash::get(u32_t key) { u32_t hashed = hash_key(key); for (u32_t i = 0; i < myTable[hashed].size(); i++) if ( myTable[hashed][i].key == key ) return myTable[hashed][i].data; return NULL; } int hash::remove(u32_t key) { u32_t hashed = hash_key(key); for (u32_t i = 0; i < myTable[hashed].size(); i++) if ( myTable[hashed][i].key == key ) { myTable[hashed].remove(i); // remove key mySize--; return 0; } return -1; } int hash::exists(u32_t key) { u32_t hashed = hash_key(key); for (u32_t i = 0; i < myTable[hashed].size(); i++) if ( myTable[hashed][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; } void hash::dump() { kprintf("hash table @ 0x%x : {\n", &myTable); for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++) { kprintf("\t%d @ 0x%x (", i, &myTable[i]); for (u32_t j = 0; j < myTable[i].size(); j++) kprintf("%s%d -> %d @ 0x%x", (j ? ", " : ""), myTable[i][j].key, myTable[i][j].data, &myTable[i][j]); kprintf(")\n"); } kprintf("}\n"); }