project structure changed for clion

This commit is contained in:
2022-05-08 13:59:28 +03:00
parent 703bd4bef4
commit c6c70c6fcc
46 changed files with 92 additions and 29 deletions

19
src/Autoarr/Autoarr.c Normal file
View File

@@ -0,0 +1,19 @@
#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_free_Unitype(Autoarr(Unitype)* ar){
Autoarr_foreach(ar, u,Unitype_free(u));
Autoarr_free(ar);
}

42
src/Autoarr/Autoarr.h Normal file
View File

@@ -0,0 +1,42 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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_free_Unitype(Autoarr(Unitype)* ar);
#define Autoarr_foreach(ar,elem,codeblock)({\
if(ar->blocks_count>0) {\
typeof(**ar->values) elem;\
for(uint32 blockI=0;blockI<ar->blocks_count-1;blockI++)\
for(uint32 elemI=0;elemI<ar->max_block_length;elemI++){\
elem=ar->values[blockI][elemI];\
(codeblock);\
}\
for(uint32 elemI=0;elemI<ar->block_length;elemI++){\
elem=ar->values[ar->blocks_count-1][elemI];\
(codeblock);\
}\
}\
})
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,38 @@
#if __cplusplus
extern "C" {
#endif
#include "Autoarr.h"
#include "../Hashtable/KeyValuePair.h"
EXPORT void CALL kerep_Autoarr_KVPair_create(uint16 max_blocks_count, uint16 max_block_length, Autoarr_KVPair** output){
*output=Autoarr_create(KVPair, max_blocks_count, max_block_length);
}
EXPORT void CALL kerep_Autoarr_KVPair_free(Autoarr_KVPair* ar){
Autoarr_free_KVPair(ar);
}
EXPORT void CALL kerep_Autoarr_KVPair_get(Autoarr_KVPair* ar, uint32 index, KVPair* output){
*output=Autoarr_get(ar, index);
}
EXPORT void CALL kerep_Autoarr_KVPair_add(Autoarr_KVPair* ar, KVPair element){
Autoarr_add(ar, element);
}
EXPORT void CALL kerep_Autoarr_KVPair_set(Autoarr_KVPair* ar, uint32 index, KVPair element){
Autoarr_set(ar, index, element);
}
EXPORT void CALL kerep_Autoarr_KVPair_length(Autoarr_KVPair* ar, uint32* output){
*output=Autoarr_length(ar);
}
EXPORT void CALL kerep_Autoarr_KVPair_max_length(Autoarr_KVPair* ar, uint32* output){
*output=Autoarr_max_length(ar);
}
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,37 @@
#if __cplusplus
extern "C" {
#endif
#include "Autoarr.h"
EXPORT void CALL kerep_Autoarr_Unitype_create(uint16 max_blocks_count, uint16 max_block_length, Autoarr_Unitype** output){
*output=Autoarr_create(Unitype, max_blocks_count, max_block_length);
}
EXPORT void CALL kerep_Autoarr_Unitype_free(Autoarr_Unitype* ar){
Autoarr_free_Unitype(ar);
}
EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, uint32 index, Unitype* output){
*output=Autoarr_get(ar, index);
}
EXPORT void CALL kerep_Autoarr_Unitype_add(Autoarr_Unitype* ar, Unitype element){
Autoarr_add(ar, element);
}
EXPORT void CALL kerep_Autoarr_Unitype_set(Autoarr_Unitype* ar, uint32 index, Unitype element){
Autoarr_set(ar, index, element);
}
EXPORT void CALL kerep_Autoarr_Unitype_length(Autoarr_Unitype* ar, uint32* output){
*output=Autoarr_length(ar);
}
EXPORT void CALL kerep_Autoarr_Unitype_max_length(Autoarr_Unitype* ar, uint32* output){
*output=Autoarr_max_length(ar);
}
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,69 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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 (*_free)(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_free_##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_free(autoarr)\
autoarr->functions->_free(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_pop(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--;\
}
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,72 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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_free_##type(Autoarr_##type* ar){\
for(uint16 i=0; i<ar->blocks_count;i++)\
free(ar->values[i]); \
free(ar->values);\
free(ar);\
}\
\
__functions_list_t_##type __functions_list_##type={\
&__Autoarr_add_##type,\
&__Autoarr_get_##type,\
&__Autoarr_getptr_##type,\
&__Autoarr_set_##type,\
&__Autoarr_free_##type\
};\
\
Autoarr_##type* __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length){\
Autoarr_##type* ar=malloc(sizeof(Autoarr_##type));\
*ar=(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\
};\
return ar;\
}
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,30 @@
#include "DtsodV24.h"
// returns UniNull if key not found
Unitype DtsodV24_get(Hashtable* dtsod, char* key){
return Hashtable_get(dtsod, key);
}
// adds or sets value
void DtsodV24_addOrSet(Hashtable* dtsod, char* key, Unitype value){
Hashtable_addOrSet(dtsod,key,value);
}
// checks for dtsod contains value or dont
bool DtsodV24_contains(Hashtable* dtsod, char* key){
Unitype* val=Hashtable_getptr(dtsod, key);
return val!=NULL;
}
// replaces value with UniNull if key exists in dtsod
bool DtsodV24_remove(Hashtable* dtsod, char* key){
Unitype* val=Hashtable_getptr(dtsod, key);
if (!val) return false;
*val=UniNull;
return true;
}
// frees memory including memory of elements (hashtables, autoarrs, etc.)
void DtsodV24_free(Hashtable* dtsod){
Hashtable_free(dtsod);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../Hashtable/Hashtable.h"
// parses text to binary values
Maybe DtsodV24_deserialize(char* text);
// creates text representation of dtsod
Maybe DtsodV24_serialize(Hashtable* dtsod);
// returns value or UniNull if key not found
Unitype DtsodV24_get(Hashtable* dtsod, char* key);
// adds or sets value
void DtsodV24_addOrSet(Hashtable* dtsod, char* key, Unitype value);
// checks for dtsod contains value or dont
bool DtsodV24_contains(Hashtable* dtsod, char* key);
// replaces value with UniNull if key exists in dtsod
bool DtsodV24_remove(Hashtable* dtsod, char* key);
// frees memory including memory of elements (hashtables, autoarrs, etc.)
void DtsodV24_free(Hashtable* dtsod);
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,342 @@
#include "DtsodV24.h"
#include "../String/StringBuilder.h"
#define ARR_BC 64
#define ARR_BL 1024
typedef struct DeserializeSharedData{
const char* sh_text_first;
char* sh_text;
bool sh_partOfDollarList;
bool sh_calledRecursively;
} DeserializeSharedData;
#define text shared->sh_text
#define partOfDollarList shared->sh_partOfDollarList
#define calledRecursively shared->sh_calledRecursively
// special func for throwing error messages about wrong characters in deserializing text
Maybe ERROR_WRONGCHAR(const char c, char* _text, char* text_first, const char* srcfile, int line, const char* funcname){
char errBuf[68];
for(uint8 n=0; n<sizeof(errBuf);n++)
errBuf[n]='\0';
char* errText=_text-32;
uint8 cplace=32;
if(errText<text_first) {
cplace=_text-text_first;
errText=text_first;
}
uint8 i=0;
for(; i<cplace; i++){
// writes 32 chars before the wrongchar
errBuf[i]=errText[i];
}
//prints wrongchar in braces
errBuf[i++]='<';
errBuf[i++]=c;
errBuf[i++]='>';
for(; i<cplace+3+32; i++){
// writes 32 chars after the wrongchar
char _c=errText[i-2];
errBuf[i]=_c;
if(!_c) break;
}
char errmsg[1024];
IFWIN(
sprintf_s(errmsg,1024, "unexpected <%c> at:\n"
" \"%s\"\n"
"\\___[%s:%d] %s()",
c,errBuf, srcfile,line,funcname),
sprintf(errmsg, "unexpected <%c> at:\n"
" \"%s\"\n"
" \\___[%s:%d] %s()",
c,errBuf, srcfile,line,funcname)
);
safethrow(errmsg,;);
}
#define safethrow_wrongchar(C, freeMem) { freeMem; return ERROR_WRONGCHAR(C, text, shared->sh_text_first, __FILE__,__LINE__,__func__); }
Maybe __SkipComment(DeserializeSharedData* shared) {
char c;
while ((c=*++text) != '\n')
if (!c) safethrow(ERR_ENDOFSTR,;);
return MaybeNull;
}
#define SkipComment() __SkipComment(shared)
Maybe __ReadName(DeserializeSharedData* shared){
char c;
string nameStr={text+1,0};
while ((c=*++text)) switch (c){
case ' ': case '\t':
case '\r': case '\n':
if(nameStr.length!=0)
safethrow_wrongchar(c,;);
nameStr.ptr++;
break;
case '=': case ';':
case '\'': case '"':
case '[': case ']':
case '{':
safethrow_wrongchar(c,;);
break;
case '#': ;
char _c=c;
char* _text=text;
try(SkipComment(),_,;);
if(nameStr.length!=0){
text=_text;
safethrow_wrongchar(_c,;);
}
nameStr.ptr=text+1; // skips '\n'
break;
case '}':
if(!calledRecursively || nameStr.length!=0)
safethrow_wrongchar(c,;);
return SUCCESS(UniPtr(CharPtr,NULL));
case ':':
return SUCCESS(UniPtr(CharPtr,string_extract(nameStr)));
case '$':
if(nameStr.length!=0)
safethrow_wrongchar(c,;);
nameStr.ptr++;
partOfDollarList=true;
break;
default:
nameStr.length++;
break;
}
if(nameStr.length>0) safethrow(ERR_ENDOFSTR,;);
return SUCCESS(UniPtr(CharPtr,NULL));
}
#define ReadName() __ReadName(shared)
Maybe __deserialize(char** _text, bool _calledRecursively);
Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
#define ReadValue(rL) __ReadValue(shared, rL)
// returns part of <text> without quotes
Maybe __ReadString(DeserializeSharedData* shared){
char c;
bool prevIsBackslash=false;
StringBuilder* b=StringBuilder_create();
while ((c=*++text)){
if(c=='"') {
if(prevIsBackslash) {
// replacing <\"> with <">
StringBuilder_rmchar(b);
StringBuilder_append_char(b,c);
prevIsBackslash=false;
}
else {
char* str=StringBuilder_build(b).ptr;
return SUCCESS(UniPtr(CharPtr,str));
}
}
else {
prevIsBackslash= c=='\\' && !prevIsBackslash;
StringBuilder_append_char(b,c);
}
}
safethrow(ERR_ENDOFSTR, StringBuilder_free(b));
}
#define ReadString() __ReadString(shared)
Maybe __ReadList(DeserializeSharedData* shared){
Autoarr(Unitype)* list=Autoarr_create(Unitype,ARR_BC,ARR_BL);
bool readingList=true;
while (true){
try(ReadValue((&readingList)), val, Autoarr_free_Unitype(list))
Autoarr_add(list,val.value);
if (!readingList){
if(val.value.type==Null)
Autoarr_pop(list);
break;
}
}
return SUCCESS(UniPtr(AutoarrUnitypePtr,list));
};
#define ReadList() __ReadList(shared)
Maybe __ParseValue(DeserializeSharedData* shared, string str){
const string trueStr={"true",4};
const string falseStr={"false",5};
switch(str.ptr[str.length-1]){
// Bool
case 'e':
if(string_compare(str,trueStr))
return SUCCESS(UniTrue);
else if(string_compare(str,falseStr))
return SUCCESS(UniFalse);
else safethrow_wrongchar(*str.ptr,;);
break;
// Float64
case 'f': {
char* _c=string_extract(str);
Unitype rez=Uni(Float64,strtod(_c,NULL));
free(_c);
return SUCCESS(rez);
}
// UInt64
case 'u': {
uint64 lu=0;
char* _c=string_extract(str);
if(sscanf(_c,"%lu",&lu)!=1){
char err[64];
IFWIN(
sprintf_s(err,64,"can't parse to int: <%s>",_c),
sprintf(err,"can't parse to int: <%s>",_c)
);
safethrow(err,free(_c));
}
free(_c);
return SUCCESS(Uni(UInt64,lu));
}
// Int64
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_extract(str);
if(sscanf(_c,"%li",&li)!=1){
char err[64];
IFWIN(
sprintf_s(err,64,"can't parse to int: <%s>",_c),
sprintf(err,"can't parse to int: <%s>",_c)
);
safethrow(err,free(_c));
}
free(_c);
return SUCCESS(Uni(Int64,li));
}
// wrong type
default:
safethrow_wrongchar(str.ptr[str.length-1],;);
}
safethrow(ERR_ENDOFSTR,;);
};
#define ParseValue(str) __ParseValue(shared, str)
Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
char c;
string valueStr={text+1,0};
Unitype value=UniNull;
bool spaceAfterVal=false;
while ((c=*++text)) switch (c){
case ' ': case '\t':
case '\r': case '\n':
if(valueStr.length!=0)
spaceAfterVal=true;
else valueStr.ptr++;
break;
case '=': case ':':
case '}': case '$':
case '\'':
safethrow_wrongchar(c,Unitype_free(value));
break;
case '#':;
char _c=c;
char* _text=text;
try(SkipComment(),_,;);
if(valueStr.length!=0){
text=_text;
safethrow_wrongchar(_c,Unitype_free(value));
}
valueStr.ptr=text+1; // skips '\n'
break;
case '"':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
try(ReadString(),maybeString,;)
value=maybeString.value;
break;
case '{':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
++text; // skips '{'
try(__deserialize(&text,true), val,Unitype_free(value))
value=val.value;
break;
case '[':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
try(ReadList(),maybeList,Unitype_free(value))
value=maybeList.value;
break;
case ']':
if(!readingList) safethrow_wrongchar(c,Unitype_free(value));
*readingList=false;
case ';':
case ',':
if(valueStr.length!=0){
if(value.type!=Null)
safethrow_wrongchar(c,Unitype_free(value));
try(ParseValue(valueStr),maybeParsed,;)
value=maybeParsed.value;
}
return SUCCESS(value);
default:
if(spaceAfterVal)
safethrow_wrongchar(c,Unitype_free(value));
valueStr.length++;
break;
}
safethrow(ERR_ENDOFSTR,;);
}
Maybe __deserialize(char** _text, bool _calledRecursively) {
DeserializeSharedData _shared={
.sh_text_first=*_text,
.sh_text=*_text,
.sh_partOfDollarList=false,
.sh_calledRecursively=_calledRecursively
};
DeserializeSharedData* shared=&_shared;
Hashtable* dict=Hashtable_create();
text--;
while(true){
try(ReadName(), maybeName, Hashtable_free(dict))
if(!maybeName.value.VoidPtr) // end of file or '}' in recursive call
goto END;
char* nameCPtr=maybeName.value.VoidPtr;
try(ReadValue(NULL), val, {
Hashtable_free(dict);
free(nameCPtr);
}) {
if(partOfDollarList){
partOfDollarList=false;
Autoarr(Unitype)* list;
Unitype lu;
if(Hashtable_try_get(dict,nameCPtr, &lu)){
list=(Autoarr(Unitype)*)lu.VoidPtr;
}
else{
list=Autoarr_create(Unitype,ARR_BC,ARR_BL);
Hashtable_add(dict,nameCPtr,UniPtr(AutoarrUnitypePtr,list));
}
Autoarr_add(list,val.value);
}
else Hashtable_add(dict,nameCPtr,val.value);
}
}
END:
*_text=text;
return SUCCESS(UniPtr(HashtablePtr,dict));
}
Maybe DtsodV24_deserialize(char* _text) {
return __deserialize(&_text, false);
}

