diff --git a/build.sh b/build.sh index f497caf..cead1a7 100644 --- a/build.sh +++ b/build.sh @@ -1,31 +1,38 @@ #!/bin/bash set -eo pipefail + CMP="gcc" -ARGS="-Wall -Wno-discarded-qualifiers -O2" -SRC="$(find . -name '*.c')" -LINK="-L. -lkerep" +WARN="-Wall -Wextra -Wno-discarded-qualifiers -Wno-unused-parameter" +ARGS="-O2 -flto -fdata-sections -ffunction-sections -Wl,--gc-sections" +SRC="$(find src -name '*.c')" -OS=$(./detect_os.sh) -ARCH=$(./detect_arch.sh) +OS="$(./detect_os.sh)" +ARCH="$(./detect_arch.sh)" +LINK="-Lkerep/bin -lkerep-$OS-$ARCH" -if [[ OS == "windows" ]]; then +if [[ OS -eq "windows" ]]; then OUT_FILE="cbuild.exe" else OUT_FILE="cbuild" fi command="$CMP $ARGS - -DOS=$OS -DARCH=$ARCH + $WARN + -DOS=\"$OS\" -DARCH=\"$ARCH\" $SRC $LINK -o bin/$OUT_FILE" +if [ ! -f "kerep/bin/libkerep-$OS-$ARCH.a" ]; then + echo "libkerep-$OS-$ARCH.a not found" + cd kerep + ./build.sh + cd .. +fi + rm -rf bin mkdir bin +echo "----------------[cbuild]----------------" echo "$command" -tar xJf libkerep.a.tar.xz - $($command) - -rm libkerep.a diff --git a/detect_arch.sh b/detect_arch.sh index 5779297..08d3e0c 100644 --- a/detect_arch.sh +++ b/detect_arch.sh @@ -20,4 +20,4 @@ case "$uname_rezult" in ;; esac -echo "\"$ARCH\"" +echo "$ARCH" diff --git a/detect_os.sh b/detect_os.sh index 673c5f7..541dd96 100644 --- a/detect_os.sh +++ b/detect_os.sh @@ -23,4 +23,4 @@ case "$uname_rezult" in ;; esac -echo "\"$OS\"" +echo "$OS" diff --git a/kerep-headers/DtsodParser/DtsodV24.h b/kerep-headers/DtsodParser/DtsodV24.h deleted file mode 100644 index a49f07e..0000000 --- a/kerep-headers/DtsodParser/DtsodV24.h +++ /dev/null @@ -1,32 +0,0 @@ -#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 \ No newline at end of file diff --git a/kerep/.gitignore b/kerep/.gitignore new file mode 100644 index 0000000..56cdcd2 --- /dev/null +++ b/kerep/.gitignore @@ -0,0 +1,2 @@ +obj/ +libkerep.* diff --git a/kerep/build.sh b/kerep/build.sh new file mode 100644 index 0000000..8bfebca --- /dev/null +++ b/kerep/build.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -eo pipefail + +CMP="gcc" +WARN="-std=c11 -Wall -Wno-discarded-qualifiers -Wno-unused-parameter" +ARGS="-O2 -flto -fpic -fdata-sections -ffunction-sections" +SRC="$(find src -name '*.c')" + +OS=$(../detect_os.sh) +ARCH=$(../detect_arch.sh) +OUTFILE="bin/libkerep-$OS-$ARCH.a" + +rm -rf obj +mkdir obj +mkdir -p bin + +echo "----------------[kerep]-----------------" +compiler_call="$CMP $WARN $ARGS -c" +echo "$compiler_call" +OBJECTS= +for srcfile in $SRC +do + echo " $srcfile" + object="obj/$(basename $srcfile).o" + OBJECTS="$OBJECTS + $object" + command="$compiler_call $srcfile -o $object" + if ! $($command); then + exit 1 + fi +done + +command="ar rcs $OUTFILE $OBJECTS" +echo "$command" +if $($command) +then + echo "static lib $OUTFILE created" + rm -r obj +else + exit 1 +fi diff --git a/kerep/src/Autoarr/Autoarr.c b/kerep/src/Autoarr/Autoarr.c new file mode 100644 index 0000000..f2159c8 --- /dev/null +++ b/kerep/src/Autoarr/Autoarr.c @@ -0,0 +1,17 @@ +#include "Autoarr.h" + +Autoarr_define(Pointer, true) +Autoarr_define(char, false) +Autoarr_define(bool, false) +Autoarr_define(f32, false) +Autoarr_define(f64, false) +Autoarr_define(u8, false) +Autoarr_define(i8, false) +Autoarr_define(u16, false) +Autoarr_define(i16, false) +Autoarr_define(u32, false) +Autoarr_define(i32, false) +Autoarr_define(u64, false) +Autoarr_define(i64, false) + +Autoarr_define(Unitype, false) diff --git a/kerep-headers/Autoarr/Autoarr.h b/kerep/src/Autoarr/Autoarr.h similarity index 100% rename from kerep-headers/Autoarr/Autoarr.h rename to kerep/src/Autoarr/Autoarr.h diff --git a/kerep-headers/Autoarr/Autoarr_declare.h b/kerep/src/Autoarr/Autoarr_declare.h similarity index 100% rename from kerep-headers/Autoarr/Autoarr_declare.h rename to kerep/src/Autoarr/Autoarr_declare.h diff --git a/kerep-headers/Autoarr/Autoarr_define.h b/kerep/src/Autoarr/Autoarr_define.h similarity index 100% rename from kerep-headers/Autoarr/Autoarr_define.h rename to kerep/src/Autoarr/Autoarr_define.h diff --git a/kerep-headers/Autoarr/README.md b/kerep/src/Autoarr/README.md similarity index 100% rename from kerep-headers/Autoarr/README.md rename to kerep/src/Autoarr/README.md diff --git a/kerep/src/DtsodParser/DtsodV24.h b/kerep/src/DtsodParser/DtsodV24.h new file mode 100644 index 0000000..d4987e1 --- /dev/null +++ b/kerep/src/DtsodParser/DtsodV24.h @@ -0,0 +1,17 @@ +#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); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/kerep/src/DtsodParser/DtsodV24_deserialize.c b/kerep/src/DtsodParser/DtsodV24_deserialize.c new file mode 100644 index 0000000..57ac4d0 --- /dev/null +++ b/kerep/src/DtsodParser/DtsodV24_deserialize.c @@ -0,0 +1,344 @@ +#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, i32 line, const char* funcname){ + char errBuf[68]; + for(u8 n=0; n 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,;); + 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(UniHeapPtr(char,NULL)); + case ':': + return SUCCESS(UniHeapPtr(char,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(UniHeapPtr(char,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 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(UniHeapPtr(char,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)), m_val, Autoarr_free(list, true)) + Autoarr_add(list,m_val.value); + if (!readingList){ + if(Unitype_isUniNull(m_val.value)) + Autoarr_pop(list); + break; + } + } + + return SUCCESS(UniHeapPtr(Autoarr_Unitype,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,;); + // Float64 + case 'f': { + char* _c=string_extract(str); + Unitype rez=UniFloat64(strtod(_c,NULL)); + free(_c); + return SUCCESS(rez); + } + // UInt64 + case 'u': { + u64 lu=0; + char* _c=string_extract(str); + if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){ + char err[64]; + IFMSC( + 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(UniUInt64(lu)); + } + // Int64 + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + i64 li=0; + char* _c=string_extract(str); + if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){ + char err[64]; + IFMSC( + 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(UniInt64(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)); + 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; + goto return_value; + case ';': + case ',': + return_value: + if(valueStr.length!=0){ + if(!Unitype_isUniNull(value)) + 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_tryGet(dict,nameCPtr, &lu)){ + list=(Autoarr(Unitype)*)lu.VoidPtr; + // Key is not used in that case, because it is already added + // to the table with the first dollar list item. + free(nameCPtr); + } + else{ + list=Autoarr_create(Unitype,ARR_BC,ARR_BL); + Hashtable_add(dict,nameCPtr,UniHeapPtr(Autoarr_Unitype,list)); + } + Autoarr_add(list,val.value); + } + else Hashtable_add(dict,nameCPtr,val.value); + } + } + + END: + *_text=text; + return SUCCESS(UniHeapPtr(Hashtable,dict)); +} + +Maybe DtsodV24_deserialize(char* _text) { + return __deserialize(&_text, false); +} diff --git a/kerep/src/DtsodParser/DtsodV24_serialize.c b/kerep/src/DtsodParser/DtsodV24_serialize.c new file mode 100644 index 0000000..1c81feb --- /dev/null +++ b/kerep/src/DtsodParser/DtsodV24_serialize.c @@ -0,0 +1,130 @@ +#include "DtsodV24.h" +#include "../String/StringBuilder.h" + + +STRUCT(SerializeSharedData, + StringBuilder* sh_builder; + u8 sh_tabs; +) +#define b shared->sh_builder +#define tabs shared->sh_tabs + +Maybe __serialize(StringBuilder* _b, u8 _tabs, Hashtable* dtsod); + +#define addc(C) StringBuilder_append_char(b,C) + + +void __AppendTabs(SerializeSharedData* shared) { + for (u8 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){ + if(u.typeId==ktid_name(i64)){ + StringBuilder_append_i64(b,u.Int64); + } + else if(u.typeId==ktid_name(u64)){ + StringBuilder_append_u64(b,u.UInt64); + addc('u'); + } + else if(u.typeId==ktid_name(f64)){ + StringBuilder_append_f64(b,u.Float64); + addc('f'); + } + else if(u.typeId==ktid_ptrName(char)){ + addc('"'); + char c; + while((c=*(char*)(u.VoidPtr++))){ + if(c=='\"') addc('\\'); + addc(c); + } + addc('"'); + } + else if(u.typeId==ktid_name(bool)){ + StringBuilder_append_cptr(b, u.Bool ? "true" : "false"); + } + else if(Unitype_isUniNull(u)){ + safethrow("Null isn't supported in DtsodV24",;); + } + else if(u.typeId==ktid_ptrName(Autoarr_Unitype)){ + 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(']'); + } + } + else if(u.typeId==ktid_ptrName(Hashtable)){ + // check hashtable is blank + bool hashtableNotBlank=false; + Hashtable_foreach(((Hashtable*)u.VoidPtr), __, + hashtableNotBlank=true; + if(__.key) {} // weird way to disable warning + break; + ); + + if(hashtableNotBlank){ + addc('\n'); + AppendTabs(); + addc('{'); + addc('\n'); + try(__serialize(b,tabs+1,u.VoidPtr),___,;); + AppendTabs(); + addc('}'); + } + else { + addc('{'); + addc('}'); + } + } + else { + dbg((u.typeId)); + safethrow(ERR_WRONGTYPE,;); + } + return MaybeNull; +}; + +Maybe __serialize(StringBuilder* _b, u8 _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(UniHeapPtr(char, str)); +} diff --git a/kerep-headers/DtsodParser/README.md b/kerep/src/DtsodParser/README.md similarity index 100% rename from kerep-headers/DtsodParser/README.md rename to kerep/src/DtsodParser/README.md diff --git a/kerep/src/Filesystem/dir.c b/kerep/src/Filesystem/dir.c new file mode 100644 index 0000000..812c755 --- /dev/null +++ b/kerep/src/Filesystem/dir.c @@ -0,0 +1,69 @@ +#include "filesystem.h" +#include "io_includes.h" +#include "../kprint/kprint.h" + +bool dir_exists(const char* path){ + if(path[0]=='.'){ + if(path[1]==0 || (path[1]==path_sep && path[1]==0)) + return true; // dir . or ./ always exists + // else if(path[1]=='.' && path[2]==path_sep) + //TODO path_resolve because windows doesnt recognize .\ pattern + } +#if KFS_USE_WINDOWS_H + DWORD dwAttrib = GetFileAttributes(path); + return (bool)( + (dwAttrib != INVALID_FILE_ATTRIBUTES) && // file exists + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); // file is a directory +#else + struct stat stats; + i32 rez=stat(path, &stats); + return (bool)( + (rez!=-1) && // file exists + (S_ISDIR(stats.st_mode))); // file is a directory +#endif +} + +Maybe dir_create(const char* path){ + if (dir_exists(path)) + return MaybeNull; + char* parentDir=path_parentDir(path); + dir_create(parentDir); + free(parentDir); +#if KFS_USE_WINDOWS_H + if(!CreateDirectory(path, NULL)) +#else + if(mkdir(path, 0777) == -1) +#endif + { + char err[512]; + IFWIN( + sprintf_s(err, 512, "can't create dicectory <%s>", path), + sprintf(err, "can't create dicectory <%s>", path)); + safethrow(err,;); + } + + return MaybeNull; +} + +Maybe dir_delete(const char* path){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} + +Maybe dir_getFiles(const char* path, bool recursive){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} +Maybe dir_getDirs(const char* path, bool recursive){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} + +Maybe dir_findFiles(const char* path, char* searchPattern, bool recursive){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} +Maybe dir_findDirs(const char* path, char* searchPattern, bool recursive){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} diff --git a/kerep-headers/Filesystem/dir.h b/kerep/src/Filesystem/dir.h similarity index 81% rename from kerep-headers/Filesystem/dir.h rename to kerep/src/Filesystem/dir.h index 3821229..385c0be 100644 --- a/kerep-headers/Filesystem/dir.h +++ b/kerep/src/Filesystem/dir.h @@ -13,14 +13,14 @@ Maybe dir_create(const char* path); ///@return Maybe Maybe dir_delete(const char* path); -///@return Maybe +///@return Maybe Maybe dir_getFiles(const char* path, bool recursive); -///@return Maybe +///@return Maybe Maybe dir_getDirs(const char* path, bool recursive); -///@return Maybe +///@return Maybe Maybe dir_findFiles(const char* path, char* searchPattern, bool recursive); -///@return Maybe +///@return Maybe Maybe dir_findDirs(const char* path, char* searchPattern, bool recursive); #if __cplusplus diff --git a/kerep/src/Filesystem/file.c b/kerep/src/Filesystem/file.c new file mode 100644 index 0000000..5c38523 --- /dev/null +++ b/kerep/src/Filesystem/file.c @@ -0,0 +1,138 @@ +#include "filesystem.h" +#include "../String/StringBuilder.h" +#include "io_includes.h" + +void __file_freeMembers(void* _f){ fclose((FileHandle)_f); } + +kt_define(FileHandle, __file_freeMembers, NULL) + +bool file_exists(const char* path){ + if(path[0]=='.'){ + if(path[1]==0 || (path[1]==path_sep && path[2]==0)) + return false; // . or ./ is not a file + // else if(path[1]=='.' && path[2]==path_sep) + //TODO path_resolve because windows doesnt recognize .\ pattern + } + +#if KFS_USE_WINDOWS_H + DWORD dwAttrib = GetFileAttributes(path); + return (bool)( + (dwAttrib != INVALID_FILE_ATTRIBUTES) && // file exists + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); // file is not directory +#else + struct stat stats; + i32 rez=stat(path, &stats); + return (bool)( + (rez!=-1) && // file exists + !(S_ISDIR(stats.st_mode))); // file is not directory +#endif +} + +Maybe file_delete(const char* path, bool recursive){ + throw(ERR_NOTIMPLEMENTED); + return MaybeNull; +} + +char* FileOpenMode_toStr(FileOpenMode m){ + char* p; + switch(m){ + case FileOpenMode_Read: p="rb"; break; + case FileOpenMode_Write: p="wb"; break; + case FileOpenMode_Append: p="ab"; break; + case FileOpenMode_ReadWrite: p="wb+"; break; + case FileOpenMode_ReadAppend: p="ab+"; break; + default: + dbg(m); + throw(ERR_UNEXPECTEDVAL); + } + return p; +} + +Maybe file_open(const char* path, FileOpenMode mode){ + FileHandle file=fopen(path, FileOpenMode_toStr(mode)); + if(!file) + safethrow(cptr_concat("can't open file ", (char*)path),;); + return SUCCESS(UniHeapPtr(FileHandle,file)); +} + +Maybe file_close(FileHandle file){ + if(!file) + safethrow(ERR_NULLPTR,;); + if(fclose(file)) + safethrow(ERR_IO,;); + return MaybeNull; +} + +#define ioWriteCheck() \ + if(rezult==EOF) \ + safethrow(ERR_IO_EOF,;); \ + if(rezult!=0) \ + safethrow(ERR_IO,;); + +Maybe file_writeChar(FileHandle file, char byte){ + i32 rezult=fputc(byte, file); + ioWriteCheck(); + return MaybeNull; +} + +Maybe file_writeBuffer(FileHandle file, char* buffer, u64 length){ + i32 rezult=0; + for(u64 i=0; i uses <..>, that's not allowed"),); + return MaybeNull; +} + +char* path_parentDir(char* dir){ + char* copy=cptr_copy(dir); + i32 length=cptr_length(copy); + i32 i=cptr_lastIndexOfChar(copy,path_sep); + if(i!=-1 && i==length-1){ + copy[length-1]=0; + i=cptr_lastIndexOfChar(copy,path_sep); + } + if(i==-1){ + free(copy); + copy=malloc(2); + copy[0]='.'; + copy[1]=0; + } + return copy; +} + + +char* path_basename(char* path, bool with_extension){ + i32 nameIndex=cptr_lastIndexOfChar(path, path_sep)+1; + string rezult=string_fromCptr(path+nameIndex); + if(!with_extension){ + i32 extIndex=cptr_lastIndexOfChar(rezult.ptr, '.'); + if(extIndex!=0 && extIndex!=-1) + rezult.length=extIndex; + } + return string_extract(rezult); +} diff --git a/kerep-headers/Filesystem/path.h b/kerep/src/Filesystem/path.h similarity index 100% rename from kerep-headers/Filesystem/path.h rename to kerep/src/Filesystem/path.h diff --git a/kerep/src/HashFunctions/hash.c b/kerep/src/HashFunctions/hash.c new file mode 100644 index 0000000..3f2761b --- /dev/null +++ b/kerep/src/HashFunctions/hash.c @@ -0,0 +1,111 @@ +#include "hash.h" + +u32 hash_sdbm32(u32 oldhash, void* buf, u32 len){ + u8* ubuf=(u8*)buf; + register u32 hash=oldhash; + for (; len ; len--, ubuf++) + hash=(hash<<6)+(hash<<16)-hash+*ubuf; + return hash; +} + +static const u32 crc_32_tab[]={ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +u32 hash_crc32(u32 oldhash, void* buf, u32 len){ + u8* ubuf=(u8*)buf; + register u32 crc=oldhash; + for (; len; --len, ++ubuf) + crc=crc_32_tab[(crc^(*ubuf)) & 0xff] ^ (crc>>8); + return ~crc; +} + + +// bool hashf_crc32c(char *name, u32 *crc, long *charcnt) { +// register FILE *fin; +// register u32 oldcrc32; +// register i32 c; + +// oldcrc32 = 0xFFFFFFFF; *charcnt = 0; +// if ((fin=fopen(name, "r"))==NULL) { +// perror(name); +// return false; +// } +// while ((c=getc(fin))!=EOF) { +// ++*charcnt; +// oldcrc32 = UPDC32(c, oldcrc32); +// } + +// if (ferror(fin)) { +// perror(name); +// *charcnt = -1; +// } + +// fclose(fin); + +// *crc = oldcrc32 = ~oldcrc32; +// return true; +// } diff --git a/kerep-headers/HashFunctions/hash.h b/kerep/src/HashFunctions/hash.h similarity index 100% rename from kerep-headers/HashFunctions/hash.h rename to kerep/src/HashFunctions/hash.h diff --git a/kerep/src/Hashtable/Hashtable.c b/kerep/src/Hashtable/Hashtable.c new file mode 100644 index 0000000..9c8fe15 --- /dev/null +++ b/kerep/src/Hashtable/Hashtable.c @@ -0,0 +1,133 @@ +#include "Hashtable.h" + +kt_define(Hashtable, __Hashtable_free, NULL); + +// amount of rows +static const u16 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(u16 i=0;irows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL); + return ht; +} + +void __Hashtable_free(void* _ht){ + Hashtable* ht=_ht; + for(u16 i=0;ihein];i++) + Autoarr_free(ht->rows[i], true); + free(ht->rows); +} +void Hashtable_free(Hashtable* ht){ + __Hashtable_free(ht); + free(ht); +} + +u16 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(u16 i=0;ihein];i++) + newrows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL); + + for(u16 i=0;ihein-1];i++){ + Autoarr(KVPair)* ar=ht->rows[i]; + u32 arlen=Autoarr_length(ar); + for(u32 k=0;khein]; + Autoarr(KVPair)* newar=newrows[newrown]; + Autoarr_add(newar,p); + } + // there is no need to free array values, because they are copied into new array + // so dont replace this incorrect auto-generated function + Autoarr_freeWithoutMembers(ar, true); + } + + free(ht->rows); + ht->rows=newrows; +} + +Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){ + u32 hash=hashs(hash_sdbm32, key); + Autoarr(KVPair)* ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; + if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar)) + Hashtable_expand(ht); + ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; + return ar; +} + +/// @param key must be heap allocated +/// Hashtable_free will free this pointer +void Hashtable_add(Hashtable* ht, char* key, Unitype u){ + KVPair p={ .key=key, .value=u }; + Autoarr_add(getrow(ht,key,true),p); +} + +void Hashtable_addMany(Hashtable* ht, KVPair* pair_array, u32 count){ + for(u32 i=0; ikey)) return &p->value; + } + return NULL; +} + +Unitype Hashtable_get(Hashtable* ht, char* key){ + Autoarr(KVPair)* ar=getrow(ht,key,false); + u32 arlen=Autoarr_length(ar); + for(u32 i=0;icompl_bufs) + b->compl_bufs=Autoarr_create(string,BL_C,BL_L); + u32 len=Autoarr_length(b->curr_buf); + if(!len) return; + string str={.length=len, .ptr=malloc(len)}; + u32 i=0; + Autoarr_foreach(b->curr_buf, c, + str.ptr[i++]=c; + ); + Autoarr_add(b->compl_bufs,str); + Autoarr_free(b->curr_buf, true); + b->curr_buf=Autoarr_create(i8,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(i8,BL_C,BL_L); + return b; +} + +void __StringBuilder_free(void* _b){ + StringBuilder* b=_b; + if(b->compl_bufs) Autoarr_free(b->compl_bufs, true); + Autoarr_free(b->curr_buf, true); +} +void StringBuilder_free(StringBuilder* b){ + __StringBuilder_free(b); + free(b); +} + +string StringBuilder_build(StringBuilder* b){ + complete_buf(b); + u32 len=0; + Autoarr_foreach(b->compl_bufs, cs, + len+=cs.length; + ); + string str= { .length=len, .ptr=malloc(len+1) }; + str.ptr[len]='\0'; + u32 i=0; + Autoarr_foreach(b->compl_bufs, cs, + for(u32 n=0;ncurr_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(u32 i=0; icurr_buf,s.ptr[i]); +} + +void StringBuilder_append_i64(StringBuilder* b, i64 a){ + try_complete_buf(b); + u8 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_u64(StringBuilder* b, u64 a){ + try_complete_buf(b); + u8 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_f64(StringBuilder* b, f64 a){ + try_complete_buf(b); + char buf[32]; + IFMSC( + sprintf_s(buf,32,"%lf",a), + sprintf(buf,"%lf",a) + ); + curr_buf_add_string(b, (string){.ptr=buf, .length=cptr_length(buf)}); +} diff --git a/kerep-headers/String/StringBuilder.h b/kerep/src/String/StringBuilder.h similarity index 100% rename from kerep-headers/String/StringBuilder.h rename to kerep/src/String/StringBuilder.h diff --git a/kerep/src/String/string.c b/kerep/src/String/string.c new file mode 100644 index 0000000..ffa17ce --- /dev/null +++ b/kerep/src/String/string.c @@ -0,0 +1,47 @@ +#include "string.h" + +kt_define(string, NULL, NULL); +Autoarr_define(string, false); + +// 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 and adds \0 at the end +string string_copy(string src){ + if(!src.ptr) + return src; + string nstr; + nstr.length=src.length; + nstr.ptr=malloc(nstr.length+1); + for(u32 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){ + if(s.length==0) return s; + string r={malloc(s.length), s.length}; + for(u32 i=0; i + +// returns length of char buffer (without \0) +u32 cptr_length(const char* str){ + const char *const str_first=str; + while(*str) + str++; + return str-str_first; +} + +// allocates new char[] and copies src there +char* cptr_copy(const char* src){ + u32 len=cptr_length(src)+1; + char* dst=malloc(len); + while(len--!=0) + dst[len]=src[len]; + return dst; +} + +// multiplies char n times +char* char_multiply(char c, u32 n){ + char* rez=malloc(n+1); + rez[n]=0; + while(n--!=0) + rez[n]=c; + return rez; +} + +bool cptr_equals(const char* key0, const char* key1){ + char c0=*key0; + char c1=*key1; + bool eq=c0==c1; + while(c0 && c1 && eq) { + c0=*++key0; + c1=*++key1; + eq=c0==c1; + } + return eq; +} + +bool cptr_startsWith(const char* src, const char* fragment){ + char c0=*src; + char c1=*fragment; + bool eq=c0==c1 && c0 !=0 && c1!=0; + while(c0 && c1 && eq) { + c0=*++src; + c1=*++fragment; + eq=c0==c1; + if(c1==0) + return true; + } + return eq; +} + +bool cptr_endsWith(const char* src, const char* fragment){ + u32 src_len=cptr_length(src); + u32 fr_len=cptr_length(fragment); + if(src_len0) + StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=src_remains_len}); + string rezult=StringBuilder_build(sb); + return rezult.ptr; +} diff --git a/kerep-headers/base/cptr.h b/kerep/src/base/cptr.h similarity index 100% rename from kerep-headers/base/cptr.h rename to kerep/src/base/cptr.h diff --git a/kerep/src/base/endian.c b/kerep/src/base/endian.c new file mode 100644 index 0000000..282a53b --- /dev/null +++ b/kerep/src/base/endian.c @@ -0,0 +1,13 @@ +#include "endian.h" + +static const union +{ + u16 number; + Endian bytes[2]; +} _endian_union={ .number=0x0102 }; + +Endian getEndian(){ + // if 0x0102 == { 1, 2 } then BigEndian + // if 0x0102 == { 2, 1 } then LittleEndian + return _endian_union.bytes[1]; +} diff --git a/kerep-headers/base/endian.h b/kerep/src/base/endian.h similarity index 100% rename from kerep-headers/base/endian.h rename to kerep/src/base/endian.h diff --git a/kerep/src/base/errors.c b/kerep/src/base/errors.c new file mode 100644 index 0000000..6f093f1 --- /dev/null +++ b/kerep/src/base/errors.c @@ -0,0 +1,59 @@ +#include "std.h" +#include "errors.h" +#include "cptr.h" +#include "../kprint/kprintf.h" + +char* errname(ErrorId err){ + switch(err){ + case SUCCESS: return nameof(SUCCESS); + case ERR_MAXLENGTH: return nameof(ERR_MAXLENGTH); + case ERR_WRONGTYPE: return nameof(ERR_WRONGTYPE); + case ERR_WRONGINDEX: return nameof(ERR_WRONGINDEX); + case ERR_NOTIMPLEMENTED: return nameof(ERR_NOTIMPLEMENTED); + case ERR_NULLPTR: return nameof(ERR_NULLPTR); + case ERR_ENDOFSTR: return nameof(ERR_ENDOFSTR); + case ERR_KEYNOTFOUND: return nameof(ERR_KEYNOTFOUND); + case ERR_FORMAT: return nameof(ERR_FORMAT); + case ERR_UNEXPECTEDVAL: return nameof(ERR_UNEXPECTEDVAL); + case ERR_IO: return nameof(ERR_IO); + case ERR_IO_EOF: return nameof(ERR_IO_EOF); + default: return "UNKNOWN_ERROR"; + } +} + +#define ERRMSG_MAXLENGTH 1024 + +char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){ + size_t bufsize=ERRMSG_MAXLENGTH; + char* rezult=malloc(bufsize); + IFMSC( + 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, i32 line, const char* funcname){ + size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH; + char* rezult=malloc(bufsize); + IFMSC( + 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) kprintf("%s\n",e.errmsg); + else printuni(e.value); +} + +char* __doNothing(char* a) {return a;} + +char* __unknownErr() {return "UNKNOWN ERROR";} diff --git a/kerep-headers/base/errors.h b/kerep/src/base/errors.h similarity index 100% rename from kerep-headers/base/errors.h rename to kerep/src/base/errors.h diff --git a/kerep-headers/base/optime.h b/kerep/src/base/optime.h similarity index 100% rename from kerep-headers/base/optime.h rename to kerep/src/base/optime.h diff --git a/kerep-headers/base/std.h b/kerep/src/base/std.h similarity index 98% rename from kerep-headers/base/std.h rename to kerep/src/base/std.h index 816d328..225f57b 100644 --- a/kerep-headers/base/std.h +++ b/kerep/src/base/std.h @@ -38,6 +38,10 @@ typedef u8 bool; #define false 0 #endif +#ifndef typeof +#define typeof __typeof__ +#endif + #define dbg(N) kprintf("\e[95m%d\n",N) #define nameof(V) #V diff --git a/kerep-headers/base/type_system/README.md b/kerep/src/base/type_system/README.md similarity index 100% rename from kerep-headers/base/type_system/README.md rename to kerep/src/base/type_system/README.md diff --git a/kerep/src/base/type_system/base_toString.c b/kerep/src/base/type_system/base_toString.c new file mode 100644 index 0000000..b63d82d --- /dev/null +++ b/kerep/src/base/type_system/base_toString.c @@ -0,0 +1,238 @@ +#include "base_toString.h" +#include "../base.h" +#include "../../kprint/kprint_format.h" + + +// accepts char* (ptr to char) and char* (ptr to string) +// uses format kp_s and kp_c to determine what type is argument +char* __toString_char(void* c, u32 fmt) { + // *c=char* + if(kp_fmt_dataFormat(fmt)==kp_s){ + return cptr_copy((char*)c); // to avoid segmentation fault on free() when *c allocalet on stack + } + // *c=char + if(kp_fmt_dataFormat(fmt)==kp_c){ + char* cc=malloc(2); + cc[0]=*(char*)c; + cc[1]=0; + return cc; + } + else throw(ERR_FORMAT); +} + +char* __toString_bool(void* c, u32 fmt) { + static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" }; + u8 strind=*(bool*)c==1 + kp_fmt_isUpper(fmt)*2; + char* rez=malloc(6); + rez[0]=_strbool[strind][0]; + rez[1]=_strbool[strind][1]; + rez[2]=_strbool[strind][2]; + rez[3]=_strbool[strind][3]; + rez[4]=_strbool[strind][4]; + rez[5]=0; + return rez; +} + +char* toString_i64(i64 n){ + i64 d=n<0 ? -1*n : n; + char str[32]; + u8 i=sizeof(str); + str[--i]=0; + if(d==0) + str[--i]='0'; + else while(d!=0){ + str[--i]='0' + d%10; + d/=10; + } + if(n<0) + str[--i]='-'; + return cptr_copy((char*)str+i); +} + +char* toString_u64(u64 n, bool withPostfix, bool uppercase){ + char str[32]; + u8 i=sizeof(str); + str[--i]=0; + if(withPostfix) + str[--i]= uppercase ? 'U' : 'u'; + if(n==0) + str[--i]='0'; + else while(n!=0){ + str[--i]='0' + n%10; + n/=10; + } + return cptr_copy((char*)str+i); +} + +#define _toString_float_impl(bufsize, maxPrecision) { \ + char str[bufsize]; \ + if(precision>maxPrecision) \ + throw("too big precision"); \ + if(precision==0) \ + precision=toString_float_default_precision; \ + i32 cn=IFMSC( \ + sprintf_s(str, bufsize, "%.*f", precision, n), \ + sprintf(str, "%.*f", precision, n) \ + ); \ + /* remove trailing zeroes except .0*/ \ + while(str[cn-1]=='0' && str[cn-2]!='.') \ + cn--; \ + if(withPostfix) \ + str[cn++]= uppercase ? 'F' : 'f'; \ + str[cn]='\0'; \ + return cptr_copy(str); \ +} + +char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase) + _toString_float_impl(48, toString_f32_max_precision) + +char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase) + _toString_float_impl(512, toString_f64_max_precision) + +#define byte_to_bits(byte) { \ + str[cn++]='0' + (u8)((byte>>7)&1); /* 8th bit */ \ + str[cn++]='0' + (u8)((byte>>6)&1); /* 7th bit */ \ + str[cn++]='0' + (u8)((byte>>5)&1); /* 6th bit */ \ + str[cn++]='0' + (u8)((byte>>4)&1); /* 5th bit */ \ + str[cn++]='0' + (u8)((byte>>3)&1); /* 4th bit */ \ + str[cn++]='0' + (u8)((byte>>2)&1); /* 3th bit */ \ + str[cn++]='0' + (u8)((byte>>1)&1); /* 2th bit */ \ + str[cn++]='0' + (u8)((byte>>0)&1); /* 1th bit */ \ +} + +char* toString_bin(void* _bytes, u32 size, bool inverse, bool withPrefix){ + char* bytes=_bytes; + char* str=malloc(size*8 + (withPrefix?2:0) +1); + u32 cn=0; // char number + if(withPrefix){ + str[cn++]='0'; + str[cn++]='b'; + } + if(inverse){ + // byte number + for(i32 bn=size-1; bn>=0; bn--) + byte_to_bits(bytes[bn]) + } else { + for(u32 bn=0; bn=0; bn--){ + unsigned char byte=bytes[bn]; + str[cn++]=_4bitsHex(byte/16, uppercase); + str[cn++]=_4bitsHex(byte%16, uppercase); + } + } + // right to left + else { + for(u32 bn=0; bnid, 0,0); + char *s1 = toString_u64(d->size, 0,0); + char *s2 = d->toString ? toString_hex(d->toString, sizeof(void*), 0,1,0) : n; + char *s3 = d->freeMembers ? toString_hex(d->freeMembers, sizeof(void*), 0,1,0) : n; + char *rez=cptr_concat("ktDescriptor {" + " name:", d->name, + " id:",s0, + " size:",s1, + " toString:",s2, + " freeMembers:",s3, + " }"); + free(s0); + free(s1); + if(s2!=n) free(s2); + if(s3!=n) free(s3); + return rez; +} + +char* _ktDescriptor_toString(void* _d, u32 fmt) { return ktDescriptor_toString(_d); } + +kt_define(ktDescriptor, NULL, _ktDescriptor_toString); + +typedef ktDescriptor* ktDescriptor_Ptr; + +// type descriptors are stored here during initialization +Autoarr(Pointer)* __descriptorPointers=NULL; +// here type descriptors are stored when initialization is complited +ktDescriptor** typeDescriptors=NULL; +ktid ktid_last=-1; + +ENUM(ktDescriptorsState, + NotInitialized, Initializing, Initialized +) +ktDescriptorsState initState=NotInitialized; + +void kt_beginInit(){ +#if DEBUG + kprintf("\e[94mtype descriptors initializing...\n"); +#endif + __descriptorPointers=Autoarr_create(Pointer, 256, 256); +} + +void kt_endInit(){ + if(__descriptorPointers==NULL) + throw(ERR_NULLPTR); + typeDescriptors=(ktDescriptor**)Autoarr_toArray(__descriptorPointers); + Autoarr_free(__descriptorPointers,true); + if(typeDescriptors==NULL) throw(ERR_NULLPTR); +#if DEBUG + kprintf("\e[92minitialized %u type descriptors\n", ktid_last); +#endif +} + +void __kt_register(ktDescriptor* descriptor){ + descriptor->id=++ktid_last; + Autoarr_add(__descriptorPointers, descriptor); +} + +ktDescriptor* ktDescriptor_get(ktid id){ + if(id>ktid_last || id==ktid_undefined) { + kprintf("\ntype id: %u\n",id); + throw("invalid type id"); + } + return typeDescriptors[id]; +} + +void kt_free(){ + free(typeDescriptors); +} diff --git a/kerep-headers/base/type_system/kt_functions.h b/kerep/src/base/type_system/kt_functions.h similarity index 100% rename from kerep-headers/base/type_system/kt_functions.h rename to kerep/src/base/type_system/kt_functions.h diff --git a/kerep-headers/base/type_system/ktid.h b/kerep/src/base/type_system/ktid.h similarity index 100% rename from kerep-headers/base/type_system/ktid.h rename to kerep/src/base/type_system/ktid.h diff --git a/kerep-headers/base/type_system/type_system.h b/kerep/src/base/type_system/type_system.h similarity index 100% rename from kerep-headers/base/type_system/type_system.h rename to kerep/src/base/type_system/type_system.h diff --git a/kerep-headers/base/type_system/typedef_macros.h b/kerep/src/base/type_system/typedef_macros.h similarity index 100% rename from kerep-headers/base/type_system/typedef_macros.h rename to kerep/src/base/type_system/typedef_macros.h diff --git a/kerep/src/base/type_system/unitype.c b/kerep/src/base/type_system/unitype.c new file mode 100644 index 0000000..a85c05e --- /dev/null +++ b/kerep/src/base/type_system/unitype.c @@ -0,0 +1,100 @@ +#include "../../kprint/kprint_format.h" +#include "../base.h" + +char *__Unitype_toString(void *_u, u32 fmt) +{ + return Unitype_toString(*(Unitype *)_u, fmt); +} + +kt_define(Unitype, __UnitypePtr_free, __Unitype_toString); + +void Unitype_free(Unitype u) +{ + if (u.typeId == ktid_undefined) + { + if (u.VoidPtr != NULL) + throw("unitype with undefined typeId has value"); + return; + } + + ktDescriptor *type = ktDescriptor_get(u.typeId); + if (type->freeMembers) + type->freeMembers(u.VoidPtr); + if (u.allocatedInHeap) + free(u.VoidPtr); +} +void __UnitypePtr_free(void *u) +{ + Unitype_free(*(Unitype *)u); +} + +char *Unitype_toString(Unitype u, u32 fmt) +{ + if (u.typeId == ktid_undefined) + { + if (u.VoidPtr != NULL) + throw("unitype with undefined typeId has value"); + return cptr_copy("{ERROR_TYPE}"); + } + + if (fmt == 0) + { + if (u.typeId == ktid_name(bool) || u.typeId == ktid_name(i8) || u.typeId == ktid_name(i16) || + u.typeId == ktid_name(i32) || u.typeId == ktid_name(i64)) + { + // auto format set + fmt = kp_i; + // replaces value with pointer to value to pass into toString_i64(void*, u32) + i64 value = u.Int64; + u.VoidPtr = &value; + } + else if (u.typeId == ktid_name(u8) || u.typeId == ktid_name(u16) || u.typeId == ktid_name(u32) || + u.typeId == ktid_name(u64)) + { + fmt = kp_u; + u64 value = u.UInt64; + u.VoidPtr = &value; + } + else if (u.typeId == ktid_name(f32) || u.typeId == ktid_name(f64)) + { + fmt = kp_f; + f64 value = u.Float64; + u.VoidPtr = &value; + } + else if (u.typeId == ktid_name(char)) + { + fmt = kp_c; + i64 value = u.Int64; + u.VoidPtr = &value; + } + else if (u.typeId == ktid_ptrName(char)) + { + fmt = kp_s; + } + else if (u.typeId == ktid_name(Pointer)) + { + if (u.VoidPtr == NULL) + return cptr_copy("{ UniNull }"); + fmt = kp_h; + } + } + + ktDescriptor *type = ktDescriptor_get(u.typeId); + char *valuestr; + if (type->toString) + valuestr = type->toString(u.VoidPtr, fmt); + else + valuestr = "ERR_NO_TOSTRING_FUNC"; + char *rezult = cptr_concat("{ type: ", type->name, ", allocated on heap: ", (u.allocatedInHeap ? "true" : "false"), + ", value:", valuestr, " }"); + if (type->toString) + free(valuestr); + return rezult; +} + +void printuni(Unitype v) +{ + char *s = Unitype_toString(v, 0); + fputs(s, stdout); + free(s); +} \ No newline at end of file diff --git a/kerep-headers/base/type_system/unitype.h b/kerep/src/base/type_system/unitype.h similarity index 100% rename from kerep-headers/base/type_system/unitype.h rename to kerep/src/base/type_system/unitype.h diff --git a/kerep-headers/kprint/README.md b/kerep/src/kprint/README.md similarity index 100% rename from kerep-headers/kprint/README.md rename to kerep/src/kprint/README.md diff --git a/kerep/src/kprint/kprint.c b/kerep/src/kprint/kprint.c new file mode 100644 index 0000000..046cf29 --- /dev/null +++ b/kerep/src/kprint/kprint.c @@ -0,0 +1,211 @@ +#include "../String/StringBuilder.h" +#include "kprint.h" + +ktid __typeFromFormat(kp_fmt f){ + ktid typeId=kp_fmt_ktid(f); + if(typeId) + return typeId; + switch(kp_fmt_dataFormat(f)){ + case kp_i: + case kp_h: + case kp_b: + return ktid_name(i64); + case kp_u: + return ktid_name(u64); + case kp_f: + return ktid_name(f64); + case kp_c: + return ktid_name(char); + case kp_s: + return ktid_ptrName(char); + default: + return ktid_undefined; + } +} + +Maybe __next_toString(kp_fmt f, void* object){ + // detecting type + ktid typeId=__typeFromFormat(f); + if(typeId==ktid_undefined) + safethrow("typeId is undefined, can't autodetect type",;); + + if(typeId==ktid_ptrName(char)) + object=*(char**)object; // dereferencing char** to char* + + ktDescriptor* type=ktDescriptor_get(typeId); + if(!type->toString) + safethrow("type descriptor doesnt have toString() func",;); + return SUCCESS(UniHeapPtr(char, type->toString(object, f))); +} + +Maybe check_argsN(u8 n){ + if(n%2 != 0) safethrow("kprint recieved non-even number of arguments",;); + if(n > 32) safethrow("kprint recieved >32 number of arguments",;); + return MaybeNull; +} + +Maybe __ksprint(u8 n, kp_fmt* formats, __kp_value_union* objects){ + try(check_argsN(n), _,;); + n/=2; + StringBuilder* strb=StringBuilder_create(); + for(u8 i=0; i +#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED + +DWORD kp_fgColor_toWin(kp_fgColor f){ + //kprintf("fg: %x\n", f); + switch(f){ + case kp_fgBlack: return 0; + case kp_fgRedD: return FOREGROUND_RED; + case kp_fgGreenD: return FOREGROUND_GREEN; + case kp_fgYellowD: return FOREGROUND_GREEN | FOREGROUND_RED; + case kp_fgBlueD: return FOREGROUND_BLUE; + case kp_fgMagentaD: return FOREGROUND_RED | FOREGROUND_BLUE; + case kp_fgCyanD: return FOREGROUND_BLUE | FOREGROUND_GREEN; + case kp_fgGray: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + case kp_fgGrayD: return FOREGROUND_INTENSITY; + case kp_fgRed: return FOREGROUND_RED | FOREGROUND_INTENSITY; + case kp_fgGreen: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case kp_fgYellow: return FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + case kp_fgBlue: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; + case kp_fgMagenta: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; + case kp_fgCyan: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case kp_fgWhite: return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + default: throw(ERR_FORMAT); + } +} + +DWORD kp_bgColor_toWin(kp_bgColor f){ + //kprintf("bg: %x\n", f); + switch(f){ + case kp_bgBlack: return 0; + case kp_bgRedD: return BACKGROUND_RED; + case kp_bgGreenD: return BACKGROUND_GREEN; + case kp_bgYellowD: return BACKGROUND_GREEN | BACKGROUND_RED; + case kp_bgBlueD: return BACKGROUND_BLUE; + case kp_bgMagentaD: return BACKGROUND_RED | BACKGROUND_BLUE; + case kp_bgCyanD: return BACKGROUND_BLUE | BACKGROUND_GREEN; + case kp_bgGray: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; + case kp_bgGrayD: return BACKGROUND_INTENSITY; + case kp_bgRed: return BACKGROUND_RED | BACKGROUND_INTENSITY; + case kp_bgGreen: return BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case kp_bgYellow: return BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + case kp_bgBlue: return BACKGROUND_BLUE | BACKGROUND_INTENSITY; + case kp_bgMagenta: return BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY; + case kp_bgCyan: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case kp_bgWhite: return BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + default: throw(ERR_FORMAT); + } +} + +void kprint_setColor(kp_fmt f){ + DWORD color=0; + if(!kp_fmt_fgColorSet(f) & !kp_fmt_bgColorSet(f)) + return; + if(kp_fmt_fgColorSet(f)) + color+=kp_fgColor_toWin(kp_fmt_fgColor(f)); + if(kp_fmt_bgColorSet(f)) + color+=kp_bgColor_toWin(kp_fmt_bgColor(f)); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, color); +} +#else +void kprint_setColor(kp_fmt f){ + if(kp_fmt_fgColorSet(f)){ + u8 fg=(f&0x0f000000)>>24; + if(fg<8) fg+=30; + else fg+=90-8; + printf("\e[%um", fg); + } + if(kp_fmt_bgColorSet(f)){ + u8 bg=(f&0x00f00000)>>20; + if(bg<8) bg+=40; + else bg+=100-8; + printf("\e[%um", bg); + } +} +#endif + +/* Maybe ksprint_ar(u32 count, kp_fmt format, ktid typeId, void* array){ + ktDescriptor* type=ktDescriptor_get(format.typeId); + if(!type->toString) + safethrow("type descriptor doesnt have toString() func",;); + StringBuilder* strb=StringBuilder_create(); + StringBuilder_append_char(strb, '['); + for (u16 e=1; etoString(array+type->size*e, &format); + StringBuilder_append_cptr(strb, elStr); + StringBuilder_append_char(strb, ','); + } + StringBuilder_rmchar(strb); + StringBuilder_append_char(strb, ' '); + StringBuilder_append_char(strb, ']'); +} */ + +static const char* _kp_colorNames[16]={ + "black", + "dark_red", + "dark_green", + "dark_yellow", + "dark_blue", + "dark_magenta", + "dark_cyan", + "gray", + "dark_gray", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", + "white" +}; + +char* kp_bgColor_toString(kp_bgColor c){ + u32 color_index=(c&0x00f00000)>>20; + if(color_index>15) throw(ERR_WRONGINDEX); + return _kp_colorNames[color_index]; +} +char* kp_fgColor_toString(kp_fgColor c){ + u32 color_index=(c&0x00f00000)>>24; + if(color_index>15) throw(ERR_WRONGINDEX); + return _kp_colorNames[color_index]; +} diff --git a/kerep-headers/kprint/kprint.h b/kerep/src/kprint/kprint.h similarity index 100% rename from kerep-headers/kprint/kprint.h rename to kerep/src/kprint/kprint.h diff --git a/kerep-headers/kprint/kprint_colors.h b/kerep/src/kprint/kprint_colors.h similarity index 100% rename from kerep-headers/kprint/kprint_colors.h rename to kerep/src/kprint/kprint_colors.h diff --git a/kerep-headers/kprint/kprint_format.h b/kerep/src/kprint/kprint_format.h similarity index 100% rename from kerep-headers/kprint/kprint_format.h rename to kerep/src/kprint/kprint_format.h diff --git a/kerep-headers/kprint/kprint_format.md b/kerep/src/kprint/kprint_format.md similarity index 100% rename from kerep-headers/kprint/kprint_format.md rename to kerep/src/kprint/kprint_format.md diff --git a/kerep/src/kprint/kprintf.c b/kerep/src/kprint/kprintf.c new file mode 100644 index 0000000..0f9e0a6 --- /dev/null +++ b/kerep/src/kprint/kprintf.c @@ -0,0 +1,155 @@ +#include "kprintf.h" +#include "../base/base.h" + +#if defined(_WIN64) || defined(_WIN32) +#include + +WORD unixColorToWin(u8 c){ + switch(c){ + //foreground + case 30: return 0; + case 31: return FOREGROUND_RED; + case 32: return FOREGROUND_GREEN; + case 33: return FOREGROUND_GREEN | FOREGROUND_RED; + case 34: return FOREGROUND_BLUE; + case 35: return FOREGROUND_RED | FOREGROUND_BLUE; + case 36: return FOREGROUND_BLUE | FOREGROUND_GREEN; + case 37: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + case 90: return FOREGROUND_INTENSITY; + case 91: return FOREGROUND_RED | FOREGROUND_INTENSITY; + case 92: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case 93: return FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + case 94: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; + case 95: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; + case 96: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case 97: return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + //background + case 40: return 0; + case 41: return BACKGROUND_RED; + case 42: return BACKGROUND_GREEN; + case 43: return BACKGROUND_GREEN | BACKGROUND_RED; + case 44: return BACKGROUND_BLUE; + case 45: return BACKGROUND_RED | BACKGROUND_BLUE; + case 46: return BACKGROUND_BLUE | BACKGROUND_GREEN; + case 47: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; + case 100: return BACKGROUND_INTENSITY; + case 101: return BACKGROUND_RED | BACKGROUND_INTENSITY; + case 102: return BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case 103: return BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + case 104: return BACKGROUND_BLUE | BACKGROUND_INTENSITY; + case 105: return BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY; + case 106: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case 107: return BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + default: return 0; + } +} +#endif + +void kprintf(const char* format, ...){ + va_list vl; + va_start(vl, format); + u32 i=0; + for(char c=format[i++]; c!=0; c=format[i++]){ + // value format specifiers + if(c=='%'){ + char* argstr=NULL; + bool l=false; + c=format[i++]; + format_escape_seq: + switch (c) { + case 'u': + argstr=toString_u64( + l ? va_arg(vl, u64) : va_arg(vl, u32) + ,0,0); + break; + case 'i': case 'd': + argstr=toString_i64( + l ? va_arg(vl, i64) : va_arg(vl, i32) + ); + break; + case 'f': + // f32 is promoted to f64 when passed through '...' + argstr=toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0); + break; + case 'l': + l=true; + if((c=format[i++])) + goto format_escape_seq; + break; + case 'p': ; + void* phex=va_arg(vl, void*); + argstr=toString_hex(&phex,getEndian()==LittleEndian,sizeof(phex),1,0); + break; + case 'x': ; + if(l){ + u64 xhex=va_arg(vl, u64); + argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); + } + else { + u32 xhex=va_arg(vl, u32); + argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); + } + break; + case 's': ; + char* cptr=va_arg(vl,char*); + if(!cptr) + cptr=""; + if(*cptr) + fputs(cptr, stdout); + break; + case 'c': + argstr=malloc(2); + argstr[0]=(char)va_arg(vl,int); + argstr[1]=0; + break; + default: + putc('\n',stdout); + putc('<',stdout); + putc(c,stdout); + putc('>',stdout); + throw(ERR_FORMAT); + } + if(argstr){ + fputs(argstr, stdout); + free(argstr); + } + } + // escape sequences + else if(c=='\e'){ + IFWIN( + /* WINDOWS */ + ({ + if((c=format[i++])=='['){ + u8 colorUnix=0; + for(i8 n=0; n<6 && c!=0; n++){ + c=format[i++]; + switch (c){ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + colorUnix=colorUnix*10+c-'0'; + break; + case 'm': ; + WORD colorWin=unixColorToWin(colorUnix); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, colorWin); + goto end_iteration; + default: + goto end_iteration; + } + } + } + }), + /* UNIX */ + putc(c,stdout); + ); + } + // common characters + else { + putc(c,stdout); + } + #if defined(_WIN64) || defined(_WIN32) + end_iteration:; + #endif + } + va_end(vl); +} diff --git a/kerep-headers/kprint/kprintf.h b/kerep/src/kprint/kprintf.h similarity index 100% rename from kerep-headers/kprint/kprintf.h rename to kerep/src/kprint/kprintf.h diff --git a/kerep-headers/random/krandom.h b/kerep/src/random/krandom.h similarity index 100% rename from kerep-headers/random/krandom.h rename to kerep/src/random/krandom.h diff --git a/kerep/src/random/splitmix64/splitmix64.c b/kerep/src/random/splitmix64/splitmix64.c new file mode 100644 index 0000000..c267b9e --- /dev/null +++ b/kerep/src/random/splitmix64/splitmix64.c @@ -0,0 +1,34 @@ +#include "splitmix64.h" + +/* +This is a fixed-increment version of Java 8's SplittableRandom generator +See http://dx.doi.org/10.1145/2714064.2660195 and +http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html +It is a very fast generator passing BigCrush, and it can be useful if +for some reason you absolutely want 64 bits of state; otherwise, we +rather suggest to use a xoroshiro128+ (for moderately parallel +computations) or xorshift1024* (for massively parallel computations) +generator. +*/ + +// The state can be seeded with any (upto) 64 bit integer value. + +void* splitmix64_init(u64 seed){ + splitmix64_state* state=malloc(sizeof(splitmix64_state)); + *state=seed; + return state; +} + +u64 splitmix64_next(void* _state) { + splitmix64_state* state=_state; + // increment the state variable + *state += 0x9e3779b97f4a7c15; + // copy the state to a working variable + u64 z = *state; + // xor the variable with the variable right bit shifted 30 then multiply by a constant + z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9; + // xor the variable with the variable right bit shifted 27 then multiply by a constant + z = (z ^ (z>>27)) * 0x94d049bb133111eb; + // return the variable xored with itself right bit shifted 31 + return z ^ (z>>31); +} diff --git a/kerep-headers/random/splitmix64/splitmix64.h b/kerep/src/random/splitmix64/splitmix64.h similarity index 100% rename from kerep-headers/random/splitmix64/splitmix64.h rename to kerep/src/random/splitmix64/splitmix64.h diff --git a/kerep-headers/random/xoroshiro/32bitValue/xoroshiro64.h b/kerep/src/random/xoroshiro/32bitValue/xoroshiro64.h similarity index 100% rename from kerep-headers/random/xoroshiro/32bitValue/xoroshiro64.h rename to kerep/src/random/xoroshiro/32bitValue/xoroshiro64.h diff --git a/kerep/src/random/xoroshiro/32bitValue/xoroshiro64star.c b/kerep/src/random/xoroshiro/32bitValue/xoroshiro64star.c new file mode 100644 index 0000000..ca57d35 --- /dev/null +++ b/kerep/src/random/xoroshiro/32bitValue/xoroshiro64star.c @@ -0,0 +1,49 @@ +/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro64.h" + +/* +This is xoroshiro64* 1.0, our best and fastest 32-bit small-state +generator for 32-bit floating-poi32 numbers. We suggest to use its +upper bits for floating-poi32 generation, as it is slightly faster than +xoroshiro64**. It passes all tests we are aware of except for linearity +tests, as the lowest six bits have low linear complexity, so if low +linear complexity is not considered an issue (as it is usually the +case) it can be used to generate 32-bit outputs, too. + +We suggest to use a sign test to extract a random Boolean value, and +right shifts to extract subsets of bits. + +The state must be seeded so that it is not everywhere zero. +*/ + +static inline u32 rotl(const u32 x, i32 k) { + return (x << k) | (x >> (32 - k)); +} + +u32 xoroshiro64star_next(void* _state) { + xoroshiro64_state* state=_state; + const u32 s0 = state->s[0]; + u32 s1 = state->s[1]; + const u32 result = s0 * 0x9E3779BB; + + s1 ^= s0; + state->s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9); // a, b + state->s[1] = rotl(s1, 13); // c + + return result; +} + +void* xoroshiro64_init(u64 seed){ + xoroshiro64_state* state=malloc(sizeof(xoroshiro64_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->merged=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/kerep/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c b/kerep/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c new file mode 100644 index 0000000..40d93fc --- /dev/null +++ b/kerep/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c @@ -0,0 +1,37 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro64.h" + +/* This is xoroshiro64** 1.0, our 32-bit all-purpose, rock-solid, + small-state generator. It is extremely fast and it passes all tests we + are aware of, but its state space is not large enough for any parallel + application. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoroshiro64* is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline u32 rotl(const u32 x, i32 k) { + return (x << k) | (x >> (32 - k)); +} + +u32 xoroshiro64starstar_next(void* _state) { + xoroshiro64_state* state=_state; + const u32 s0 = state->s[0]; + u32 s1 = state->s[1]; + const u32 result = rotl(s0 * 0x9E3779BB, 5) * 5; + + s1 ^= s0; + state->s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9); // a, b + state->s[1] = rotl(s1, 13); // c + + return result; +} diff --git a/kerep-headers/random/xoroshiro/64bitValue/xoroshiro128.h b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128.h similarity index 100% rename from kerep-headers/random/xoroshiro/64bitValue/xoroshiro128.h rename to kerep/src/random/xoroshiro/64bitValue/xoroshiro128.h diff --git a/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plus.c b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plus.c new file mode 100644 index 0000000..05760ec --- /dev/null +++ b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plus.c @@ -0,0 +1,59 @@ +/* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128+ 1.0, our best and fastest small-state generator + for floating-poi32 numbers, but its state space is large enough only + for mild parallelism. We suggest to use its upper bits for + floating-poi32 generation, as it is slightly faster than + xoroshiro128++/xoroshiro128**. It passes all tests we are aware of + except for the four lower bits, which might fail linearity tests (and + just those), so if low linear complexity is not considered an issue (as + it is usually the case) it can be used to generate 64-bit outputs, too; + moreover, this generator has a very mild Hamming-weight dependency + making our test (http://prng.di.unimi.it/hwd.php) fail after 5 TB of + output; we believe this slight bias cannot affect any application. If + you are concerned, use xoroshiro128++, xoroshiro128** or xoshiro256+. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. + + NOTE: the parameters (a=24, b=16, b=37) of this version give slightly + better results in our test than the 2016 version (a=55, b=14, c=36). +*/ + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x >> (64 - k)); +} + +u64 xoroshiro128plus_next(void* _state){ + xoroshiro128_state* state=_state; + const u64 s0 = state->s[0]; + u64 s1 = state->s[1]; + const u64 result = s0 + s1; + + s1 ^= s0; + state->s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + state->s[1] = rotl(s1, 37); // c + + return result; +} + +void* xoroshiro128_init(u64 seed){ + xoroshiro128_state* state=malloc(sizeof(xoroshiro128_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->s[0]=splitmix64_next(splitmix); + state->s[1]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c new file mode 100644 index 0000000..43e110e --- /dev/null +++ b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c @@ -0,0 +1,39 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128++ 1.0, one of our all-purpose, rock-solid, + small-state generators. It is extremely (sub-ns) fast and it passes all + tests we are aware of, but its state space is large enough only for + mild parallelism. + + For generating just floating-poi32 numbers, xoroshiro128+ is even + faster (but it has a very mild bias, see notes in the comments). + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x >> (64 - k)); +} + +u64 xoroshiro128plusplus_next(void* _state){ + xoroshiro128_state* state=_state; + const u64 s0 = state->s[0]; + u64 s1 = state->s[1]; + const u64 result = rotl(s0 + s1, 17) + s0; + + s1 ^= s0; + state->s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b + state->s[1] = rotl(s1, 28); // c + + return result; +} diff --git a/kerep/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c new file mode 100644 index 0000000..5e25851 --- /dev/null +++ b/kerep/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c @@ -0,0 +1,39 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128** 1.0, one of our all-purpose, rock-solid, + small-state generators. It is extremely (sub-ns) fast and it passes all + tests we are aware of, but its state space is large enough only for + mild parallelism. + + For generating just floating-poi32 numbers, xoroshiro128+ is even + faster (but it has a very mild bias, see notes in the comments). + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x >> (64 - k)); +} + +u64 xoroshiro128starstar_next(void* _state){ + xoroshiro128_state* state=_state; + const u64 s0 = state->s[0]; + u64 s1 = state->s[1]; + const u64 result = rotl(s0 * 5, 7) * 9; + + s1 ^= s0; + state->s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + state->s[1] = rotl(s1, 37); // c + + return result; +} diff --git a/kerep-headers/random/xoroshiro/xoroshiro.h b/kerep/src/random/xoroshiro/xoroshiro.h similarity index 100% rename from kerep-headers/random/xoroshiro/xoroshiro.h rename to kerep/src/random/xoroshiro/xoroshiro.h diff --git a/kerep-headers/random/xoshiro-xoroshiro.md b/kerep/src/random/xoshiro-xoroshiro.md similarity index 100% rename from kerep-headers/random/xoshiro-xoroshiro.md rename to kerep/src/random/xoshiro-xoroshiro.md diff --git a/kerep-headers/random/xoshiro/32bitValue/xoshiro128.h b/kerep/src/random/xoshiro/32bitValue/xoshiro128.h similarity index 100% rename from kerep-headers/random/xoshiro/32bitValue/xoshiro128.h rename to kerep/src/random/xoshiro/32bitValue/xoshiro128.h diff --git a/kerep/src/random/xoshiro/32bitValue/xoshiro128plus.c b/kerep/src/random/xoshiro/32bitValue/xoshiro128plus.c new file mode 100644 index 0000000..f68b3d5 --- /dev/null +++ b/kerep/src/random/xoshiro/32bitValue/xoshiro128plus.c @@ -0,0 +1,54 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128+ 1.0, our best and fastest 32-bit generator for 32-bit + floating-poi32 numbers. We suggest to use its upper bits for + floating-poi32 generation, as it is slightly faster than xoshiro128**. + It passes all tests we are aware of except for + linearity tests, as the lowest four bits have low linear complexity, so + if low linear complexity is not considered an issue (as it is usually + the case) it can be used to generate 32-bit outputs, too. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline u32 rotl(const u32 x, i32 k) { + return (x << k) | (x >> (32 - k)); +} + +u32 xoshiro128plus_next(void* _state){ + xoshiro128_state* state=_state; + const u32 result = state->s[0] + state->s[3]; + + const u32 t = state->s[1] << 9; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 11); + + return result; +} + +void* xoshiro128_init(u64 seed){ + xoshiro128_state* state=malloc(sizeof(xoshiro128_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->merged[0]=splitmix64_next(splitmix); + state->merged[1]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/kerep/src/random/xoshiro/32bitValue/xoshiro128plusplus.c b/kerep/src/random/xoshiro/32bitValue/xoshiro128plusplus.c new file mode 100644 index 0000000..8fea492 --- /dev/null +++ b/kerep/src/random/xoshiro/32bitValue/xoshiro128plusplus.c @@ -0,0 +1,42 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline u32 rotl(const u32 x, i32 k) { + return (x << k) | (x >> (32 - k)); +} + +u32 xoshiro128plusplus_next(void* _state){ + xoshiro128_state* state=_state; + const u32 result = rotl(state->s[0] + state->s[3], 7) + state->s[0]; + + const u32 t = state->s[1] << 9; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 11); + + return result; +} diff --git a/kerep/src/random/xoshiro/32bitValue/xoshiro128starstar.c b/kerep/src/random/xoshiro/32bitValue/xoshiro128starstar.c new file mode 100644 index 0000000..87a20bc --- /dev/null +++ b/kerep/src/random/xoshiro/32bitValue/xoshiro128starstar.c @@ -0,0 +1,45 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + Note that version 1.0 had mistakenly state->s[0] instead of state->s[1] as state + word passed to the scrambler. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline u32 rotl(const u32 x, i32 k) { + return (x << k) | (x >> (32 - k)); +} + +u32 xoshiro128starstar_next(void* _state){ + xoshiro128_state* state=_state; + const u32 result = rotl(state->s[1] * 5, 7) * 9; + + const u32 t = state->s[1] << 9; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 11); + + return result; +} diff --git a/kerep-headers/random/xoshiro/64bitValue/xoshiro256.h b/kerep/src/random/xoshiro/64bitValue/xoshiro256.h similarity index 100% rename from kerep-headers/random/xoshiro/64bitValue/xoshiro256.h rename to kerep/src/random/xoshiro/64bitValue/xoshiro256.h diff --git a/kerep/src/random/xoshiro/64bitValue/xoshiro256plus.c b/kerep/src/random/xoshiro/64bitValue/xoshiro256plus.c new file mode 100644 index 0000000..ee7ae32 --- /dev/null +++ b/kerep/src/random/xoshiro/64bitValue/xoshiro256plus.c @@ -0,0 +1,58 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256+ 1.0, our best and fastest generator for floating-point + numbers. We suggest to use its upper bits for floating-point + generation, as it is slightly faster than xoshiro256++/xoshiro256**. It + passes all tests we are aware of except for the lowest three bits, + which might fail linearity tests (and just those), so if low linear + complexity is not considered an issue (as it is usually the case) it + can be used to generate 64-bit outputs, too. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x >> (64 - k)); +} + +u64 xoshiro256plus_next(void* _state){ + xoshiro256_state* state=_state; + const u64 result = state->s[0] + state->s[3]; + + const u64 t = state->s[1] << 17; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 45); + + return result; +} + +void* xoshiro256_init(u64 seed){ + xoshiro256_state* state=malloc(sizeof(xoshiro256_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->s[0]=splitmix64_next(splitmix); + state->s[1]=splitmix64_next(splitmix); + state->s[2]=splitmix64_next(splitmix); + state->s[3]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/kerep/src/random/xoshiro/64bitValue/xoshiro256plusplus.c b/kerep/src/random/xoshiro/64bitValue/xoshiro256plusplus.c new file mode 100644 index 0000000..d28eb7c --- /dev/null +++ b/kerep/src/random/xoshiro/64bitValue/xoshiro256plusplus.c @@ -0,0 +1,37 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators. + It has excellent (sub-ns) speed, a state (256 bits) that is large + enough for any parallel application, and it passes all tests we are + aware of. + + For generating just floating-poi32 numbers, xoshiro256+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x>>(64 - k)); +} + +u64 xoshiro256plusplus_next(void* _state) { + xoshiro256_state* state=_state; + const u64 result=rotl(state->s[0] + state->s[3], 23) + state->s[0]; + const u64 t=state->s[1] << 17; + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + state->s[2] ^= t; + state->s[3]=rotl(state->s[3], 45); + return result; +} diff --git a/kerep/src/random/xoshiro/64bitValue/xoshiro256starstar.c b/kerep/src/random/xoshiro/64bitValue/xoshiro256starstar.c new file mode 100644 index 0000000..804007c --- /dev/null +++ b/kerep/src/random/xoshiro/64bitValue/xoshiro256starstar.c @@ -0,0 +1,42 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256** 1.0, one of our all-purpose, rock-solid + generators. It has excellent (sub-ns) speed, a state (256 bits) that is + large enough for any parallel application, and it passes all tests we + are aware of. + + For generating just floating-poi32 numbers, xoshiro256+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +static inline u64 rotl(const u64 x, i32 k) { + return (x << k) | (x >> (64 - k)); +} + +u64 xoshiro256starstar_next(void* _state){ + xoshiro256_state* state=_state; + const u64 result = rotl(state->s[1] * 5, 7) * 9; + + const u64 t = state->s[1] << 17; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 45); + + return result; +} diff --git a/kerep-headers/random/xoshiro/xoshiro.h b/kerep/src/random/xoshiro/xoshiro.h similarity index 100% rename from kerep-headers/random/xoshiro/xoshiro.h rename to kerep/src/random/xoshiro/xoshiro.h diff --git a/libkerep.a.tar.xz b/libkerep.a.tar.xz deleted file mode 100644 index 06af52d..0000000 Binary files a/libkerep.a.tar.xz and /dev/null differ diff --git a/src/CompilationScenario.c b/src/CompilationScenario.c index 9b27881..df00b44 100644 --- a/src/CompilationScenario.c +++ b/src/CompilationScenario.c @@ -125,5 +125,5 @@ Maybe CompilationScenario_exec(CompilationScenario* sc){ return false; } );*/ - return true; + return MaybeNull; } diff --git a/src/CompilationScenario.h b/src/CompilationScenario.h index 5f6626e..d4b7beb 100644 --- a/src/CompilationScenario.h +++ b/src/CompilationScenario.h @@ -1,4 +1,4 @@ -#include "../kerep-headers/DtsodParser/DtsodV24.h" +#include "../kerep/src/DtsodParser/DtsodV24.h" extern const char* os; extern const char* arch; diff --git a/src/cbuilld.c b/src/cbuilld.c index 909d5d4..8410add 100644 --- a/src/cbuilld.c +++ b/src/cbuilld.c @@ -1,6 +1,6 @@ -#include "../kerep-headers/base/base.h" -#include "../kerep-headers/Filesystem/filesystem.h" -#include "../kerep-headers/DtsodParser/DtsodV24.h" +#include "../kerep/src/base/base.h" +#include "../kerep/src/Filesystem/filesystem.h" +#include "../kerep/src/DtsodParser/DtsodV24.h" #include "CompilationScenario.h" #ifndef OS @@ -15,9 +15,8 @@ const char* arch=ARCH; const char* global_out_dir="bin"; const char* configuration="release"; -const char* task="exe"; -const char** projects=NULL; -u16 project_count = 0; +const char* project_dir_or_file="./"; +Autoarr(Pointer)* tasks; int erri(ErrorId err_code){ throw(err_code); @@ -37,72 +36,66 @@ int main(const int argc, const char** argv){ kt_initKerepTypes(); kt_endInit(); - if(cptr_equals(os, "UNDEFINED")) - throw("Operation system undefined. Recompile cbuild with flag -DOS=$(./detect_os.sh)"); - if(cptr_equals(arch, "UNDEFINED")) - throw("CPU architecture undefined. Recompile cbuild with flag -DARCH=$(./detect_arch.sh)"); + tasks = Autoarr_create(Pointer, 16, 32); - Autoarr(Pointer)* projects_ar = Autoarr_create(Pointer, 16, 32); + if(cptr_equals(os, "UNDEFINED")) + throw("Operation system undefined. Recompile cbuild with flag -DOS=\\\"$(./detect_os.sh)\\\""); + if(cptr_equals(arch, "UNDEFINED")) + throw("CPU architecture undefined. Recompile cbuild with flag -DARCH=\\\"$(./detect_arch.sh)\\\""); for(int argi = 1; argi < argc; argi++){ const char* arg = argv[argi]; kprintf("arg: %s\n", arg); - if(argIs("-h") || argIs("--help") || argIs("/?")) - kprintf("Usage: cbuild [options] [projects files/dirs]\n" + if(argIs("-h") || argIs("--help") || argIs("/?")){ + kprintf("Usage: cbuild [options] [tasks0 task1...]\n" " Options:\n" " -h, --help, /? Display this message.\n" " -o, --out-dir Set global output directory (default=bin).\n" " -c, --configuration Select project configuration (default=release).\n" - " -t, --task Select build task from project.\n"); + " -p, --project Set project directory/file (default=./).\n"); + return 0; + } else if(argIs("-o") || argIs("--out-dir")) global_out_dir = argNext(); else if(argIs("-c") || argIs("--configuration")) configuration = argNext(); - else if(argIs("-t") || argIs("--task")) - task = argNext(); + else if(argIs("-p") || argIs("--project")) + project_dir_or_file = argNext(); else { if(arg[0] == '-') throw(cptr_concat("invalid argument: ", arg)); - Autoarr_add(projects_ar, arg); + Autoarr_add(tasks, arg); } } - project_count = Autoarr_length(projects_ar); - projects = (const char**)Autoarr_toArray(projects_ar); - Autoarr_freeWithoutMembers(projects_ar, true); - if(project_count == 0){ - projects = malloc(sizeof(char*)); - projects[0] = projectFileFromDir("."); - } + const char* proj_file_path = NULL; + if(file_exists(project_dir_or_file)) + proj_file_path = project_dir_or_file; + else if(dir_exists(project_dir_or_file)) + proj_file_path = projectFileFromDir(project_dir_or_file); + else throw(cptr_concat("can't find a project at path '", project_dir_or_file, "'")); + + tryLast(file_open(proj_file_path, FileOpenMode_Read), _m1, ;); + FileHandle proj_file = _m1.value.VoidPtr; + char* proj_file_text = NULL; + tryLast(file_readAll(proj_file, &proj_file_text), _m2, file_close(proj_file)); + file_close(proj_file); - for(u16 i=0; i < project_count; i++){ - const char* proj = projects[i]; - const char* proj_file_path = NULL; - if(file_exists(proj)) - proj_file_path = proj; - else if(dir_exists(proj)) - proj_file_path = projectFileFromDir(proj); - - tryLast(file_open(proj_file_path, FileOpenMode_Read), _m1, ;); - FileHandle proj_file = _m1.value.VoidPtr; - char* proj_file_text; - tryLast(file_readAll(proj_file, &proj_file_text), _m2, file_close(proj_file)); - file_close(proj_file); + tryLast(DtsodV24_deserialize(proj_file_text), _m3, free(proj_file_text)); + Hashtable* proj_dtsod = _m3.value.VoidPtr; - tryLast(DtsodV24_deserialize(proj_file_text), _m3, free(proj_file_text)); - Hashtable* proj_dtsod = _m3.value.VoidPtr; + Autoarr_foreach(tasks, task, CompilationScenario proj_sc; CompilationScenario_construct(&proj_sc); - tryLast(CompilationScenario_applyProjectOptions(&proj_sc, proj_dtsod, configuration, task), _m4, free(proj_file_text)) - - if(!CompilationScenario_exec(&proj_sc)) - throw("compilation error"); - + tryLast(CompilationScenario_applyProjectOptions(&proj_sc, proj_dtsod, configuration, task), _m4, ) + tryLast(CompilationScenario_exec(&proj_sc), _m5, ;) CompilationScenario_destruct(&proj_sc); - Hashtable_free(proj_dtsod); - free(proj_file_text); - } + ) +#if DEBUG + Hashtable_free(proj_dtsod); + free(proj_file_text); kt_free(); +#endif return 0; }