master
Avril 6 years ago
parent cf84b9fa46
commit 1561566b04
No known key found for this signature in database
GPG Key ID: DDDD9B6759158726

@ -2,14 +2,27 @@
#define H_DEFAULT_BLOCKSIZE 255 #define H_DEFAULT_BLOCKSIZE 255
struct _h_kvpair_t { #define H_FLAG_EXCHECK (1<<0) //don't check the hash, check the key itself
unsigned int crc32;
struct h_kvpair {
unsigned char fillbit;
unsigned int32_t crc32;
unsigned char data[]; unsigned char data[];
}; };
struct h_page {
struct h_page* next;
struct h_kvpair pairs[]; //blocksize
};
typedef struct { typedef struct {
list_t* back;
size_t keysize; size_t keysize;
size_t valuesize;
size_t blocksize;
unsigned int flags;
h_page* page0;
} hashtable_t; } hashtable_t;
#endif /* _HASHTABLE_H */ #endif /* _HASHTABLE_H */

@ -8,26 +8,123 @@
#include <hashtable.h> #include <hashtable.h>
int32_t _h_getid(void* key, unsigned long* sum, size_t keysize, size_t blocksize) #define h_page struct h_page
#define FILLBIT 0xAB
static int32_t _h_getid(const void* key, unsigned long* sum, size_t keysize, size_t blocksize)
{ {
return (int32_t)((*sum = _h_crc32(0xffffffffu, key, keysize)) % blocksize); return (int32_t)((*sum = _h_crc32(0xffffffffu, key, keysize)) % blocksize);
} }
hashtable_t* h_create(size_t keytype, size_t valuetype, size_t blocksize) static h_page* _h_create_page(size_t keytype, size_t valuetype, size_t blocksize)
{
h_page* page = (h_page*)malloc(sizeof(h_page) + (blocksize*(sizeof(h_kvpair)+keytype+valuetype)));
memset(page, 0, sizeof(h_page) +(blocksize*(sizeof(h_kvpair)+keytype+valuetype)));
return page;
}
static int _h_contains(const h_page* p, int32_t id)
{
return p->pairs[id].fillbit == FILLBIT;
}
static void _h_create_pair(h_kvpair* pair, int32_t crc32,const void * key, size_t keysize, const void* value, size_t valuesize)
{
pair->fillbit = FILLBIT;
pair->crc32 = crc32;
memcpy(pair->data, key, keysize);
memcpy(pair->data+keysize, value, valuesize);
}
static int _h_check_key(const h_kvpair *pair, int32_t crc32, void* key, int ks)
{
if(key) return memcmp(pair->data, key, ks)==0;
else return pair->crc32 == crc32;
}
hashtable_t* h_create(size_t keytype, size_t valuetype, size_t blocksize, unsigned int flags)
{ {
hashtable_t* proto = (hashtable_t*)malloc(sizeof(hashtable_t)); hashtable_t* proto = (hashtable_t*)malloc(sizeof(hashtable_t));
proto->back = l_create(sizeof(struct _h_kvpair_t)+keytype+valuetype, blocksize); proto->page0 = _h_create_page(keytype, valuetype, blocksize); //back = l_create(sizeof(struct _h_kvpair_t)+keytype+valuetype, blocksize);
proto->keysize = keytype; proto->keysize = keytype;
proto->valuesize = valuetype; //we don't need to save this but we will to make it easier.
proto->blocksize = blocksize;
proto->flags = flags;
return proto; return proto;
} }
void h_add(hashtable_t* hash, void* key, void* value) void h_add(hashtable_t* hash, const void* key, const void* value)
{
unsigned long crc32;
int32_t id = _h_getid(key, &crc32, hash->keysize, hash->blocksize);
//TODO: search through pages for empty id match
h_page* page = hash->page0;
while(_h_contains(page, id))
if(page->next==NULL)
{
page->next = _h_create_page(hash->keysize, hash->valuesize, hash->blocksize);
page = page->next;
break; // we know this new one is empty
}
else
page = page->next; //at the moment we allow the same key to be added twice.
_h_create_pair(&page->pairs[id], (int32_t)crc32, key, hash->keysize, value, hash->valuesize);
}
static void* _h_find(const hashtable_t* hash, int32_t* _crc32, h_page** _page, int32_t* _id, const void* key)
{ {
unsigned long crc32; unsigned long crc32;
int32_t id = _h_getid(key, &crc32, hash->keysize, hash->back->blocksize); int32_t id = _h_getid(key, &crc32, hash->keysize, hash->blocksize);
h_page* page = hash->page0;
do {
if(_h_contains(page, id))
{
h_kvpair* pair = &page->pairs[id];
if(_h_check_key(pair, (int32_t)crc32, (hash->flags&H_FLAG_EXCHECK?key:NULL), hash->keysize)) {
if(_crc32!=NULL) *_crc32 = (int32_t)crc32;
if(_page!=NULL) *_page = page;
if(_id!=NULL) *_id = id;
return pair->data+hash->keysize;
}
}
page = page->next;
} while(page!=NULL);
return NULL;
}
void* h_get(const hashtable_t* hash, const void* key)
{
return _h_find(hash, NULL, NULL, NULL, key);
}
void h_set(hashtable_t* hash, const void* key, const void* value)
{
int32_t crc32;
h_kvpair *pair = _h_find(hash, &crc32, NULL, NULL, key);
if(pair!=NULL)
_h_create_pair(pair, crc32, key, value);
}
int h_contains(const hashtable_t* hash, const void* key)
{
return _h_find(hash, NULL,NULL,NULL,key)!=NULL;
}
//TODO: search through blocks as pages for empty id match void h_remove(hashtable_t* hash, const void* key)
{
h_kvpair *pair = _h_find(hash, NULL, NULL, NULL, key);
if(pair!=NULL)
memset(pair, 0, sizeof(h_kvpair)+hash->keysize+hash->valuesize); //we could just set the fillbit to 0, but...
}
int h_count(const hashtable_t* hash)
{
//TODO: Count all entries in all pages
} }

@ -21,7 +21,7 @@ static int _mem_isnull(unsigned char* data, size_t le)
static l_block* _l_create_block(size_t type,int blocksize) static l_block* _l_create_block(size_t type,int blocksize)
{ {
l_block* block= (l_block*) malloc(sizeof(l_block*) + ( blocksize*type)); l_block* block= (l_block*) malloc(sizeof(l_block) + ( blocksize*type));
memset(block, 0, sizeof(l_block*) + ( blocksize*type)); memset(block, 0, sizeof(l_block*) + ( blocksize*type));
return block; return block;
} }

Loading…
Cancel
Save