View File

@@ -0,0 +1,62 @@
//
// 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_free(Hashtable* dtsod){
DtsodV24_free(dtsod);
}
EXPORT void CALL kerep_DtsodV24_height(Hashtable* dtsod, uint16* heigth){
*heigth=Hashtable_height(dtsod);
}
EXPORT void CALL kerep_DtsodV24_getrow(Hashtable* dtsod, uint16 h, Autoarr_KVPair** row){
*row=dtsod->rows[h];
}
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,130 @@
#include "DtsodV24.h"
#include "../String/StringBuilder.h"
typedef struct SerializeSharedData{
StringBuilder* sh_builder;
uint8 sh_tabs;
} SerializeSharedData;
#define b shared->sh_builder
#define tabs shared->sh_tabs
Maybe __serialize(StringBuilder* _b, uint8 _tabs, Hashtable* dtsod);
#define addc(C) StringBuilder_append_char(b,C)
void __AppendTabs(SerializeSharedData* shared) {
for (uint8 t = 0; t < tabs; t++)
addc( '\t');
};
#define AppendTabs() __AppendTabs(shared)
Maybe __AppendValue(SerializeSharedData* shared, Unitype u);
#define AppendValue(UNI) __AppendValue(shared, UNI)
Maybe __AppendValue(SerializeSharedData* shared, Unitype u){
switch(u.type){
case Int64:
StringBuilder_append_int64(b,u.Int64);
break;
case UInt64:
StringBuilder_append_uint64(b,u.UInt64);
addc('u');
break;
case Float64:
StringBuilder_append_float64(b,u.Float64);
addc('f');
break;
case CharPtr:
addc('"');
char c;
while((c=*(char*)(u.VoidPtr++))){
if(c=='\"') addc('\\');
addc(c);
}
addc('"');
break;
case Bool:
StringBuilder_append_cptr(b, u.Bool ? "true" : "false");
break;
case Null:
safethrow("Null isn't supported in DtsodV24",;);
break;
case AutoarrUnitypePtr:
if(Autoarr_length(((Autoarr_Unitype*)(u.VoidPtr)))){
addc('\n');
AppendTabs();
addc('[');
tabs++;
Autoarr_foreach(((Autoarr_Unitype*)(u.VoidPtr)), e, ({
addc('\n');
AppendTabs();
try(AppendValue(e),__,;);
addc(',');
}));
StringBuilder_rmchar(b);
addc('\n');
tabs--;
AppendTabs();
addc(']');
}
else {
addc('[');
addc(']');
}
break;
case HashtablePtr:
// check hashtable is blank
Hashtable_foreach(((Hashtable*)u.VoidPtr), __, ({
goto hashtableNotBlank;
if(__.key); // weird way to disable warning
}));
// blank hashtable
addc('{');
addc('}');
break;
// not blank hashtable
hashtableNotBlank:
addc('\n');
AppendTabs();
addc('{');
addc('\n');
try(__serialize(b,tabs+1,u.VoidPtr),___,;);
AppendTabs();
addc('}');
break;
default: dbg((u.type)); safethrow(ERR_WRONGTYPE,;);
}
return MaybeNull;
};
Maybe __serialize(StringBuilder* _b, uint8 _tabs, Hashtable* dtsod){
SerializeSharedData _shared={
.sh_builder=_b,
.sh_tabs=_tabs
};
SerializeSharedData* shared=&_shared;
Hashtable_foreach(dtsod, p, ({
AppendTabs();
StringBuilder_append_cptr(b,p.key);
addc(':');
addc(' ');
try(AppendValue(p.value),__,;);
addc(';');
addc('\n');
}));
return MaybeNull;
}
Maybe DtsodV24_serialize(Hashtable* dtsod){
StringBuilder* sb=StringBuilder_create();
try(__serialize(sb,0,dtsod),__, StringBuilder_free(sb));
char* str=StringBuilder_build(sb).ptr;
return SUCCESS(UniPtr(CharPtr, str));
}

