commit 20ce758528fe57fdacac1960682ac8759c5a4c9c Author: Timerix22 Date: Fri Mar 18 20:39:06 2022 +0300 moved files from DTLib repo diff --git a/Autoarr/Autoarr.c b/Autoarr/Autoarr.c new file mode 100644 index 0000000..e22daaf --- /dev/null +++ b/Autoarr/Autoarr.c @@ -0,0 +1,23 @@ +#include "Autoarr.h" + +define_Autoarr(uint8) +define_Autoarr(int8) +define_Autoarr(uint16) +define_Autoarr(int16) +define_Autoarr(uint32) +define_Autoarr(int32) +define_Autoarr(uint64) +define_Autoarr(int64) +define_Autoarr(float) +define_Autoarr(double) +define_Autoarr(Unitype) + +//right func to clear array of unitype values +void Autoarr_Unitype_clear(Autoarr(Unitype)* ar){ + for(uint32 blockI=0;blockIblocks_count-1;blockI++) + for(uint32 elemI=0;elemImax_block_length;elemI++) + Unitype_free(ar->values[blockI][elemI]); + for(uint32 elemI=0;elemIblock_length;elemI++) + Unitype_free(ar->values[ar->blocks_count-1][elemI]); + Autoarr_clear(ar); +} diff --git a/Autoarr/Autoarr.h b/Autoarr/Autoarr.h new file mode 100644 index 0000000..aefaf0d --- /dev/null +++ b/Autoarr/Autoarr.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Autoarr_declare.h" +#include "Autoarr_define.h" + +declare_Autoarr(uint8) +declare_Autoarr(int8) +declare_Autoarr(uint16) +declare_Autoarr(int16) +declare_Autoarr(uint32) +declare_Autoarr(int32) +declare_Autoarr(uint64) +declare_Autoarr(int64) +declare_Autoarr(float) +declare_Autoarr(double) +declare_Autoarr(Unitype) + +//right func to clear array of unitype values +void Autoarr_Unitype_clear(Autoarr(Unitype)* ar); + +#define Autoarr_foreach(ar,elem,codeblock)({\ + if(ar->blocks_count>0) {\ + typeof(**ar->values) elem;\ + for(uint32 blockI=0;blockIblocks_count-1;blockI++)\ + for(uint32 elemI=0;elemImax_block_length;elemI++){dbg(5);\ + elem=ar->values[blockI][elemI];\ + (codeblock);\ + }\ + for(uint32 elemI=0;elemIblock_length;elemI++){\ + elem=ar->values[ar->blocks_count-1][elemI];\ + (codeblock);\ + }\ + }\ +}) diff --git a/Autoarr/Autoarr_declare.h b/Autoarr/Autoarr_declare.h new file mode 100644 index 0000000..9686a4a --- /dev/null +++ b/Autoarr/Autoarr_declare.h @@ -0,0 +1,61 @@ +#pragma once + +#include "../base/base.h" + +#define declare_Autoarr(type)\ +\ +struct Autoarr_##type;\ +\ +typedef struct {\ + void (*add)(struct Autoarr_##type* ar, type element);\ + type (*get)(struct Autoarr_##type* ar, uint32 index);\ + type* (*getptr)(struct Autoarr_##type* ar, uint32 index);\ + void (*set)(struct Autoarr_##type* ar, uint32 index, type element);\ + void (*clear)(struct Autoarr_##type* ar);\ +} __functions_list_t_##type;\ +\ +typedef struct Autoarr_##type{\ + uint16 blocks_count;\ + uint16 max_blocks_count;\ + uint16 block_length;\ + uint16 max_block_length;\ + type** values;\ + __functions_list_t_##type* functions;\ +} Autoarr_##type;\ +\ +void __Autoarr_add_##type(Autoarr_##type* ar, type element);\ +type __Autoarr_get_##type(Autoarr_##type* ar, uint32 index);\ +type* __Autoarr_getptr_##type(Autoarr_##type* ar, uint32 index);\ +void __Autoarr_set_##type(Autoarr_##type* ar, uint32 index, type element);\ +void __Autoarr_clear_##type(Autoarr_##type* ar);\ +Autoarr_##type __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length); + +#define Autoarr(type) Autoarr_##type + +#define Autoarr_add(autoarr, element)\ + autoarr->functions->add(autoarr, element) +#define Autoarr_get(autoarr, index)\ + autoarr->functions->get(autoarr,index) +#define Autoarr_getptr(autoarr, index)\ + autoarr->functions->getptr(autoarr,index) +#define Autoarr_set(autoarr, index, element)\ + autoarr->functions->set(autoarr, index, element) +#define Autoarr_clear(autoarr)\ + autoarr->functions->clear(autoarr) +#define Autoarr_create(type, max_blocks_count, max_block_length)\ + __Autoarr_create_##type(max_blocks_count, max_block_length) + +#define Autoarr_length(autoarr) \ + (uint32)(!autoarr->blocks_count ? 0 : \ + autoarr->max_block_length*(autoarr->blocks_count-1)+autoarr->block_length) +#define Autoarr_max_length(autoarr)\ + (uint32)(autoarr->max_block_length*autoarr->max_blocks_count) + +#define Autoarr_remove(AR){\ + if(AR->block_length==1){\ + AR->blocks_count--;\ + AR->block_length=AR->max_block_length;\ + free(AR->values[AR->blocks_count]);\ + }\ + else AR->block_length--;\ +} diff --git a/Autoarr/Autoarr_define.h b/Autoarr/Autoarr_define.h new file mode 100644 index 0000000..a02d2ff --- /dev/null +++ b/Autoarr/Autoarr_define.h @@ -0,0 +1,64 @@ +#pragma once + +#include "../base/base.h" + +#define define_Autoarr(type)\ +\ +void __Autoarr_add_##type(Autoarr_##type* ar, type element){\ + if(!ar->values){\ + ar->values=malloc(ar->max_blocks_count*sizeof(type*));\ + goto create_block;\ + }\ + if(ar->block_length==ar->max_block_length){\ + if (ar->blocks_count>=ar->max_blocks_count) throw(ERR_MAXLENGTH);\ + ar->block_length=0;\ +create_block:\ + ar->values[ar->blocks_count]=malloc(ar->max_block_length*sizeof(type));\ + ar->blocks_count++;\ + }\ + ar->values[ar->blocks_count-1][ar->block_length]=element;\ + ar->block_length++;\ +}\ +\ +type __Autoarr_get_##type(Autoarr_##type* ar, uint32 index){\ + if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX);\ + return ar->values[index/ar->max_block_length][index%ar->max_block_length];\ +}\ +\ +type* __Autoarr_getptr_##type(Autoarr_##type* ar, uint32 index){\ + if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX);\ + return ar->values[index/ar->max_block_length]+(index%ar->max_block_length);\ +}\ +\ +void __Autoarr_set_##type(Autoarr_##type* ar, uint32 index, type element){\ + if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX);\ + ar->values[index/ar->max_block_length][index%ar->max_block_length]=element;\ +}\ +\ +void __Autoarr_clear_##type(Autoarr_##type* ar){\ + for(uint16 i=0; iblocks_count;i++)\ + free(ar->values[i]); \ + free(ar->values);\ + ar->values=NULL;\ + ar->blocks_count=0;\ + ar->block_length=0;\ +}\ +\ +__functions_list_t_##type __functions_list_##type={\ + &__Autoarr_add_##type,\ + &__Autoarr_get_##type,\ + &__Autoarr_getptr_##type,\ + &__Autoarr_set_##type,\ + &__Autoarr_clear_##type\ +};\ +\ +Autoarr_##type __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length){\ + return (Autoarr_##type){\ + .max_blocks_count=max_blocks_count,\ + .blocks_count=0,\ + .max_block_length=max_block_length,\ + .block_length=0,\ + .values=NULL,\ + .functions=&__functions_list_##type\ + };\ +} diff --git a/Autoarr/StringBuilder.c b/Autoarr/StringBuilder.c new file mode 100644 index 0000000..1eb729e --- /dev/null +++ b/Autoarr/StringBuilder.c @@ -0,0 +1,71 @@ +#include "StringBuilder.h" + +StringBuilder StringBuilder_create(uint16 max_blocks_count, uint16 max_block_length){ + return Autoarr_create(int8,max_blocks_count,max_block_length); +} + +void StringBuilder_append_char(StringBuilder* b, char c){ + Autoarr_add(b,c); +} + +void StringBuilder_append_cptr(StringBuilder* b, char* s){ + char c; + while((c=*s++)) + Autoarr_add(b,c); +} + +void StringBuilder_append_string(StringBuilder* b, string s){ + while(s.length>0){ + Autoarr_add(b,*s.ptr++); + s.length--; + } +} + +void StringBuilder_append_int64(StringBuilder* b, int64 a){ + uint8 i=0; + if(a==0){ + Autoarr_add(b,'0'); + } + else if(a<0){ + Autoarr_add(b,'-'); + a=-a; + } + char buf[24]; + while(a!=0){ + buf[i++]='0'+a%10; + a/=10; + } + string rev=string_reverse((string){buf,i}); + StringBuilder_append_string(b,rev); + free(rev.ptr); +} + +void StringBuilder_append_uint64(StringBuilder* b, uint64 a){ + uint8 i=0; + if(a==0){ + Autoarr_add(b,'0'); + } + char buf[24]; + while(a!=0){ + buf[i++]='0'+a%10; + a/=10; + } + string rev=string_reverse((string){buf,i}); + StringBuilder_append_string(b,rev); + free(rev.ptr); +} + +void StringBuilder_append_double(StringBuilder* b, double a){ + char buf[32]; + sprintf(buf,"%lf",a); + StringBuilder_append_cptr(b,buf); +} + +char* StringBuilder_build(StringBuilder* b){ + uint32 len=Autoarr_length(b); + char* str=malloc(len+1); + str[len]=0; + for(uint32 i=0;i0) throw(ERR_ENDOFSTR); + return nameStr; + }; + + Unitype ReadValue(){ + //returns part of without quotes + char* ReadString(){ + bool prevIsBackslash=false; + StringBuilder _b=StringBuilder_create(STRB_BC,STRB_BL); + StringBuilder* b=&_b; + while ((c=*++text)){ + if(c=='"') { + if(prevIsBackslash) { + //replacing <\"> with <"> + Autoarr_remove(b); + StringBuilder_append_char(b,c); + } + else { + char* str=StringBuilder_build(b); + Autoarr_clear(b); + return str; + } + } + else { + prevIsBackslash= c=='\\' && !prevIsBackslash; + StringBuilder_append_char(b,c); + } + } + throw(ERR_ENDOFSTR); + return NULL; + }; + + Autoarr(Unitype)* ReadList(){ + Autoarr(Unitype)* list=malloc(sizeof(Autoarr(Unitype))); + *list=Autoarr_create(Unitype,ARR_BC,ARR_BL); + readingList=true; + while (true){ + Autoarr_add(list,ReadValue()); + if (!readingList) break; + } + return list; + }; + + Hashtable* ReadDtsod(){ + ++text; //skips '{' + return __deserialize(&text,true); + } + + Unitype ParseValue(string str){ + //printf("\e[94m<\e[96m%s\e[94m>\n",string_cpToCharPtr(str)); + const string nullStr={"null",4}; + const string trueStr={"true",4}; + const string falseStr={"false",5}; + switch(*str.ptr){ + case 'n': + if(string_compare(str,nullStr)) + return UniNull; + else throw_wrongchar(*str.ptr); + break; + case 't': + if(string_compare(str,trueStr)) + return UniTrue; + else throw_wrongchar(*str.ptr); + break; + case 'f': + if(string_compare(str,falseStr)) + return UniFalse; + else throw_wrongchar(*str.ptr); + break; + default: + switch(str.ptr[str.length-1]){ + case 'f': { + char* _c=string_cpToCharPtr(str); + Unitype rez=Uni(Double,strtod(_c,NULL)); + free(_c); + return rez; + } + case 'u': { + uint64 lu=0; + char* _c=string_cpToCharPtr(str); + sscanf(_c,"%lu",&lu); + free(_c); + return Uni(UInt64,lu); + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + int64 li=0; + char* _c=string_cpToCharPtr(str); + if(sscanf(_c,"%li",&li)!=1){ + char err[64]; + sprintf(err,"can't parse to int: <%s>",_c); + throw(err); + } + + free(_c); + return Uni(Int64,li); + } + default: + throw_wrongchar(str.ptr[str.length-1]); + } + } + throw(ERR_ENDOFSTR); + return UniNull; + }; + + string valueStr={text+1,0}; + Unitype value; + while ((c=*++text)) switch (c){ + case ' ': case '\t': + case '\r': case '\n': + if(valueStr.length!=0) + throw_wrongchar(c); + valueStr.ptr++; + break; + case '=': case ':': + case '}': case '$': + throw_wrongchar(c); + break; + case '#':; + char _c=c; + SkipComment(); + if(valueStr.length!=0) + throw_wrongchar(_c); + valueStr.ptr=text+1; //skips '\n' + break; + case '"': + if(valueStr.length!=0) throw_wrongchar(c); + value=UniPtr(CharPtr,ReadString()); + break; + case '\'': + if(valueStr.length!=0) throw_wrongchar(c); + char valueChar=*++text; + if (*++text != '\'') throw("after <'> should be char"); + value=Uni(Char,valueChar); + break; + case '[': + if(valueStr.length!=0) throw_wrongchar(c); + value=UniPtr(AutoarrUnitypePtr,ReadList()); + case ']': + readingList=false; + break; + case '{': + if(valueStr.length!=0) throw_wrongchar(c); + value=UniPtr(HashtablePtr,ReadDtsod()); + return value; + case ';': + case ',': + if(valueStr.length!=0) + value=ParseValue(valueStr); + return value; + default: + valueStr.length++; + break; + } + + throw(ERR_ENDOFSTR); + return UniNull; + }; + + text--; + while((c=*++text)){ + string name=ReadName(); + if(name.length==0) //end of file or '}' in recursive call + goto END; + char* nameCPtr=string_cpToCharPtr(name); + Unitype value=ReadValue(); + if(partOfDollarList){ + Autoarr(Unitype)* list; + Unitype lu; + if(Hashtable_try_get(dict,nameCPtr, &lu)){ + list=(Autoarr(Unitype)*)lu.VoidPtr; + } + else{ + list=malloc(sizeof(Autoarr(Unitype))); + *list=Autoarr_create(Unitype,ARR_BC,ARR_BL); + Hashtable_add(dict,nameCPtr,UniPtr(AutoarrUnitypePtr,list)); + } + Autoarr_add(list,value); + } + else Hashtable_add(dict,nameCPtr,value); + } + END: + *_text=text; + return dict; +} + +Hashtable* DtsodV24_deserialize(char* text) { + Hashtable* r=__deserialize(&text,false); + return r; +} diff --git a/DtsodParser/DtsodV24_serialize.c b/DtsodParser/DtsodV24_serialize.c new file mode 100644 index 0000000..eb71929 --- /dev/null +++ b/DtsodParser/DtsodV24_serialize.c @@ -0,0 +1,90 @@ +#include "DtsodV24.h" +#include "../Autoarr/StringBuilder.h" + +//65536 max length! +#define STRB_BC 64 +#define STRB_BL 1024 + +#define addc(B,C) StringBuilder_append_char(B,C) + +void __serialize(StringBuilder* b, uint8 tabs, Hashtable* dtsod){ + + void AppendTabs(){ + for(uint8 t=0; t + + +## Building on Linux +**Required packages:** gcc + +```bash +make build +```` diff --git a/Hashtable/Hashtable.c b/Hashtable/Hashtable.c new file mode 100644 index 0000000..393d0e8 --- /dev/null +++ b/Hashtable/Hashtable.c @@ -0,0 +1,101 @@ +#include "Hashtable.h" + +// amount of rows +#define HT_HEIN_MIN 0 +#define HT_HEIN_MAX 5 +static const uint16 HT_HEIGHTS[]={61,257,1021,4099,16381,65521}; + +#define ARR_BC 2 +#define ARR_BL 8 + +Hashtable* Hashtable_create(){ + Hashtable* ht=malloc(sizeof(Hashtable)); + ht->hein=HT_HEIN_MIN; + ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KeyValuePair))); + for(uint16 i=0;irows[i]=Autoarr_create(KeyValuePair,ARR_BC,ARR_BL); + return ht; +} + +void Hashtable_free(Hashtable* ht){ + for(uint16 i=0;ihein];i++){ + Autoarr_KeyValuePair_clear(ht->rows+i); + } + free(ht->rows); + free(ht); +} + +uint32 Hashtable_height(Hashtable* ht){ return HT_HEIGHTS[ht->hein]; } + + +void Hashtable_expand(Hashtable* ht){ + if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH); + Autoarr(KeyValuePair)* newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KeyValuePair))); + for(uint16 i=0;ihein];i++) + newrows[i]=Autoarr_create(KeyValuePair,ARR_BC,ARR_BL); + for(uint16 i=0;ihein-1];i++){ + Autoarr(KeyValuePair)* ar=ht->rows+i; + uint32 arlen=Autoarr_length(ar); + for(uint16 k=0;khein]; + Autoarr(KeyValuePair)* newar=newrows+newrown; + Autoarr_add(newar,p); + } + Autoarr_clear(ar); + } + free(ht->rows); + ht->rows=newrows; +} + +Autoarr(KeyValuePair)* getrow(Hashtable* ht, char* key, bool can_expand){ + Autoarr(KeyValuePair)* ar=ht->rows+ihash(key)%HT_HEIGHTS[ht->hein]; + if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar)) + optime("expand",1,(Hashtable_expand(ht))); + ar=ht->rows+ihash(key)%HT_HEIGHTS[ht->hein]; + return ar; +} + + +void Hashtable_add_pair(Hashtable* ht, KeyValuePair p){ + Autoarr_add(getrow(ht,p.key,true),p); +} +void Hashtable_add(Hashtable* ht, char* key, Unitype u){ + Hashtable_add_pair(ht,KVPair(key,u)); +} + +//returns null or pointer to value in hashtable +Unitype* Hashtable_getptr(Hashtable* ht, char* key){ + Autoarr(KeyValuePair)* ar=getrow(ht,key,false); + uint32 arlen=Autoarr_length(ar); + for(uint32 i=0;ikey)) return &p->value; + } + return NULL; +} + +Unitype Hashtable_get(Hashtable* ht, char* key){ + Autoarr(KeyValuePair)* ar=getrow(ht,key,false); + uint32 arlen=Autoarr_length(ar); + for(uint32 i=0;irows+h;\ + Autoarr_foreach(AR, EL, codeblock);\ + }\ +}) diff --git a/Hashtable/KeyValuePair.c b/Hashtable/KeyValuePair.c new file mode 100644 index 0000000..c11ae9f --- /dev/null +++ b/Hashtable/KeyValuePair.c @@ -0,0 +1,26 @@ +#include "KeyValuePair.h" + +define_Autoarr(KeyValuePair) + + +//proper way to clear a KVP +void KeyValuePair_free(KeyValuePair p){ + free(p.key); + Unitype_free(p.value); +} + +//func for KVP array clearing +void Autoarr_KeyValuePair_clear(Autoarr_KeyValuePair* ar){ + for(uint16 blockI=0; blockI < ar->blocks_count-1; blockI++) + for(uint16 elemI=0; elemI < ar->max_block_length; elemI++) + KeyValuePair_free(ar->values[blockI][elemI]); + for(uint16 elemI=0; elemI < ar->block_length; elemI++) + KeyValuePair_free(ar->values[ar->blocks_count-1][elemI]); + Autoarr_clear(ar); +} + +void printkvp(KeyValuePair p){ + printf("{\"%s\", ",p.key); + printuni(p.value); + printf("}"); +} diff --git a/Hashtable/KeyValuePair.h b/Hashtable/KeyValuePair.h new file mode 100644 index 0000000..efde40a --- /dev/null +++ b/Hashtable/KeyValuePair.h @@ -0,0 +1,17 @@ +#include "../base/base.h" +#include "../Autoarr/Autoarr.h" + +typedef struct KeyValuePair{ + char* key; + Unitype value; +} KeyValuePair; + +declare_Autoarr(KeyValuePair) + +//proper way to clear a KVP +void KeyValuePair_free(KeyValuePair p); + +//func to clear KVP array +void Autoarr_KeyValuePair_clear(Autoarr_KeyValuePair* ar); + +void printkvp(KeyValuePair p); diff --git a/Hashtable/hash.c b/Hashtable/hash.c new file mode 100644 index 0000000..32ff34f --- /dev/null +++ b/Hashtable/hash.c @@ -0,0 +1,15 @@ +#include "hash.h" + +uint32 ihash(char *str){ + uint32 hash=5381; + for (char c=*str;c;c=*(++str)) + hash=((hash<<5)+hash)+c; + return hash; +} + +uint64 lhash(char* str){ + uint64 hash = 0; + for (char c=*str;c;c=*(++str)) + hash=c+(hash<<6)+(hash<<16)-hash; + return hash; +} diff --git a/Hashtable/hash.h b/Hashtable/hash.h new file mode 100644 index 0000000..6f9ac73 --- /dev/null +++ b/Hashtable/hash.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../base/base.h" + +//djb2 hash function from http://www.cse.yorku.ca/~oz/hash.html +uint32 ihash(char *str); +//sdbm hash function +uint64 lhash(char* str); diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6bea83 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +SRC=$(wildcard [^tests]**/*.c) +TESTS=$(wildcard tests/*c) $(wildcard tests/**/*.c) +OUTDIR=.bin +OUTFILE=$(OUTDIR)/kerep_test.com +CMP=gcc +all: clear_c build test + +clear_c: + clear +clear_bin: + @echo -e '\e[96m--------------[clear_bin]--------------\e[0m' + touch $(OUTDIR)/_.com + rm $(OUTDIR)/*.com + +clang: CMP=clang +clang: all + +CMPARGS= -Wall -Wno-discarded-qualifiers $(SRC) $(TESTS) -o $(OUTFILE) +build: + @echo -e '\n\e[96m----------------[build]----------------\e[0m' + @mkdir -p $(OUTDIR) + $(CMP) -O1 -flto $(CMPARGS) +build_dbg: + @echo -e '\n\e[96m--------------[build_dbg]--------------\e[0m' + @mkdir -p $(OUTDIR) + $(CMP) -O0 -g $(CMPARGS).dbg +test: + @echo -e '\n\e[96m----------------[test]-----------------\e[0m' + $(OUTFILE) +valgrind: clear_c build_dbg + @echo -e '\n\e[96m--------------[valgrind]---------------\e[0m' + valgrind -s --read-var-info=yes --track-origins=yes --fullpath-after=kerep/ \ + --leak-check=full --show-leak-kinds=all $(OUTFILE).dbg diff --git a/README.md b/README.md new file mode 100644 index 0000000..004b191 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# kerep + +My static library written in C \ No newline at end of file diff --git a/SearchTree/SearchTree.c b/SearchTree/SearchTree.c new file mode 100644 index 0000000..6e47548 --- /dev/null +++ b/SearchTree/SearchTree.c @@ -0,0 +1,91 @@ +#include "SearchTree.h" + +STNode* STNode_create(){ + STNode* node=malloc(sizeof(STNode)); + node->branches=NULL; + node->value.type=Null; + node->value.UInt64=0; + return node; +} + +void STNode_free(STNode* node){ + if (!node) throw(ERR_NULLPTR); + if(node->branches){ + for(uint8 n32 = 0;n32<8;n32++){ + STNode*** ptrn32=(STNode***)node->branches[n32]; + if(ptrn32){ + for(uint8 n4 = 0;n4<8;n4++){ + STNode** ptrn4=ptrn32[n4]; + if (ptrn4){ + for(uint8 rem=0;rem<4;rem++){ + STNode* ptrrem=ptrn4[rem]; + if(ptrrem) + STNode_free(ptrrem); + } + free(ptrn4); + } + } + free(ptrn32); + } + } + free(node->branches); + } + if(node->value.VoidPtr) + Unitype_free(node->value); + free(node); +} + +typedef struct {uint8 n32, n4, rem;} indexes3; + +indexes3 splitindex(uint8 i){ + return (indexes3){ + .n32=i/32, + .n4=i%32/4, + .rem=i%32%4, + }; +} + +void ST_push(STNode* node_first, const char* key, Unitype value){ + if (!node_first) throw(ERR_NULLPTR); + STNode* node_last=node_first; + while(*key){ + indexes3 i3=splitindex((uint8)*key); + if(!node_last->branches){ + node_last->branches=(STNode****)malloc(8*sizeof(STNode*)); + for(uint8 i=0;i<8;i++) + node_last->branches[i]=(STNode***)NULL; + } + if(!node_last->branches[i3.n32]){ + node_last->branches[i3.n32]=(STNode***)malloc(8*sizeof(STNode*)); + for(uint8 i=0;i<8;i++) + node_last->branches[i3.n32][i]=(STNode**)NULL; + } + if(!node_last->branches[i3.n32][i3.n4]){ + node_last->branches[i3.n32][i3.n4]=(STNode**)malloc(4*sizeof(STNode*)); + for(uint8 i=0;i<4;i++) + node_last->branches[i3.n32][i3.n4][i]=(STNode*)NULL; + } + if(!node_last->branches[i3.n32][i3.n4][i3.rem]) + node_last->branches[i3.n32][i3.n4][i3.rem]=STNode_create(); + node_last=node_last->branches[i3.n32][i3.n4][i3.rem]; + key++; + } + node_last->value=value; +} + +Unitype ST_pull(STNode* node_first, const char* key){ + if (!node_first) throw(ERR_NULLPTR); + STNode* node_last=node_first; + while (*key){ + indexes3 i3=splitindex((uint8)*key); + if(!node_last->branches) return UniNull; + STNode*** ptrn32=(STNode***)node_last->branches[i3.n32]; + if(!ptrn32) return UniNull; + STNode** ptrn4=ptrn32[i3.n4]; + if(!ptrn4) return UniNull; + node_last=ptrn4[i3.rem]; + if(!node_last) return UniNull; + key++; + } + return node_last->value; +} diff --git a/SearchTree/SearchTree.h b/SearchTree/SearchTree.h new file mode 100644 index 0000000..af757c4 --- /dev/null +++ b/SearchTree/SearchTree.h @@ -0,0 +1,14 @@ +#pragma once + +#include "../base/base.h" + +typedef struct SearchTreeNode{ + struct SearchTreeNode**** branches; //*STNode[8][8][4] + Unitype value; +} STNode; + +STNode* STNode_create(); +void STNode_free(STNode* node); + +void ST_push(STNode* node, const char* key, Unitype value); +Unitype ST_pull(STNode* node, const char* key); diff --git a/SearchTree/SearchTree.md b/SearchTree/SearchTree.md new file mode 100644 index 0000000..a18d4e3 --- /dev/null +++ b/SearchTree/SearchTree.md @@ -0,0 +1,25 @@ +# Search Tree + +byte is dividing into indexes of 3d array of nodes +``` +STNode.branches byte +┃ +┣━[0]━┳━[0]━┳━[0] 0 +┃ ┃ ┣━... +┃ ┃ ┗━[3] 3 +┃ ┣━... +┃ ┃ +┃ ┗━[7]━┳━[0] 28 +┃ ┣━... +┃ ┗━[3] 31 +┣━... +┃ +┗━[7]━┳━[0]━┳━[0] 224 + ┃ ┣━... + ┃ ┗━[3] 227 + ┣━... + ┃ + ┗━[7]━┳━[0] 252 + ┣━... + ┗━[3] 255 +``` \ No newline at end of file diff --git a/base/base.h b/base/base.h new file mode 100644 index 0000000..499c6ef --- /dev/null +++ b/base/base.h @@ -0,0 +1,17 @@ +#pragma once + +#include "std.h" +#include "types.h" +#include "errors.h" +#include "mystr.h" + +// executes codeblock and prints execution time +#define optime(opname,repeats,codeblock) ({\ + struct timespec start, stop;\ + clock_gettime(CLOCK_REALTIME, &start);\ + for(uint64 ___OPREP=0;___OPREP0) + dst[len]=src[len]; + return dst; +} + +//compares two char buffers, NullPtr-friendly +bool cptr_compare(char* key0, char* key1){ + if(!key0) return key1 ? false : true; + if(!key1) return false; + while(*key0&&*key1) + if(*key0++ != *key1++) + return false; + return true; +} + +//multiplies char n times +char* char_multiply(char c, uint32 n){ + char* rez=malloc(n+1); + rez[n]=0; + while(n-->0) + rez[n]=c; + return rez; +} + +//copies str content to new char pointer value (adding '\0' at the end) +char* string_cpToCharPtr(string str){ + char* cptr=malloc(str.length*sizeof(char)+1); + if(str.length==0) return NULL; + cptr[str.length]=0; + while(str.length-->0) + cptr[str.length]=str.ptr[str.length]; + return cptr; +} + +//copies cptr content (excluding '\0' at the end) to new string +string string_cpFromCharPtr(char* cptr){ + if(!cptr) return stringNull; + string str; + str.length=cptr_length(cptr)-1; + str.ptr=malloc(str.length); + for(uint32 i=0;i0) + if(*str0.ptr++ != *str1.ptr++) + return false; + return true; +} + +//creates new string which is reversed variant of +string string_reverse(string s){ + string r={malloc(s.length), s.length}; + for(uint32 i=0; i +string string_reverse(string s); diff --git a/base/std.h b/base/std.h new file mode 100644 index 0000000..25b7fc5 --- /dev/null +++ b/base/std.h @@ -0,0 +1,13 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +#define CHOOSE(B, Y, N) __builtin_choose_expr(B, Y, N) + +#define IFTYPE(X, T) __builtin_types_compatible_p(typeof(X), T) + +#define dbg(N) printf("\e[95m%d\n",N) diff --git a/base/types.c b/base/types.c new file mode 100644 index 0000000..8ccb309 --- /dev/null +++ b/base/types.c @@ -0,0 +1,130 @@ +#include "types.h" +#include "errors.h" +#include "../Autoarr/Autoarr.h" +#include "../Hashtable/Hashtable.h" +#include "../SearchTree/SearchTree.h" + +const char* typename(my_type t){ + switch (t) { + case Null: return "Null"; + case Double: return "Double"; + case Float: return "Float"; + case Bool: return "Bool"; + case Char: return "Char"; + case Int8: return "Int8"; + case UInt8: return "UInt8"; + case Int16: return "Int16"; + case UInt16: return "UInt16"; + case Int32: return "Int32"; + case UInt32: return "UInt32"; + case Int64: return "Int64"; + case UInt64: return "UInt64"; + case Int8Ptr: return "Int8Ptr"; + case UInt8Ptr: return "UInt8Ptr"; + case Int16Ptr: return "Int16Ptr"; + case UInt16Ptr: return "UInt16Ptr"; + case Int32Ptr: return "Int32Ptr"; + case UInt32Ptr: return "UInt32Ptr"; + case Int64Ptr: return "Int64Ptr"; + case UInt64Ptr: return "UInt64Ptr"; + case CharPtr: return "CharPtr"; + case STNodePtr: return "STNodePtr"; + case HashtablePtr: return "HashtablePtr"; + case UniversalType: return "Unitype"; + case AutoarrInt8Ptr: return "AutoarrInt8Ptr"; + case AutoarrUInt8Ptr: return "AutoarrUInt8Ptr"; + case AutoarrInt16Ptr: return "AutoarrInt16Ptr"; + case AutoarrUInt16Ptr: return "AutoarrUInt16Ptr"; + case AutoarrInt32Ptr: return "AutoarrInt32Ptr"; + case AutoarrUInt32Ptr: return "AutoarrUInt32Ptr"; + case AutoarrInt64Ptr: return "AutoarrInt64Ptr"; + case AutoarrUInt64Ptr: return "AutoarrUInt64Ptr"; + case AutoarrUnitypePtr: return "AutoarrUnitypePtr"; + case AutoarrKVPairPtr: return "AutoarrKVPairPtr"; + default: throw(ERR_WRONGTYPE); return "ERROR"; + } +} + +//frees VoidPtr value or does nothing if type isn't pointer +void Unitype_free(Unitype u){ + switch (u.type) { + case Null: + case Float: + case Double: + case Char: + case Bool: + case Int8: + case UInt8: + case Int16: + case UInt16: + case Int32: + case UInt32: + case Int64: + case UInt64: + break; + case Int8Ptr: + case UInt8Ptr: + case Int16Ptr: + case UInt16Ptr: + case Int32Ptr: + case UInt32Ptr: + case Int64Ptr: + case UInt64Ptr: + case CharPtr: + free(u.VoidPtr); + break; + case HashtablePtr: + Hashtable_free(u.VoidPtr); + break; + case STNodePtr: + STNode_free(u.VoidPtr); + break; + case AutoarrInt8Ptr: + Autoarr_clear(((Autoarr(int8)*)u.VoidPtr)); + break; + case AutoarrUInt8Ptr: + Autoarr_clear(((Autoarr(uint8)*)u.VoidPtr)); + break; + case AutoarrInt16Ptr: + Autoarr_clear(((Autoarr(int16)*)u.VoidPtr)); + break; + case AutoarrUInt16Ptr: + Autoarr_clear(((Autoarr(uint16)*)u.VoidPtr)); + break; + case AutoarrInt32Ptr: + Autoarr_clear(((Autoarr(int32)*)u.VoidPtr)); + break; + case AutoarrUInt32Ptr: + Autoarr_clear(((Autoarr(uint32)*)u.VoidPtr)); + break; + case AutoarrInt64Ptr: + Autoarr_clear(((Autoarr(int64)*)u.VoidPtr)); + break; + case AutoarrUInt64Ptr: + Autoarr_clear(((Autoarr(uint64)*)u.VoidPtr)); + break; + case AutoarrUnitypePtr: + Autoarr_Unitype_clear(u.VoidPtr); + free((Autoarr(Unitype)*)u.VoidPtr); + break; + case AutoarrKVPairPtr: + Autoarr_KeyValuePair_clear(u.VoidPtr); + free((Autoarr(KeyValuePair)*)u.VoidPtr); + break; + default: throw(ERR_WRONGTYPE); + } +} + + +void printuni(Unitype v){ + switch (v.type) { + case Null: printf("{Null}");break; + case Double: printf("{%s : %lf}",typename(v.type),v.Double);break; + case Char: printf("{%s : '%c'}",typename(v.type),v.Char);break; + case Bool: + case UInt64: printf("{%s : %lu}",typename(v.type),v.UInt64);break; + case Int64: printf("{%s : %ld}",typename(v.type),v.Int64);break; + case CharPtr: printf("{%s : \"%s\"}",typename(v.type),(char*)v.VoidPtr);break; + default: printf("{%s : %p}",typename(v.type),v.VoidPtr);break; + } +} diff --git a/base/types.h b/base/types.h new file mode 100644 index 0000000..3bc5728 --- /dev/null +++ b/base/types.h @@ -0,0 +1,52 @@ +#pragma once + +#include "std.h" + +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +typedef enum my_type{ + Null, Float, Double, Char, Bool, + UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, + UInt8Ptr, Int8Ptr, UInt16Ptr, Int16Ptr, UInt32Ptr, Int32Ptr, UInt64Ptr, Int64Ptr, + CharPtr, STNodePtr, HashtablePtr, + UniversalType, + AutoarrInt8Ptr, AutoarrUInt8Ptr, AutoarrInt16Ptr, AutoarrUInt16Ptr, + AutoarrInt32Ptr, AutoarrUInt32Ptr, AutoarrInt64Ptr, AutoarrUInt64Ptr, + AutoarrUnitypePtr, AutoarrKVPairPtr +} __attribute__ ((__packed__)) my_type; + +//returns type name +const char* typename(my_type t); + +// returns size of type in bytes +int8 typesize(my_type type); + +// can store any base type +typedef struct Unitype{ + my_type type; + union { + int64 Int64; + uint64 UInt64; + double Double; + char Char; + bool Bool; + void* VoidPtr; + }; +} Unitype; + +static const Unitype UniNull={Null,.VoidPtr=NULL}; +static const Unitype UniTrue={Bool,.Bool=true}; +static const Unitype UniFalse={Bool,.Bool=false}; + +#define Uni(TYPE,VAL) (Unitype){.type=TYPE,.TYPE=VAL} +#define UniPtr(TYPE,VAL) (Unitype){.type=TYPE,.VoidPtr=VAL} + +//frees VoidPtr value or does nothing if type isn't pointer +void Unitype_free(Unitype u); +void printuni(Unitype v); diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..e9ffe28 --- /dev/null +++ b/tests/main.c @@ -0,0 +1,19 @@ +#include "../base/base.h" +#include "tests.h" + +void test_all(){ + /* test_searchtree(); + test_autoarr(); + test_hashtable(); + test_string(); */ + test_dtsod(); + printf("\e[96m---------------------------------------\e[0m\n"); +} + +int main(){ + setlocale(LC_ALL, "en-US.Unicode"); + printf("\e[92mdtsod parser in c language!\e[97m\n"); + optime("test_all",1,{test_all();}); + printf("\e[0m\n"); + return 0; +} diff --git a/tests/test_autoarr.c b/tests/test_autoarr.c new file mode 100644 index 0000000..7faf28d --- /dev/null +++ b/tests/test_autoarr.c @@ -0,0 +1,52 @@ +#include "tests.h" +#include "../Autoarr/Autoarr.h" + +static void printautoarr(Autoarr(uint16)* ar){ + printf("\e[94mAutoarr(uint16): %lu\n" + " max_blocks_count: %u\n" + " blocks_count: %u\n" + " max_block_length: %u\n" + " block_length: %u\n" + " max_length: %u\n" + " length: %u\n", + sizeof(Autoarr(uint16)), + ar->max_blocks_count, + ar->blocks_count, + ar->max_block_length, + ar->block_length, + Autoarr_max_length(ar), + Autoarr_length(ar)); +} + +static void fillar(Autoarr(uint16)* ar){ + for (uint16 i=0;ihein, + Hashtable_height(ht), + ht->rows); +} + +void printrowgraph(Hashtable* ht){ + printf("\e[94mrow length graph:\n"); + uint16 lgs_l=1000; + uint32 lgs[lgs_l]; + for(uint32 i=0; irows+h; + uint32 l=Autoarr_length(ar); + lgs[l]++; + } + for(uint32 i=0; i0) { + char* str0=char_multiply(' ',i>=100?0:(i>=10?1:2)); + char* str1=char_multiply(' ',lgs[i]>=100?0:(lgs[i]>=10?1:2)); + char* str2=char_multiply('#',lgs[i]/100); + printf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2); + free(str0); + free(str1); + free(str2); + } +} + +void fill(Hashtable* ht){ + for(uint32 i=0;i<100000;i++){ + char* key=malloc(12); + sprintf(key,"key__%u",i); + Hashtable_add(ht,key,Uni(UInt64,i)); + } +} + +Unitype gett(Hashtable* ht){ + char* key=malloc(12); + Unitype u; + for(uint32 i=0;i<100000;i++){ + sprintf(key,"key__%u",i); + u=Hashtable_get(ht,key); + } + free(key); + return u; +} + + +void test_hashtable(){ + optime("test_hashtable",1,({ + printf("\e[96m-----------[test_hashtable]------------\n"); + Hashtable* ht=Hashtable_create(); + printf("\e[92mhashtable created\n"); + print_hashtable(ht); + optime("fill",1,fill(ht)); + optime("get",1,gett(ht)); + printrowgraph(ht); + print_hashtable(ht); + Hashtable_free(ht); + printf("\e[92mhashtable freed\n"); + })); +} diff --git a/tests/test_searchtree.c b/tests/test_searchtree.c new file mode 100644 index 0000000..eab380b --- /dev/null +++ b/tests/test_searchtree.c @@ -0,0 +1,71 @@ +#include "tests.h" +#include "../SearchTree/SearchTree.h" + +void printstnode(STNode* node){ + printf("\e[94mSTNode: %lu\n address: %p\n value: ",sizeof(STNode),node); + printuni(node->value); + // prints pointers to all existing branches + printf("\n branches: %p\n", node->branches); + if(node->branches) for(uint8 i=0;i<8;i++){ + printf(" \e[90m[%u]=%p\n",i,node->branches[i]); + if(node->branches[i]) + for (uint8 ii = 0; ii < 8; ii++){ + printf(" \e[90m[%u]=%p\n",ii,node->branches[i][ii]); + if(node->branches[i][ii]) + for (uint8 iii = 0; iii < 4; iii++) + printf(" \e[90m[%u]=%p\n",iii,node->branches[i][ii][iii]); + } + + } +} + +void test_searchtree(){ + optime("test_searchtree",1,({ + printf("\e[96m-----------[test_searchtree]-----------\n"); + STNode* node=STNode_create(); + printf("\e[92mnode created\n"); + printf("push:\e[94m\n "); + Unitype u={.type=Int64,.Int64=-3}; + printuni(u); + ST_push(node,"type", u); + printf(" -> type\n "); + u=(Unitype){.type=Int64,.Int64=25}; + printuni(u); + ST_push(node,"time", u); + printf(" -> time\n "); + u=(Unitype){.type=Double,.Double=-542.00600}; + printuni(u); + ST_push(node,"author_id", u); + printf(" -> author_id\n "); + u=(Unitype){.type=Int64,.Int64=-31255}; + printuni(u); + ST_push(node,"channel_id", u); + printf(" -> channel_id\n "); + u=(Unitype){.type=Double,.Double=32.2004}; + printuni(u); + ST_push(node,"message_id", u); + printf(" -> message_id\n "); + u=(Unitype){.type=Int8Ptr,.VoidPtr=malloc(1)}; + printuni(u); + ST_push(node,"text", u); + printf(" -> text\n"); + printf("\e[92mpull:\e[94m"); + printf("\n type -> "); + printuni(ST_pull(node,"type")); + printf("\n time -> "); + printuni(ST_pull(node,"time")); + printf("\n author_id -> "); + printuni(ST_pull(node,"author_id")); + printf("\n channel_id -> "); + printuni(ST_pull(node,"channel_id")); + printf("\n message_id -> "); + printuni(ST_pull(node,"message_id")); + printf("\n text -> "); + printuni(ST_pull(node,"text")); + printf("\n"); + printf("\e[92mfirst node: "); + printstnode(node); + STNode_free(node); + printf("\e[92mnode deleted\n"); + })); +} diff --git a/tests/test_string.c b/tests/test_string.c new file mode 100644 index 0000000..d6202ef --- /dev/null +++ b/tests/test_string.c @@ -0,0 +1,16 @@ +#include "tests.h" +#include "../base/mystr.h" + +void test_string(){ + optime(__func__,1,({ + printf("\e[96m-------------[test_string]-------------\n"); + char c[]="0123456789abcdef"; + string s=string_cpFromCharPtr(c); + printf("\e[92m\"%s\" -> string_cpFromCharPtr()\n",c); + if(s.length!=16) throw("string created with incorrect length"); + char* p=string_cpToCharPtr(s); + printf("\e[92mstring_cpToCharPtr() -> \"%s\"\n",p); + free(p); + free(s.ptr); + })); +} \ No newline at end of file diff --git a/tests/tests.h b/tests/tests.h new file mode 100644 index 0000000..a357fd2 --- /dev/null +++ b/tests/tests.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../base/base.h" + +void printuni(Unitype v); + +void test_searchtree(); +void test_autoarr(); +void test_hashtable(); +void test_string(); +void test_dtsod();