hos/kernel/proc/hash.cpp

136 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;
myTable = new (vector<hash_entry_t *> *)[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<hash_entry_t *> *vec = myTable[hashed];
kprintf("$2$");
if (!vec)
myTable[hashed] = vec = new vector<hash_entry_t *>;
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<hash_entry_t *> **oldTable = myTable;
mySizeIndex++;
myTable = new (vector<hash_entry_t *> *)[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<hash_entry_t *> *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<hash_entry_t *> *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<hash_entry_t *> *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;
}