13
src/DtsodParser/README.md Normal file
View File

@@ -0,0 +1,13 @@
# DtsodC
DtsodV23 parser in C# works too slow, so i wrote V24 parser in C
<br>
## Building on Linux
**Required packages:** gcc
```bash
make build
````

100
src/Hashtable/Hashtable.c Normal file
View File

@@ -0,0 +1,100 @@
#include "Hashtable.h"
// amount of rows
static const uint16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
#define HT_HEIN_MIN 0
#define HT_HEIN_MAX 6
#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(KVPair)*));
for(uint16 i=0;i<HT_HEIGHTS[HT_HEIN_MIN];i++)
ht->rows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
return ht;
}
void Hashtable_free(Hashtable* ht){
for(uint16 i=0;i<HT_HEIGHTS[ht->hein];i++)
Autoarr_free_KVPair(ht->rows[i]);
free(ht->rows);
free(ht);
}
uint16 Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
void Hashtable_expand(Hashtable* ht){
if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH);
Autoarr(KVPair)** newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*));
for(uint16 i=0;i<HT_HEIGHTS[ht->hein];i++)
newrows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
for(uint16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
Autoarr(KVPair)* ar=ht->rows[i];
uint32 arlen=Autoarr_length(ar);
for(uint16 k=0;k<arlen;k++){
KVPair p=Autoarr_get(ar,k);
uint16 newrown=ihash(p.key)%HT_HEIGHTS[ht->hein];
Autoarr(KVPair)* newar=newrows[newrown];
Autoarr_add(newar,p);
}
// it is a feature, not a bug
// no need to free kvpair keys and values, they just moved to new autoarrs
Autoarr_free(ar);
}
free(ht->rows);
ht->rows=newrows;
}
Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){
uint32 hash=ihash(key);
Autoarr(KVPair)* ar=ht->rows[hash%HT_HEIGHTS[ht->hein]];
if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar))
optime("expand",1,(Hashtable_expand(ht)));
ar=ht->rows[hash%HT_HEIGHTS[ht->hein]];
return ar;
}
void Hashtable_add(Hashtable* ht, char* key, Unitype u){
KVPair p={ .key=key, .value=u };
Autoarr_add(getrow(ht,key,true),p);
}
// returns null or pointer to value in hashtable
Unitype* Hashtable_getptr(Hashtable* ht, char* key){
Autoarr(KVPair)* ar=getrow(ht,key,false);
uint32 arlen=Autoarr_length(ar);
for(uint32 i=0;i<arlen;i++){
KVPair* p=Autoarr_getptr(ar,i);
if(cptr_compare(key,p->key)) return &p->value;
}
return NULL;
}
Unitype Hashtable_get(Hashtable* ht, char* key){
Autoarr(KVPair)* ar=getrow(ht,key,false);
uint32 arlen=Autoarr_length(ar);
for(uint32 i=0;i<arlen;i++){
KVPair p=Autoarr_get(ar,i);
if(cptr_compare(key,p.key)) return p.value;
}
return UniNull;
}
bool Hashtable_try_get(Hashtable* ht, char* key, Unitype* output){
Unitype u=Hashtable_get(ht,key);
*output=u;
return u.type!=Null;
}
void Hashtable_addOrSet(Hashtable* ht, char* key, Unitype u){
Unitype* val=Hashtable_getptr(ht, key);
if(val) *val=u;
else Hashtable_add(ht, key, u);
}

45
src/Hashtable/Hashtable.h Normal file
View File

@@ -0,0 +1,45 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
#include "hash.h"
#include "KeyValuePair.h"
typedef struct Hashtable{
uint8 hein; // height=HT_HEIGHTS[hein]
Autoarr(KVPair)** rows; // Autoarr[height]
} Hashtable;
Hashtable* Hashtable_create();
void Hashtable_free(Hashtable* ht);
// amount of rows
uint16 Hashtable_height(Hashtable* ht);
// don't add pairs with the same keys,
// or something weird will happen
// if not sure, use Hashtable_addOrSet()
void Hashtable_add(Hashtable* ht, char* key, Unitype u);
void Hashtable_addOrSet(Hashtable* ht, char* key, Unitype u);
// returns null or pointer to value in hashtable
Unitype* Hashtable_getptr(Hashtable* ht, char* key);
Unitype Hashtable_get(Hashtable* ht, char* key);
bool Hashtable_try_get(Hashtable* ht, char* key, Unitype* output);
#define Hashtable_foreach(HT, EL, codeblock)({\
uint16 hmax=Hashtable_height(HT);\
for(uint16 h=0; h<hmax; h++){\
Autoarr(KVPair)* AR=HT->rows[h];\
Autoarr_foreach(AR, EL, codeblock);\
}\
})
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,22 @@
#include "KeyValuePair.h"
define_Autoarr(KVPair)
// proper way to clear a KVP
void KVPair_free(KVPair p){
free(p.key);
Unitype_free(p.value);
}
// func for KVP array clearing
void Autoarr_free_KVPair(Autoarr_KVPair* ar){
Autoarr_foreach(ar,k,KVPair_free(k));
Autoarr_free(ar);
}
void printkvp(KVPair p){
printf("{\"%s\", ",p.key);
printuni(p.value);
printf("}");
}

View File

@@ -0,0 +1,27 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
#include "../Autoarr/Autoarr.h"
typedef struct KVPair{
char* key;
Unitype value;
} KVPair;
declare_Autoarr(KVPair)
// proper way to clear a KVP
void KVPair_free(KVPair p);
// func to clear KVP array
void Autoarr_free_KVPair(Autoarr_KVPair* ar);
void printkvp(KVPair p);
#if __cplusplus
}
#endif

15
src/Hashtable/hash.c Normal file
View File

@@ -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;
}

16
src/Hashtable/hash.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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);
#if __cplusplus
}
#endif

View File

@@ -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;
}

View File

@@ -0,0 +1,22 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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);
#if __cplusplus
}
#endif

View File

@@ -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
```

