Hashtable

This commit is contained in:
timerix 2023-10-27 14:21:29 +06:00
parent b6088845d9
commit 885ef7fea6
7 changed files with 43 additions and 112 deletions

View File

@ -295,7 +295,9 @@ Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al
.sh_tmp_al=_tmp_al .sh_tmp_al=_tmp_al
}; };
DeserializeSharedData* shared=&_shared; DeserializeSharedData* shared=&_shared;
Hashtable* dict=Hashtable_create(); Hashtable _dict;
Hashtable* dict = &_dict;
Hashtable_construct(dict, _tmp_al);
text--; text--;
while(true){ while(true){

View File

@ -1,62 +0,0 @@
//
// I planned to export functions from DtsodV24.h,
// but C# P/Invoke can't get returned values for some reason.
// Following functions return values by pointer, which looks in C# like out parameter
//
#if __cplusplus
extern "C" {
#endif
#include "DtsodV24.h"
// parses text to binary values
EXPORT void CALL kerep_DtsodV24_deserialize(char* text, Hashtable** output, char** errmsg){
Maybe r=DtsodV24_deserialize(text);
*errmsg=r.errmsg;
*output=r.value.VoidPtr;
}
// creates text representation of dtsod
EXPORT void CALL kerep_DtsodV24_serialize(Hashtable* dtsod, char** output, char** errmsg){
Maybe r=DtsodV24_serialize(dtsod);
*errmsg=r.errmsg;
*output=r.value.VoidPtr;
}
// returns value or UniNull if key not found
EXPORT void CALL kerep_DtsodV24_get(Hashtable* dtsod, char* key, Unitype* output){
*output=DtsodV24_get(dtsod, key);
}
// adds or sets the value
EXPORT void CALL kerep_DtsodV24_addOrSet(Hashtable* dtsod, char* key, Unitype value){
DtsodV24_addOrSet(dtsod, key, value);
}
// checks for dtsod contains value or dont
EXPORT void CALL kerep_DtsodV24_contains(Hashtable* dtsod, char* key, bool* output){
*output=DtsodV24_contains(dtsod, key);
}
// replaces value with UniNull if key exists in dtsod
EXPORT void CALL kerep_DtsodV24_remove(Hashtable* dtsod, char* key, bool* output){
*output=DtsodV24_remove(dtsod, key);
}
// replaces value with UniNull if key exists in dtsod
EXPORT void CALL kerep_DtsodV24_destruct(Hashtable* dtsod){
DtsodV24_destruct(dtsod);
}
EXPORT void CALL kerep_DtsodV24_height(Hashtable* dtsod, u16* heigth){
*heigth=Hashtable_height(dtsod);
}
EXPORT void CALL kerep_DtsodV24_getrow(Hashtable* dtsod, u16 h, Autoarr_KVPair** row){
*row=dtsod->rows[h];
}
#if __cplusplus
}
#endif

View File

@ -7,51 +7,47 @@ static const u16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
#define HT_HEIN_MIN 0 #define HT_HEIN_MIN 0
#define HT_HEIN_MAX 6 #define HT_HEIN_MAX 6
#define ARR_BC 2 #define ARR_SIZE_MAX 16
#define ARR_BL 8
Hashtable* Hashtable_create(){ void Hashtable_construct(Hashtable* ht, allocator_ptr external_al){
Hashtable* ht=malloc(sizeof(Hashtable)); InternalAllocator_setExternalOrConstruct(ht, external_al, LinearAllocator, 1024);
ht->hein=HT_HEIN_MIN; ht->hein=HT_HEIN_MIN;
ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*)); ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*));
allocator_ptr internal_al = InternalAllocator_getPtr(ht);
for(u16 i=0; i<HT_HEIGHTS[HT_HEIN_MIN]; i++) for(u16 i=0; i<HT_HEIGHTS[HT_HEIN_MIN]; i++)
ht->rows[i]=Autoarr_construct(KVPair,ARR_BC,ARR_BL); Autoarr_construct(&ht->rows[i], KVPair, 16, internal_al);
return ht;
} }
u16 __Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
void __Hashtable_destruct(void* _ht){ void __Hashtable_destruct(void* _ht){
Hashtable* ht=_ht; Hashtable* ht=_ht;
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++) for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
Autoarr_destruct(ht->rows[i], true); Autoarr_destruct(&ht->rows[i]);
free(ht->rows); allocator_free(InternalAllocator_getPtr(ht), ht->rows);
InternalAllocator_destructIfInternal(LinearAllocator, ht);
} }
void Hashtable_destruct(Hashtable* ht){ void Hashtable_destruct(Hashtable* ht){
__Hashtable_destruct(ht); __Hashtable_destruct(ht);
free(ht);
} }
u16 Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
void Hashtable_expand(Hashtable* ht){ void Hashtable_expand(Hashtable* ht){
if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH); if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH);
Autoarr(KVPair)** newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*)); Autoarr(KVPair)* newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*));
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++) for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
newrows[i]=Autoarr_construct(KVPair,ARR_BC,ARR_BL); Autoarr_construct(&newrows[i], KVPair, ARR_SIZE_MAX, InternalAllocator_getPtr(ht));
for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){ for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
Autoarr(KVPair)* ar=ht->rows[i]; Autoarr(KVPair)* ar=&ht->rows[i];
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 k=0;k<arlen;k++){ for(u32 k=0;k<arlen;k++){
KVPair p=Autoarr_get(ar,k); KVPair p=Autoarr_get(ar,k);
u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein]; u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein];
Autoarr(KVPair)* newar=newrows[newrown]; Autoarr(KVPair)* newar=&newrows[newrown];
Autoarr_add(newar,p); Autoarr_add(newar,p);
} }
// there is no need to free array values, because they are copied into new array Autoarr_destruct(ar);
// so dont replace this incorrect auto-generated function
Autoarr_destructWithoutMembers(ar, true);
} }
free(ht->rows); free(ht->rows);
@ -60,10 +56,10 @@ void Hashtable_expand(Hashtable* ht){
Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){ Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){
u32 hash=hashs(hash_sdbm32, key); u32 hash=hashs(hash_sdbm32, key);
Autoarr(KVPair)* ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; Autoarr(KVPair)* ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar)) if(can_expand && Autoarr_length(ar) == ARR_SIZE_MAX)
Hashtable_expand(ht); Hashtable_expand(ht);
ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
return ar; return ar;
} }
@ -86,7 +82,8 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair* p=Autoarr_getPtr(ar,i); KVPair* p=Autoarr_getPtr(ar,i);
if(cptr_equals(key,p->key)) return &p->value; if(cptr_equals(key,p->key))
return &p->value;
} }
return NULL; return NULL;
} }
@ -96,7 +93,8 @@ Unitype Hashtable_get(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair p=Autoarr_get(ar,i); KVPair p=Autoarr_get(ar,i);
if(cptr_equals(key,p.key)) return p.value; if(cptr_equals(key,p.key))
return p.value;
} }
return UniNull; return UniNull;
} }

