Compare commits
10 Commits
683395983c
...
d873ee19c1
| Author | SHA1 | Date | |
|---|---|---|---|
| d873ee19c1 | |||
| 6fe1d5a511 | |||
| ab2f7b14a1 | |||
| 91b5eef3dc | |||
| 1b5efdb146 | |||
| 16f86ce592 | |||
| c53500d6ac | |||
| 15085957fc | |||
| a2fc40b006 | |||
| 44ee9e210f |
35
.vscode/launch.json
vendored
Normal file
35
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Debug",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/bin",
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}\\bin\\cbuild.exe",
|
||||
},
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/bin/cbuild",
|
||||
},
|
||||
"args": [ "-p", "../example.proj.dtsod", "exe"],
|
||||
"preLaunchTask": "build",
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
24
.vscode/tasks.json
vendored
Normal file
24
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "build",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"${workspaceRoot}/build.sh",
|
||||
"debug"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
77
TODO.md
Normal file
77
TODO.md
Normal file
@@ -0,0 +1,77 @@
|
||||
## cbuild logic description
|
||||
+ verify cbuild version
|
||||
+ foreach dep in import
|
||||
+ if dep starts with "./"
|
||||
+ import local file
|
||||
+ else
|
||||
+ if find(dep in ./cbuild)
|
||||
+ else if find (dep in global_config_dir/**)
|
||||
+ else error: "import target 'dep' not found, try 'fluzm find dep'"
|
||||
+ apply proj settings
|
||||
+ apply platform settings
|
||||
+ apply configuration settings
|
||||
+ apply platform settings
|
||||
+ foreach task in tasks
|
||||
+ apply platform settings
|
||||
+ foreach tool in tool_order
|
||||
+ apply task settings
|
||||
+ foreach src in find(dir, langs)
|
||||
+ if platform, settings, src or src_deps (included headers) were changed
|
||||
+ src -> src_to_process
|
||||
+ if parallel
|
||||
+ foreach src in src_to_process
|
||||
+ run tool on src
|
||||
+ else
|
||||
+ run tool on src_to_process
|
||||
|
||||
## Example of project.dtsod:
|
||||
```yml
|
||||
cbuild_version: 0;
|
||||
import: [ "c", "c++", "gcc", "./some_local_file.dtsod" ];
|
||||
|
||||
gcc: {
|
||||
src_languages: [ "c" ],
|
||||
src_dirs: [ "src" ],
|
||||
};
|
||||
|
||||
configurations: {
|
||||
release: {
|
||||
preprocess_sources: {
|
||||
src_languages: [ "c", "c++" ],
|
||||
src_dirs: [ "src" ],
|
||||
},
|
||||
gcc: {
|
||||
pre_args: [ "-O2" ],
|
||||
post_args: [ "-Wl,--gc-sections" ],
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
tasks: {
|
||||
exe: {
|
||||
pre_tasks: [ ],
|
||||
tool_order: [ "preprocess_sources", "gcc", "g++", "g++-link" ],
|
||||
g++: [ ... ],
|
||||
};
|
||||
};
|
||||
|
||||
languages: [
|
||||
{
|
||||
aliases: [ "c" ],
|
||||
file_extensions: [ "c" ],
|
||||
},
|
||||
{
|
||||
aliases: [ "c-header" ],
|
||||
file_extensions: [ "h" ],
|
||||
}
|
||||
];
|
||||
|
||||
tools: [
|
||||
{
|
||||
aliases: [ "gcc" ],
|
||||
exe_file: [ "gcc" ],
|
||||
supported_languages: [ "c" ]; # set to "any" to use with any lang
|
||||
parallel: true,
|
||||
}
|
||||
];
|
||||
```
|
||||
40
build.sh
40
build.sh
@@ -1,31 +1,47 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
CONFIG_DIR="/etc/cbuild"
|
||||
CMP="gcc"
|
||||
ARGS="-Wall -Wno-discarded-qualifiers -O2"
|
||||
SRC="$(find . -name '*.c')"
|
||||
LINK="-L. -lkerep"
|
||||
WARN="-Wall -Wextra -Wno-discarded-qualifiers -Wno-unused-parameter"
|
||||
|
||||
OS=$(./detect_os.sh)
|
||||
ARCH=$(./detect_arch.sh)
|
||||
ARGS_DEBUG="-O0 -g"
|
||||
ARGS_RELEASE="-O2 -flto=auto -fdata-sections -ffunction-sections -Wl,--gc-sections"
|
||||
if [[ "$1" = "debug" ]]; then
|
||||
ARGS=$ARGS_DEBUG
|
||||
else
|
||||
ARGS=$ARGS_RELEASE
|
||||
fi
|
||||
|
||||
if [[ OS == "windows" ]]; then
|
||||
SRC="$(find src -name '*.c')"
|
||||
|
||||
OS="$(./detect_os.sh)"
|
||||
ARCH="$(./detect_arch.sh)"
|
||||
LINK="-Lkerep/bin -lkerep-$OS-$ARCH"
|
||||
|
||||
if [ "$OS" = "windows" ]; then
|
||||
OUT_FILE="cbuild.exe"
|
||||
else
|
||||
OUT_FILE="cbuild"
|
||||
fi
|
||||
|
||||
command="$CMP $ARGS
|
||||
-DOS=$OS -DARCH=$ARCH
|
||||
$WARN
|
||||
-DOS=\"$OS\" -DARCH=\"$ARCH\" -DCONFIG_DIR=\"$CONFIG_DIR\"
|
||||
$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
|
||||
mkdir -p bin
|
||||
echo "----------------[cbuild]----------------"
|
||||
echo "$command"
|
||||
|
||||
tar xJf libkerep.a.tar.xz
|
||||
|
||||
$($command)
|
||||
|
||||
rm libkerep.a
|
||||
|
||||
@@ -20,4 +20,4 @@ case "$uname_rezult" in
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "\"$ARCH\""
|
||||
echo "$ARCH"
|
||||
|
||||
@@ -23,4 +23,4 @@ case "$uname_rezult" in
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "\"$OS\""
|
||||
echo "$OS"
|
||||
|
||||
48
example.proj.dtsod
Normal file
48
example.proj.dtsod
Normal file
@@ -0,0 +1,48 @@
|
||||
cbuild_version: 0;
|
||||
import: [ "c", "c++", "gcc", "./some_local_file.dtsod" ];
|
||||
|
||||
gcc: {
|
||||
src_languages: [ "c" ],
|
||||
src_dirs: [ "src" ],
|
||||
};
|
||||
|
||||
configurations: {
|
||||
release: {
|
||||
preprocess_sources: {
|
||||
src_languages: [ "c", "c++" ],
|
||||
src_dirs: [ "src" ],
|
||||
},
|
||||
gcc: {
|
||||
pre_args: [ "-O2" ],
|
||||
post_args: [ "-Wl,--gc-sections" ],
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
tasks: {
|
||||
exe: {
|
||||
pre_tasks: [ ],
|
||||
tool_order: [ "preprocess_sources", "gcc", "g++", "g++-link" ],
|
||||
#g++: [ ... ],
|
||||
};
|
||||
};
|
||||
|
||||
languages: [
|
||||
{
|
||||
aliases: [ "c" ],
|
||||
file_extensions: [ "c" ],
|
||||
},
|
||||
{
|
||||
aliases: [ "c-header" ],
|
||||
file_extensions: [ "h" ],
|
||||
}
|
||||
];
|
||||
|
||||
tools: [
|
||||
{
|
||||
aliases: [ "gcc" ],
|
||||
exe_file: "gcc",
|
||||
supported_languages: [ "c" ]; # set to "any" to use with any lang
|
||||
parallel: false,
|
||||
}
|
||||
];
|
||||
@@ -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
|
||||
2
kerep/.gitignore
vendored
Normal file
2
kerep/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
obj/
|
||||
libkerep.*
|
||||
41
kerep/build.sh
Normal file
41
kerep/build.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
CMP="gcc"
|
||||
WARN="-std=c11 -Wall -Wno-discarded-qualifiers -Wno-unused-parameter"
|
||||
ARGS="-O2 -flto=auto -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
|
||||
17
kerep/src/Autoarr/Autoarr.c
Normal file
17
kerep/src/Autoarr/Autoarr.c
Normal file
@@ -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)
|
||||
17
kerep/src/DtsodParser/DtsodV24.h
Normal file
17
kerep/src/DtsodParser/DtsodV24.h
Normal file
@@ -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
|
||||
344
kerep/src/DtsodParser/DtsodV24_deserialize.c
Normal file
344
kerep/src/DtsodParser/DtsodV24_deserialize.c
Normal file
@@ -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<sizeof(errBuf);n++)
|
||||
errBuf[n]='\0';
|
||||
char* errText=_text-32;
|
||||
u8 cplace=32;
|
||||
if(errText<text_first) {
|
||||
cplace=_text-text_first;
|
||||
errText=text_first;
|
||||
}
|
||||
u8 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];
|
||||
IFMSC(
|
||||
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,;);
|
||||
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 <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(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);
|
||||
}
|
||||
130
kerep/src/DtsodParser/DtsodV24_serialize.c
Normal file
130
kerep/src/DtsodParser/DtsodV24_serialize.c
Normal file
@@ -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));
|
||||
}
|
||||
69
kerep/src/Filesystem/dir.c
Normal file
69
kerep/src/Filesystem/dir.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -13,14 +13,14 @@ Maybe dir_create(const char* path);
|
||||
///@return Maybe<void>
|
||||
Maybe dir_delete(const char* path);
|
||||
|
||||
///@return Maybe<Array_string>
|
||||
///@return Maybe<char**>
|
||||
Maybe dir_getFiles(const char* path, bool recursive);
|
||||
///@return Maybe<Array_string>
|
||||
///@return Maybe<char**>
|
||||
Maybe dir_getDirs(const char* path, bool recursive);
|
||||
|
||||
///@return Maybe<Array_string>
|
||||
///@return Maybe<char**>
|
||||
Maybe dir_findFiles(const char* path, char* searchPattern, bool recursive);
|
||||
///@return Maybe<Array_string>
|
||||
///@return Maybe<char**>
|
||||
Maybe dir_findDirs(const char* path, char* searchPattern, bool recursive);
|
||||
|
||||
#if __cplusplus
|
||||
138
kerep/src/Filesystem/file.c
Normal file
138
kerep/src/Filesystem/file.c
Normal file
@@ -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<length && !rezult; i++)
|
||||
rezult=fputc(buffer[i], file);
|
||||
ioWriteCheck();
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe file_writeCptr(FileHandle file, char* cptr){
|
||||
i32 rezult=fputs(cptr, file);
|
||||
ioWriteCheck();
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
|
||||
Maybe file_readChar(FileHandle file){
|
||||
i32 rezult=fgetc(file);
|
||||
if(feof(file)) safethrow(ERR_IO_EOF,;);
|
||||
if(ferror(file)) safethrow(ERR_IO,;);
|
||||
return SUCCESS(UniUInt64(rezult));
|
||||
}
|
||||
|
||||
Maybe file_readBuffer(FileHandle file, char* buffer, u64 length){
|
||||
i32 rezult=0;
|
||||
u64 i=0;
|
||||
for(; i<length && rezult!=EOF; i++){
|
||||
rezult=fgetc(file);
|
||||
buffer[i]=(char)rezult;
|
||||
}
|
||||
if(ferror(file)) safethrow(ERR_IO,;);
|
||||
return SUCCESS(UniUInt64(i));
|
||||
}
|
||||
|
||||
Maybe file_readAll(FileHandle file, char** allBytes){
|
||||
i32 rezult=0;
|
||||
char buffer[256];
|
||||
string bufStr={.ptr=buffer, .length=sizeof(buffer)};
|
||||
StringBuilder* sb=StringBuilder_create();
|
||||
u64 i=0;
|
||||
while(true){
|
||||
rezult=fgetc(file);
|
||||
if(rezult==EOF){
|
||||
if(ferror(file))
|
||||
safethrow(ERR_IO, StringBuilder_free(sb));
|
||||
break;
|
||||
}
|
||||
buffer[i%sizeof(buffer)]=(char)rezult;
|
||||
i++;
|
||||
if(!(i%sizeof(buffer)))
|
||||
StringBuilder_append_string(sb,bufStr);
|
||||
}
|
||||
bufStr.length=i%sizeof(buffer);
|
||||
if(bufStr.length!=0)
|
||||
StringBuilder_append_string(sb,bufStr);
|
||||
string str=StringBuilder_build(sb);
|
||||
*allBytes=str.ptr;
|
||||
// i dont know how can it happen, but if it will have, it will be very dangerous
|
||||
if(i!=str.length)
|
||||
throw(ERR_UNEXPECTEDVAL);
|
||||
return SUCCESS(UniUInt64(i));
|
||||
}
|
||||
84
kerep/src/Filesystem/path.c
Normal file
84
kerep/src/Filesystem/path.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "filesystem.h"
|
||||
|
||||
char* __path_concat(u32 n, ...){
|
||||
char** parts=(char**)malloc(n*sizeof(char*));
|
||||
u32* lengths=malloc(n*sizeof(u32));
|
||||
u32 totalLength=0;
|
||||
|
||||
// reading args from va_list
|
||||
va_list vl;
|
||||
va_start(vl, n);
|
||||
for(u16 i=0; i<n; i++){
|
||||
char* part=va_arg(vl,char*);
|
||||
i16 length=cptr_length(part);
|
||||
parts[i]=part;
|
||||
lengths[i]=length;
|
||||
totalLength+=length;
|
||||
}
|
||||
va_end(vl);
|
||||
|
||||
// allocating memory for output value
|
||||
char* totality=malloc(totalLength+1);
|
||||
const char* output=totality;
|
||||
totality[totalLength]=0;
|
||||
|
||||
// copying content of all strings to rezult
|
||||
u16 k=0;
|
||||
for(; k<n-1; k++){
|
||||
memcopy(parts[k], totality, lengths[k]);
|
||||
totality+=lengths[k];
|
||||
*totality=path_sep;
|
||||
totality++;
|
||||
}
|
||||
memcopy(parts[k], totality, lengths[k]);
|
||||
|
||||
free(parts);
|
||||
free(lengths);
|
||||
return output;
|
||||
}
|
||||
|
||||
char* path_fixSeparators(const char* path){
|
||||
char* pathCopy=cptr_copy(path);
|
||||
char c;
|
||||
while((c=*pathCopy)){
|
||||
if(c==path_notSep)
|
||||
*pathCopy=path_sep;
|
||||
pathCopy++;
|
||||
}
|
||||
return pathCopy;
|
||||
}
|
||||
|
||||
Maybe path_throwIfEscapes(const char* path){
|
||||
if(cptr_contains(path,".."))
|
||||
safethrow(cptr_concat("path <",path,"> 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);
|
||||
}
|
||||
111
kerep/src/HashFunctions/hash.c
Normal file
111
kerep/src/HashFunctions/hash.c
Normal file
@@ -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;
|
||||
// }
|
||||
133
kerep/src/Hashtable/Hashtable.c
Normal file
133
kerep/src/Hashtable/Hashtable.c
Normal file
@@ -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;i<HT_HEIGHTS[HT_HEIN_MIN];i++)
|
||||
ht->rows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
|
||||
return ht;
|
||||
}
|
||||
|
||||
void __Hashtable_free(void* _ht){
|
||||
Hashtable* ht=_ht;
|
||||
for(u16 i=0;i<HT_HEIGHTS[ht->hein];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;i<HT_HEIGHTS[ht->hein];i++)
|
||||
newrows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
|
||||
|
||||
for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
|
||||
Autoarr(KVPair)* ar=ht->rows[i];
|
||||
u32 arlen=Autoarr_length(ar);
|
||||
for(u32 k=0;k<arlen;k++){
|
||||
KVPair p=Autoarr_get(ar,k);
|
||||
u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein];
|
||||
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; i<count; i++){
|
||||
Hashtable_add(ht, pair_array[i].key, pair_array[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
// returns null or pointer to value in hashtable
|
||||
Unitype* Hashtable_getPtr(Hashtable* ht, char* key){
|
||||
Autoarr(KVPair)* ar=getrow(ht,key,false);
|
||||
u32 arlen=Autoarr_length(ar);
|
||||
for(u32 i=0;i<arlen;i++){
|
||||
KVPair* p=Autoarr_getPtr(ar,i);
|
||||
if(cptr_equals(key,p->key)) 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;i<arlen;i++){
|
||||
KVPair p=Autoarr_get(ar,i);
|
||||
if(cptr_equals(key,p.key)) return p.value;
|
||||
}
|
||||
return UniNull;
|
||||
}
|
||||
|
||||
bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output){
|
||||
Unitype u=Hashtable_get(ht,key);
|
||||
*output=u;
|
||||
return !Unitype_isUniNull(u);
|
||||
}
|
||||
|
||||
|
||||
bool Hashtable_trySet(Hashtable* ht, char* key, Unitype u){
|
||||
Unitype* val=Hashtable_getPtr(ht,key);
|
||||
if(val==NULL)
|
||||
return false;
|
||||
*val=u;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Hashtable_tryAdd(Hashtable* ht, char* key, Unitype u){
|
||||
Unitype* val=Hashtable_getPtr(ht,key);
|
||||
if(val==NULL){
|
||||
Hashtable_add(ht, key, u);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Hashtable_addOrSet(Hashtable* ht, char* key, Unitype u){
|
||||
Unitype* val=Hashtable_getPtr(ht, key);
|
||||
if(val==NULL)
|
||||
Hashtable_add(ht, key, u); // add
|
||||
else *val=u; // set
|
||||
}
|
||||
18
kerep/src/Hashtable/KeyValuePair.c
Normal file
18
kerep/src/Hashtable/KeyValuePair.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "KeyValuePair.h"
|
||||
|
||||
kt_define(KVPair, __KVPair_free, NULL);
|
||||
|
||||
Autoarr_define(KVPair, false)
|
||||
|
||||
// proper way to clean a KVP
|
||||
void KVPair_free(KVPair p){
|
||||
free(p.key);
|
||||
Unitype_free(p.value);
|
||||
}
|
||||
void __KVPair_free(void* p){ KVPair_free(*(KVPair*)p); }
|
||||
|
||||
void printkvp(KVPair p){
|
||||
kprintf("{\"%s\", ",p.key);
|
||||
printuni(p.value);
|
||||
kprintf("}");
|
||||
}
|
||||
147
kerep/src/String/StringBuilder.c
Normal file
147
kerep/src/String/StringBuilder.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "StringBuilder.h"
|
||||
|
||||
kt_define(StringBuilder, __StringBuilder_free, NULL);
|
||||
|
||||
#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);
|
||||
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;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(u32 i=0; i<s.length; i++)
|
||||
Autoarr_add(b->curr_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)});
|
||||
}
|
||||
47
kerep/src/String/string.c
Normal file
47
kerep/src/String/string.c
Normal file
@@ -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;i<nstr.length;i++)
|
||||
nstr.ptr[i]=src.ptr[i];
|
||||
nstr.ptr[nstr.length]='\0';
|
||||
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(u32 i=0; i<s.length; i++)
|
||||
r.ptr[i]=s.ptr[s.length-i-1];
|
||||
return r;
|
||||
}
|
||||
217
kerep/src/base/cptr.c
Normal file
217
kerep/src/base/cptr.c
Normal file
@@ -0,0 +1,217 @@
|
||||
#include "base.h"
|
||||
#include "../String/StringBuilder.h"
|
||||
#include <ctype.h>
|
||||
|
||||
// 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_len<fr_len || src_len==0 || fr_len==0)
|
||||
return false;
|
||||
src+=src_len-fr_len;
|
||||
return cptr_equals(src, fragment);
|
||||
}
|
||||
|
||||
|
||||
i32 cptr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src, fc=*fragment;
|
||||
if(sc==0 || fc==0)
|
||||
return -1;
|
||||
u32 fr_start=startIndex;
|
||||
for(u32 si=startIndex; si-startIndex<seekLength && sc!=0; si++){
|
||||
sc=src[si];
|
||||
fc=fragment[si-fr_start];
|
||||
if(fc==0)
|
||||
return fr_start;
|
||||
if(sc!=fc)
|
||||
fr_start++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 cptr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src, fc=*fragment;
|
||||
if(sc==0 || fc==0)
|
||||
return -1;
|
||||
i32 len=cptr_length(src);
|
||||
if(startIndex==(u32)-1)
|
||||
startIndex=len-1;
|
||||
u32 fr_len=cptr_length(fragment);
|
||||
for(u32 si=startIndex; si<(u32)-1 && si!=len-1-seekLength; si--){
|
||||
if(si+1<fr_len)
|
||||
return -1;
|
||||
sc=src[si];
|
||||
fc=fragment[0];
|
||||
u32 fr_start=si;
|
||||
for(u32 fi=0; fc==sc ; fi++){
|
||||
if(fi==fr_len)
|
||||
return fr_start;
|
||||
fc=fragment[fi];
|
||||
sc=src[si--];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 cptr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src;
|
||||
if(sc==0 || fragment==0)
|
||||
return -1;
|
||||
for(u32 si=startIndex; si-startIndex<seekLength && sc!=0; si++){
|
||||
sc=src[si];
|
||||
if(sc==fragment)
|
||||
return si;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src;
|
||||
if(sc==0 || fragment==0)
|
||||
return -1;
|
||||
i32 len=cptr_length(src);
|
||||
if(startIndex==(u32)-1)
|
||||
startIndex=len-1;
|
||||
for(u32 si=startIndex; si<(u32)-1 && si!=len-1-seekLength; si--){
|
||||
sc=src[si];
|
||||
if(sc==fragment)
|
||||
return si;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void memcopy(void* from, void* to, u32 size){
|
||||
if(from==NULL || to==NULL)
|
||||
throw(ERR_NULLPTR);
|
||||
for(u32 i=0; i<size; i++)
|
||||
((char*)to)[i]=((char*)from)[i];
|
||||
}
|
||||
|
||||
char* __cptr_concat(u32 n, ...){
|
||||
char** strs=(char**)malloc(n*sizeof(char*));
|
||||
u32* lengths=malloc(n*sizeof(u32));
|
||||
u32 totalLength=0;
|
||||
|
||||
// reading args from va_list
|
||||
va_list vl;
|
||||
va_start(vl, n);
|
||||
for(u16 i=0; i<n; i++){
|
||||
char* str=va_arg(vl,char*);
|
||||
i16 length=cptr_length(str);
|
||||
strs[i]=str;
|
||||
lengths[i]=length;
|
||||
totalLength+=length;
|
||||
}
|
||||
va_end(vl);
|
||||
|
||||
// allocating memory for output value
|
||||
char* totality=malloc(totalLength+1);
|
||||
char* output=totality;
|
||||
totality[totalLength]=0;
|
||||
|
||||
// copying content of all strings to rezult
|
||||
for(u16 k=0; k<n; k++){
|
||||
memcopy(strs[k], totality, lengths[k]);
|
||||
totality+=lengths[k];
|
||||
}
|
||||
|
||||
free(strs);
|
||||
free(lengths);
|
||||
return output;
|
||||
}
|
||||
|
||||
char* cptr_toLower(const char* src) {
|
||||
u32 length=cptr_length(src);
|
||||
char *p=malloc(length+1);
|
||||
p[length]=0;
|
||||
for(u32 i=0; i<length; i++)
|
||||
p[i]=tolower(src[i]);
|
||||
return p;
|
||||
}
|
||||
|
||||
char* cptr_toUpper(const char* src) {
|
||||
u32 length=cptr_length(src);
|
||||
char *p=malloc(length+1);
|
||||
p[length]=0;
|
||||
for(u32 i=0; i<length; i++)
|
||||
p[i]=toupper(src[i]);
|
||||
return p;
|
||||
}
|
||||
|
||||
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){
|
||||
char* rzlt=cptr_copy(src);
|
||||
for(u32 i=startIndex; i!=seekLength && src[i]!=0; i++){
|
||||
if(src[i]==c_old)
|
||||
rzlt[i]=c_new;
|
||||
}
|
||||
return rzlt;
|
||||
}
|
||||
|
||||
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength){
|
||||
StringBuilder* sb=StringBuilder_create();
|
||||
const u32 str_old_len=cptr_length(str_old);
|
||||
const u32 str_new_len=cptr_length(str_new);
|
||||
i32 i=startIndex;
|
||||
while( (i=cptr_seek(src, str_old, startIndex, seekLength)) !=-1 ){
|
||||
if(i!=0)
|
||||
StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=i});
|
||||
StringBuilder_append_string(sb, (string){.ptr=str_new, .length=str_new_len});
|
||||
src+=i+str_old_len;
|
||||
}
|
||||
u32 src_remains_len=cptr_length(src);
|
||||
if(src_remains_len>0)
|
||||
StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=src_remains_len});
|
||||
string rezult=StringBuilder_build(sb);
|
||||
return rezult.ptr;
|
||||
}
|
||||
13
kerep/src/base/endian.c
Normal file
13
kerep/src/base/endian.c
Normal file
@@ -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];
|
||||
}
|
||||
59
kerep/src/base/errors.c
Normal file
59
kerep/src/base/errors.c
Normal file
@@ -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";}
|
||||
@@ -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
|
||||
238
kerep/src/base/type_system/base_toString.c
Normal file
238
kerep/src/base/type_system/base_toString.c
Normal file
@@ -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 <c> 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<size; bn++)
|
||||
byte_to_bits(bytes[bn])
|
||||
}
|
||||
str[cn]=0;
|
||||
return str;
|
||||
}
|
||||
|
||||
// converts number from 0 to F to char
|
||||
char _4bitsHex(u8 u, bool uppercase){
|
||||
switch(u){
|
||||
case 0: case 1: case 2: case 3: case 4:
|
||||
case 5: case 6: case 7: case 8: case 9:
|
||||
return '0'+u;
|
||||
case 0xA: case 0xB: case 0xC:
|
||||
case 0xD: case 0xE: case 0xF:
|
||||
return (uppercase ? 'A' : 'a') + u -10;
|
||||
default:
|
||||
dbg(u);
|
||||
throw("incorrect number");
|
||||
return 219;
|
||||
}
|
||||
}
|
||||
|
||||
char* toString_hex(void* _bytes, u32 size, bool inverse, bool withPrefix, bool uppercase){
|
||||
char* bytes=_bytes;
|
||||
char* str=malloc(size*2 + (withPrefix?2:0) + 1);
|
||||
u32 cn=0; // char number
|
||||
if(withPrefix){
|
||||
str[cn++]='0';
|
||||
str[cn++]='x';
|
||||
}
|
||||
// left to right
|
||||
if(inverse){
|
||||
// byte number
|
||||
for(i32 bn=size-1; 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; bn<size; bn++){ // byte number
|
||||
unsigned char byte=bytes[bn];
|
||||
str[cn++]=_4bitsHex(byte/16, uppercase);
|
||||
str[cn++]=_4bitsHex(byte%16, uppercase);
|
||||
}
|
||||
}
|
||||
str[cn]=0;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
#define __toString_i32_def(BITS) char* __toString_i##BITS(void* _n, u32 f){ \
|
||||
switch(kp_fmt_dataFormat(f)){ \
|
||||
case kp_i: ; \
|
||||
i##BITS n=*(i##BITS*)_n; \
|
||||
return toString_i64(n); \
|
||||
case kp_b: \
|
||||
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||
case kp_h: \
|
||||
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||
default: \
|
||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||
throw(ERR_FORMAT); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
__toString_i32_def(8)
|
||||
__toString_i32_def(16)
|
||||
__toString_i32_def(32)
|
||||
__toString_i32_def(64)
|
||||
|
||||
#define __toString_u_def(BITS) char* __toString_u##BITS(void* _n, u32 f){ \
|
||||
switch(kp_fmt_dataFormat(f)){ \
|
||||
case kp_u: ; \
|
||||
u##BITS n=*(u##BITS*)_n; \
|
||||
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
||||
case kp_b: \
|
||||
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||
case kp_h: \
|
||||
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||
default: \
|
||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||
throw(ERR_FORMAT); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
__toString_u_def(8)
|
||||
__toString_u_def(16)
|
||||
__toString_u_def(32)
|
||||
// __toString_u_def(64)
|
||||
char* __toString_u64(void* _n, u32 f){
|
||||
switch(kp_fmt_dataFormat(f)){
|
||||
case kp_u: ;
|
||||
u64 n=*(u64*)_n;
|
||||
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f));
|
||||
case kp_b:
|
||||
return toString_bin(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f));
|
||||
case kp_h:
|
||||
return toString_hex(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f));
|
||||
default:
|
||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); throw(ERR_FORMAT); return NULL; }
|
||||
}
|
||||
|
||||
#define __toString_float_def(BITS) char* __toString_f##BITS(void* _n, u32 f){ \
|
||||
switch(kp_fmt_dataFormat(f)){ \
|
||||
case kp_f: ; \
|
||||
f##BITS n=*(f##BITS*)_n; \
|
||||
return toString_f64(n, toString_float_default_precision, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
||||
case kp_b: \
|
||||
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||
case kp_h: \
|
||||
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||
default: \
|
||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||
throw(ERR_FORMAT); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
__toString_float_def(32)
|
||||
__toString_float_def(64)
|
||||
65
kerep/src/base/type_system/init.c
Normal file
65
kerep/src/base/type_system/init.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "../base.h"
|
||||
#include "../../Autoarr/Autoarr.h"
|
||||
#include "../../Hashtable/Hashtable.h"
|
||||
#include "../../String/StringBuilder.h"
|
||||
#include "../../Filesystem/filesystem.h"
|
||||
#include "base_toString.h"
|
||||
|
||||
void kt_initKerepTypes(){
|
||||
// base types
|
||||
kt_register(Pointer);
|
||||
if(ktid_Pointer!=0) // this can break UnitypeNull
|
||||
throw("ktid_Pointer!=0, you must init kerep types before any other types");
|
||||
|
||||
kt_register(char);
|
||||
kt_register(bool);
|
||||
kt_register(f32);
|
||||
kt_register(f64);
|
||||
kt_register(i8);
|
||||
kt_register(u8);
|
||||
kt_register(i16);
|
||||
kt_register(u16);
|
||||
kt_register(i32);
|
||||
kt_register(u32);
|
||||
kt_register(i64);
|
||||
kt_register(u64);
|
||||
|
||||
// ktDescriptor
|
||||
kt_register(ktDescriptor);
|
||||
|
||||
// base type autoarrs
|
||||
kt_register(Autoarr_Pointer);
|
||||
kt_register(Autoarr_char);
|
||||
kt_register(Autoarr_bool);
|
||||
kt_register(Autoarr_f32);
|
||||
kt_register(Autoarr_f64);
|
||||
kt_register(Autoarr_i8);
|
||||
kt_register(Autoarr_u8);
|
||||
kt_register(Autoarr_i16);
|
||||
kt_register(Autoarr_u16);
|
||||
kt_register(Autoarr_i32);
|
||||
kt_register(Autoarr_u32);
|
||||
kt_register(Autoarr_i64);
|
||||
kt_register(Autoarr_u64);
|
||||
|
||||
// Unitype
|
||||
kt_register(Unitype);
|
||||
kt_register(Autoarr_Unitype);
|
||||
|
||||
// KeyValuePair
|
||||
kt_register(KVPair);
|
||||
kt_register(Autoarr_KVPair);
|
||||
|
||||
// Hashtable
|
||||
kt_register(Hashtable);
|
||||
|
||||
// string
|
||||
kt_register(string);
|
||||
kt_register(Autoarr_string);
|
||||
|
||||
// StringBuilder
|
||||
kt_register(StringBuilder);
|
||||
|
||||
//File
|
||||
kt_register(FileHandle);
|
||||
}
|
||||
90
kerep/src/base/type_system/kt_functions.c
Normal file
90
kerep/src/base/type_system/kt_functions.c
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "../../Autoarr/Autoarr.h"
|
||||
#include "type_system.h"
|
||||
#include "base_toString.h"
|
||||
|
||||
kt_define(Pointer, NULL, __toString_u64);
|
||||
kt_define(char,NULL, __toString_char);
|
||||
kt_define(bool,NULL, __toString_bool);
|
||||
kt_define(f32, NULL, __toString_f32);
|
||||
kt_define(f64, NULL, __toString_f64);
|
||||
kt_define(i8, NULL, __toString_i8);
|
||||
kt_define(u8, NULL, __toString_u8);
|
||||
kt_define(i16, NULL, __toString_i16);
|
||||
kt_define(u16, NULL, __toString_u16);
|
||||
kt_define(i32, NULL, __toString_i32);
|
||||
kt_define(u32, NULL, __toString_u32);
|
||||
kt_define(i64, NULL, __toString_i64);
|
||||
kt_define(u64, NULL, __toString_u64);
|
||||
|
||||
|
||||
char* ktDescriptor_toString(ktDescriptor* d){
|
||||
const char* n="null";
|
||||
char *s0 = toString_u64(d->id, 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);
|
||||
}
|
||||
100
kerep/src/base/type_system/unitype.c
Normal file
100
kerep/src/base/type_system/unitype.c
Normal file
@@ -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);
|
||||
}
|
||||
211
kerep/src/kprint/kprint.c
Normal file
211
kerep/src/kprint/kprint.c
Normal file
@@ -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<n; i++){
|
||||
try(__next_toString(formats[i], &objects[i]),mStr,;);
|
||||
StringBuilder_append_cptr(strb, mStr.value.VoidPtr);
|
||||
Unitype_free(mStr.value);
|
||||
}
|
||||
char* rezult=StringBuilder_build(strb).ptr;
|
||||
return SUCCESS(UniHeapPtr(char, rezult));
|
||||
}
|
||||
|
||||
Maybe __kfprint(FILE* file, u8 n, kp_fmt* formats, __kp_value_union* objects){
|
||||
try(check_argsN(n), _,;);
|
||||
n/=2;
|
||||
for(u8 i=0; i<n; i++){
|
||||
try(__next_toString(formats[i], &objects[i]),maybeStr,;);
|
||||
if(fputs(maybeStr.value.VoidPtr, file)==EOF)
|
||||
safethrow("can't write string to file", Unitype_free(maybeStr.value));
|
||||
Unitype_free(maybeStr.value);
|
||||
}
|
||||
fflush(file);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
|
||||
tryLast(check_argsN(n), _,;);
|
||||
n/=2;
|
||||
for(u8 i=0; i<n; i++){
|
||||
kp_fmt fmt=formats[i];
|
||||
kprint_setColor(fmt);
|
||||
tryLast(__next_toString(fmt, &objects[i]),maybeStr, kprint_setColor(kp_bgBlack|kp_fgGray));
|
||||
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF) \
|
||||
throw("can't write string to stdout");
|
||||
//, Unitype_free(maybeStr.value)
|
||||
Unitype_free(maybeStr.value);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)|| defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#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; e<count; e++){
|
||||
StringBuilder_append_char(strb, ' ');
|
||||
char* elStr=type->toString(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];
|
||||
}
|
||||
155
kerep/src/kprint/kprintf.c
Normal file
155
kerep/src/kprint/kprintf.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include "kprintf.h"
|
||||
#include "../base/base.h"
|
||||
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
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="<nullstr>";
|
||||
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);
|
||||
}
|
||||
34
kerep/src/random/splitmix64/splitmix64.c
Normal file
34
kerep/src/random/splitmix64/splitmix64.c
Normal file
@@ -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);
|
||||
}
|
||||
49
kerep/src/random/xoroshiro/32bitValue/xoroshiro64star.c
Normal file
49
kerep/src/random/xoroshiro/32bitValue/xoroshiro64star.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
37
kerep/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c
Normal file
37
kerep/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
59
kerep/src/random/xoroshiro/64bitValue/xoroshiro128plus.c
Normal file
59
kerep/src/random/xoroshiro/64bitValue/xoroshiro128plus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
39
kerep/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c
Normal file
39
kerep/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
39
kerep/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c
Normal file
39
kerep/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
54
kerep/src/random/xoshiro/32bitValue/xoshiro128plus.c
Normal file
54
kerep/src/random/xoshiro/32bitValue/xoshiro128plus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
42
kerep/src/random/xoshiro/32bitValue/xoshiro128plusplus.c
Normal file
42
kerep/src/random/xoshiro/32bitValue/xoshiro128plusplus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
45
kerep/src/random/xoshiro/32bitValue/xoshiro128starstar.c
Normal file
45
kerep/src/random/xoshiro/32bitValue/xoshiro128starstar.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
58
kerep/src/random/xoshiro/64bitValue/xoshiro256plus.c
Normal file
58
kerep/src/random/xoshiro/64bitValue/xoshiro256plus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
37
kerep/src/random/xoshiro/64bitValue/xoshiro256plusplus.c
Normal file
37
kerep/src/random/xoshiro/64bitValue/xoshiro256plusplus.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
42
kerep/src/random/xoshiro/64bitValue/xoshiro256starstar.c
Normal file
42
kerep/src/random/xoshiro/64bitValue/xoshiro256starstar.c
Normal file
@@ -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 <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
#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;
|
||||
}
|
||||
Binary file not shown.
@@ -1,47 +1,108 @@
|
||||
#include <unistd.h>
|
||||
#include "CompilationScenario.h"
|
||||
#include "unistd.h"
|
||||
#include "../kerep/src/Filesystem/filesystem.h"
|
||||
#include "process/Process.h"
|
||||
|
||||
kt_define(Language, NULL, NULL);
|
||||
kt_define(Tool, NULL, NULL);
|
||||
kt_define(CompilationScenario, (freeMembers_t)CompilationScenario_destruct, NULL);
|
||||
|
||||
void CompilationScenario_construct(CompilationScenario* ptr){
|
||||
ptr->compiler = "UNDEFINED_COMPILER";
|
||||
ptr->obj_dir = "obj";
|
||||
ptr->out_file = "bin/out";
|
||||
ptr->args = Autoarr_create(Pointer, 32, 32);
|
||||
ptr->sources = Autoarr_create(Pointer, 32, 32);
|
||||
ptr->languages = Hashtable_create();
|
||||
ptr->tools = Hashtable_create();
|
||||
ptr->tool_order = Autoarr_create(Pointer, 32, 32);
|
||||
}
|
||||
|
||||
void CompilationScenario_destruct(CompilationScenario* ptr){
|
||||
Autoarr_freeWithoutMembers(ptr->args, true);
|
||||
Autoarr_freeWithoutMembers(ptr->sources, true);
|
||||
// TODO
|
||||
}
|
||||
|
||||
#define Dtsod_setStrField(FIELD) \
|
||||
void Tool_construct(Tool* ptr, Autoarr(Pointer)* aliases, const char* exe_file, bool parallel, Autoarr(Pointer)* supported_languages){
|
||||
ptr->aliases = aliases;
|
||||
ptr->exe_file = exe_file;
|
||||
ptr->parallel = parallel;
|
||||
ptr->supported_languages = Hashtable_create();
|
||||
Autoarr_foreach(supported_languages, _l,
|
||||
Language* l = _l;
|
||||
Autoarr_foreach(l->aliases, l_name,
|
||||
Hashtable_add(ptr->supported_languages, l_name, UniHeapPtr(Language, l)));
|
||||
)
|
||||
ptr->src_languages = Hashtable_create();
|
||||
ptr->src_dirs = Autoarr_create(Pointer, 32, 32);
|
||||
ptr->pre_args = Autoarr_create(Pointer, 32, 32);
|
||||
ptr->post_args = Autoarr_create(Pointer, 32, 32);
|
||||
}
|
||||
|
||||
void Tool_destruct(Tool* ptr){
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Language_construct(Language* ptr, Autoarr(Pointer)* aliases, Autoarr(Pointer)* file_extensions){
|
||||
ptr->aliases = aliases;
|
||||
ptr->file_extensions = file_extensions;
|
||||
}
|
||||
|
||||
void Language_destruct(Language* ptr){
|
||||
// TODO
|
||||
}
|
||||
|
||||
#define Dtsod_getStrField(FIELD, OBJ) \
|
||||
if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \
|
||||
if(val.typeId != ktid_char_Ptr) \
|
||||
if(!UniCheckTypePtr(val, char)) \
|
||||
safethrow(#FIELD " value expected to be string",;);\
|
||||
sc->FIELD = val.VoidPtr; \
|
||||
OBJ->FIELD = val.VoidPtr; \
|
||||
}
|
||||
|
||||
#define Dtsod_addArrField(FIELD, ELEM_TYPE) \
|
||||
|
||||
#define Dtsod_addToStrAr(FIELD, OBJ) \
|
||||
if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \
|
||||
if(val.typeId != ktid_Autoarr_Unitype_Ptr) \
|
||||
safethrow(#FIELD " value expected to be array", ;); \
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype))) \
|
||||
safethrow(#FIELD " value expected to be a string array", ;); \
|
||||
Autoarr(Unitype)* ar = val.VoidPtr; \
|
||||
Autoarr_foreach(ar, el, \
|
||||
if(el.typeId != ktid_ptrName(ELEM_TYPE)) \
|
||||
safethrow(#FIELD " array values expected to be " #ELEM_TYPE, ;); \
|
||||
Autoarr_add(sc->FIELD, el.VoidPtr); \
|
||||
if(!UniCheckTypePtr(el, char)) \
|
||||
safethrow(#FIELD " array values expected to be string", ;); \
|
||||
Autoarr_add(OBJ->FIELD, el.VoidPtr); \
|
||||
) \
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod){
|
||||
Maybe Tool_tryApplyOptions(Tool* t, Hashtable* dtsod){
|
||||
Unitype val = UniNull;
|
||||
Dtsod_setStrField(compiler);
|
||||
Dtsod_setStrField(obj_dir);
|
||||
Dtsod_setStrField(out_file);
|
||||
Dtsod_addArrField(args, char);
|
||||
Dtsod_addArrField(sources, char);
|
||||
Dtsod_addToStrAr(src_dirs, t);
|
||||
Dtsod_addToStrAr(pre_args, t);
|
||||
Dtsod_addToStrAr(post_args, t);
|
||||
if(Hashtable_tryGet(dtsod, "src_languages", &val)){
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow("src_languages value expected to be a string array", ;);
|
||||
Autoarr(Unitype)* ar = val.VoidPtr;
|
||||
Autoarr_foreach(ar, el,
|
||||
if(!UniCheckTypePtr(el, char))
|
||||
safethrow("src_languages array values expected to be string", ;);
|
||||
const char* l_name = el.VoidPtr;
|
||||
if(!Hashtable_tryGet(t->supported_languages, l_name, &val))
|
||||
safethrow(cptr_concat("language '", l_name, "' isn't supported by tool '", Autoarr_get(t->aliases, 0), "'"), ;);
|
||||
Hashtable_add(t->src_languages, l_name, val);
|
||||
)
|
||||
}
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_tryApplyToolsOptions(CompilationScenario* sc, Hashtable* dtsod){
|
||||
Unitype val = UniNull;
|
||||
|
||||
// adds tools to tool_order
|
||||
Dtsod_addToStrAr(tool_order, sc);
|
||||
|
||||
// sets options for each tool
|
||||
try(CompilationScenario_tryApplyPlatformSpecificOptions(sc, dtsod), _m0, ;);
|
||||
Hashtable_foreach(sc->tools, _tool,
|
||||
Tool* tool = _tool.value.VoidPtr;
|
||||
if(Hashtable_tryGet(dtsod, _tool.key, &val)){
|
||||
if(!UniCheckTypePtr(val, Hashtable))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Hashtable* tool_dtsod = val.VoidPtr;
|
||||
try(Tool_tryApplyOptions(tool, tool_dtsod), _m1, ;);
|
||||
}
|
||||
)
|
||||
|
||||
return SUCCESS(UniBool(Unitype_isUniNull(val) || _m0.value.Bool));
|
||||
}
|
||||
@@ -49,10 +110,10 @@ Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dt
|
||||
Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Hashtable* dtsod, const char* condition_name){
|
||||
Unitype val = UniNull;
|
||||
if(Hashtable_tryGet(dtsod, condition_name, &val)){
|
||||
if(val.typeId != ktid_Hashtable_Ptr)
|
||||
if(!UniCheckTypePtr(val, Hashtable))
|
||||
safethrow(cptr_concat(condition_name, " expected to be key-value map"), ;);
|
||||
Hashtable* conditional_options = val.VoidPtr;
|
||||
try(CompilationScenario_tryApplyOptions(sc, conditional_options), _m0, ;);
|
||||
try(CompilationScenario_tryApplyToolsOptions(sc, conditional_options), _m0, ;);
|
||||
return SUCCESS(UniTrue);
|
||||
}
|
||||
else return SUCCESS(UniFalse);
|
||||
@@ -87,9 +148,136 @@ Maybe CompilationScenario_applyTaskOptions(CompilationScenario* sc, Hashtable* d
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_tryRegisterLanguages(CompilationScenario* sc, Hashtable* dtsod){
|
||||
Unitype val = UniNull;
|
||||
if(!Hashtable_tryGet(dtsod, "languages", &val))
|
||||
return SUCCESS(UniFalse);
|
||||
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* languages_serializad = val.VoidPtr;
|
||||
|
||||
Autoarr_foreach(languages_serializad, ldtsod,
|
||||
if(!UniCheckTypePtr(ldtsod, Hashtable))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
|
||||
// reads aliases: string[] from dtsod
|
||||
if(!Hashtable_tryGet(ldtsod.VoidPtr, "aliases", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* aliases_uni = val.VoidPtr;
|
||||
Autoarr(Pointer)* aliases = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(aliases_uni, au,
|
||||
if(!UniCheckTypePtr(au, char))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr_add(aliases, au.VoidPtr);
|
||||
)
|
||||
|
||||
// reads file_extensions: string[] from dtsod
|
||||
if(!Hashtable_tryGet(ldtsod.VoidPtr, "file_extensions", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* file_extensions_uni = val.VoidPtr;
|
||||
Autoarr(Pointer)* file_extensions = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(file_extensions_uni, feu,
|
||||
if(!UniCheckTypePtr(feu, char))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr_add(file_extensions, feu.VoidPtr);
|
||||
)
|
||||
|
||||
Language* lang = malloc(sizeof(Language));
|
||||
Language_construct(lang, aliases, file_extensions);
|
||||
// registers each alias of the language
|
||||
Autoarr_foreach(aliases, l_name,
|
||||
if(!Hashtable_tryAdd(sc->languages, l_name, UniHeapPtr(Language, lang)))
|
||||
safethrow(cptr_concat("language '", l_name, "has been already registered"), ;);
|
||||
)
|
||||
)
|
||||
|
||||
return SUCCESS(UniTrue);
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_tryRegisterTools(CompilationScenario* sc, Hashtable* dtsod){
|
||||
Unitype val = UniNull;
|
||||
if(!Hashtable_tryGet(dtsod, "tools", &val))
|
||||
return SUCCESS(UniFalse);
|
||||
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* tools_serializad = val.VoidPtr;
|
||||
|
||||
Autoarr_foreach(tools_serializad, tdtsod,
|
||||
if(!UniCheckTypePtr(tdtsod, Hashtable))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
|
||||
// reads exe_file: string from dtsod
|
||||
if(!Hashtable_tryGet(tdtsod.VoidPtr, "exe_file", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckTypePtr(val, char))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
char* exe_file = val.VoidPtr;
|
||||
|
||||
// reads parallel: bool from dtsod
|
||||
if(!Hashtable_tryGet(tdtsod.VoidPtr, "parallel", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckType(val, bool))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
bool parallel = val.Bool;
|
||||
|
||||
// reads aliases: string[] from dtsod
|
||||
if(!Hashtable_tryGet(tdtsod.VoidPtr, "aliases", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* aliases_uni = val.VoidPtr;
|
||||
Autoarr(Pointer)* aliases = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(aliases_uni, au,
|
||||
if(!UniCheckTypePtr(au, char))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr_add(aliases, au.VoidPtr);
|
||||
)
|
||||
|
||||
// reads supported_languages: string[] dtsod
|
||||
if(!Hashtable_tryGet(tdtsod.VoidPtr, "supported_languages", &val))
|
||||
safethrow(ERR_FORMAT, ;);
|
||||
if(!UniCheckTypePtr(val, Autoarr(Unitype)))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Autoarr(Unitype)* supported_languages_uni = val.VoidPtr;
|
||||
Autoarr(Pointer)* supported_languages = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(supported_languages_uni, lu,
|
||||
if(!UniCheckTypePtr(lu, char))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
char* l_name = lu.VoidPtr;
|
||||
// gets language pointer from CompilationScenario regisgered languages
|
||||
if(!Hashtable_tryGet(sc->languages, l_name, &val))
|
||||
safethrow(ERR_KEYNOTFOUND, ;);
|
||||
if(!UniCheckTypePtr(val, Language))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Language* lang = val.VoidPtr;
|
||||
Autoarr_add(supported_languages, lang);
|
||||
)
|
||||
|
||||
Tool* tool = malloc(sizeof(Tool));
|
||||
Tool_construct(tool, aliases, exe_file, parallel, supported_languages);
|
||||
// registers each alias of the tool
|
||||
Autoarr_foreach(aliases, t_name,
|
||||
if(!Hashtable_tryAdd(sc->tools, t_name, UniHeapPtr(Tool, tool)))
|
||||
safethrow(cptr_concat("tool '", t_name, "has been already registered"), ;);
|
||||
)
|
||||
)
|
||||
|
||||
return SUCCESS(UniTrue);
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration, const char* task){
|
||||
// general options
|
||||
try(CompilationScenario_tryApplyOptions(sc, dtsod), _m0, ;);
|
||||
// TODO version check
|
||||
// TODO import
|
||||
try(CompilationScenario_tryRegisterLanguages(sc, dtsod), _m05, ;);
|
||||
try(CompilationScenario_tryRegisterTools(sc, dtsod), _m06, ;);
|
||||
// project-wide options
|
||||
try(CompilationScenario_tryApplyToolsOptions(sc, dtsod), _m0, ;);
|
||||
// configuration options
|
||||
try(CompilationScenario_applyConfigurationOptions(sc, dtsod, configuration), _m1, ;);
|
||||
// task options
|
||||
@@ -97,33 +285,56 @@ Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Tool_exec(Tool* tool){
|
||||
Autoarr(Pointer)* args_ar = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(tool->pre_args, arg,
|
||||
Autoarr_add(args_ar, arg));
|
||||
|
||||
/*
|
||||
universal compilation:
|
||||
pre-compilation tools
|
||||
parallel foreach src
|
||||
apply proj settings
|
||||
apply lang settings
|
||||
apply dir settings
|
||||
if platform, settings or src were changed
|
||||
compile object to onj/lang
|
||||
concurrent add obj to obj_ar
|
||||
post-compilation tools
|
||||
example: if linkage enabled
|
||||
apply proj linker settings
|
||||
link
|
||||
post-link tools
|
||||
move files to general_out_dir
|
||||
*/
|
||||
Autoarr(Pointer)* sources = Autoarr_create(Pointer, 32, 32);
|
||||
Autoarr_foreach(tool->src_dirs, dir,
|
||||
try(dir_getFiles(dir, true), _m2, ;);
|
||||
char** files = _m2.value.VoidPtr;
|
||||
while(*files){
|
||||
Autoarr_add(sources, *files);
|
||||
files++;
|
||||
}
|
||||
);
|
||||
|
||||
if(tool->parallel){
|
||||
safethrow(ERR_NOTIMPLEMENTED, ;);
|
||||
}
|
||||
else {
|
||||
Autoarr_foreach(sources, file,
|
||||
Autoarr_add(args_ar, file));
|
||||
}
|
||||
|
||||
Autoarr_foreach(tool->post_args, arg,
|
||||
Autoarr_add(args_ar, arg));
|
||||
|
||||
const char** args = (const char**)Autoarr_toArray(args_ar);
|
||||
i32 argc = Autoarr_length(args_ar);
|
||||
Autoarr_freeWithoutMembers(args_ar, true);
|
||||
|
||||
Process tool_proc;
|
||||
try(Process_start(&tool_proc, tool->exe_file, args, argc, true), _m5512, Autoarr_freeWithoutMembers(sources, true))
|
||||
|
||||
// TODO wrap tool_proc->io
|
||||
Process_waitForExit(&tool_proc);
|
||||
|
||||
Autoarr_freeWithoutMembers(sources, true);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe CompilationScenario_exec(CompilationScenario* sc){
|
||||
/*const char ** compiler_args;
|
||||
Autoarr_foreach(sc->sources, arg,
|
||||
int rzlt = -1;
|
||||
if(rzlt != 0){
|
||||
kprintf("\nprocess exited with code %i\n", rzlt);
|
||||
return false;
|
||||
}
|
||||
);*/
|
||||
return true;
|
||||
Autoarr_foreach(sc->tool_order, tool_name,
|
||||
kprintf("tool: '%s'\n", tool_name);
|
||||
Unitype uni;
|
||||
if(!Hashtable_tryGet(sc->tools, tool_name, &uni))
|
||||
safethrow(ERR_KEYNOTFOUND, ;);
|
||||
if(!UniCheckTypePtr(uni, Tool))
|
||||
safethrow(ERR_WRONGTYPE, ;);
|
||||
Tool* tool = uni.VoidPtr;
|
||||
try(Tool_exec(tool), _m1, ;);
|
||||
)
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
#include "../kerep-headers/DtsodParser/DtsodV24.h"
|
||||
#include "../kerep/src/DtsodParser/DtsodV24.h"
|
||||
|
||||
extern const char* os;
|
||||
extern const char* arch;
|
||||
|
||||
typedef struct {
|
||||
const char* language;
|
||||
const char* compiler;
|
||||
const char* obj_dir;
|
||||
const char* out_file;
|
||||
Autoarr(Pointer)* args;
|
||||
Autoarr(Pointer)* sources;
|
||||
} CompilationScenario;
|
||||
STRUCT(Language,
|
||||
Autoarr(Pointer)* aliases;
|
||||
Autoarr(Pointer)* file_extensions;
|
||||
)
|
||||
|
||||
STRUCT(Tool,
|
||||
Autoarr(Pointer)* aliases;
|
||||
const char* exe_file;
|
||||
bool parallel;
|
||||
Hashtable* supported_languages;
|
||||
Hashtable* src_languages;
|
||||
Autoarr(Pointer)* src_dirs;
|
||||
Autoarr(Pointer)* pre_args;
|
||||
Autoarr(Pointer)* post_args;
|
||||
)
|
||||
|
||||
STRUCT(CompilationScenario,
|
||||
Hashtable* tools; /* Hashtable<Tool> */
|
||||
Hashtable* languages; /* Hashtable<Languages> */
|
||||
Autoarr(Pointer)* tool_order; /* Autoarr(char[]) */
|
||||
)
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
@@ -29,13 +42,23 @@ Maybe CompilationScenario_exec(CompilationScenario* sc);
|
||||
|
||||
/* Internal Functions */
|
||||
|
||||
/// tries to register proramming languages from dtsod field "languages"
|
||||
///@return Maybe<bool>
|
||||
Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod);
|
||||
Maybe CompilationScenario_tryRegisterLanguages(CompilationScenario* sc, Hashtable* dtsod);
|
||||
|
||||
/// tries to register tools from dtsod field "tools"
|
||||
///@return Maybe<bool>
|
||||
Maybe CompilationScenario_tryRegisterTools(CompilationScenario* sc, Hashtable* dtsod);
|
||||
|
||||
/// tries to set options for tools registered in the project
|
||||
///@return Maybe<bool>
|
||||
Maybe CompilationScenario_tryApplyToolsOptions(CompilationScenario* sc, Hashtable* dtsod);
|
||||
|
||||
/// tries to get any options from field <condition_name>
|
||||
///@return Maybe<bool>
|
||||
Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Hashtable* dtsod, const char* condition_name);
|
||||
|
||||
/// tries to get options from dtsod fields named "windows", "linux", "android", "x64", "android-arm32", "windows_x86", etc.
|
||||
/// tries to get options from dtsod fields named "windowss", "linux", "android", "x64", "android-arm32", "windows_x86", etc.
|
||||
///@return Maybe<bool>
|
||||
Maybe CompilationScenario_tryApplyPlatformSpecificOptions(CompilationScenario* sc, Hashtable* dtsod);
|
||||
|
||||
|
||||
109
src/cbuilld.c
109
src/cbuilld.c
@@ -1,23 +1,28 @@
|
||||
#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"
|
||||
#include "process/Process.h"
|
||||
|
||||
#ifndef OS
|
||||
#error undefined OS
|
||||
#define OS "UNDEFINED"
|
||||
#endif
|
||||
#ifndef ARCH
|
||||
#error undefined ARCH
|
||||
#define ARCH "UNDEFINED"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DIR
|
||||
#error undefined CONFIG_DIR
|
||||
#define CONFIG_DIR "UNDEFINED"
|
||||
#endif
|
||||
const char* os=OS;
|
||||
const char* arch=ARCH;
|
||||
const char* global_config_dir=CONFIG_DIR;
|
||||
|
||||
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);
|
||||
@@ -35,74 +40,74 @@ char* projectFileFromDir(const char* dir){
|
||||
int main(const int argc, const char** argv){
|
||||
kt_beginInit();
|
||||
kt_initKerepTypes();
|
||||
kt_register(CompilationScenario);
|
||||
kt_register(Language);
|
||||
kt_register(Tool);
|
||||
kt_register(Process);
|
||||
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("Undefined operation system. Recompile cbuild with flag -DOS=\\\"$(./detect_os.sh)\\\"");
|
||||
if(cptr_equals(arch, "UNDEFINED"))
|
||||
throw("Undefined CPU architecture. Recompile cbuild with flag -DARCH=\\\"$(./detect_arch.sh)\\\"");
|
||||
if(cptr_equals(global_config_dir, "UNDEFINED"))
|
||||
throw("Undefined global config directory. Recompile cbuild with flag -DCONFIG_DIR=\\\"/etc/cbuild\\\"");
|
||||
|
||||
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");
|
||||
else if(argIs("-o") || argIs("--out-dir"))
|
||||
global_out_dir = argNext();
|
||||
" -p, --project Set project directory/file (default=./).\n");
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
char* platform = cptr_concat(os, "-", arch);
|
||||
Autoarr_foreach(tasks, task,
|
||||
kprintf("executing task '%s', configuration '%s', platform '%s'\n",
|
||||
task, configuration, platform);
|
||||
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;
|
||||
}
|
||||
|
||||
33
src/process/Process.h
Normal file
33
src/process/Process.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "../../kerep/src/base/base.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_PROCESS_API
|
||||
typedef void* PipeHandle;
|
||||
#else
|
||||
typedef int PipeHandle;
|
||||
#endif
|
||||
|
||||
typedef struct Process {
|
||||
int id;
|
||||
const char* file_path;
|
||||
const char** args;
|
||||
PipeHandle input;
|
||||
PipeHandle output;
|
||||
PipeHandle error;
|
||||
#ifdef USE_WINDOWS_PROCESS_API
|
||||
void* _winProcHandle;
|
||||
#endif
|
||||
} Process;
|
||||
kt_declare(Process);
|
||||
|
||||
///@param search_in_PATH if true and file_path doesn't contain path separator characters, will search in PATH for the file_path
|
||||
///@return Maybe<void>
|
||||
Maybe Process_start(Process* ptr, const char* file_path, const char** args, int argc, bool search_in_PATH);
|
||||
|
||||
///@return Maybe<void>
|
||||
Maybe Process_waitForExit(Process* p);
|
||||
|
||||
///@return Maybe<void>
|
||||
Maybe Process_stop(Process* p);
|
||||
|
||||
i32 PipeHandle_read(PipeHandle pipe, char* buf, i32 bufsize);
|
||||
99
src/process/Process_posix.c
Normal file
99
src/process/Process_posix.c
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "process.h"
|
||||
|
||||
#ifndef USE_WINDOWS_PROCESS_API
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
extern int kill (__pid_t __pid, int __sig) __THROW;
|
||||
extern void * memset(void * __dst, int __val, size_t __n);
|
||||
|
||||
#define throw_if_negative(expr) if(expr < 0) throw(cptr_concat(#expr " exited with error ", toString_i64(errno)));
|
||||
#define safethrow_if_negative(expr) if(expr < 0) safethrow(cptr_concat(#expr " exited with error ", toString_i64(errno)), ;);
|
||||
|
||||
Maybe Process_start(Process* p, const char* file_path, const char** args, int argc, bool search_in_PATH){
|
||||
memset(p, 0, sizeof(Process));
|
||||
int input_pipe[2];
|
||||
int output_pipe[2];
|
||||
int error_pipe[2];
|
||||
safethrow_if_negative(pipe(input_pipe));
|
||||
safethrow_if_negative(pipe(output_pipe));
|
||||
safethrow_if_negative(pipe(error_pipe));
|
||||
|
||||
int pid = fork();
|
||||
if(pid == -1)
|
||||
safethrow("fork() error", ;);
|
||||
|
||||
// child process
|
||||
if(pid == 0){
|
||||
printf("child");
|
||||
throw_if_negative(close(input_pipe[1])); // close writing
|
||||
throw_if_negative(close(output_pipe[0])); // close reading
|
||||
throw_if_negative(close(error_pipe[0])); // close reading
|
||||
|
||||
// redirect io streams to pipes
|
||||
throw_if_negative(dup2(input_pipe[0], STDIN_FILENO));
|
||||
throw_if_negative(dup2(output_pipe[1], STDOUT_FILENO));
|
||||
throw_if_negative(dup2(error_pipe[1], STDERR_FILENO));
|
||||
|
||||
//
|
||||
const char** argv = malloc(sizeof(char*) * (argc+2));
|
||||
argv[0] = file_path;
|
||||
for(int i=0; i<argc; i++){
|
||||
argv[i+1] = args[i];
|
||||
}
|
||||
argv[argc+1] = NULL;
|
||||
// start new process
|
||||
int rzlt = search_in_PATH ? execvp(file_path, (char* const*)argv) : execv (file_path, (char* const*)argv);
|
||||
exit(rzlt);
|
||||
}
|
||||
|
||||
// parent process
|
||||
safethrow_if_negative(close(input_pipe[0])); // close reading
|
||||
safethrow_if_negative(close(output_pipe[1])); // close writing
|
||||
safethrow_if_negative(close(error_pipe[1])); // close writing
|
||||
|
||||
p->file_path = file_path;
|
||||
p->args = args;
|
||||
p->id=pid;
|
||||
p->input=input_pipe[1];
|
||||
p->output=output_pipe[0];
|
||||
p->error=error_pipe[0];
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_closeHandles(Process* p){
|
||||
safethrow_if_negative(close(p->input));
|
||||
safethrow_if_negative(close(p->output));
|
||||
safethrow_if_negative(close(p->error));
|
||||
p->id=0;
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_waitForExit(Process* p){
|
||||
int wstatus=0;
|
||||
if(waitpid(p->id, &wstatus, 0) == -1)
|
||||
safethrow("waitpid() error", ;);
|
||||
if(!WIFEXITED(wstatus))
|
||||
safethrow(ERR_NOTIMPLEMENTED, ;)
|
||||
int exitCode = WEXITSTATUS(wstatus);
|
||||
if(exitCode != 0)
|
||||
safethrow(cptr_concat("process ", toString_i64(p->id), " exited with code ", toString_i64(exitCode)), ;)
|
||||
Process_closeHandles(p);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_stop(Process* p){
|
||||
safethrow_if_negative(kill(p->id, SIGINT));
|
||||
try(Process_closeHandles(p), _m864, ;);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
kt_define(Process, (freeMembers_t)(void*)Process_stop, NULL)
|
||||
|
||||
i32 PipeHandle_read(PipeHandle pipe, char* buf, i32 bufsize){
|
||||
return read(pipe, buf, bufsize);
|
||||
}
|
||||
|
||||
#endif
|
||||
141
src/process/Process_windows.c
Normal file
141
src/process/Process_windows.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "process.h"
|
||||
|
||||
#ifdef USE_WINDOWS_PROCESS_API
|
||||
#include <windows.h>
|
||||
#include "../../kerep/src/String/StringBuilder.h"
|
||||
|
||||
#define safethrow_if_false(expr) if(!expr) safethrow(cptr_concat(#expr " exited with error ", toString_i64(GetLastError())), ;);
|
||||
|
||||
Maybe Process_start(Process* p, const char* file_path, const char** args, int argc, bool search_in_PATH){
|
||||
memset(p, 0, sizeof(Process));
|
||||
if(search_in_PATH && !cptr_contains(file_path, "\\")){
|
||||
LPSTR lpFilePart;
|
||||
char search_rezult[MAX_PATH];
|
||||
safethrow_if_false(SearchPath( NULL, file_path, NULL, MAX_PATH, search_rezult, &lpFilePart))
|
||||
file_path = cptr_copy(search_rezult);
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
// Set the bInheritHandle flag so pipe handles are inherited
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
HANDLE in_pipe_r = NULL;
|
||||
HANDLE in_pipe_w = NULL;
|
||||
HANDLE out_pipe_r = NULL;
|
||||
HANDLE out_pipe_w = NULL;
|
||||
HANDLE err_pipe_r = NULL;
|
||||
HANDLE err_pipe_w = NULL;
|
||||
|
||||
// Create a pipe for the child process's STDIN.
|
||||
safethrow_if_false( CreatePipe(&in_pipe_r, &in_pipe_w, &saAttr, 0));
|
||||
// Ensure the write handle to the pipe for STDIN is not inherited.
|
||||
safethrow_if_false( SetHandleInformation(in_pipe_w, HANDLE_FLAG_INHERIT, 0) );
|
||||
|
||||
// Create a pipe for the child process's STDOUT.
|
||||
safethrow_if_false( CreatePipe(&out_pipe_r, &out_pipe_w, &saAttr, 0) )
|
||||
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
||||
safethrow_if_false( SetHandleInformation(out_pipe_r, HANDLE_FLAG_INHERIT, 0) );
|
||||
|
||||
// Create a pipe for the child process's STDERR.
|
||||
safethrow_if_false( CreatePipe(&err_pipe_r, &err_pipe_w, &saAttr, 0) );
|
||||
// Ensure the read handle to the pipe for STDERR is not inherited.
|
||||
safethrow_if_false( SetHandleInformation(err_pipe_r, HANDLE_FLAG_INHERIT, 0) )
|
||||
|
||||
STARTUPINFO si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.hStdInput = in_pipe_r;
|
||||
si.hStdOutput = out_pipe_w;
|
||||
si.hStdError = err_pipe_w;
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
|
||||
StringBuilder* b = StringBuilder_create();
|
||||
|
||||
StringBuilder_append_char(b, '"');
|
||||
StringBuilder_append_cptr(b, file_path);
|
||||
StringBuilder_append_char(b, '"');
|
||||
StringBuilder_append_char(b, ' ');
|
||||
for(int i = 0; i < argc; i++) {
|
||||
StringBuilder_append_char(b, '"');
|
||||
StringBuilder_append_cptr(b, args[i]);
|
||||
StringBuilder_append_char(b, '"');
|
||||
StringBuilder_append_char(b, ' ');
|
||||
}
|
||||
string args_str = StringBuilder_build(b);
|
||||
|
||||
// Start the child process.
|
||||
if( !CreateProcess(
|
||||
file_path, // Program executable path (optional)
|
||||
args_str.ptr, // Command line args
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
TRUE, // Inherit IO handles
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&si, // Pointer to STARTUPINFO structure
|
||||
&pi) // Pointer to PROCESS_INFORMATION structure
|
||||
) {
|
||||
safethrow(cptr_concat("process_start(", file_path, ", ", args_str, ", ", search_in_PATH ? "true" : "false",
|
||||
") error: CreateProcess() failed with error code ", toString_i64(GetLastError())), ;)
|
||||
}
|
||||
|
||||
|
||||
// Close thread handle and child process pipe ends
|
||||
safethrow_if_false(CloseHandle(in_pipe_r));
|
||||
safethrow_if_false(CloseHandle(out_pipe_w));
|
||||
safethrow_if_false(CloseHandle(err_pipe_w));
|
||||
safethrow_if_false(CloseHandle(pi.hThread));
|
||||
|
||||
p->file_path = file_path;
|
||||
p->args = args;
|
||||
p->id=pi.dwProcessId;
|
||||
p->_winProcHandle = pi.hProcess;
|
||||
|
||||
p->input = in_pipe_w;
|
||||
p->output= out_pipe_r;
|
||||
p->error = err_pipe_r;
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_closeHandles(Process* p){
|
||||
safethrow_if_false(CloseHandle(p->_winProcHandle));
|
||||
safethrow_if_false(CloseHandle(p->input));
|
||||
safethrow_if_false(CloseHandle(p->output));
|
||||
safethrow_if_false(CloseHandle(p->error));
|
||||
p->id=0;
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_waitForExit(Process* p){
|
||||
if(WaitForSingleObject(p->_winProcHandle, INFINITE) != 0)
|
||||
safethrow("WaitForSingleObject() failed", ;);
|
||||
DWORD exitCode = 0;
|
||||
safethrow_if_false(GetExitCodeProcess(p->_winProcHandle, &exitCode));
|
||||
if(exitCode != 0)
|
||||
safethrow(cptr_concat("process ", toString_i64(p->id), " exited with code ", toString_i64(exitCode)), ;)
|
||||
Process_closeHandles(p);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
Maybe Process_stop(Process* p){
|
||||
safethrow_if_false(TerminateProcess(p->_winProcHandle, 1));
|
||||
try(Process_closeHandles(p), _m864, ;);
|
||||
return MaybeNull;
|
||||
}
|
||||
|
||||
kt_define(Process, (freeMembers_t)(void*)Process_stop, NULL)
|
||||
|
||||
i32 PipeHandle_read(PipeHandle pipe, char* buf, i32 bufsize){
|
||||
DWORD bytesRead = 0;
|
||||
if(!ReadFile(pipe, buf, bufsize, &bytesRead, NULL))
|
||||
return -1;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user