144
src/String/StringBuilder.c Normal file
View File

@@ -0,0 +1,144 @@
#include "StringBuilder.h"
define_Autoarr(string)
#define MAXLENGTH 32768
#define BL_C 32
#define BL_L 1024
void complete_buf(StringBuilder* b){
if(!b->compl_bufs)
b->compl_bufs=Autoarr_create(string,BL_C,BL_L);
uint32 len=Autoarr_length(b->curr_buf);
if(!len) return;
string str={.length=len, .ptr=malloc(len)};
uint32 i=0;
Autoarr_foreach(b->curr_buf, c, ({
str.ptr[i++]=c;
}));
Autoarr_add(b->compl_bufs,str);
Autoarr_free(b->curr_buf);
b->curr_buf=Autoarr_create(int8,BL_C,BL_L);
}
void try_complete_buf(StringBuilder* b){
if(b->curr_buf->blocks_count==BL_C)
complete_buf(b);
}
StringBuilder* StringBuilder_create(){
StringBuilder* b=malloc(sizeof(StringBuilder));
b->compl_bufs=NULL;
b->curr_buf=Autoarr_create(int8,BL_C,BL_L);
return b;
}
void StringBuilder_free(StringBuilder* b){
if(b->compl_bufs) Autoarr_free(b->compl_bufs);
Autoarr_free(b->curr_buf);
free(b);
}
string StringBuilder_build(StringBuilder* b){
complete_buf(b);
uint32 len=0;
Autoarr_foreach(b->compl_bufs, cs, ({
len+=cs.length;
}));
string str= { .length=len, .ptr=malloc(len+1) };
str.ptr[len]='\0';
uint32 i=0;
Autoarr_foreach(b->compl_bufs, cs, ({
for(uint32 n=0;n<cs.length;n++)
str.ptr[i++]=cs.ptr[n];
free(cs.ptr);
}));
StringBuilder_free(b);
return str;
}
void StringBuilder_rmchar(StringBuilder* b){
if(b->curr_buf->block_length!=0)
Autoarr_pop(b->curr_buf)
else {
if(!b->compl_bufs) throw(ERR_NULLPTR);
string* lastcb=Autoarr_getptr(b->compl_bufs, (Autoarr_length(b->compl_bufs)-1));
lastcb->length--;
}
}
void StringBuilder_append_char(StringBuilder* b, char c){
try_complete_buf(b);
Autoarr_add(b->curr_buf,c);
}
void StringBuilder_append_string(StringBuilder* b, string s){
complete_buf(b);
Autoarr_add(b->compl_bufs, string_copy(s));
}
void StringBuilder_append_cptr(StringBuilder* b, char* s){
string str={
.ptr=s,
.length=cptr_length(s)
};
StringBuilder_append_string(b,str);
}
void curr_buf_add_string(StringBuilder* b, string s){
for(uint32 i=0; i<s.length; i++)
Autoarr_add(b->curr_buf,s.ptr[i]);
}
void StringBuilder_append_int64(StringBuilder* b, int64 a){
try_complete_buf(b);
uint8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
return;
}
else if(a<0){
Autoarr_add(b->curr_buf,'-');
a=-a;
}
char buf[24];
while(a!=0){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
}
void StringBuilder_append_uint64(StringBuilder* b, uint64 a){
try_complete_buf(b);
uint8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
return;
}
char buf[24];
while(a!=0){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
}
void StringBuilder_append_float64(StringBuilder* b, double a){
try_complete_buf(b);
char buf[32];
IFWIN(
sprintf_s(buf,32,"%lf",a),
sprintf(buf,"%lf",a)
);
curr_buf_add_string(b, (string){.ptr=buf, .length=cptr_length(buf)});
}