View File

@ -9,17 +9,15 @@ extern "C" {
#include "KeyValuePair.h" #include "KeyValuePair.h"
STRUCT(Hashtable, STRUCT(Hashtable,
InternalAllocator_declare(LinearAllocator);
u8 hein; // height=HT_HEIGHTS[hein] u8 hein; // height=HT_HEIGHTS[hein]
Autoarr(KVPair)** rows; // Autoarr[height] Autoarr(KVPair)* rows; // Autoarr[height]
) )
Hashtable* Hashtable_create(); void Hashtable_construct(Hashtable* ht, allocator_ptr external_al);
void Hashtable_destruct(Hashtable* ht); void Hashtable_destruct(Hashtable* ht);
void __Hashtable_destruct(void* ht); void __Hashtable_destruct(void* ht);
// amount of rows
u16 Hashtable_height(Hashtable* ht);
// don't add pairs with the same keys, // don't add pairs with the same keys,
// or something weird will happen // or something weird will happen
// if not sure, use Hashtable_addOrSet() // if not sure, use Hashtable_addOrSet()
@ -36,11 +34,13 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key);
Unitype Hashtable_get(Hashtable* ht, char* key); Unitype Hashtable_get(Hashtable* ht, char* key);
bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output); bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output);
u16 __Hashtable_height(Hashtable* ht);
#define Hashtable_foreach(HT, EL, codeblock...) { \ #define Hashtable_foreach(HT, EL, codeblock...) { \
u16 hmax=Hashtable_height(HT); \ u16 hmax=__Hashtable_height(HT); \
for(u16 h=0; h<hmax; h++){ \ for(u16 h=0; h<hmax; h++){ \
Autoarr(KVPair)* AR=HT->rows[h]; \ Autoarr(KVPair)* row=&HT->rows[h]; \
Autoarr_foreach(AR, EL, codeblock); \ Autoarr_foreach(row, EL, codeblock); \
} \ } \
} }

