diff --git a/.gitignore b/.gitignore index 6e5b49f..cab1d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,8 @@ obj/ # user files .old*/ .vs/ -.vscode/ .vshistory/ .editorconfig *.user *.vcxproj.filters -.config +current.config diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dd060e8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cbuild"] + path = cbuild + url = https://github.com/Timerix22/cbuild.git diff --git a/.vscode/.gitignore b/.vscode/.gitignore new file mode 100644 index 0000000..c3d3a20 --- /dev/null +++ b/.vscode/.gitignore @@ -0,0 +1 @@ +settings.json \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..421e47a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Debug", + "type": "cppdbg", + "request": "launch", + "preLaunchTask": "build_exec_dbg", + "program": "${workspaceFolder}/bin/kerep.com", + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "externalConsole": true, + "internalConsoleOptions": "openOnSessionStart", + "miDebuggerPath": "/usr/bin/gdb", + "MIMode": "gdb", + "pipeTransport": { + "debuggerPath": "gdb", + "pipeProgram": "bash", + "pipeArgs": ["-c"], + "pipeCwd": "${workspaceFolder}" + } + }, + { + "name": "(msvc) Debug", + "type": "cppvsdbg", + "request": "launch", + "preLaunchTask": "build_dbg", + "cwd": "${workspaceFolder}\\bin", + "program": "${workspaceFolder}\\bin\\kerep.com", + "stopAtEntry": false, + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..7fb803b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,57 @@ + +{ + + "version": "2.0.0", + "tasks": [ + { + "label": "build_exec", + "detail": "build project", + "type": "cppbuild", + "command": "make", + "args": [ + "build_exec" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": false, + "clear": true + } + }, + + { + "label": "build_exec_dbg", + "detail": "build project with debug symbols", + "type": "cppbuild", + "command": "make", + "args": [ + "build_exec_dbg" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": false, + "clear": true + } + } + ] + } \ No newline at end of file diff --git a/Makefile b/Makefile index 49eea86..c61ed41 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,24 @@ -###### Building tasks ####### -build_test: - @build_scripts/build_configurations/build_test.sh - -build_test_dbg: - @build_scripts/build_configurations/build_test_dbg.sh +###### Build cbuild/default_tasks ####### +build_exec: + @cbuild/call_task.sh build_exec +build_exec_dbg: + @cbuild/call_task.sh build_exec_dbg build_shared_lib: - @build_scripts/build_configurations/build_shared_lib.sh + @cbuild/call_task.sh build_shared_lib +build_shared_lib_dbg: + @cbuild/call_task.sh build_shared_lib_dbg build_static_lib: - @build_scripts/build_configurations/build_static_lib.sh - + @cbuild/call_task.sh build_static_lib build_static_lib_dbg: - @build_scripts/build_configurations/build_static_lib_dbg.sh + @cbuild/call_task.sh build_static_lib_dbg -###### Testing tasks ####### -test: build_test - @build_scripts/build_configurations/test.sh +###### Launch cbuild/default_tasks ####### +exec: build_exec + @cbuild/call_task.sh exec -test_valgrind: build_test_dbg - @build_scripts/build_configurations/test_valgrind.sh +valgrind: build_exec_dbg + @cbuild/call_task.sh valgrind -all: build_test +all: build_exec diff --git a/build_scripts/build_configurations/build_shared_lib.sh b/build_scripts/build_configurations/build_shared_lib.sh deleted file mode 100644 index dbe33c9..0000000 --- a/build_scripts/build_configurations/build_shared_lib.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}==========[build_shared_lib]==========\n" -clear_dir "$OUTDIR" -clear_dir "$OBJDIR" -compile_c "$BUILD_SHARED_LIB_C_ARGS" "$SRC_C tests/test_marshalling.c" -compile_cpp "$BUILD_SHARED_LIB_CPP_ARGS" "$SRC_CPP" -link "$BUILD_SHARED_LIB_CPP_ARGS $BUILD_SHARED_LIB_LINKER_ARGS" "$SHARED_LIB_FILE" diff --git a/build_scripts/build_configurations/build_static_lib.sh b/build_scripts/build_configurations/build_static_lib.sh deleted file mode 100644 index 692155e..0000000 --- a/build_scripts/build_configurations/build_static_lib.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}==========[build_static_lib]==========\n" -clear_dir "$OUTDIR" -clear_dir "$OBJDIR" -compile_c "$BUILD_STATIC_LIB_C_ARGS" "$SRC_C tests/test_marshalling.c" -compile_cpp "$BUILD_STATIC_LIB_CPP_ARGS" "$SRC_CPP" -pack_static_lib "$STATIC_LIB_FILE" diff --git a/build_scripts/build_configurations/build_static_lib_dbg.sh b/build_scripts/build_configurations/build_static_lib_dbg.sh deleted file mode 100644 index ef8aa3d..0000000 --- a/build_scripts/build_configurations/build_static_lib_dbg.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}==========[build_static_lib_dbg]==========\n" -clear_dir "$OUTDIR" -clear_dir "$OBJDIR" -compile_c "$BUILD_STATIC_LIB_DBG_C_ARGS" "$SRC_C tests/test_marshalling.c" -compile_cpp "$BUILD_STATIC_LIB_DBG_CPP_ARGS" "$SRC_CPP" -pack_static_lib "$STATIC_LIB_DBG_FILE" diff --git a/build_scripts/build_configurations/build_test.sh b/build_scripts/build_configurations/build_test.sh deleted file mode 100644 index 570de5a..0000000 --- a/build_scripts/build_configurations/build_test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}=============[build_test]=============\n" -clear_dir "$OUTDIR" -clear_dir "$OBJDIR" -compile_c "$BUILD_TEST_C_ARGS" "$SRC_C $TESTS_C" -compile_cpp "$BUILD_TEST_CPP_ARGS" "$SRC_CPP $TESTS_CPP" -link "$BUILD_TEST_CPP_ARGS $BUILD_TEST_LINKER_ARGS" $TEST_FILE diff --git a/build_scripts/build_configurations/build_test_dbg.sh b/build_scripts/build_configurations/build_test_dbg.sh deleted file mode 100644 index ff56aa0..0000000 --- a/build_scripts/build_configurations/build_test_dbg.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}===========[build_test_dbg]===========\n" -clear_dir "$OUTDIR" -clear_dir "$OBJDIR" -compile_c "$BUILD_TEST_DBG_C_ARGS" "$SRC_C $TESTS_C" -compile_cpp "$BUILD_TEST_DBG_CPP_ARGS" "$SRC_CPP $TESTS_CPP" -link "$BUILD_TEST_DBG_CPP_ARGS $BUILD_TEST_DBG_LINKER_ARGS" $TEST_DBG_FILE diff --git a/build_scripts/build_configurations/test.sh b/build_scripts/build_configurations/test.sh deleted file mode 100644 index 45ac85c..0000000 --- a/build_scripts/build_configurations/test.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}================[test]================\n" -cd $OUTDIR -./$TEST_FILE -cd .. diff --git a/build_scripts/build_configurations/test_valgrind.sh b/build_scripts/build_configurations/test_valgrind.sh deleted file mode 100644 index a92df20..0000000 --- a/build_scripts/build_configurations/test_valgrind.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -source build_scripts/init.sh - -print "${CYAN}===========[test_valgrind]============\n" -cd $OUTDIR -valgrind $VALGRIND_ARGS ./$TEST_DBG_FILE -cat "valgrind.log" -cd .. diff --git a/build_scripts/colors.sh b/build_scripts/colors.sh deleted file mode 100644 index e3e8363..0000000 --- a/build_scripts/colors.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -BLACK='\033[0;30m' -GRAY='\033[0;37m' -WHITE='\033[0;97m' -RED='\033[0;91m' -GREEN='\033[0;92m' -YELLOW='\033[0;93m' -BLUE='\033[0;94m' -PURPLE='\033[0;95m' -CYAN='\033[0;96m' diff --git a/build_scripts/default.config.sh b/build_scripts/default.config.sh deleted file mode 100644 index fa3755e..0000000 --- a/build_scripts/default.config.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -OUTDIR=bin -OBJDIR=obj -CMP_C=gcc -CMP_CPP=g++ -STD_C=c11 -STD_CPP=c++17 -WARN_C="-Wall -Wno-discarded-qualifiers" #-Wextra -WARN_CPP="-Wall -Wno-unused-variable -Wno-return-type" #-Wextra -SRC_C="$( find src -name '*.c')" -SRC_CPP="$( find src -name '*.cpp')" -TESTS_C="$( find tests -name '*.c')" -TESTS_CPP="$(find tests -name '*.cpp')" -VALGRIND_ARGS="-s --log-file=valgrind.log --read-var-info=yes --track-origins=yes --fullpath-after=kerep/ --leak-check=full --show-leak-kinds=all" - -# build_test -TEST_FILE=kerep.com -BUILD_TEST_C_ARGS="-O2" -BUILD_TEST_CPP_ARGS="$BUILD_TEST_C_ARGS" -BUILD_TEST_LINKER_ARGS="" - -# build_test_dbg -TEST_DBG_FILE=$TEST_FILE -BUILD_TEST_DBG_C_ARGS="-O0 -g" -BUILD_TEST_DBG_CPP_ARGS="$BUILD_TEST_DBG_C_ARGS" -BUILD_TEST_DBG_LINKER_ARGS="" - -# build_shared_lib -SHARED_LIB_FILE=kerep.so -BUILD_SHARED_LIB_C_ARGS="-O2 -fpic -flto -shared" -BUILD_SHARED_LIB_CPP_ARGS="$BUILD_SHARED_LIB_C_ARGS" -BUILD_SHARED_LIB_LINKER_ARGS="-Wl,-soname,$SHARED_LIB_FILE" - -# build_static_lib -STATIC_LIB_FILE=kerep.a -BUILD_STATIC_LIB_C_ARGS="-O2 -fpic" -BUILD_STATIC_LIB_CPP_ARGS="$BUILD_STATIC_LIB_C_ARGS" - -# build_static_lib_dbg -STATIC_LIB_DBG_FILE="$STATIC_LIB_FILE" -BUILD_STATIC_LIB_DBG_C_ARGS="-O0 -g" -BUILD_STATIC_LIB_DBG_CPP_ARGS="$BUILD_STATIC_LIB_DBG_C_ARGS" diff --git a/build_scripts/functions.sh b/build_scripts/functions.sh deleted file mode 100644 index a2486e0..0000000 --- a/build_scripts/functions.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash - -function print { - printf "$1$GRAY" -} - -function clear_dir { - print "${BLUE}clearing $1\n" - rm -rf $1 - mkdir $1 -} - -function compile { - local cmp=$1 - print "${BLUE}compiler: ${GRAY}$cmp\n" - local std=$2 - print "${BLUE}standard: ${GRAY}$std\n" - local warn=$3 - print "${BLUE}warnings: ${GRAY}$warn\n" - local args=$4 - print "${BLUE}args: ${GRAY}$args\n" - local sources=$5 - print "${BLUE}sources: ${GRAY}$sources\n" - local compilation_error=0 - - for srcfile in $sources - do ( - local object="$OBJDIR/$(basename $srcfile).o" - if ! $($cmp -std=$std $warn $args -c -o $object $srcfile) - then - print "${RED}some error happened\n" - compilation_error=1 - fi - ) & done - wait - - if [ $compilation_error != 0 ] - then - exit 1 - fi -} - -# (args, sources) -function compile_c { - print "${CYAN}-------------[compile_c]--------------\n" - compile $CMP_C $STD_C "$WARN_C" "$1" "$2" -} - -# (args, sources) -function compile_cpp { - print "${CYAN}------------[compile_cpp]-------------\n" - compile $CMP_CPP $STD_CPP "$WARN_CPP" "$1" "$2" -} - -# (args, outfile) -function link { - print "${CYAN}----------------[link]----------------\n" - local args=$1 - print "${BLUE}args: ${GRAY}$args\n" - local outfile=$OUTDIR/$2 - print "${BLUE}outfile: ${GRAY}$outfile\n" - local objects="$(find $OBJDIR -name *.o)" - print "${BLUE}objects: ${GRAY}$objects\n" - if $CMP_CPP $args -o $outfile $(echo $objects | tr '\n' ' ') - then - print "${GREEN}file $CYAN$outfile ${GREEN}created\n" - rm -rf $OBJDIR - else - print "${RED}some error happened\n" - exit 1 - fi -} - -# (outfile) -function pack_static_lib { - print "${CYAN}----------------[link]----------------\n" - local outfile=$OUTDIR/$1 - print "${BLUE}outfile: ${GRAY}$outfile\n" - local objects="$(find $OBJDIR -name *.o)" - print "${BLUE}objects: ${GRAY}$objects\n" - if ar rcs $outfile $(echo $objects | tr '\n' ' ') - then - print "${GREEN}file $CYAN$outfile ${GREEN}created\n" - rm -rf $OBJDIR - else - print "${RED}some error happened\n" - exit 1 - fi -} \ No newline at end of file diff --git a/build_scripts/init.sh b/build_scripts/init.sh deleted file mode 100644 index 868baf5..0000000 --- a/build_scripts/init.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -tabs 4 - -source build_scripts/colors.sh -source build_scripts/functions.sh - -if [ ! -f ".config" ]; then - print "${YELLOW}./.config doesn't exists\n" - cp build_scripts/default.config.sh .config - print "${YELLOW}default config created\n" - while true; do - print "${WHITE}continue? (y/n) " - read answ - case $answ in - [Yy] ) break;; - [Nn] ) exit;; - * ) print "${RED}incorrect answer\n";; - esac - done -fi -source .config diff --git a/default.config b/default.config new file mode 100644 index 0000000..37c5883 --- /dev/null +++ b/default.config @@ -0,0 +1,77 @@ +#!/bin/bash +CONFIG_VERSION=3 +CBUILD_VERSION=2 + +PROJECT=kerep +CMP_C=gcc +CMP_CPP=g++ +STD_C=c11 +STD_CPP=c++17 +WARN_C="-Wall -Wno-discarded-qualifiers -Wno-int-conversion" +WARN_CPP="-Wall" +SRC_C="$( find src -name '*.c')" +SRC_CPP="$( find src -name '*.cpp')" +TESTS_C="$( find tests -name '*.c')" +TESTS_CPP="$(find tests -name '*.cpp')" + +OUTDIR=bin +OBJDIR=obj +EXEC_FILE=$PROJECT.com +SHARED_LIB_FILE=$PROJECT.so +STATIC_LIB_FILE=$PROJECT.a + +case $TASK in + build_exec) + C_ARGS="-O2" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="" + TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + build_exec_dbg) + C_ARGS="-O0 -g" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="" + TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + build_shared_lib) + C_ARGS="-O2 -fpic -flto -shared" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="-Wl,-soname,$SHARED_LIB_FILE" + TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + build_shared_lib_dbg) + C_ARGS="-O0 -g -fpic -shared" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="-Wl,-soname,$SHARED_LIB_FILE" + TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + build_static_lib) + C_ARGS="-O2 -fpic" + CPP_ARGS="$C_ARGS" + TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + build_static_lib_dbg) + C_ARGS="-O0 -g" + CPP_ARGS="$C_ARGS" + TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh + PRE_TASK_SCRIPT=tasks/pre_build.sh + POST_TASK_SCRIPT= + ;; + exec) + TASK_SCRIPT=cbuild/default_tasks/exec.sh + ;; + valgrind) + VALGRIND_ARGS="-s --log-file=valgrind.log --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all" + TASK_SCRIPT=cbuild/default_tasks/valgrind.sh + ;; +esac diff --git a/kerep.vcxproj b/kerep.vcxproj index 159f0fe..33807a4 100644 --- a/kerep.vcxproj +++ b/kerep.vcxproj @@ -32,9 +32,6 @@ - - - @@ -44,7 +41,6 @@ - @@ -63,11 +59,6 @@ - - - - - @@ -261,4 +252,4 @@ - \ No newline at end of file + diff --git a/src/Array/Array.h b/src/Array/Array.h new file mode 100644 index 0000000..ac9dabc --- /dev/null +++ b/src/Array/Array.h @@ -0,0 +1,40 @@ +#include "Array_declare.h" + +Array_declare(char) +Array_declare(bool) +Array_declare(float32) +Array_declare(float64) +Array_declare(int8) +Array_declare(uint8) +Array_declare(int16) +Array_declare(uint16) +Array_declare(int32) +Array_declare(uint32) +Array_declare(int64) +Array_declare(uint64) + +ktId_declare(ArrayChar); +ktId_declare(ArrayBool); +ktId_declare(ArrayFloat32); +ktId_declare(ArrayFloat64); +ktId_declare(ArrayInt8); +ktId_declare(ArrayUInt8); +ktId_declare(ArrayInt16); +ktId_declare(ArrayUInt16); +ktId_declare(ArrayInt32); +ktId_declare(ArrayUInt32); +ktId_declare(ArrayInt64); +ktId_declare(ArrayUInt64); + +ktId_declare(ArrayCharPtr); +ktId_declare(ArrayBoolPtr); +ktId_declare(ArrayFloat32Ptr); +ktId_declare(ArrayFloat64Ptr); +ktId_declare(ArrayInt8Ptr); +ktId_declare(ArrayUInt8Ptr); +ktId_declare(ArrayInt16Ptr); +ktId_declare(ArrayUInt16Ptr); +ktId_declare(ArrayInt32Ptr); +ktId_declare(ArrayUInt32Ptr); +ktId_declare(ArrayInt64Ptr); +ktId_declare(ArrayUInt64Ptr); diff --git a/src/Array/Array_declare.h b/src/Array/Array_declare.h new file mode 100644 index 0000000..6d12ead --- /dev/null +++ b/src/Array/Array_declare.h @@ -0,0 +1,40 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../base/base.h" + +#define Array_declare(type)\ +typedef struct Array_##type{\ + type* values;\ + uint32 length;\ + bool allocatedOnHeap;\ +} Array_##type;\ +\ +\ +static inline Array_##type Array_##type##_allocValues(uint32 length){\ + return (Array_##type) {\ + .values=(type##*)malloc(sizeof(type)*length),\ + .length=length,\ + .allocatedOnHeap=true\ + };\ +}\ +\ +static inline Array_##type Array_##type##_fromBuffer(type##* buffer, uint32 bufferLength, bool allocatedOnHeap){\ + return (Array_##type) {\ + .values=buffer,\ + .length=bufferLength,\ + .allocatedOnHeap=allocatedOnHeap\ + };\ +}\ +\ +static inline void Array_##type##_freeValues(Array_##type* array){\ + if(array->allocatedOnHeap)\ + free(array->values);\ +} + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/Array/README.md b/src/Array/README.md new file mode 100644 index 0000000..931ff09 --- /dev/null +++ b/src/Array/README.md @@ -0,0 +1,2 @@ +# Array struct +This struct stores array pointer and length. If you want to use `Array` of some type, it should be declared in header file by macro `Array_declare`. It uses `static inline` functions, so all definitions will be generated in header. diff --git a/src/Autoarr/Autoarr.c b/src/Autoarr/Autoarr.c index 48d595a..c72a299 100644 --- a/src/Autoarr/Autoarr.c +++ b/src/Autoarr/Autoarr.c @@ -1,19 +1,51 @@ #include "Autoarr.h" -Autoarr_define(uint8); -Autoarr_define(int8); -Autoarr_define(uint16); -Autoarr_define(int16); -Autoarr_define(uint32); -Autoarr_define(int32); -Autoarr_define(uint64); -Autoarr_define(int64); -Autoarr_define(float); -Autoarr_define(double); -Autoarr_define(Unitype); +Autoarr_define(char) +Autoarr_define(bool) +Autoarr_define(float32) +Autoarr_define(float64) +Autoarr_define(uint8) +Autoarr_define(int8) +Autoarr_define(uint16) +Autoarr_define(int16) +Autoarr_define(uint32) +Autoarr_define(int32) +Autoarr_define(uint64) +Autoarr_define(int64) + +ktId_define(AutoarrChar); +ktId_define(AutoarrBool); +ktId_define(AutoarrFloat32); +ktId_define(AutoarrFloat64); +ktId_define(AutoarrInt8); +ktId_define(AutoarrUInt8); +ktId_define(AutoarrInt16); +ktId_define(AutoarrUInt16); +ktId_define(AutoarrInt32); +ktId_define(AutoarrUInt32); +ktId_define(AutoarrInt64); +ktId_define(AutoarrUInt64); + +ktId_define(AutoarrCharPtr); +ktId_define(AutoarrBoolPtr); +ktId_define(AutoarrFloat32Ptr); +ktId_define(AutoarrFloat64Ptr); +ktId_define(AutoarrInt8Ptr); +ktId_define(AutoarrUInt8Ptr); +ktId_define(AutoarrInt16Ptr); +ktId_define(AutoarrUInt16Ptr); +ktId_define(AutoarrInt32Ptr); +ktId_define(AutoarrUInt32Ptr); +ktId_define(AutoarrInt64Ptr); +ktId_define(AutoarrUInt64Ptr); + +Autoarr_define(Unitype) +ktId_define(AutoarrUnitype); +ktId_define(AutoarrUnitypePtr); // right func to clear array of unitype values -void Autoarr_free_Unitype(Autoarr(Unitype)* ar){ +void __Autoarr_free_Unitype_(Autoarr(Unitype)* ar, bool freePtr){ Autoarr_foreach(ar, u,Unitype_free(u)); - Autoarr_free(ar); + __Autoarr_free_Unitype(ar, freePtr); } +void ____Autoarr_free_Unitype_(void* ar) { __Autoarr_free_Unitype_((Autoarr(Unitype)*)ar, false); } \ No newline at end of file diff --git a/src/Autoarr/Autoarr.h b/src/Autoarr/Autoarr.h index 89440a4..3a953c0 100644 --- a/src/Autoarr/Autoarr.h +++ b/src/Autoarr/Autoarr.h @@ -7,20 +7,52 @@ extern "C" { #include "Autoarr_declare.h" #include "Autoarr_define.h" -Autoarr_declare(uint8) +Autoarr_declare(char) +Autoarr_declare(bool) +Autoarr_declare(float32) +Autoarr_declare(float64) Autoarr_declare(int8) -Autoarr_declare(uint16) +Autoarr_declare(uint8) Autoarr_declare(int16) -Autoarr_declare(uint32) +Autoarr_declare(uint16) Autoarr_declare(int32) -Autoarr_declare(uint64) +Autoarr_declare(uint32) Autoarr_declare(int64) -Autoarr_declare(float) -Autoarr_declare(double) -Autoarr_declare(Unitype) +Autoarr_declare(uint64) -// right func to clear array of unitype values -void Autoarr_free_Unitype(Autoarr(Unitype)* ar); +ktId_declare(AutoarrChar); +ktId_declare(AutoarrBool); +ktId_declare(AutoarrFloat32); +ktId_declare(AutoarrFloat64); +ktId_declare(AutoarrInt8); +ktId_declare(AutoarrUInt8); +ktId_declare(AutoarrInt16); +ktId_declare(AutoarrUInt16); +ktId_declare(AutoarrInt32); +ktId_declare(AutoarrUInt32); +ktId_declare(AutoarrInt64); +ktId_declare(AutoarrUInt64); + +ktId_declare(AutoarrCharPtr); +ktId_declare(AutoarrBoolPtr); +ktId_declare(AutoarrFloat32Ptr); +ktId_declare(AutoarrFloat64Ptr); +ktId_declare(AutoarrInt8Ptr); +ktId_declare(AutoarrUInt8Ptr); +ktId_declare(AutoarrInt16Ptr); +ktId_declare(AutoarrUInt16Ptr); +ktId_declare(AutoarrInt32Ptr); +ktId_declare(AutoarrUInt32Ptr); +ktId_declare(AutoarrInt64Ptr); +ktId_declare(AutoarrUInt64Ptr); + +Autoarr_declare(Unitype) +ktId_declare(AutoarrUnitype); +ktId_declare(AutoarrUnitypePtr); + +// this function is injected in kerep_init() +void __Autoarr_free_Unitype_(Autoarr(Unitype)* ar, bool freePtr); +void ____Autoarr_free_Unitype_(void* ar); #define Autoarr_foreach(ar,elem,codeblock)({\ if(ar->blocks_count>0) {\ diff --git a/src/Autoarr/Autoarr_KVPair_exported.c b/src/Autoarr/Autoarr_KVPair_exported.c index 18fa4aa..8bfbd56 100644 --- a/src/Autoarr/Autoarr_KVPair_exported.c +++ b/src/Autoarr/Autoarr_KVPair_exported.c @@ -10,7 +10,7 @@ EXPORT void CALL kerep_Autoarr_KVPair_create(uint16 max_blocks_count, uint16 max } EXPORT void CALL kerep_Autoarr_KVPair_free(Autoarr_KVPair* ar){ - Autoarr_free_KVPair(ar); + Autoarr_free(ar, true); } EXPORT void CALL kerep_Autoarr_KVPair_get(Autoarr_KVPair* ar, uint32 index, KVPair* output){ diff --git a/src/Autoarr/Autoarr_Unitype_exported.c b/src/Autoarr/Autoarr_Unitype_exported.c index 8ad5efd..2aded2e 100644 --- a/src/Autoarr/Autoarr_Unitype_exported.c +++ b/src/Autoarr/Autoarr_Unitype_exported.c @@ -9,7 +9,7 @@ EXPORT void CALL kerep_Autoarr_Unitype_create(uint16 max_blocks_count, uint16 ma } EXPORT void CALL kerep_Autoarr_Unitype_free(Autoarr_Unitype* ar){ - Autoarr_free_Unitype(ar); + Autoarr_free(ar, true); } EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, uint32 index, Unitype* output){ diff --git a/src/Autoarr/Autoarr_declare.h b/src/Autoarr/Autoarr_declare.h index 80169bd..404a361 100644 --- a/src/Autoarr/Autoarr_declare.h +++ b/src/Autoarr/Autoarr_declare.h @@ -15,7 +15,8 @@ typedef struct {\ type (*get)(struct Autoarr_##type* ar, uint32 index);\ type* (*getptr)(struct Autoarr_##type* ar, uint32 index);\ void (*set)(struct Autoarr_##type* ar, uint32 index, type element);\ - void (*_free)(struct Autoarr_##type* ar);\ + void (*freear)(struct Autoarr_##type* ar, bool freePtr);\ + type* (*toArray)(struct Autoarr_##type* ar);\ } __functions_list_t_##type;\ \ typedef struct Autoarr_##type{\ @@ -27,15 +28,14 @@ typedef struct Autoarr_##type{\ __functions_list_t_##type* functions;\ } Autoarr_##type;\ \ -void __Autoarr_add_##type(Autoarr_##type* ar, type element);\ -type __Autoarr_get_##type(Autoarr_##type* ar, uint32 index);\ -type* __Autoarr_getptr_##type(Autoarr_##type* ar, uint32 index);\ -void __Autoarr_set_##type(Autoarr_##type* ar, uint32 index, type element);\ -void __Autoarr_free_##type(Autoarr_##type* ar);\ -Autoarr_##type* __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length); +Autoarr_##type* __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length);\ +void __Autoarr_free_##type(Autoarr_##type* ar, bool freePtr);\ +void ____Autoarr_free_##type(void* ar); #define Autoarr(type) Autoarr_##type +#define Autoarr_create(type, max_blocks_count, max_block_length)\ + __Autoarr_create_##type(max_blocks_count, max_block_length) #define Autoarr_add(autoarr, element)\ autoarr->functions->add(autoarr, element) #define Autoarr_get(autoarr, index)\ @@ -44,10 +44,10 @@ Autoarr_##type* __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_bloc autoarr->functions->getptr(autoarr,index) #define Autoarr_set(autoarr, index, element)\ autoarr->functions->set(autoarr, index, element) -#define Autoarr_free(autoarr)\ - autoarr->functions->_free(autoarr) -#define Autoarr_create(type, max_blocks_count, max_block_length)\ - __Autoarr_create_##type(max_blocks_count, max_block_length) +#define Autoarr_free(autoarr, freePtr)\ + autoarr->functions->freear(autoarr, freePtr) +#define Autoarr_toArray(autoarr)\ + autoarr->functions->toArray(autoarr) #define Autoarr_length(autoarr) \ (uint32)(!autoarr->blocks_count ? 0 : \ diff --git a/src/Autoarr/Autoarr_define.h b/src/Autoarr/Autoarr_define.h index 441c9b6..b70ad86 100644 --- a/src/Autoarr/Autoarr_define.h +++ b/src/Autoarr/Autoarr_define.h @@ -39,11 +39,22 @@ void __Autoarr_set_##type(Autoarr_##type* ar, uint32 index, type element){\ ar->values[index/ar->max_block_length][index%ar->max_block_length]=element;\ }\ \ -void __Autoarr_free_##type(Autoarr_##type* ar){\ +void __Autoarr_free_##type(Autoarr_##type* ar, bool freePtr){\ for(uint16 i=0; iblocks_count;i++)\ free(ar->values[i]); \ free(ar->values);\ - free(ar);\ + if(freePtr) free(ar);\ +}\ +void ____Autoarr_free_##type(void* ar){\ + __Autoarr_free_##type((Autoarr_##type*)ar, false);\ +}\ +\ +type* __Autoarr_toArray_##type(Autoarr_##type* ar){\ + uint32 length=Autoarr_length(ar);\ + type* array=malloc(length * sizeof(type));\ + for(uint32 i=0; i0) safethrow(ERR_ENDOFSTR,;); - return SUCCESS(UniPtr(CharPtr,NULL)); + return SUCCESS(UniHeap(ktId_CharPtr,NULL)); } #define ReadName() __ReadName(shared) @@ -137,7 +137,7 @@ Maybe __ReadString(DeserializeSharedData* shared){ } else { char* str=StringBuilder_build(b).ptr; - return SUCCESS(UniPtr(CharPtr,str)); + return SUCCESS(UniHeap(ktId_CharPtr,str)); } } else { @@ -154,16 +154,16 @@ Maybe __ReadList(DeserializeSharedData* shared){ Autoarr(Unitype)* list=Autoarr_create(Unitype,ARR_BC,ARR_BL); bool readingList=true; while (true){ - try(ReadValue((&readingList)), val, Autoarr_free_Unitype(list)) + try(ReadValue((&readingList)), val, Autoarr_free(list, true)) Autoarr_add(list,val.value); if (!readingList){ - if(val.value.type==Null) + if(val.value.typeId==ktId_Null) Autoarr_pop(list); break; } } - return SUCCESS(UniPtr(AutoarrUnitypePtr,list)); + return SUCCESS(UniHeap(ktId_AutoarrUnitypePtr,list)); }; #define ReadList() __ReadList(shared) @@ -182,7 +182,7 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){ // Float64 case 'f': { char* _c=string_extract(str); - Unitype rez=Uni(Float64,strtod(_c,NULL)); + Unitype rez=UniFloat64(strtod(_c,NULL)); free(_c); return SUCCESS(rez); } @@ -199,7 +199,7 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){ safethrow(err,free(_c)); } free(_c); - return SUCCESS(Uni(UInt64,lu)); + return SUCCESS(UniUInt64(lu)); } // Int64 case '0': case '1': case '2': case '3': case '4': @@ -215,7 +215,7 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){ safethrow(err,free(_c)); } free(_c); - return SUCCESS(Uni(Int64,li)); + return SUCCESS(UniInt64(li)); } // wrong type default: @@ -275,7 +275,7 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){ case ';': case ',': if(valueStr.length!=0){ - if(value.type!=Null) + if(value.typeId!=ktId_Null) safethrow_wrongchar(c,Unitype_free(value)); try(ParseValue(valueStr),maybeParsed,;) value=maybeParsed.value; @@ -321,7 +321,7 @@ Maybe __deserialize(char** _text, bool _calledRecursively) { } else{ list=Autoarr_create(Unitype,ARR_BC,ARR_BL); - Hashtable_add(dict,nameCPtr,UniPtr(AutoarrUnitypePtr,list)); + Hashtable_add(dict,nameCPtr,UniHeap(ktId_AutoarrUnitypePtr,list)); } Autoarr_add(list,val.value); } @@ -331,7 +331,7 @@ Maybe __deserialize(char** _text, bool _calledRecursively) { END: *_text=text; - return SUCCESS(UniPtr(HashtablePtr,dict)); + return SUCCESS(UniHeap(ktId_HashtablePtr,dict)); } Maybe DtsodV24_deserialize(char* _text) { diff --git a/src/DtsodParser/DtsodV24_serialize.c b/src/DtsodParser/DtsodV24_serialize.c index 4618104..cf48d34 100644 --- a/src/DtsodParser/DtsodV24_serialize.c +++ b/src/DtsodParser/DtsodV24_serialize.c @@ -23,70 +23,65 @@ void __AppendTabs(SerializeSharedData* shared) { Maybe __AppendValue(SerializeSharedData* shared, Unitype u); #define AppendValue(UNI) __AppendValue(shared, UNI) Maybe __AppendValue(SerializeSharedData* shared, Unitype u){ - switch(u.type){ - case Int64: - StringBuilder_append_int64(b,u.Int64); - break; - case UInt64: - StringBuilder_append_uint64(b,u.UInt64); - addc('u'); - break; - case Float64: - StringBuilder_append_float64(b,u.Float64); - addc('f'); - break; - case CharPtr: - addc('"'); - char c; - while((c=*(char*)(u.VoidPtr++))){ - if(c=='\"') addc('\\'); - addc(c); - } - addc('"'); - break; - case Bool: - StringBuilder_append_cptr(b, u.Bool ? "true" : "false"); - break; - case Null: - safethrow("Null isn't supported in DtsodV24",;); - case AutoarrUnitypePtr: - if(Autoarr_length(((Autoarr_Unitype*)(u.VoidPtr)))){ + if(u.typeId==ktId_Int64){ + StringBuilder_append_int64(b,u.Int64); + } + else if(u.typeId==ktId_UInt64){ + StringBuilder_append_uint64(b,u.UInt64); + addc('u'); + } + else if(u.typeId==ktId_Float64){ + StringBuilder_append_float64(b,u.Float64); + addc('f'); + } + else if(u.typeId==ktId_CharPtr){ + addc('"'); + char c; + while((c=*(char*)(u.VoidPtr++))){ + if(c=='\"') addc('\\'); + addc(c); + } + addc('"'); + } + else if(u.typeId==ktId_Bool){ + StringBuilder_append_cptr(b, u.Bool ? "true" : "false"); + } + else if(u.typeId==ktId_Null){ + safethrow("Null isn't supported in DtsodV24",;); + } + else if(u.typeId==ktId_AutoarrUnitypePtr){ + if(Autoarr_length(((Autoarr_Unitype*)(u.VoidPtr)))){ + addc('\n'); + AppendTabs(); + addc('['); + tabs++; + Autoarr_foreach(((Autoarr_Unitype*)(u.VoidPtr)), e, ({ addc('\n'); AppendTabs(); - addc('['); - tabs++; - Autoarr_foreach(((Autoarr_Unitype*)(u.VoidPtr)), e, ({ - addc('\n'); - AppendTabs(); - try(AppendValue(e),__,;); - addc(','); - })); - StringBuilder_rmchar(b); - addc('\n'); - tabs--; - AppendTabs(); - addc(']'); - } - else { - addc('['); - addc(']'); - } - break; - case HashtablePtr: - // check hashtable is blank - Hashtable_foreach(((Hashtable*)u.VoidPtr), __, ({ - goto hashtableNotBlank; - if(__.key); // weird way to disable warning + try(AppendValue(e),__,;); + addc(','); })); - - - // blank hashtable - addc('{'); - addc('}'); + StringBuilder_rmchar(b); + addc('\n'); + tabs--; + AppendTabs(); + addc(']'); + } + else { + addc('['); + addc(']'); + } + } + else if(u.typeId==ktId_HashtablePtr){ + // check hashtable is blank + bool hashtableNotBlank=false; + Hashtable_foreach(((Hashtable*)u.VoidPtr), __, ({ + hashtableNotBlank=true; + if(__.key); // weird way to disable warning break; - - // not blank hashtable - hashtableNotBlank: + })); + + if(hashtableNotBlank){ addc('\n'); AppendTabs(); addc('{'); @@ -94,10 +89,16 @@ Maybe __AppendValue(SerializeSharedData* shared, Unitype u){ try(__serialize(b,tabs+1,u.VoidPtr),___,;); AppendTabs(); addc('}'); - break; - default: dbg((u.type)); safethrow(ERR_WRONGTYPE,;); + } + else { + addc('{'); + addc('}'); + } + } + else { + dbg((u.typeId)); + safethrow(ERR_WRONGTYPE,;); } - return MaybeNull; }; @@ -125,5 +126,5 @@ Maybe DtsodV24_serialize(Hashtable* dtsod){ StringBuilder* sb=StringBuilder_create(); try(__serialize(sb,0,dtsod),__, StringBuilder_free(sb)); char* str=StringBuilder_build(sb).ptr; - return SUCCESS(UniPtr(CharPtr, str)); + return SUCCESS(UniHeap(ktId_CharPtr, str)); } diff --git a/src/Filesystem/filesystem.c b/src/Filesystem/filesystem.c new file mode 100644 index 0000000..fe535da --- /dev/null +++ b/src/Filesystem/filesystem.c @@ -0,0 +1,38 @@ +#include "filesystem.h" + +char* __path_concat(uint16 n, char* prev_part, ...){ + char** parts=(char**)malloc(n*sizeof(char*)); + uint32* lengths=malloc(n*sizeof(uint32)); + uint32 totalLength=0; + + // reading args from va_list + va_list vl; + va_start(vl, prev_part); + for(uint16 i=0; ihein];i++) - Autoarr_free_KVPair(ht->rows[i]); + Autoarr_free(ht->rows[i], true); free(ht->rows); +} +void Hashtable_free(Hashtable* ht){ + __Hashtable_free(ht); free(ht); } @@ -43,7 +50,8 @@ void Hashtable_expand(Hashtable* ht){ Autoarr(KVPair)* newar=newrows[newrown]; Autoarr_add(newar,p); } - Autoarr_free(ar); + // there is no need to free array values, because they are copied into new array + __Autoarr_free_KVPair(ar, true); } free(ht->rows); @@ -88,7 +96,7 @@ Unitype Hashtable_get(Hashtable* ht, char* key){ bool Hashtable_try_get(Hashtable* ht, char* key, Unitype* output){ Unitype u=Hashtable_get(ht,key); *output=u; - return u.type!=Null; + return u.typeId!=ktId_Null; } void Hashtable_addOrSet(Hashtable* ht, char* key, Unitype u){ diff --git a/src/Hashtable/Hashtable.h b/src/Hashtable/Hashtable.h index 3500199..520c2e4 100644 --- a/src/Hashtable/Hashtable.h +++ b/src/Hashtable/Hashtable.h @@ -11,9 +11,12 @@ typedef struct Hashtable{ uint8 hein; // height=HT_HEIGHTS[hein] Autoarr(KVPair)** rows; // Autoarr[height] } Hashtable; +ktId_declare(Hashtable); +ktId_declare(HashtablePtr); Hashtable* Hashtable_create(); void Hashtable_free(Hashtable* ht); +void __Hashtable_free(void* ht); // amount of rows uint16 Hashtable_height(Hashtable* ht); diff --git a/src/Hashtable/KeyValuePair.c b/src/Hashtable/KeyValuePair.c index cbe22dd..667487e 100644 --- a/src/Hashtable/KeyValuePair.c +++ b/src/Hashtable/KeyValuePair.c @@ -1,22 +1,30 @@ #include "KeyValuePair.h" -Autoarr_define(KVPair) +ktId_define(KVPair); +ktId_define(KVPairPtr); +Autoarr_define(KVPair) +ktId_define(AutoarrKVPair); +ktId_define(AutoarrKVPairPtr); // proper way to clear a KVP void KVPair_free(KVPair p){ free(p.key); Unitype_free(p.value); } +void __KVPair_free(void* p){ KVPair_free(*(KVPair*)p); } // func for KVP array clearing -void Autoarr_free_KVPair(Autoarr_KVPair* ar){ +void __Autoarr_free_KVPair_(Autoarr_KVPair* ar, bool freePtr){ Autoarr_foreach(ar,k,KVPair_free(k)); - Autoarr_free(ar); + __Autoarr_free_KVPair(ar, freePtr); +} +void ____Autoarr_free_KVPair_(void* ar){ + __Autoarr_free_KVPair_((Autoarr_KVPair*)ar, false); } void printkvp(KVPair p){ - printf("{\"%s\", ",p.key); + kprintf("{\"%s\", ",p.key); printuni(p.value); - printf("}"); + kprintf("}"); } diff --git a/src/Hashtable/KeyValuePair.h b/src/Hashtable/KeyValuePair.h index 19cc277..ef6a32b 100644 --- a/src/Hashtable/KeyValuePair.h +++ b/src/Hashtable/KeyValuePair.h @@ -11,14 +11,20 @@ typedef struct KVPair{ char* key; Unitype value; } KVPair; +ktId_declare(KVPair); +ktId_declare(KVPairPtr); Autoarr_declare(KVPair) +ktId_declare(AutoarrKVPair); +ktId_declare(AutoarrKVPairPtr); // proper way to clear a KVP void KVPair_free(KVPair p); +void __KVPair_free(void* p); // func to clear KVP array -void Autoarr_free_KVPair(Autoarr_KVPair* ar); +void __Autoarr_free_KVPair_(Autoarr_KVPair* ar, bool freePtr); +void ____Autoarr_free_KVPair_(void* ar); void printkvp(KVPair p); diff --git a/src/SearchTree/SearchTree.c b/src/SearchTree/SearchTree.c index e7cfac6..29e772d 100644 --- a/src/SearchTree/SearchTree.c +++ b/src/SearchTree/SearchTree.c @@ -1,14 +1,18 @@ #include "SearchTree.h" +ktId_define(STNode); +ktId_define(STNodePtr); + STNode* STNode_create(){ STNode* node=malloc(sizeof(STNode)); node->branches=NULL; - node->value.type=Null; + node->value.typeId=ktId_Null; node->value.UInt64=0; return node; } -void STNode_free(STNode* node){ +void __STNode_free(void* _node){ + STNode* node=_node; if (!node) throw(ERR_NULLPTR); if(node->branches){ for(uint8 n32 = 0;n32<8;n32++){ @@ -32,6 +36,9 @@ void STNode_free(STNode* node){ } if(node->value.VoidPtr) Unitype_free(node->value); +} +void STNode_free(STNode* node){ + __STNode_free(node); free(node); } diff --git a/src/SearchTree/SearchTree.h b/src/SearchTree/SearchTree.h index fc4eb8c..a11de86 100644 --- a/src/SearchTree/SearchTree.h +++ b/src/SearchTree/SearchTree.h @@ -11,9 +11,12 @@ typedef struct SearchTreeNode{ struct SearchTreeNode**** branches; // *STNode[8][8][4] Unitype value; } STNode; +ktId_declare(STNode); +ktId_declare(STNodePtr); STNode* STNode_create(); void STNode_free(STNode* node); +void __STNode_free(void* node); void ST_push(STNode* node, char* key, Unitype value); void ST_pushString(STNode* node, string key, Unitype value); diff --git a/src/String/StringBuilder.c b/src/String/StringBuilder.c index c0b46a9..8f7cff5 100644 --- a/src/String/StringBuilder.c +++ b/src/String/StringBuilder.c @@ -1,6 +1,11 @@ #include "StringBuilder.h" Autoarr_define(string) +ktId_define(AutoarrString); +ktId_define(AutoarrStringPtr); + +ktId_define(StringBuilder); +ktId_define(StringBuilderPtr); #define BL_C 32 #define BL_L 1024 @@ -17,7 +22,7 @@ void complete_buf(StringBuilder* b){ str.ptr[i++]=c; })); Autoarr_add(b->compl_bufs,str); - Autoarr_free(b->curr_buf); + Autoarr_free(b->curr_buf, true); b->curr_buf=Autoarr_create(int8,BL_C,BL_L); } @@ -34,9 +39,13 @@ StringBuilder* StringBuilder_create(){ 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){ - if(b->compl_bufs) Autoarr_free(b->compl_bufs); - Autoarr_free(b->curr_buf); + __StringBuilder_free(b); free(b); } diff --git a/src/String/StringBuilder.h b/src/String/StringBuilder.h index 8e19420..a5f13ef 100644 --- a/src/String/StringBuilder.h +++ b/src/String/StringBuilder.h @@ -8,14 +8,19 @@ extern "C" { #include "string.h" Autoarr_declare(string) +ktId_declare(AutoarrString); +ktId_declare(AutoarrStringPtr); typedef struct StringBuilder{ Autoarr(string)* compl_bufs; Autoarr(int8)* curr_buf; } StringBuilder; +ktId_declare(StringBuilder); +ktId_declare(StringBuilderPtr); StringBuilder* StringBuilder_create(void); void StringBuilder_free(StringBuilder* b); +void __StringBuilder_free(void* b); // Joins all strings from compl_bufs. // Returns zero-terminated string. // No need to call string_extract()! diff --git a/src/String/string.c b/src/String/string.c index 2926359..93c0ed9 100644 --- a/src/String/string.c +++ b/src/String/string.c @@ -1,5 +1,8 @@ #include "string.h" +ktId_define(string); +ktId_define(stringPtr); + // copies str content to new char pointer value (adding '\0' at the end) char* string_extract(string str){ if(str.length==0) return NULL; diff --git a/src/String/string.h b/src/String/string.h index e2076ee..caf5e73 100644 --- a/src/String/string.h +++ b/src/String/string.h @@ -12,6 +12,8 @@ typedef struct string{ char* ptr; // char pointer uint32 length; // amount of chars in ptr value } string; +ktId_declare(string); +ktId_declare(stringPtr); static const string stringNull={NULL,0}; diff --git a/src/base/base.h b/src/base/base.h index d49b6d7..7263d4b 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -5,10 +5,11 @@ extern "C" { #endif #include "std.h" -#include "types.h" #include "errors.h" #include "cptr.h" #include "optime.h" +#include "type_system/type_system.h" +#include "../kprint/kprintf.h" #if __cplusplus } diff --git a/src/base/cptr.c b/src/base/cptr.c index 22a6b36..0086edd 100644 --- a/src/base/cptr.c +++ b/src/base/cptr.c @@ -34,3 +34,56 @@ char* char_multiply(char c, uint32 n){ rez[n]=c; return rez; } + +bool cptr_startsWith(char* ptr, char* fragment){ + for(char cs=*ptr, cf=*fragment; cf; cs=*++ptr, cf=*++fragment) + if(cs!=cf) return false; + return true; +} + +bool cptr_endsWith(char* ptr, char* fragment){ + ptr+=cptr_length(ptr)-cptr_length(fragment); + for(char cs=*ptr, cf=*fragment; cf; cs=*++ptr, cf=*++fragment) + if(cs!=cf) return false; + return true; +} + +void memcopy(void* from, void* to, uint32 size){ + if(from==NULL || to==NULL) + throw(ERR_NULLPTR); + for(uint32 i=0; i #include #include +#include #include #include #include +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +typedef float float32; +typedef double float64; -#define dbg(N) printf("\e[95m%d\n",N) - +#define dbg(N) kprintf("\e[95m%d\n",N) #ifdef _MSC_VER #pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK @@ -29,13 +39,12 @@ extern "C" { #define CALL #endif #ifndef typeof - #define typeof __typeof__ + #define typeof(X) __typeof__(X) #endif #else #pragma GCC error "unknown compiler" #endif - #ifdef _MSC_VER #define IFWIN(YES, NO) YES #define IFMSC(YES, NO) YES @@ -49,6 +58,23 @@ extern "C" { #pragma GCC error "unknown compiler" #endif +#ifndef sprintf_s + #define sprintf_s(BUF, BUFSIZE, FORMAT, ...) sprintf(BUF, FORMAT, ## __VA_ARGS__) +#endif + + +#define __count_args(\ + a0, a1, a2, a3, a4, a5, a6, a7,\ + a8, a9, a10,a11,a12,a13,a14,a15,\ + a16,a17,a18,a19,a20,a21,a22,a23,\ + a24,a25,a26,a27,a28,a29,a30,a31,\ + a32,...) a32 +#define count_args(ARGS...) __count_args(\ + ARGS,\ + 32,31,30,29,28,27,26,25,\ + 24,23,22,21,20,19,18,17,\ + 16,15,14,13,12,11,10,9,\ + 8, 7, 6, 5, 4, 3, 2, 1, 0) #if __cplusplus } diff --git a/src/base/type_system/README.md b/src/base/type_system/README.md new file mode 100644 index 0000000..356cd5d --- /dev/null +++ b/src/base/type_system/README.md @@ -0,0 +1,32 @@ +# kerep type system + +For using some kerep capabilities, such as generic structs, unitype, and kprint, types should be *registered*. + +## type id + +Every registered type has its own id (`ktId`), which should be declared in header file and defined in source file. +Example: +```c +//someStruct.h +typedef struct { } someStruct; +ktId_declare(someStruct); +ktId_declare(someStructPtr); // pointer to type is another type +``` +```c +//someStruct.c +ktId_define(someStruct); +ktId_define(someStructPtr); +``` + +## type descriptors + +Every registered type should have it's own descriptor (`ktDescriptor`). It's a struct, which contains some information about type and pointers to some specific functions for this type (`toString`, `freeMembers`). + +## type registration + +To finally register a type, you should call macro `kt_register()` between `ktDescriptors_beginInit()` and `ktDescriptors_endInit()`. Better do it at the start of your program. To register all types from kerep, call `ktDescriptors_initKerepTypes()`. + +You can free internal ktDescriptors storage by calling `ktDescriptors_free()` at exit, if your debugger (valgrind in my case) sees a memory leak. +Examples: ++ [ktDescriptors_initKerepTypes()](src/base/type_system/init.c) ++ [kerep types registration](tests/main.cpp) diff --git a/src/base/type_system/base_toString.c b/src/base/type_system/base_toString.c new file mode 100644 index 0000000..02be90f --- /dev/null +++ b/src/base/type_system/base_toString.c @@ -0,0 +1,186 @@ +#include "base_toString.h" +#include "../base.h" +#include "../../kprint/kprint_format.h" + +char* __toString_char(void* c, uint32 fmt) { + char* cc=malloc(2); + cc[0]=*(char*)c; + cc[1]=0; + return cc; +} + +char* __toString_charPtr(void* c, uint32 fmt){ + return cptr_copy(*(char**)c); +} + +char* __toString_bool(void* c, uint32 fmt) { + static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" }; + uint8 strind=*(bool*)c==1 + kprint_format_uppercase(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_int(int64 n){ + int64 d=n; + char str[32]; + uint8 i=sizeof(str); + str[--i]=0; + while(d!=0){ + str[--i]='0' + d%10; + d/=10; + } + if(n>>63) + str[--i]='-'; + return cptr_copy((char*)str+i); +} + +char* toString_uint(uint64 n, bool withPostfix, bool uppercase){ + uint64 d=n; + char str[32]; + uint8 i=sizeof(str); + str[--i]=0; + if(withPostfix) + str[--i]= uppercase ? 'U' : 'u'; + while(d!=0){ + str[--i]='0' + d%10; + d/=10; + } + return cptr_copy((char*)str+i); +} + +char* toString_float(float64 n, bool withPostfix, bool uppercase){ + // int64 d=n; + // float64 r=n-d; + // char* strint=toString_int(d); + // char strfract[32]; + // uint8 i=0; + // strfract[i++]='.'; + // while(r!=0){ + // r*=10.0; + // char fc=r; + // strfract[i++]=fc; + // r-=fc; + // } + // if(withPostfix) + // strfract[i++]= uppercase ? 'F' : 'f'; + // strfract[i]=0; + // char* str==cptr_concat(strint, strfract); + // free(strint); + // return str; + return cptr_copy(""); +} + +char* toString_bin(void* _bytes, uint32 size, bool withPrefix){ + char* bytes=_bytes; + char* str=malloc(size*8 + (withPrefix?2:0) +1); + uint32 cn=0; + if(withPrefix){ + str[cn++]='0'; + str[cn++]='b'; + } + for(uint32 bn=0; bn>i); + } + str[cn]=0; + return str; +} + +char _4bitsHex(uint8 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, uint32 size, bool withPrefix, bool uppercase){ + char* bytes=_bytes; + char* str=malloc(size*2 + (withPrefix?2:0) + 1); + uint32 cn=0; + if(withPrefix){ + str[cn++]='0'; + str[cn++]='x'; + } + for(uint32 bn=0; bnfunctions->freear=__Autoarr_free_Unitype_; + Autoarr_free(_uar, true); + + // SearchTreeNode + kt_register(STNode, ktId_STNode, __STNode_free, NULL); + kt_register(STNode*, ktId_STNodePtr, __STNode_free, NULL); + + // KeyValuePair + kt_register(KVPair, ktId_KVPair, __KVPair_free, NULL); + kt_register(KVPair*, ktId_KVPairPtr, __KVPair_free, NULL); + kt_register(Autoarr_KVPair, ktId_AutoarrKVPair, ____Autoarr_free_KVPair_, NULL); + kt_register(Autoarr_KVPair*, ktId_AutoarrKVPairPtr, ____Autoarr_free_KVPair_, NULL); + // replacing autogenerated freear() function to custom + Autoarr_KVPair* _kvpar=Autoarr_create(KVPair, 1, 1); + _kvpar->functions->freear=__Autoarr_free_KVPair_; + Autoarr_free(_kvpar, true); + + // Hashtable + kt_register(Hashtable, ktId_Hashtable, __Hashtable_free, NULL); + kt_register(Hashtable*, ktId_HashtablePtr, __Hashtable_free, NULL); + + // string + kt_register(string, ktId_string, NULL, NULL); + kt_register(string*, ktId_stringPtr, NULL, NULL); + kt_register(string, ktId_AutoarrString, ____Autoarr_free_string, NULL); + kt_register(string*, ktId_AutoarrStringPtr, ____Autoarr_free_string, NULL); + // StringBuilder + kt_register(StringBuilder, ktId_StringBuilder, __StringBuilder_free, NULL); + kt_register(StringBuilder*, ktId_StringBuilderPtr, __StringBuilder_free, NULL); +} diff --git a/src/base/type_system/init.h b/src/base/type_system/init.h new file mode 100644 index 0000000..d08ef9d --- /dev/null +++ b/src/base/type_system/init.h @@ -0,0 +1,12 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +// call this between ktDescriptors_beginInit() and ktDescriptors_endInit() +void ktDescriptors_initKerepTypes(); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/base/type_system/ktDescriptor.h b/src/base/type_system/ktDescriptor.h new file mode 100644 index 0000000..a12facb --- /dev/null +++ b/src/base/type_system/ktDescriptor.h @@ -0,0 +1,20 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../std.h" +#include "ktId.h" + +typedef struct ktDescriptor{ + char* name; + ktId id; + uint16 size; + void (*freeMembers)(void*); // NULL or function which frees all struct members + char* (*toString)(void* obj, uint32 fmt); // NULL or function which generates string representaion of object +} ktDescriptor; + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/base/type_system/ktId.h b/src/base/type_system/ktId.h new file mode 100644 index 0000000..63f7847 --- /dev/null +++ b/src/base/type_system/ktId.h @@ -0,0 +1,17 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../std.h" +typedef uint16 ktId; + +#define ktId_declare(TYPE_NAME)\ + extern ktId ktId_##TYPE_NAME +#define ktId_define(TYPE_NAME)\ + ktId ktId_##TYPE_NAME=-1 + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/base/type_system/kt_functions.c b/src/base/type_system/kt_functions.c new file mode 100644 index 0000000..fa4a26d --- /dev/null +++ b/src/base/type_system/kt_functions.c @@ -0,0 +1,82 @@ +#include "../../Autoarr/Autoarr.h" + +Autoarr_declare(ktDescriptor) +Autoarr_define(ktDescriptor) + +ktId_define(Null); + +ktId_define(Char); +ktId_define(Bool); +ktId_define(Float32); +ktId_define(Float64); +ktId_define(Int8); +ktId_define(UInt8); +ktId_define(Int16); +ktId_define(UInt16); +ktId_define(Int32); +ktId_define(UInt32); +ktId_define(Int64); +ktId_define(UInt64); + +ktId_define(CharPtr); +ktId_define(BoolPtr); +ktId_define(Float32Ptr); +ktId_define(Float64Ptr); +ktId_define(Int8Ptr); +ktId_define(UInt8Ptr); +ktId_define(Int16Ptr); +ktId_define(UInt16Ptr); +ktId_define(Int32Ptr); +ktId_define(UInt32Ptr); +ktId_define(Int64Ptr); +ktId_define(UInt64Ptr); + +ktId_define(ktDescriptor); +ktId_define(ktDescriptorPtr); + +// type descriptors are stored here during initialization +Autoarr(ktDescriptor)* __ktDescriptors=NULL; +// here type descriptors are stored when initialization is complited +ktDescriptor* typeDescriptors=NULL; +ktId ktId_last=-1; + +typedef enum{ + NotInitialized, Initializing, Initialized +} ktDescriptorsState; +ktDescriptorsState initState=NotInitialized; + +void ktDescriptors_beginInit(){ + kprintf("\e[94mtype descriptors initializing...\n"); + __ktDescriptors=Autoarr_create(ktDescriptor, 256, 256); + if(__ktDescriptors==NULL) throw(ERR_NULLPTR); +} + +void ktDescriptors_endInit(){ + typeDescriptors=Autoarr_toArray(__ktDescriptors); + Autoarr_free(__ktDescriptors,true); + if(typeDescriptors==NULL) throw(ERR_NULLPTR); + kprintf("\e[92minitialized %u type descriptors\n", ktId_last); +} + +void __kt_register(char* name, int16 size, void (*freeMembers)(void*), char* (*toString)(void*, uint32)){ + ktDescriptor typeDesc={ + .name=name, + .size=size, + .id=++ktId_last, + .freeMembers=freeMembers, + .toString=toString + }; + Autoarr_add(__ktDescriptors, typeDesc); +} + +ktDescriptor ktDescriptor_get(ktId id){ + if(id>ktId_last) { + kprintf("\ntype id: %u\n",id); + throw("invalid type id"); + } + return typeDescriptors[id]; +} + +void ktDescriptors_free(){ + free(typeDescriptors); +} diff --git a/src/base/type_system/kt_functions.h b/src/base/type_system/kt_functions.h new file mode 100644 index 0000000..cf27d3e --- /dev/null +++ b/src/base/type_system/kt_functions.h @@ -0,0 +1,60 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../std.h" +#include "ktId.h" +#include "ktDescriptor.h" + +extern ktId ktId_last; +void __kt_register(char* name, int16 size, void (*freeMembers)(void*), char* (*toString)(void*, uint32)); + +#define kt_register(TYPE, ID_VAR_NAME, FREE_MEMBERS_FUNC, TO_STRING_FUNC)\ + __kt_register(#ID_VAR_NAME, sizeof(TYPE), FREE_MEMBERS_FUNC, TO_STRING_FUNC);\ + ID_VAR_NAME=ktId_last; + +void ktDescriptors_beginInit(); +void ktDescriptors_endInit(); + +/// @param id id of registered type +ktDescriptor ktDescriptor_get(ktId id); + +// call it to free heap-allocated ktDescriptors array +void ktDescriptors_free(); + +ktId_declare(Null); + +ktId_declare(Char); +ktId_declare(Bool); +ktId_declare(Float32); +ktId_declare(Float64); +ktId_declare(Int8); +ktId_declare(UInt8); +ktId_declare(Int16); +ktId_declare(UInt16); +ktId_declare(Int32); +ktId_declare(UInt32); +ktId_declare(Int64); +ktId_declare(UInt64); + +ktId_declare(CharPtr); +ktId_declare(BoolPtr); +ktId_declare(Float32Ptr); +ktId_declare(Float64Ptr); +ktId_declare(Int8Ptr); +ktId_declare(UInt8Ptr); +ktId_declare(Int16Ptr); +ktId_declare(UInt16Ptr); +ktId_declare(Int32Ptr); +ktId_declare(UInt32Ptr); +ktId_declare(Int64Ptr); +ktId_declare(UInt64Ptr); + +ktId_declare(ktDescriptor); +ktId_declare(ktDescriptorPtr); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/base/type_system/type_system.h b/src/base/type_system/type_system.h new file mode 100644 index 0000000..2c20ac0 --- /dev/null +++ b/src/base/type_system/type_system.h @@ -0,0 +1,5 @@ +#include "init.h" +#include "ktId.h" +#include "ktDescriptor.h" +#include "kt_functions.h" +#include "unitype.h" diff --git a/src/base/type_system/unitype.c b/src/base/type_system/unitype.c new file mode 100644 index 0000000..59892fb --- /dev/null +++ b/src/base/type_system/unitype.c @@ -0,0 +1,53 @@ +#include "../base.h" + +ktId_define(Unitype); +ktId_define(UnitypePtr); + +void Unitype_free(Unitype u){ + 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* toString_Unitype(void* _u, uint32 fmt){ + Unitype* u=_u; + ktDescriptor type=ktDescriptor_get(u->typeId); + char* valuestr=type.toString(_u, fmt); + char* rezult=cptr_concat("{ type: ", type.name, + ", allocated on heap: ", (u->allocatedInHeap ? "true" : "false"), + ", value:", valuestr, " }"); + free(valuestr); + return rezult; +} + + + +#define BUFSIZE 64 +char* sprintuni(Unitype v){ + char* buf=malloc(BUFSIZE); + ktDescriptor type=ktDescriptor_get(v.typeId); + if(v.typeId==ktId_Null) + sprintf_s(buf, BUFSIZE, "{Null}"); + else if(v.typeId==ktId_Float64) + sprintf_s(buf, BUFSIZE, "{%s : %lf}", type.name,v.Float64); + else if(v.typeId==ktId_Bool || v.typeId==ktId_UInt64) + sprintf_s(buf, BUFSIZE, "{%s : " IFWIN("%llu", "%lu") "}", type.name,v.UInt64); + else if(v.typeId==ktId_Int64) + sprintf_s(buf, BUFSIZE, "{%s : " IFWIN("%lld", "%ld") "}", type.name,v.Int64); + else if(v.typeId==ktId_CharPtr){ + size_t newBUFSIZE=cptr_length(v.VoidPtr) + BUFSIZE/2; + buf=realloc(buf, newBUFSIZE); + sprintf_s(buf, BUFSIZE, "{%s : \"%s\"}", type.name,(char*)v.VoidPtr); + } + else sprintf_s(buf, BUFSIZE, "{%s : %p}", type.name,v.VoidPtr); + return buf; +} + +void printuni(Unitype v){ + char* s=sprintuni(v); + fputs(s, stdout); + free(s); +} \ No newline at end of file diff --git a/src/base/type_system/unitype.h b/src/base/type_system/unitype.h new file mode 100644 index 0000000..666ee3e --- /dev/null +++ b/src/base/type_system/unitype.h @@ -0,0 +1,50 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "ktId.h" + +typedef struct Unitype{ + union { + int64 Int64; + uint64 UInt64; + double Float64; + bool Bool; + void* VoidPtr; + char Bytes[8]; + }; + ktId typeId; + bool allocatedInHeap; // should Unitype_free call free() to VoidPtr* +} Unitype; +ktId_declare(Unitype); +ktId_declare(UnitypePtr); + + +#define __UniDef(TYPE, VAL) (Unitype){\ + .TYPE=VAL, .typeId=ktId_##TYPE, .allocatedInHeap=false} + +#define UniInt64(VAL) __UniDef(Int64, VAL) +#define UniUInt64(VAL) __UniDef(UInt64, VAL) +#define UniFloat64(VAL) __UniDef(Float64, VAL) +#define UniBool(VAL) __UniDef(Bool, VAL) + +#define UniStack(ID_VAR_NAME, VAL) (Unitype){\ + .VoidPtr=VAL, .typeId=ID_VAR_NAME, .allocatedInHeap=false} +#define UniHeap(ID_VAR_NAME, VAL) (Unitype){\ + .VoidPtr=VAL, .typeId=ID_VAR_NAME, .allocatedInHeap=true} + +#define UniNull UniStack(ktId_Null, NULL) +#define UniTrue UniBool(true) +#define UniFalse UniBool(false) + +// frees VoidPtr value or does nothing if type isn't pointer +void Unitype_free(Unitype u); +void __UnitypePtr_free(void* u); +void printuni(Unitype v); +char* sprintuni(Unitype v); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/base/types.c b/src/base/types.c deleted file mode 100644 index fed1f0b..0000000 --- a/src/base/types.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "types.h" -#include "errors.h" -#include "../Autoarr/Autoarr.h" -#include "../Hashtable/Hashtable.h" -#include "../SearchTree/SearchTree.h" - -const char* my_type_name(my_type t){ - switch (t) { - case Null: return "Null"; - case Float64: return "Float64"; - case Float32: return "Float32"; - case Bool: return "Bool"; - case Char: return "Char"; - case Int8: return "Int8"; - case UInt8: return "UInt8"; - case Int16: return "Int16"; - case UInt16: return "UInt16"; - case Int32: return "Int32"; - case UInt32: return "UInt32"; - case Int64: return "Int64"; - case UInt64: return "UInt64"; - case Int8Ptr: return "Int8Ptr"; - case UInt8Ptr: return "UInt8Ptr"; - case Int16Ptr: return "Int16Ptr"; - case UInt16Ptr: return "UInt16Ptr"; - case Int32Ptr: return "Int32Ptr"; - case UInt32Ptr: return "UInt32Ptr"; - case Int64Ptr: return "Int64Ptr"; - case UInt64Ptr: return "UInt64Ptr"; - case CharPtr: return "CharPtr"; - case STNodePtr: return "STNodePtr"; - case HashtablePtr: return "HashtablePtr"; - case UniversalType: return "Unitype"; - case AutoarrInt8Ptr: return "AutoarrInt8Ptr"; - case AutoarrUInt8Ptr: return "AutoarrUInt8Ptr"; - case AutoarrInt16Ptr: return "AutoarrInt16Ptr"; - case AutoarrUInt16Ptr: return "AutoarrUInt16Ptr"; - case AutoarrInt32Ptr: return "AutoarrInt32Ptr"; - case AutoarrUInt32Ptr: return "AutoarrUInt32Ptr"; - case AutoarrInt64Ptr: return "AutoarrInt64Ptr"; - case AutoarrUInt64Ptr: return "AutoarrUInt64Ptr"; - case AutoarrUnitypePtr: return "AutoarrUnitypePtr"; - case AutoarrKVPairPtr: return "AutoarrKVPairPtr"; - default: throw(ERR_WRONGTYPE); - } -} - -// frees VoidPtr value or does nothing if type isn't pointer -void Unitype_free(Unitype u){ - switch (u.type) { - case Null: - case Float32: - case Float64: - case Char: - case Bool: - case Int8: - case UInt8: - case Int16: - case UInt16: - case Int32: - case UInt32: - case Int64: - case UInt64: - break; - case Int8Ptr: - case UInt8Ptr: - case Int16Ptr: - case UInt16Ptr: - case Int32Ptr: - case UInt32Ptr: - case Int64Ptr: - case UInt64Ptr: - case CharPtr: - free(u.VoidPtr); - break; - case HashtablePtr: - Hashtable_free(u.VoidPtr); - break; - case STNodePtr: - STNode_free(u.VoidPtr); - break; - case AutoarrInt8Ptr: - __Autoarr_free_int8(u.VoidPtr); - break; - case AutoarrUInt8Ptr: - __Autoarr_free_uint8(u.VoidPtr); - break; - case AutoarrInt16Ptr: - __Autoarr_free_int16(u.VoidPtr); - break; - case AutoarrUInt16Ptr: - __Autoarr_free_uint16(u.VoidPtr); - break; - case AutoarrInt32Ptr: - __Autoarr_free_int32(u.VoidPtr); - break; - case AutoarrUInt32Ptr: - __Autoarr_free_uint32(u.VoidPtr); - break; - case AutoarrInt64Ptr: - __Autoarr_free_int64(u.VoidPtr); - break; - case AutoarrUInt64Ptr: - __Autoarr_free_uint64(u.VoidPtr); - break; - case AutoarrUnitypePtr: - Autoarr_free_Unitype(u.VoidPtr); - break; - case AutoarrKVPairPtr: - Autoarr_free_KVPair(u.VoidPtr); - break; - default: throw(ERR_WRONGTYPE); - } -} - -#define BUFSIZE 64 -char* sprintuni(Unitype v){ - char* buf=malloc(BUFSIZE); - IFMSC( - switch (v.type) { - case Null: sprintf_s(buf, BUFSIZE, "{Null}");break; - case Float64: sprintf_s(buf, BUFSIZE, "{%s : %lf}", my_type_name(v.type),v.Float64);break; - case Bool: - case UInt64: sprintf_s(buf, BUFSIZE, "{%s : %lu}", my_type_name(v.type),v.UInt64);break; - case Int64: sprintf_s(buf, BUFSIZE, "{%s : %ld}", my_type_name(v.type),v.Int64);break; - case CharPtr: ; - size_t newBUFSIZE=cptr_length(v.VoidPtr) + BUFSIZE/2; - buf=realloc(buf, newBUFSIZE); - sprintf_s(buf, newBUFSIZE, "{%s : \"%s\"}", my_type_name(v.type),(char*)v.VoidPtr); - break; - default: sprintf_s(buf, BUFSIZE, "{%s : %p}", my_type_name(v.type),v.VoidPtr);break; - }, - switch (v.type) { - case Null: sprintf(buf, "{Null}"); break; - case Float64: sprintf(buf, "{%s : %lf}", my_type_name(v.type),v.Float64); break; - case Bool: - case UInt64: sprintf(buf, "{%s : " IFWIN("%llu", "%lu") "}", my_type_name(v.type),v.UInt64); break; - case Int64: sprintf(buf, "{%s : " IFWIN("%lld", "%ld") "}", my_type_name(v.type),v.Int64); break; - case CharPtr: ; - size_t newBUFSIZE=cptr_length(v.VoidPtr) + BUFSIZE/2; - buf=realloc(buf, newBUFSIZE); - sprintf(buf, "{%s : \"%s\"}", my_type_name(v.type),(char*)v.VoidPtr); - break; - default: sprintf(buf, "{%s : %p}", my_type_name(v.type),v.VoidPtr);break; - } - ); - return buf; -} - -void printuni(Unitype v){ - char* s=sprintuni(v); - fputs(s, stdout); - free(s); -} \ No newline at end of file diff --git a/src/base/types.h b/src/base/types.h deleted file mode 100644 index e34d95f..0000000 --- a/src/base/types.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#if __cplusplus -extern "C" { -#endif - -#include "std.h" - -typedef int8_t int8; -typedef uint8_t uint8; -typedef int16_t int16; -typedef uint16_t uint16; -typedef int32_t int32; -typedef uint32_t uint32; -typedef int64_t int64; -typedef uint64_t uint64; -typedef float float32; -typedef double float64; -typedef enum __attribute__((__packed__)) my_type { - Null, Float32, Float64, Char, Bool, - UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, - UInt8Ptr, Int8Ptr, UInt16Ptr, Int16Ptr, UInt32Ptr, Int32Ptr, UInt64Ptr, Int64Ptr, - CharPtr, STNodePtr, HashtablePtr, - UniversalType, - AutoarrInt8Ptr, AutoarrUInt8Ptr, AutoarrInt16Ptr, AutoarrUInt16Ptr, - AutoarrInt32Ptr, AutoarrUInt32Ptr, AutoarrInt64Ptr, AutoarrUInt64Ptr, - AutoarrUnitypePtr, AutoarrKVPairPtr, knSocketPtr -} my_type; -#define my_type_last knSocketPtr - -const char* my_type_name(my_type t); - -typedef struct Unitype{ - union { - int64 Int64; - uint64 UInt64; - double Float64; - bool Bool; - void* VoidPtr; - }; - my_type type; -} Unitype; - -static const Unitype UniNull={.VoidPtr=NULL,.type=Null}; -static const Unitype UniTrue={.Bool=true,.type=Bool}; -static const Unitype UniFalse={.Bool=false,.type=Bool}; - -#define Uni(TYPE,VAL) (Unitype){.type=TYPE,.TYPE=VAL} -#define UniPtr(TYPE,VAL) (Unitype){.type=TYPE,.VoidPtr=VAL} - -// frees VoidPtr value or does nothing if type isn't pointer -void Unitype_free(Unitype u); -void printuni(Unitype v); -char* sprintuni(Unitype v); - -#if __cplusplus -} -#endif \ No newline at end of file diff --git a/src/kprint/README.md b/src/kprint/README.md new file mode 100644 index 0000000..c59a66e --- /dev/null +++ b/src/kprint/README.md @@ -0,0 +1,36 @@ +# kprintf +It is just my variant of printf. + +# kprint +I don't really like printf function (and its variants), so i made safer and more convinient replacement. + +| function | returns | arguments | +|----------|---------|-----------| +| kprint | void/throw | kprint_format, void*, kprint_format, void*... | +| ksprint | Maybe | kprint_format, void*, kprint_format, void*... | +| kfprint | Maybe | FILE*, kprint_format, void*, kprint_format, void*... | + +## how to use it: ++ **format construction:** + ``` + kprint_format fmt= kprint_fgColor | kprint_bgColor | kprint_fdataFmt | flags | ktId; + ``` + [more about `kprint_format`](kprint_format.md) + + fgColor and bgColor can be set to change console output color + + you should set dataFormat for `int`/`uint`/`float`/`char*` arguments and ktId for other types + + flags can be set to modify TypeDescriptor.toString() behavior + + don't forget to set TypeDescriptor.toString when registering type, or kprint will crash + ++ **using base type arguments:** + you can just put them into a function + ``` + kprint(kprint_fmtHex | kprint_fmtUppercase | kprint_fmtWithPrefix, 255); + ``` + output: 0xFF ++ **using other registered types:** + should be sent as pointers + ``` + Maybe m=MaybeNull; + kprint(kprint_fgBlue | kprint_fmtString, "Maybe: ", kprint_fgGreen | ktId_MaybePtr, &m); + ``` + output: Maybe: {value={0, ktId_Null}} \ No newline at end of file diff --git a/src/kprint/kprint.c b/src/kprint/kprint.c new file mode 100644 index 0000000..97186fb --- /dev/null +++ b/src/kprint/kprint.c @@ -0,0 +1,168 @@ +#include "../String/StringBuilder.h" +#include "kprint.h" + +ktId __typeFromFormat(kprint_format f){ + ktId typeId=kprint_format_ktId(f); + if(typeId) + return typeId; + switch(kprint_format_dataFormat(f)){ + case kprint_fmtInt: + case kprint_fmtHex: + case kprint_fmtBin: + return ktId_Int64; + case kprint_fmtUInt: + return ktId_UInt64; + case kprint_fmtFloat: + return ktId_Float64; + case kprint_fmtChar: + return ktId_Char; + case kprint_fmtString: + return ktId_CharPtr; + default: + return -1; + } +} + +Maybe __next_toString(kprint_format f, __kprint_value_union* object){ + // detecting type + ktId typeId=__typeFromFormat(f); + if(typeId==-1) + safethrow("typeId is not set, can't autodetect type",;); + ktDescriptor typeDesc=ktDescriptor_get(typeId); + if(!typeDesc.toString) + safethrow("type descriptor doesnt have toString() func",;); + return SUCCESS(UniHeap(ktId_CharPtr, typeDesc.toString(object, f))); +} + +Maybe __ksprint(uint8 n, kprint_format* formats, __kprint_value_union* objects){ + n/=2; + StringBuilder* strb=StringBuilder_create(); + for(uint8 i=0; i +#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED + +DWORD kprint_fgColor_toWin(kprint_fgColor f){ + //kprintf("fg: %x\n", f); + switch(f){ + case kprint_fgBlack: return 0; + case kprint_fgDarkRed: return FOREGROUND_RED; + case kprint_fgDarkGreen: return FOREGROUND_GREEN; + case kprint_fgDarkYellow: return FOREGROUND_GREEN | FOREGROUND_RED; + case kprint_fgDarkBlue: return FOREGROUND_BLUE; + case kprint_fgDarkMagenta: return FOREGROUND_RED | FOREGROUND_BLUE; + case kprint_fgDarkCyan: return FOREGROUND_BLUE | FOREGROUND_GREEN; + case kprint_fgGray: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + case kprint_fgDarkGray: return FOREGROUND_INTENSITY; + case kprint_fgRed: return FOREGROUND_RED | FOREGROUND_INTENSITY; + case kprint_fgGreen: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case kprint_fgYellow: return FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + case kprint_fgBlue: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; + case kprint_fgMagenta: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; + case kprint_fgCyan: return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case kprint_fgWhite: return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + default: throw(ERR_FORMAT); + } +} + +DWORD kprint_bgColor_toWin(kprint_bgColor f){ + //kprintf("bg: %x\n", f); + switch(f){ + case kprint_bgBlack: return 0; + case kprint_bgDarkRed: return BACKGROUND_RED; + case kprint_bgDarkGreen: return BACKGROUND_GREEN; + case kprint_bgDarkYellow: return BACKGROUND_GREEN | BACKGROUND_RED; + case kprint_bgDarkBlue: return BACKGROUND_BLUE; + case kprint_bgDarkMagenta: return BACKGROUND_RED | BACKGROUND_BLUE; + case kprint_bgDarkCyan: return BACKGROUND_BLUE | BACKGROUND_GREEN; + case kprint_bgGray: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; + case kprint_bgDarkGray: return BACKGROUND_INTENSITY; + case kprint_bgRed: return BACKGROUND_RED | BACKGROUND_INTENSITY; + case kprint_bgGreen: return BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case kprint_bgYellow: return BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + case kprint_bgBlue: return BACKGROUND_BLUE | BACKGROUND_INTENSITY; + case kprint_bgMagenta: return BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY; + case kprint_bgCyan: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + case kprint_bgWhite: return BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + default: throw(ERR_FORMAT); + } +} + +void kprint_setColor(kprint_format f){ + DWORD color=0; + if(!kprint_format_fgColorChanged(f) & !kprint_format_bgColorChanged(f)) + return; + if(kprint_format_fgColorChanged(f)) + color+=kprint_fgColor_toWin(kprint_format_fgColor(f)); + if(kprint_format_bgColorChanged(f)) + color+=kprint_bgColor_toWin(kprint_format_bgColor(f)); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, color); +} +#else +void kprint_setColor(kprint_format f){ + if(kprint_format_fgColorChanged(f)){ + uint8 fg=(f&0x0f000000)>>24; + if(fg<8) fg+=30; + else fg+=90-8; + printf("\e[%um", fg); + } + if(kprint_format_bgColorChanged(f)){ + uint8 bg=(f&0x00f00000)>>20; + if(bg<8) bg+=40; + else bg+=100-8; + printf("\e[%um", bg); + } +} +#endif + +/* Maybe ksprint_ar(uint32 count, kprint_format format, ktId typeId, void* array){ + ktDescriptor typeDesc=ktDescriptor_get(format.typeId); + if(!typeDesc.toString) + safethrow("type descriptor doesnt have toString() func",;); + StringBuilder* strb=StringBuilder_create(); + StringBuilder_append_char(strb, '['); + for (uint16 e=1; e + +WORD unixColorToWin(uint8 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); + uint32 i=0; + for(char c=format[i++]; c!=0; c=format[i++]){ + if(c=='%'){ + char* argstr=NULL; + c=format[i++]; + format_escape_seq: + switch (c) { + case 'u': + argstr=toString_uint(va_arg(vl, uint64),0,0); + break; + case 'i': case 'd': + argstr=toString_int(va_arg(vl, uint64)); + break; + case 'f': + argstr=toString_float(va_arg(vl, float64),0,0); + break; + case 'l': + if((c=format[i++])) + goto format_escape_seq; + break; + // switch (c) { + // case 'u': + // argstr=toString_uint(va_arg(vl, uint64),0,0); + // break; + // case 'i': + // argstr=toString_int(va_arg(vl, uint64)); + // break; + // case 'f': + // argstr=toString_float(va_arg(vl, float64),0,0); + // break; + // default: + // throw(ERR_FORMAT); + // } + // break; + case 'p': + case 'x': + uint64 px=va_arg(vl, uint64); + argstr=toString_hex(&px,sizeof(px),1,0); + break; + case 's': + char* cptr=va_arg(vl,char*); + if(!cptr) + cptr=""; + if(*cptr) + fputs(cptr, stdout); + break; + case 'c': + argstr=malloc(2); + argstr[0]=(char)va_arg(vl,int); + argstr[1]=0; + break; + default: + putc('\n',stdout); + putc('<',stdout); + putc(c,stdout); + putc('>',stdout); + throw(ERR_FORMAT); + } + if(argstr){ + fputs(argstr, stdout); + free(argstr); + } + } else if(c=='\e'){ + IFWIN( + ({ + if((c=format[i++])=='['){ + uint8 colorUnix=0; + for(int8 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; + } + } + } + }), + putc(c,stdout); + ); + } else { + putc(c,stdout); + } + #if defined(_WIN64) || defined(_WIN32) + end_iteration: + #endif + } + va_end(vl); +} diff --git a/src/kprint/kprintf.h b/src/kprint/kprintf.h new file mode 100644 index 0000000..0ca5a68 --- /dev/null +++ b/src/kprint/kprintf.h @@ -0,0 +1,12 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +// cross-platform kprintf analog +void kprintf(const char* format, ...); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/krandom.h b/src/random/krandom.h new file mode 100644 index 0000000..d78b7d6 --- /dev/null +++ b/src/random/krandom.h @@ -0,0 +1,72 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../base/std.h" +#include "splitmix64/splitmix64.h" +#include "xoroshiro/xoroshiro.h" +#include "xoshiro/xoshiro.h" + +/* +You can choose any algorithm that has required functions: + + some_alg32_statePtr some_alg32_init(uint32 seed); + uint32 some_alg32_next(some_alg32_statePtr); + void some_alg32_free(some_alg32_statePtr); + + #define KRAND_ALG32_init some_alg32_init + #define KRAND_ALG32_next some_alg32_next + #define KRAND_ALG32_free some_alg32_free + #include "kerep/random/krandom.h" + +The same way it works for 64-bit RNGs +*/ + +// default rng_next function +#ifndef KRAND_ALG32_next +#define KRAND_ALG32_next xoshiro128plus##_next +#endif +#ifndef KRAND_ALG32_init +#define KRAND_ALG32_init xoshiro128plus##_init +#endif +#ifndef KRAND_ALG32_free +#define KRAND_ALG32_free xoshiro128plus##_free +#endif +#ifndef KRAND_ALG64_next +#define KRAND_ALG64_next xoshiro256plus##_next +#endif +#ifndef KRAND_ALG64_init +#define KRAND_ALG64_init xoshiro256plus##_init +#endif +#ifndef KRAND_ALG64_free +#define KRAND_ALG64_free xoshiro256plus##_free +#endif + +typedef void* krand_statePtr; +#define KRAND_ALG32_initFromTime xoshiro128plus##_initFromTime +#define KRAND_ALG64_initFromTime xoshiro256plus##_initFromTime + +#define __krand_next_definition(VALUE_SIZE) { return from+KRAND_ALG##VALUE_SIZE##_next(state)%(to-from); } + +// ready-to-use functions +static inline int8 krand_next8 (krand_statePtr state, int8 from, int8 to) __krand_next_definition(32) +static inline int16 krand_next16(krand_statePtr state, int16 from, int16 to) __krand_next_definition(32) +static inline int32 krand_next32(krand_statePtr state, int32 from, int32 to) __krand_next_definition(32) +static inline int64 krand_next64(krand_statePtr state, int64 from, int64 to) __krand_next_definition(64) + +// divides random number by 2^64 to return a value between 0 and 1 +static inline float32 krand_nextFloat32(krand_statePtr state) {return (uint32)KRAND_ALG32_next(state)/0xffffffff; } +static inline float64 krand_nextFloat64(krand_statePtr state) {return KRAND_ALG64_next(state)/0xffffffff; } + + +///@param chance (0-1.0) is probability of success +static inline bool fate(krand_statePtr state,float chance){ + int limit=1/chance + 0.01f; + return KRAND_ALG32_next(state)%limit == 0; +} + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/splitmix64/splitmix64.c b/src/random/splitmix64/splitmix64.c new file mode 100644 index 0000000..591167c --- /dev/null +++ b/src/random/splitmix64/splitmix64.c @@ -0,0 +1,34 @@ +#include "splitmix64.h" + +/* +This is a fixed-increment version of Java 8's SplittableRandom generator +See http://dx.doi.org/10.1145/2714064.2660195 and +http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html +It is a very fast generator passing BigCrush, and it can be useful if +for some reason you absolutely want 64 bits of state; otherwise, we +rather suggest to use a xoroshiro128+ (for moderately parallel +computations) or xorshift1024* (for massively parallel computations) +generator. +*/ + +// The state can be seeded with any (upto) 64 bit integer value. + +void* splitmix64_init(uint64 seed){ + splitmix64_state* state=malloc(sizeof(splitmix64_state)); + *state=seed; + return state; +} + +uint64 splitmix64_next(void* _state) { + splitmix64_state* state=_state; + // increment the state variable + *state += 0x9e3779b97f4a7c15; + // copy the state to a working variable + uint64 z = *state; + // xor the variable with the variable right bit shifted 30 then multiply by a constant + z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9; + // xor the variable with the variable right bit shifted 27 then multiply by a constant + z = (z ^ (z>>27)) * 0x94d049bb133111eb; + // return the variable xored with itself right bit shifted 31 + return z ^ (z>>31); +} diff --git a/src/random/splitmix64/splitmix64.h b/src/random/splitmix64/splitmix64.h new file mode 100644 index 0000000..8cf8104 --- /dev/null +++ b/src/random/splitmix64/splitmix64.h @@ -0,0 +1,22 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../base/base.h" + +typedef uint64 splitmix64_state; +typedef void* splitmix64_statePtr; + +splitmix64_statePtr splitmix64_init(uint64 seed); +static inline splitmix64_statePtr splitmix64_initFromTime(void) { return splitmix64_init(time(NULL)); } + +uint64 splitmix64_next(splitmix64_statePtr); +static inline void splitmix64_free(splitmix64_statePtr state) { + free(state); +} + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/xoroshiro/32bitValue/xoroshiro64.h b/src/random/xoroshiro/32bitValue/xoroshiro64.h new file mode 100644 index 0000000..6377bba --- /dev/null +++ b/src/random/xoroshiro/32bitValue/xoroshiro64.h @@ -0,0 +1,35 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../../base/std.h" +#include "../../splitmix64/splitmix64.h" + +typedef union { + uint64 merged; + uint32 s[2]; +} xoroshiro64_state; +typedef void* xoroshiro64_statePtr; + +xoroshiro64_statePtr xoroshiro64_init(uint64 seed); +#define xoroshiro64star_init xoroshiro64_init +#define xoroshiro64starstar_init xoroshiro64_init + +static inline xoroshiro64_statePtr xoroshiro64_initFromTime(void) { return xoroshiro64_init(time(NULL)); } +#define xoroshiro64star_initFromTime xoroshiro64_initFromTime +#define xoroshiro64starstar_initFromTime xoroshiro64_initFromTime + +uint32 xoroshiro64star_next(xoroshiro64_statePtr); +uint32 xoroshiro64starstar_next(xoroshiro64_statePtr); + +static inline void xoroshiro64_free(xoroshiro64_statePtr state) { + free(state); +} +#define xoroshiro64star_free xoroshiro64_free +#define xoroshiro64starstar_free xoroshiro64_free + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/xoroshiro/32bitValue/xoroshiro64star.c b/src/random/xoroshiro/32bitValue/xoroshiro64star.c new file mode 100644 index 0000000..7c2fd3c --- /dev/null +++ b/src/random/xoroshiro/32bitValue/xoroshiro64star.c @@ -0,0 +1,49 @@ +/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro64.h" + +/* +This is xoroshiro64* 1.0, our best and fastest 32-bit small-state +generator for 32-bit floating-point numbers. We suggest to use its +upper bits for floating-point 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 uint32 rotl(const uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} + +uint32 xoroshiro64star_next(void* _state) { + xoroshiro64_state* state=_state; + const uint32 s0 = state->s[0]; + uint32 s1 = state->s[1]; + const uint32 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(uint64 seed){ + xoroshiro64_state* state=malloc(sizeof(xoroshiro64_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->merged=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c b/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c new file mode 100644 index 0000000..df4432e --- /dev/null +++ b/src/random/xoroshiro/32bitValue/xoroshiro64starstar.c @@ -0,0 +1,37 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro64.h" + +/* This is xoroshiro64** 1.0, our 32-bit all-purpose, rock-solid, + small-state generator. It is extremely fast and it passes all tests we + are aware of, but its state space is not large enough for any parallel + application. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoroshiro64* is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline uint32 rotl(const uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} + +uint32 xoroshiro64starstar_next(void* _state) { + xoroshiro64_state* state=_state; + const uint32 s0 = state->s[0]; + uint32 s1 = state->s[1]; + const uint32 result = rotl(s0 * 0x9E3779BB, 5) * 5; + + s1 ^= s0; + state->s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9); // a, b + state->s[1] = rotl(s1, 13); // c + + return result; +} diff --git a/src/random/xoroshiro/64bitValue/xoroshiro128.h b/src/random/xoroshiro/64bitValue/xoroshiro128.h new file mode 100644 index 0000000..63ed537 --- /dev/null +++ b/src/random/xoroshiro/64bitValue/xoroshiro128.h @@ -0,0 +1,39 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../../base/std.h" +#include "../../splitmix64/splitmix64.h" + + +typedef union { + uint32 s[2]; +} xoroshiro128_state; +typedef void* xoroshiro128_statePtr; + +xoroshiro128_statePtr xoroshiro128_init(uint64 seed); +#define xoroshiro128plus_init xoroshiro128_init +#define xoroshiro128plusplus_init xoroshiro128_init +#define xoroshiro128starstar_init xoroshiro128_init + +static inline xoroshiro128_statePtr xoroshiro128_initFromTime(void) { return xoroshiro128_init(time(NULL)); } +#define xoroshiro128plus_initFromTime xoroshiro128_initFromTime +#define xoroshiro128plusplus_initFromTime xoroshiro128_initFromTime +#define xoroshiro128starstar_initFromTime xoroshiro128_initFromTime + +uint64 xoroshiro128plus_next(xoroshiro128_statePtr); +uint64 xoroshiro128plusplus_next(xoroshiro128_statePtr); +uint64 xoroshiro128starstar_next(xoroshiro128_statePtr); + +static inline void xoroshiro128_free(xoroshiro128_statePtr state) { + free(state); +} +#define xoroshiro128plus_free xoroshiro128_free +#define xoroshiro128plusplus_free xoroshiro128_free +#define xoroshiro128starstar_free xoroshiro128_free + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/xoroshiro/64bitValue/xoroshiro128plus.c b/src/random/xoroshiro/64bitValue/xoroshiro128plus.c new file mode 100644 index 0000000..e01e0b5 --- /dev/null +++ b/src/random/xoroshiro/64bitValue/xoroshiro128plus.c @@ -0,0 +1,59 @@ +/* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128+ 1.0, our best and fastest small-state generator + for floating-point numbers, but its state space is large enough only + for mild parallelism. We suggest to use its upper bits for + floating-point 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 uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64 xoroshiro128plus_next(void* _state){ + xoroshiro128_state* state=_state; + const uint64 s0 = state->s[0]; + uint64 s1 = state->s[1]; + const uint64 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(uint64 seed){ + xoroshiro128_state* state=malloc(sizeof(xoroshiro128_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->s[0]=splitmix64_next(splitmix); + state->s[1]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c b/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c new file mode 100644 index 0000000..c01fb30 --- /dev/null +++ b/src/random/xoroshiro/64bitValue/xoroshiro128plusplus.c @@ -0,0 +1,39 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128++ 1.0, one of our all-purpose, rock-solid, + small-state generators. It is extremely (sub-ns) fast and it passes all + tests we are aware of, but its state space is large enough only for + mild parallelism. + + For generating just floating-point 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 uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64 xoroshiro128plusplus_next(void* _state){ + xoroshiro128_state* state=_state; + const uint64 s0 = state->s[0]; + uint64 s1 = state->s[1]; + const uint64 result = rotl(s0 + s1, 17) + s0; + + s1 ^= s0; + state->s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b + state->s[1] = rotl(s1, 28); // c + + return result; +} diff --git a/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c b/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c new file mode 100644 index 0000000..3e9ac72 --- /dev/null +++ b/src/random/xoroshiro/64bitValue/xoroshiro128starstar.c @@ -0,0 +1,39 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoroshiro128.h" + +/* This is xoroshiro128** 1.0, one of our all-purpose, rock-solid, + small-state generators. It is extremely (sub-ns) fast and it passes all + tests we are aware of, but its state space is large enough only for + mild parallelism. + + For generating just floating-point 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 uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64 xoroshiro128starstar_next(void* _state){ + xoroshiro128_state* state=_state; + const uint64 s0 = state->s[0]; + uint64 s1 = state->s[1]; + const uint64 result = rotl(s0 * 5, 7) * 9; + + s1 ^= s0; + state->s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + state->s[1] = rotl(s1, 37); // c + + return result; +} diff --git a/src/random/xoroshiro/xoroshiro.h b/src/random/xoroshiro/xoroshiro.h new file mode 100644 index 0000000..127c937 --- /dev/null +++ b/src/random/xoroshiro/xoroshiro.h @@ -0,0 +1,2 @@ +#include "32bitValue/xoroshiro64.h" +#include "64bitValue/xoroshiro128.h" diff --git a/src/random/xoshiro-xoroshiro.md b/src/random/xoshiro-xoroshiro.md new file mode 100644 index 0000000..269477c --- /dev/null +++ b/src/random/xoshiro-xoroshiro.md @@ -0,0 +1,24 @@ +# Xoshiro/Xoroshiro RNG algorithms +There are a bunch of versions of xoshiro/xoroshiro algorithms, which are created by [David Blackman and Sebastiano Vigna](https://prng.di.unimi.it/) + + +``` +xoroshiro +├── 32bitValue +| ├── xoroshiro64star.c +| └── xoroshiro64starstar.c +└── 64bitValue + ├── xoroshiro128plus.c + ├── xoroshiro128plusplus.c + └── xoroshiro128starstar.c + +xoshiro +├── 32bitValue +│ ├── xoshiro128plus.c +│ ├── xoshiro128plusplus.c +│ └── xoshiro128starstar.c +└── 64bitValue + ├── xoshiro256plus.c + ├── xoshiro256plusplus.c + └── xoshiro256starstar.c +``` diff --git a/src/random/xoshiro/32bitValue/xoshiro128.h b/src/random/xoshiro/32bitValue/xoshiro128.h new file mode 100644 index 0000000..02d52e8 --- /dev/null +++ b/src/random/xoshiro/32bitValue/xoshiro128.h @@ -0,0 +1,40 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../../base/std.h" +#include "../../splitmix64/splitmix64.h" + + +typedef union { + uint64 merged[2]; + uint32 s[4]; +} xoshiro128_state; +typedef void* xoshiro128_statePtr; + +xoshiro128_statePtr xoshiro128_init(uint64 seed); +#define xoshiro128plus_init xoshiro128_init +#define xoshiro128plusplus_init xoshiro128_init +#define xoshiro128starstar_init xoshiro128_init + +static inline xoshiro128_statePtr xoshiro128_initFromTime(void) { return xoshiro128_init(time(NULL)); } +#define xoshiro128plus_initFromTime xoshiro128_initFromTime +#define xoshiro128plusplus_initFromTime xoshiro128_initFromTime +#define xoshiro128starstar_initFromTime xoshiro128_initFromTime + +uint32 xoshiro128plus_next(xoshiro128_statePtr); +uint32 xoshiro128plusplus_next(xoshiro128_statePtr); +uint32 xoshiro128starstar_next(xoshiro128_statePtr); + +static inline void xoshiro128_free(xoshiro128_statePtr state) { + free(state); +} +#define xoshiro128plus_free xoshiro128_free +#define xoshiro128plusplus_free xoshiro128_free +#define xoshiro128starstar_free xoshiro128_free + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/xoshiro/32bitValue/xoshiro128plus.c b/src/random/xoshiro/32bitValue/xoshiro128plus.c new file mode 100644 index 0000000..8cafc8b --- /dev/null +++ b/src/random/xoshiro/32bitValue/xoshiro128plus.c @@ -0,0 +1,54 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128+ 1.0, our best and fastest 32-bit generator for 32-bit + floating-point numbers. We suggest to use its upper bits for + floating-point 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 uint32 rotl(const uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} + +uint32 xoshiro128plus_next(void* _state){ + xoshiro128_state* state=_state; + const uint32 result = state->s[0] + state->s[3]; + + const uint32 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(uint64 seed){ + xoshiro128_state* state=malloc(sizeof(xoshiro128_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->merged[0]=splitmix64_next(splitmix); + state->merged[1]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/src/random/xoshiro/32bitValue/xoshiro128plusplus.c b/src/random/xoshiro/32bitValue/xoshiro128plusplus.c new file mode 100644 index 0000000..e9be19d --- /dev/null +++ b/src/random/xoshiro/32bitValue/xoshiro128plusplus.c @@ -0,0 +1,42 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline uint32 rotl(const uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} + +uint32 xoshiro128plusplus_next(void* _state){ + xoshiro128_state* state=_state; + const uint32 result = rotl(state->s[0] + state->s[3], 7) + state->s[0]; + + const uint32 t = state->s[1] << 9; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 11); + + return result; +} diff --git a/src/random/xoshiro/32bitValue/xoshiro128starstar.c b/src/random/xoshiro/32bitValue/xoshiro128starstar.c new file mode 100644 index 0000000..40a53d2 --- /dev/null +++ b/src/random/xoshiro/32bitValue/xoshiro128starstar.c @@ -0,0 +1,45 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro128.h" + +/* This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + Note that version 1.0 had mistakenly state->s[0] instead of state->s[1] as state + word passed to the scrambler. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + +static inline uint32 rotl(const uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} + +uint32 xoshiro128starstar_next(void* _state){ + xoshiro128_state* state=_state; + const uint32 result = rotl(state->s[1] * 5, 7) * 9; + + const uint32 t = state->s[1] << 9; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 11); + + return result; +} diff --git a/src/random/xoshiro/64bitValue/xoshiro256.h b/src/random/xoshiro/64bitValue/xoshiro256.h new file mode 100644 index 0000000..479c6aa --- /dev/null +++ b/src/random/xoshiro/64bitValue/xoshiro256.h @@ -0,0 +1,39 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../../base/std.h" +#include "../../splitmix64/splitmix64.h" + + +typedef union { + uint64 s[4]; +} xoshiro256_state; +typedef void* xoshiro256_statePtr; + +xoshiro256_statePtr xoshiro256_init(uint64 seed); +#define xoshiro256plus_init xoshiro256_init +#define xoshiro256plusplus_init xoshiro256_init +#define xoshiro256starstar_init xoshiro256_init + +static inline xoshiro256_statePtr xoshiro256_initFromTime(void) { return xoshiro256_init(time(NULL)); } +#define xoshiro256plus_initFromTime xoshiro256_initFromTime +#define xoshiro256plusplus_initFromTime xoshiro256_initFromTime +#define xoshiro256starstar_initFromTime xoshiro256_initFromTime + +uint64 xoshiro256plus_next(xoshiro256_statePtr); +uint64 xoshiro256plusplus_next(xoshiro256_statePtr); +uint64 xoshiro256starstar_next(xoshiro256_statePtr); + +static inline void xoshiro256_free(xoshiro256_statePtr state) { + free(state); +} +#define xoshiro256plus_free xoshiro256_free +#define xoshiro256plusplus_free xoshiro256_free +#define xoshiro256starstar_free xoshiro256_free + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/random/xoshiro/64bitValue/xoshiro256plus.c b/src/random/xoshiro/64bitValue/xoshiro256plus.c new file mode 100644 index 0000000..066ef8a --- /dev/null +++ b/src/random/xoshiro/64bitValue/xoshiro256plus.c @@ -0,0 +1,58 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256+ 1.0, our best and fastest generator for floating-point + numbers. We suggest to use its upper bits for floating-point + generation, as it is slightly faster than xoshiro256++/xoshiro256**. It + passes all tests we are aware of except for the lowest three bits, + which might fail linearity tests (and just those), so if low linear + complexity is not considered an issue (as it is usually the case) it + can be used to generate 64-bit outputs, too. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + + +static inline uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64 xoshiro256plus_next(void* _state){ + xoshiro256_state* state=_state; + const uint64 result = state->s[0] + state->s[3]; + + const uint64 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(uint64 seed){ + xoshiro256_state* state=malloc(sizeof(xoshiro256_state)); + splitmix64_state* splitmix=splitmix64_init(seed); + state->s[0]=splitmix64_next(splitmix); + state->s[1]=splitmix64_next(splitmix); + state->s[2]=splitmix64_next(splitmix); + state->s[3]=splitmix64_next(splitmix); + splitmix64_free(splitmix); + return state; +} diff --git a/src/random/xoshiro/64bitValue/xoshiro256plusplus.c b/src/random/xoshiro/64bitValue/xoshiro256plusplus.c new file mode 100644 index 0000000..77ca943 --- /dev/null +++ b/src/random/xoshiro/64bitValue/xoshiro256plusplus.c @@ -0,0 +1,37 @@ +/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators. + It has excellent (sub-ns) speed, a state (256 bits) that is large + enough for any parallel application, and it passes all tests we are + aware of. + + For generating just floating-point 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 uint64 rotl(const uint64 x, int k) { + return (x << k) | (x>>(64 - k)); +} + +uint64 xoshiro256plusplus_next(void* _state) { + xoshiro256_state* state=_state; + const uint64 result=rotl(state->s[0] + state->s[3], 23) + state->s[0]; + const uint64 t=state->s[1] << 17; + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + state->s[2] ^= t; + state->s[3]=rotl(state->s[3], 45); + return result; +} diff --git a/src/random/xoshiro/64bitValue/xoshiro256starstar.c b/src/random/xoshiro/64bitValue/xoshiro256starstar.c new file mode 100644 index 0000000..7829096 --- /dev/null +++ b/src/random/xoshiro/64bitValue/xoshiro256starstar.c @@ -0,0 +1,42 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include "xoshiro256.h" + +/* This is xoshiro256** 1.0, one of our all-purpose, rock-solid + generators. It has excellent (sub-ns) speed, a state (256 bits) that is + large enough for any parallel application, and it passes all tests we + are aware of. + + For generating just floating-point 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 uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64 xoshiro256starstar_next(void* _state){ + xoshiro256_state* state=_state; + const uint64 result = rotl(state->s[1] * 5, 7) * 9; + + const uint64 t = state->s[1] << 17; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + + state->s[3] = rotl(state->s[3], 45); + + return result; +} diff --git a/src/random/xoshiro/xoshiro.h b/src/random/xoshiro/xoshiro.h new file mode 100644 index 0000000..121ed3a --- /dev/null +++ b/src/random/xoshiro/xoshiro.h @@ -0,0 +1,2 @@ +#include "32bitValue/xoshiro128.h" +#include "64bitValue/xoshiro256.h" diff --git a/tests/main.cpp b/tests/main.cpp index b68a42d..6338d3b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -5,17 +5,24 @@ void test_all(){ test_safethrow(); test_searchtree(); test_autoarr(); + test_autoarrVsVector(); test_hash_functions(); test_hashtable(); test_dtsod(); - test_network(); - printf("\e[96m--------------------------------------\e[0m\n"); + test_rng_algorithms(); + test_kprint_colors(); + kprintf("\e[96m--------------------------------------\e[0m\n"); } - int main(){ - setlocale(LC_ALL, "en-US.Unicode"); - printf("\e[92mkerep tests are starting!\e[97m\n"); - optime("test_all",1,test_all()); - printf("\e[0m\n"); + if(!setlocale(LC_ALL, "C.UTF8")) + kprintf("\e[93msetlocale failed\n"); + ktDescriptors_beginInit(); + ktDescriptors_initKerepTypes(); + ktDescriptors_endInit(); + kprintf("\e[97mkerep tests are starting!\n"); + //optime("test_all",1,test_all()); + ktDescriptors_free(); + kprintf("ъъъъ"); + kprintf("\e[0m\n"); return 0; } diff --git a/tests/test_autoarr-vs-vector.cpp b/tests/test_autoarr-vs-vector.cpp new file mode 100644 index 0000000..f349435 --- /dev/null +++ b/tests/test_autoarr-vs-vector.cpp @@ -0,0 +1,40 @@ +#include "tests.h" +#include "../src/Autoarr/Autoarr.h" +#include + +int64 _autoarrVsVector(uint16 blockCount, uint16 blockLength){ + uint32 count=blockLength*blockCount; + kprintf("\e[94mblock count: %u block length: %u count: " IFWIN("%llu", "%lu") "\n", blockCount, blockLength, (uint64)count); + Autoarr_int64* ar=Autoarr_create(int64, blockCount, blockLength); + std::vector vec=std::vector(); + optime("Autoarr_add", 1, ({ + for(uint32 i=0; i< count; i++) + Autoarr_add(ar, i); + })); + optime("vector_push_back", 1, ({ + for(uint32 i=0; i< count; i++) + vec.push_back(i); + })); + int64 t=0; + optime("Autoarr_get", 1, ({ + for(uint32 i=0; i< count; i++) + t=Autoarr_get(ar, i); + })); + optime("vector_get", 1, ({ + for(uint32 i=0; i< count; i++) + t=vec[i]; + })); + Autoarr_free(ar, true); + return t; +} + +void test_autoarrVsVector(){ + kprintf("\e[96m-------[test_autoarr_vs_vector]-------\n"); + _autoarrVsVector(4, 16); + _autoarrVsVector(16, 64); + _autoarrVsVector(32, 32); + _autoarrVsVector(64, 64); + _autoarrVsVector(32, 1024); + _autoarrVsVector(256, 256); + _autoarrVsVector(1024, 1024); +} diff --git a/tests/test_autoarr.c b/tests/test_autoarr.c index 11b818d..2b3d24d 100644 --- a/tests/test_autoarr.c +++ b/tests/test_autoarr.c @@ -2,7 +2,7 @@ #include "../src/Autoarr/Autoarr.h" static void printautoarr(Autoarr(uint16)* ar){ - printf("\e[94mAutoarr(uint16): " + kprintf("\e[94mAutoarr(uint16): " IFWIN("%llu", "%lu") "\n max_blocks_count: %u\n" " blocks_count: %u\n" @@ -29,25 +29,25 @@ static void resetar(Autoarr(uint16)* ar){ } static void printallval(Autoarr(uint16)* ar){ - printf("\e[90m"); + kprintf("\e[90m"); for (uint16 i=0;i=100?0:(i>=10?1:2)); char* str1=char_multiply(' ',lgs[i]>=100?0:(lgs[i]>=10?1:2)); char* str2=char_multiply('#',lgs[i]/100); - printf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2); + kprintf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2); free(str0); free(str1); free(str2); @@ -47,7 +47,7 @@ char* genkey(uint32 i){ void fill(Hashtable* ht){ for(uint32 i=0;i<100000;i++) - Hashtable_add(ht,genkey(i),Uni(UInt64,i)); + Hashtable_add(ht,genkey(i),UniUInt64(i)); } Unitype gett(Hashtable* ht){ @@ -63,15 +63,15 @@ Unitype gett(Hashtable* ht){ void test_hashtable(){ optime("test_hashtable",1,({ - printf("\e[96m-----------[test_hashtable]-----------\n"); + kprintf("\e[96m-----------[test_hashtable]-----------\n"); Hashtable* ht=Hashtable_create(); - printf("\e[92mhashtable created\n"); + kprintf("\e[92mhashtable created\n"); print_hashtable(ht); optime("fill",1,fill(ht)); optime("get",1,gett(ht)); printrowgraph(ht); print_hashtable(ht); Hashtable_free(ht); - printf("\e[92mhashtable freed\n"); + kprintf("\e[92mhashtable freed\n"); })); } diff --git a/tests/test_kprint_colors.c b/tests/test_kprint_colors.c new file mode 100644 index 0000000..afe3640 --- /dev/null +++ b/tests/test_kprint_colors.c @@ -0,0 +1,50 @@ +#include "tests.h" +#include "../src/kprint/kprint.h" +#if defined(_WIN32)|| defined(_WIN64) + #include +#endif + +#define testColor(COLOR) \ + kprint_setColor(kprint_bgBlack | kprint_fg##COLOR);\ + kprintf(#COLOR " ");\ + kprint_setColor(kprint_bg##COLOR | kprint_fgGray);\ + kprintf(#COLOR);\ + kprint_setColor(kprint_bgBlack | kprint_fgBlack);\ + kprintf("\n"); + +void test_kprint_colors(){ + /* IFWIN( + ({ + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + for(uint8 col=0; col<255; col++){ + SetConsoleTextAttribute(hConsole, col); + kprintf("%u ",col); + } + }), + ({ + for(uint8 col=0; col<255; col++) + kprintf("\e[%um%u ", col, col); + }) + ); + kprintf("\n"); */ + + testColor(Black); + testColor(DarkRed); + testColor(DarkGreen); + testColor(DarkYellow); + testColor(DarkBlue); + testColor(DarkMagenta); + testColor(DarkCyan); + testColor(Gray); + testColor(DarkGray); + testColor(Red); + testColor(Green); + testColor(Yellow); + testColor(Blue); + testColor(Magenta); + testColor(Cyan); + testColor(White); + kprint_setColor(kprint_bgBlack | kprint_fgGray); + + kprint(kprint_fmtInt | kprint_fgCyan, 8888, kprint_fmtString | kprint_fgYellow, " ooo ", kprint_fmtFloat | kprint_bgDarkGreen | kprint_fgRed, 4.01, kprint_fmtString | kprint_fgWhite, "\ngg\n"); +} \ No newline at end of file diff --git a/tests/test_marshalling.c b/tests/test_marshalling.c index 3dde3c0..a3646e6 100644 --- a/tests/test_marshalling.c +++ b/tests/test_marshalling.c @@ -4,11 +4,11 @@ EXPORT void CALL test_marshalling(char* text, KVPair** kptr){ KVPair* k=malloc(sizeof(KVPair)); k->key="message"; char* tc=cptr_copy(text); - Unitype u={.VoidPtr=tc, .type=CharPtr}; + Unitype u=UniHeap(ktId_CharPtr,tc); k->value=u; *kptr=k; } EXPORT void CALL pinvoke_print(char* msg) { - printf("printed from unmanaged code: %s\n", msg); + kprintf("printed from unmanaged code: %s\n", msg); } diff --git a/tests/test_rng_algorithms.c b/tests/test_rng_algorithms.c new file mode 100644 index 0000000..1af5ef5 --- /dev/null +++ b/tests/test_rng_algorithms.c @@ -0,0 +1,45 @@ +#include "tests.h" +#include "../src/random/krandom.h" + + +#define test_alg(ALG, VALUE_SIZE, EXPECTED_FROM_ZERO){\ + kprintf("\e[94mrng algorithm: \e[96m" #ALG "\n");\ + void* s= ALG##_init(0);\ + uint##VALUE_SIZE r=ALG##_next(s);\ + kprintf("\e[97m next from zero seed:");\ + if(r!=EXPECTED_FROM_ZERO){\ + kprintf("\e[91m " IFWIN("%llu\n","%lu\n"), (uint64)r);\ + throw(ERR_UNEXPECTEDVAL);\ + }\ + kprintf("\e[92m " IFWIN("%llu\n","%lu\n"), (uint64)r);\ + ALG##_free(s);\ + s= ALG##_initFromTime();\ + r=ALG##_next(s);\ + ALG##_free(s);\ + kprintf("\e[97m next from time seed:\e[92m " IFWIN("%llu\n","%lu\n"), (uint64)r);\ +} + +void test_rng_algorithms(){ + optime("test_rng_algorithms",1,({ + kprintf("\e[96m--------[test_rng_algorithms]---------\n"); + // for ALG32 + // xoroshiro64 + test_alg(xoroshiro64star, 32, 932574677ULL) + test_alg(xoroshiro64starstar, 32, 3183060286ULL) + // xoshiro128 + test_alg(xoshiro128plus, 32, 3918949401ULL) + test_alg(xoshiro128plusplus, 32, 1179900579ULL) + test_alg(xoshiro128starstar, 32, 3737715805ULL) + // for ALG64 + // xoroshiro128 + test_alg(xoroshiro128plus, 64, 4778832803ULL) + test_alg(xoroshiro128plusplus, 64, 626373238705583ULL) + test_alg(xoroshiro128starstar, 64, 11897572417920ULL) + // xoshiro256 + test_alg(xoshiro256plus, 64, 15757075719729598363ULL) + test_alg(xoshiro256plusplus, 64, 5987356902031041503ULL) + test_alg(xoshiro256starstar, 64, 11091344671253066420ULL) + // splitmix64 + test_alg(splitmix64, 64, 16294208416658607535ULL) + })); +} \ No newline at end of file diff --git a/tests/test_safethrow.c b/tests/test_safethrow.c index 4ccd4dc..14e4e1e 100644 --- a/tests/test_safethrow.c +++ b/tests/test_safethrow.c @@ -1,7 +1,7 @@ #include "tests.h" Maybe dont_throw(){ - return SUCCESS(Uni(UInt64, 9/2)); + return SUCCESS(UniUInt64(9/2)); } Maybe throw_error(){ @@ -14,10 +14,10 @@ Maybe throw_errcode(){ } Maybe test_maybe(){ - printf("\e[94mdont_throw returns \e[92m"); + kprintf("\e[94mdont_throw returns \e[92m"); tryLast(dont_throw(),rez0) printMaybe(rez0); - printf("\n"); + kprintf("\n"); try(throw_error(),rez1,;) printMaybe(rez1); throw("test_maybe failed"); @@ -29,13 +29,13 @@ Maybe b(){ try(c(),_,;) return MaybeNull; } Maybe a(){ try(b(),_,;) return MaybeNull; } void test_safethrow(){ - printf("\e[96m-----------[test_safethrow]-----------\n"); + kprintf("\e[96m-----------[test_safethrow]-----------\n"); optime("test_safethrow", 1, ({ Maybe e=test_maybe(); - printf("\e[94mthrow_error:\n\e[92m"); + kprintf("\e[94mthrow_error:\n\e[92m"); printMaybe(e); Maybe_free(e); - printf("\e[94mthrow_errcode:\n\e[92m"); + kprintf("\e[94mthrow_errcode:\n\e[92m"); e=a(); printMaybe(e); Maybe_free(e); diff --git a/tests/test_searchtree.c b/tests/test_searchtree.c index cff22a5..c7312e8 100644 --- a/tests/test_searchtree.c +++ b/tests/test_searchtree.c @@ -2,20 +2,21 @@ #include "../src/SearchTree/SearchTree.h" void printstnode(STNode* node){ - printf("\e[94mSTNode: " + kprintf("\e[94mSTNode: " IFWIN("%llu", "%lu") "\n address: %p\n value: ",sizeof(STNode),node); printuni(node->value); + kprintf("\n"); // prints pointers to all existing branches - /* printf("\n branches: %p\n", node->branches); + /* kprintf(" branches: %p\n", node->branches); if(node->branches) for(uint8 i=0;i<8;i++){ - printf(" \e[90m[%u]=%p\n",i,node->branches[i]); + kprintf(" \e[90m[%u]=%p\n",i,node->branches[i]); if(node->branches[i]) for (uint8 ii = 0; ii < 8; ii++){ - printf(" \e[90m[%u]=%p\n",ii,node->branches[i][ii]); + kprintf(" \e[90m[%u]=%p\n",ii,node->branches[i][ii]); if(node->branches[i][ii]) for (uint8 iii = 0; iii < 4; iii++) - printf(" \e[90m[%u]=%p\n",iii,node->branches[i][ii][iii]); + kprintf(" \e[90m[%u]=%p\n",iii,node->branches[i][ii][iii]); } } */ @@ -23,51 +24,51 @@ void printstnode(STNode* node){ void test_searchtree(){ optime("test_searchtree",1,({ - printf("\e[96m-----------[test_searchtree]----------\n"); + kprintf("\e[96m-----------[test_searchtree]----------\n"); STNode* node=STNode_create(); - printf("\e[92mnode created\n"); - printf("push:\e[94m\n "); - Unitype u={.type=Int64,.Int64=-3}; + kprintf("\e[92mnode created\n"); + kprintf("push:\e[94m\n "); + Unitype u=UniInt64(-3); printuni(u); ST_push(node,"type", u); - printf(" -> type\n "); - u=(Unitype){.type=Int64,.Int64=25}; + kprintf(" -> type\n "); + u=UniInt64(25); printuni(u); ST_push(node,"time", u); - printf(" -> time\n "); - u=(Unitype){.type=Float64,.Float64=-542.00600}; + kprintf(" -> time\n "); + u=UniFloat64(-542.00600); printuni(u); ST_push(node,"author_id", u); - printf(" -> author_id\n "); - u=(Unitype){.type=Int64,.Int64=-31255}; + kprintf(" -> author_id\n "); + u=UniInt64(-31255); printuni(u); ST_push(node,"channel_id", u); - printf(" -> channel_id\n "); - u=(Unitype){.type=Float64,.Float64=32.2004}; + kprintf(" -> channel_id\n "); + u=UniHeap(ktId_CharPtr, cptr_copy("32.2004")); printuni(u); ST_push(node,"message_id", u); - printf(" -> message_id\n "); - u=(Unitype){.type=CharPtr,.VoidPtr=cptr_copy("some text UwU")}; + kprintf(" -> message_id\n "); + u=UniStack(ktId_CharPtr,"some text UwU"); printuni(u); ST_push(node,"text", u); - printf(" -> text\n"); - printf("\e[92mpull:\e[94m"); - printf("\n type -> "); + kprintf(" -> text\n"); + kprintf("\e[92mpull:\e[94m"); + kprintf("\n type -> "); printuni(ST_pull(node,"type")); - printf("\n time -> "); + kprintf("\n time -> "); printuni(ST_pull(node,"time")); - printf("\n author_id -> "); + kprintf("\n author_id -> "); printuni(ST_pull(node,"author_id")); - printf("\n channel_id -> "); + kprintf("\n channel_id -> "); printuni(ST_pull(node,"channel_id")); - printf("\n message_id -> "); + kprintf("\n message_id -> "); printuni(ST_pull(node,"message_id")); - printf("\n text -> "); + kprintf("\n text -> "); printuni(ST_pull(node,"text")); - printf("\n"); - printf("\e[92mfirst node: "); + kprintf("\n"); + kprintf("\e[92mfirst node: "); printstnode(node); STNode_free(node); - printf("\e[92mnode deleted\n"); + kprintf("\e[92mnode deleted\n"); })); } diff --git a/tests/test_string.c b/tests/test_string.c index 9a6aac2..ff861f9 100644 --- a/tests/test_string.c +++ b/tests/test_string.c @@ -3,12 +3,12 @@ void test_string(){ optime(__func__,1,({ - printf("\e[96m-------------[test_string]------------\n"); + kprintf("\e[96m-------------[test_string]------------\n"); char c[]="0123456789abcdef"; string s={.ptr=c, .length=cptr_length(c)}; if(s.length!=sizeof(c)-1) throw("string created with incorrect length"); char* p=string_extract(s); - printf("\e[94mstring_extract() -> \e[92m\"%s\"\n",p); + kprintf("\e[94mstring_extract() -> \e[92m\"%s\"\n",p); free(p); })); } \ No newline at end of file diff --git a/tests/tests.h b/tests/tests.h index eb66a8f..8941c61 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -13,10 +13,12 @@ void test_autoarr(); void test_hash_functions(); void test_hashtable(); void test_dtsod(); -void test_network(); +void test_kprint_colors(); +void test_autoarrVsVector(); +void test_rng_algorithms(); -#define PRINT_SIZEOF(T) printf("\e[94m" #T " size: \e[96m" IFWIN("%llu", "%lu") "\n", sizeof(T)) +#define PRINT_SIZEOF(T) kprintf("\e[94m" #T " size: \e[96m" IFWIN("%llu", "%lu") "\n", sizeof(T)) #if __cplusplus } -#endif \ No newline at end of file +#endif