View File

@@ -0,0 +1,35 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../Autoarr/Autoarr.h"
#include "string.h"
declare_Autoarr(string)
typedef struct StringBuilder{
Autoarr(string)* compl_bufs;
Autoarr(int8)* curr_buf;
} StringBuilder;
StringBuilder* StringBuilder_create(void);
void StringBuilder_free(StringBuilder* b);
// Joins all strings from compl_bufs.
// Returns zero-terminated string.
// No need to call string_extract()!
// Frees StringBuilder.
string StringBuilder_build(StringBuilder* b);
// removes last char
void StringBuilder_rmchar(StringBuilder* b);
void StringBuilder_append_char(StringBuilder* b, char c);
void StringBuilder_append_cptr(StringBuilder* b, char* s);
void StringBuilder_append_string(StringBuilder* b, string s);
void StringBuilder_append_int64(StringBuilder* b, int64 a);
void StringBuilder_append_uint64(StringBuilder* b, uint64 a);
void StringBuilder_append_float64(StringBuilder* b, double a);
#if __cplusplus
}
#endif

42
src/String/string.c Normal file
View File

@@ -0,0 +1,42 @@
#include "string.h"
// copies str content to new char pointer value (adding '\0' at the end)
char* string_extract(string str){
if(str.length==0) return NULL;
char* cptr=malloc(str.length*sizeof(char)+1);
cptr[str.length]=0;
while(str.length-->0)
cptr[str.length]=str.ptr[str.length];
return cptr;
}
// copies src.ptr content to new string
string string_copy(string src){
if(!src.ptr) return src;
string nstr;
nstr.length=src.length;
nstr.ptr=malloc(nstr.length);
for(uint32 i=0;i<nstr.length;i++)
nstr.ptr[i]=src.ptr[i];
return nstr;
}
// compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1){
if(str0.length!=str1.length) return false;
if(!str0.ptr) return str1.ptr ? false : true;
else if(!str1.ptr) return false;
while(str0.length-->0)
if(*str0.ptr++ != *str1.ptr++)
return false;
return true;
}
// creates new string which is reversed variant of <s>
string string_reverse(string s){
if(s.length==0) return s;
string r={malloc(s.length), s.length};
for(uint32 i=0; i<s.length; i++)
r.ptr[i]=s.ptr[s.length-i-1];
return r;
}