View File

@ -1,15 +1,8 @@
#include "KeyValuePair.h" #include "KeyValuePair.h"
kt_define(KVPair, __KVPair_destruct, NULL); kt_define(KVPair, NULL, NULL);
Autoarr_define(KVPair, false) Autoarr_define(KVPair)
// proper way to clean a KVP
void KVPair_destruct(KVPair p){
// free(p.key);
Unitype_destruct(&p.value);
}
void __KVPair_destruct(void* p){ KVPair_destruct(*(KVPair*)p); }
void printkvp(KVPair p){ void printkvp(KVPair p){
kprintf("{\"%s\", ",p.key); kprintf("{\"%s\", ",p.key);

View File

@ -14,8 +14,6 @@ STRUCT(KVPair,
Autoarr_declare(KVPair) Autoarr_declare(KVPair)
// proper way to clean a KVP
void KVPair_destruct(KVPair p);
void __KVPair_destruct(void* p); void __KVPair_destruct(void* p);
void printkvp(KVPair p); void printkvp(KVPair p);

View File

@ -8,7 +8,7 @@ void print_hashtable(Hashtable* ht){
" rows: %p\n", " rows: %p\n",
sizeof(Hashtable), sizeof(Hashtable),
ht->hein, ht->hein,
Hashtable_height(ht), __Hashtable_height(ht),
ht->rows); ht->rows);
} }
@ -18,8 +18,8 @@ void printrowgraph(allocator_ptr al, Hashtable* ht){
u32 lgs[lgs_l]; u32 lgs[lgs_l];
for(u32 i=0; i<lgs_l; i++) for(u32 i=0; i<lgs_l; i++)
lgs[i]=0; lgs[i]=0;
for(u16 h=0;h<Hashtable_height(ht);h++){ for(u16 h=0;h<__Hashtable_height(ht);h++){
Autoarr(KVPair)* ar=ht->rows[h]; Autoarr(KVPair)* ar=&ht->rows[h];
u32 l=Autoarr_length(ar); u32 l=Autoarr_length(ar);
lgs[l]++; lgs[l]++;
} }
@ -63,7 +63,9 @@ void test_hashtable(){
StackingAllocator _al; StackingAllocator _al;
allocator_ptr al=(allocator_ptr)&_al; allocator_ptr al=(allocator_ptr)&_al;
StackingAllocator_construct(&_al, 4096); StackingAllocator_construct(&_al, 4096);
Hashtable* ht=Hashtable_create(); Hashtable _ht;
Hashtable* ht=&_ht;
Hashtable_construct(ht, al);
kprintf("\e[92mhashtable created\n"); kprintf("\e[92mhashtable created\n");
print_hashtable(ht); print_hashtable(ht);
optime("fill",1,fill(al, ht)); optime("fill",1,fill(al, ht));