126 lines
2.9 KiB
C++
126 lines
2.9 KiB
C++
// 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<hash_entry_t>());
|
|
}
|
|
|
|
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<hash_entry_t> > oldTable = myTable;
|
|
mySizeIndex++;
|
|
myTable = vector< vector<hash_entry_t> >();
|
|
for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++)
|
|
myTable.add(vector<hash_entry_t>());
|
|
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");
|
|
}
|
|
|