32
src/String/string.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
// my fixed length string struct
// doesn't store '\0' at the end
typedef struct string{
char* ptr; // char pointer
uint32 length; // amount of chars in ptr value
} string;
static const string stringNull={NULL,0};
// copies str content to new char pointer value (adding '\0' at the end)
char* string_extract(string str);
// copies src.ptr content to new string
string string_copy(string src);
// compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1);
// creates new string which is reversed variant of <s>
string string_reverse(string s);
#if __cplusplus
}
#endif

36
src/base/base.h Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "std.h"
#include "types.h"
#include "errors.h"
#include "cptr.h"
// executes codeblock and prints execution time
#ifdef CLOCK_REALTIME // non-standard high-precision clock
#define optime(opname,repeats,codeblock) ({\
struct timespec start, stop;\
clock_gettime(CLOCK_REALTIME, &start);\
for(uint64 ___OPREP=0;___OPREP<(uint64)repeats;___OPREP++)\
(codeblock);\
clock_gettime(CLOCK_REALTIME, &stop);\
double t=(double)(stop.tv_sec-start.tv_sec+(double)(stop.tv_nsec-start.tv_nsec)/1000000000)/repeats;\
printf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
})
#else //
#define optime(opname,repeats,codeblock) ({\
clock_t start=clock();\
for(uint64 ___OPREP=0;___OPREP<(uint64)repeats;___OPREP++)\
(codeblock);\
clock_t stop=clock();\
double t=(double)(stop-start)/CLOCKS_PER_SEC/repeats;\
printf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
})
#endif
#if __cplusplus
}
#endif

36
src/base/cptr.c Normal file
View File

@@ -0,0 +1,36 @@
#include "base.h"
// returns length of char buffer (without \0)
uint32 cptr_length(char* str){
uint32 len=0;
while(*(str++)) len++;
return len;
}
// allocates new char[] and copies src there
char* cptr_copy(char* src){
uint32 len=cptr_length(src);
char* dst=malloc(len+1);
while(len-->0)
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;
}

23
src/base/cptr.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "types.h"
// returns length of char buffer (without \0)
uint32 cptr_length(char* str);
// allocates new char[] and copies src there
char* cptr_copy(char* src);
// compares two char buffers, NullPtr-friendly
bool cptr_compare(char* key0, char* key1);
// multiplies char n times
char* char_multiply(char c, uint32 n);
#if __cplusplus
}
#endif

53
src/base/errors.c Normal file
View File

@@ -0,0 +1,53 @@
#include "std.h"
#include "errors.h"
#include "cptr.h"
char* errname(err_t err){
switch(err){
case SUCCESS: return "SUCCESS";
case ERR_MAXLENGTH: return "ERR_MAXLENGTH";
case ERR_WRONGTYPE: return "ERR_WRONGTYPE";
case ERR_WRONGINDEX: return "ERR_WRONGINDEX";
case ERR_NOTIMPLEMENTED: return "ERR_NOTIMPLEMENTED";
case ERR_NULLPTR: return "ERR_NULLPTR";
case ERR_ENDOFSTR: return "ERR_ENDOFSTR";
default: return "UNKNOWN_ERROR";
}
}
#define ERRMSG_MAXLENGTH 1024
char* __genErrMsg(const char* errmsg, const char* srcfile, int line, const char* funcname){
size_t bufsize=ERRMSG_MAXLENGTH;
char* rezult=malloc(bufsize);
IFWIN(
sprintf_s(rezult,bufsize,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg),
sprintf(rezult,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg)
);
return rezult;
}
char* __extendErrMsg(const char* errmsg, const char* srcfile, int line, const char* funcname){
size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH;
char* rezult=malloc(bufsize);
IFWIN(
sprintf_s(rezult,bufsize,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname),
sprintf(rezult,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname)
);
free(errmsg);
return rezult;
}
void Maybe_free(Maybe e){
free(e.errmsg);
Unitype_free(e.value);
}
void printMaybe(Maybe e){
if(e.errmsg) printf("%s\n",e.errmsg);
else printuni(e.value);
}
char* __doNothing(char* a) {return a;}
char* __unknownErr() {return "UNKNOWN ERROR";}

64
src/base/errors.h Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "std.h"
#include "types.h"
typedef enum err_t {
SUCCESS, // not an error
ERR_MAXLENGTH, ERR_WRONGTYPE, ERR_WRONGINDEX, ERR_NOTIMPLEMENTED, ERR_NULLPTR, ERR_ENDOFSTR
} err_t;
char* errname(err_t err);
char* __genErrMsg(const char* errmsg, const char* srcfile, int line, const char* funcname);
char* __extendErrMsg(const char* errmsg, const char* srcfile, int line, const char* funcname);
typedef struct Maybe{
Unitype value;
char* errmsg;
} Maybe;
// return it if func doesn't return anything
static const Maybe MaybeNull={.value.type=Null, .value.VoidPtr=NULL,.errmsg=NULL};
void Maybe_free(Maybe e);
void printMaybe(Maybe e);
#define SUCCESS(REZLT) (Maybe){.errmsg=NULL, .value=REZLT}
#define __RETURN_EXCEPTION(ERRMSG) return (Maybe){.errmsg=ERRMSG, .value=UniNull}
#define __EXIT(ERRMSG) ({ printf("\e[91m%s\e[0m \n", ERRMSG); free(ERRMSG); exit(128); })
char* __doNothing(char* a);
char* __unknownErr( );
#define __stringify_err(E) _Generic(\
(E),\
char*: __doNothing,\
int: errname,\
default: __unknownErr\
)(E)
#define throw(E) __EXIT(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__)))
#define safethrow(E, FREEMEM) { FREEMEM; __RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); }
#define try(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){\
freeMem;\
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__);\
return _rezult;\
}else
#define tryLast(_funcCall, _rezult) Maybe _rezult=_funcCall; if(_rezult.errmsg){\
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__);\
__EXIT(_rezult.errmsg);\
}else
#if __cplusplus
}
#endif

53
src/base/std.h Normal file
View File

@@ -0,0 +1,53 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <locale.h>
#include <time.h>
#include <setjmp.h>
#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)
#ifdef _MSC_VER
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
#define _CRT_SECURE_NO_WARNINGS 1
#define EXPORT __declspec(dllexport)
#define CALL __cdecl
#elif defined(__GNUC__)
#define EXPORT __attribute__((visibility("default")))
#if __SIZEOF_POINTER__ == 4
#define CALL __attribute__((__cdecl__))
#else
#define CALL
#endif
#ifndef typeof
#define typeof __typeof__
#endif
#else
#pragma GCC error "unknown compiler"
#endif
#ifdef _MSC_VER
#define IFWIN(YES, NO) YES
#elif defined(__GNUC__)
#define IFWIN(YES, NO) NO
#else
#pragma GCC error "unknown compiler"
#endif
#if __cplusplus
}
#endif

154
src/base/types.c Normal file
View File

@@ -0,0 +1,154 @@
#include "types.h"
#include "errors.h"
#include "../Autoarr/Autoarr.h"
#include "../Hashtable/Hashtable.h"
#include "../SearchTree/SearchTree.h"
const char* my_type_name(my_type t){
switch (t) {
case Null: return "Null";
case Float64: return "Float64";
case Float32: return "Float32";
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 Float32:
case Float64:
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_free_int8(u.VoidPtr);
break;
case AutoarrUInt8Ptr:
__Autoarr_free_uint8(u.VoidPtr);
break;
case AutoarrInt16Ptr:
__Autoarr_free_int16(u.VoidPtr);
break;
case AutoarrUInt16Ptr:
__Autoarr_free_uint16(u.VoidPtr);
break;
case AutoarrInt32Ptr:
__Autoarr_free_int32(u.VoidPtr);
break;
case AutoarrUInt32Ptr:
__Autoarr_free_uint32(u.VoidPtr);
break;
case AutoarrInt64Ptr:
__Autoarr_free_int64(u.VoidPtr);
break;
case AutoarrUInt64Ptr:
__Autoarr_free_uint64(u.VoidPtr);
break;
case AutoarrUnitypePtr:
Autoarr_free_Unitype(u.VoidPtr);
break;
case AutoarrKVPairPtr:
Autoarr_free_KVPair(u.VoidPtr);
break;
default: throw(ERR_WRONGTYPE);
}
}
#define BUFSIZE 64
char* sprintuni(Unitype v){
char* buf=malloc(BUFSIZE);
IFWIN(
switch (v.type) {
case Null: sprintf_s(buf, BUFSIZE, "{Null}");break;
case Float64: sprintf_s(buf, BUFSIZE, "{%s : %lf}", my_type_name(v.type),v.Float64);break;
case Bool:
case UInt64: sprintf_s(buf, BUFSIZE, "{%s : %lu}", my_type_name(v.type),v.UInt64);break;
case Int64: sprintf_s(buf, BUFSIZE, "{%s : %ld}", my_type_name(v.type),v.Int64);break;
case CharPtr: ;
size_t newBUFSIZE=cptr_length(v.VoidPtr) + BUFSIZE/2;
buf=realloc(buf, newBUFSIZE);
sprintf_s(buf, newBUFSIZE, "{%s : \"%s\"}", my_type_name(v.type),(char*)v.VoidPtr);
break;
default: sprintf_s(buf, BUFSIZE, "{%s : %p}", my_type_name(v.type),v.VoidPtr);break;
},
switch (v.type) {
case Null: sprintf(buf, "{Null}");break;
case Float64: sprintf(buf, "{%s : %lf}", my_type_name(v.type),v.Float64);break;
case Bool:
case UInt64: sprintf(buf, "{%s : %lu}", my_type_name(v.type),v.UInt64);break;
case Int64: sprintf(buf, "{%s : %ld}", my_type_name(v.type),v.Int64);break;
case CharPtr: ;
size_t newBUFSIZE=cptr_length(v.VoidPtr) + BUFSIZE/2;
buf=realloc(buf, newBUFSIZE);
sprintf(buf, "{%s : \"%s\"}", my_type_name(v.type),(char*)v.VoidPtr);
break;
default: sprintf(buf, "{%s : %p}", my_type_name(v.type),v.VoidPtr);break;
}
);
return buf;
}
void printuni(Unitype v){
char* s=sprintuni(v);
fputs(s, stdout);
free(s);
}

57
src/base/types.h Normal file
View File

@@ -0,0 +1,57 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#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 float float32;
typedef double float64;
typedef enum __attribute__((__packed__)) my_type {
Null, Float32, Float64, 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
} my_type;
const char* my_type_name(my_type t);
typedef struct Unitype{
union {
int64 Int64;
uint64 UInt64;
double Float64;
bool Bool;
void* VoidPtr;
};
my_type type;
} Unitype;
static const Unitype UniNull={.VoidPtr=NULL,.type=Null};
static const Unitype UniTrue={.Bool=true,.type=Bool};
static const Unitype UniFalse={.Bool=false,.type=Bool};
#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);
char* sprintuni(Unitype v);
#if __cplusplus
}
#endif