Merge branch 'main' into network

This commit is contained in:
2022-10-30 19:57:05 +06:00
106 changed files with 3044 additions and 699 deletions

40
src/Array/Array.h Normal file
View File

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

40
src/Array/Array_declare.h Normal file
View File

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

2
src/Array/README.md Normal file
View File

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

View File

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

View File

@@ -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) {\

View File

@@ -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){

View File

@@ -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){

View File

@@ -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 : \

View File

@@ -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; i<ar->blocks_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; i<length; i++)\
array[i]=__Autoarr_get_##type(ar, i);\
return array;\
}\
\
__functions_list_t_##type __functions_list_##type={\
@@ -51,7 +62,8 @@ __functions_list_t_##type __functions_list_##type={\
&__Autoarr_get_##type,\
&__Autoarr_getptr_##type,\
&__Autoarr_set_##type,\
&__Autoarr_free_##type\
&__Autoarr_free_##type,\
&__Autoarr_toArray_##type\
};\
\
Autoarr_##type* __Autoarr_create_##type(uint16 max_blocks_count, uint16 max_block_length){\

9
src/Autoarr/README.md Normal file
View File

@@ -0,0 +1,9 @@
# Autoarr struct
`Autoarr` means Automatically resizing array. It is my implementation of dyynamic array. If you want to use `Autoarr` of some type, it should be declared in header file by macro `Autoarr_declare` and defined in source file by `Autoarr_define`.
Examples:
[Hashtable.h](src/Hashtable/Hashtable.h)
[Hashtable.c](src/Hashtable/Hashtable.c)
### Autoarr_*_exported
Contains definitions for functions, exported for using in C# kerep wrapper.

View File

@@ -98,9 +98,9 @@ Maybe __ReadName(DeserializeSharedData* shared){
case '}':
if(!calledRecursively || nameStr.length!=0)
safethrow_wrongchar(c,;);
return SUCCESS(UniPtr(CharPtr,NULL));
return SUCCESS(UniHeap(ktId_CharPtr,NULL));
case ':':
return SUCCESS(UniPtr(CharPtr,string_extract(nameStr)));
return SUCCESS(UniHeap(ktId_CharPtr,string_extract(nameStr)));
case '$':
if(nameStr.length!=0)
safethrow_wrongchar(c,;);
@@ -113,7 +113,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
}
if(nameStr.length>0) 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) {

View File

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

View File

@@ -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; i<n; i++){
char* part=va_arg(vl,char*);
int16 length=cptr_length(part);
parts[i]=part;
lengths[i]=length;
totalLength+=length;
}
va_end(vl);
// allocating memory for output value
char* totality=malloc(totalLength+1);
const char* output=totality;
totality[totalLength]=0;
// copying content of all strings to rezult
uint16 k=0;
for(; k<n-1; k++){
memcopy(parts[k], totality, lengths[k]);
totality+=lengths[k];
*totality=path_sep;
totality++;
}
memcopy(parts[k], totality, lengths[k]);
free(parts);
free(lengths);
return output;
}

View File

@@ -0,0 +1,22 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "std.h"
#if defined(_WIN32) || defined (_WIN64)
static const char path_sep='\\';
#else
static const char path_sep='/';
#endif
char* __path_concat(uint16 n, char* path_start, ...);
#define path_concat(PATH_PARTS) __path_concat(count_args(PATH_PARTS), PATH_PARTS)
#if __cplusplus
}
#endif

View File

@@ -1,5 +1,8 @@
#include "Hashtable.h"
ktId_define(Hashtable);
ktId_define(HashtablePtr);
// amount of rows
static const uint16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
#define HT_HEIN_MIN 0
@@ -17,10 +20,14 @@ Hashtable* Hashtable_create(){
return ht;
}
void Hashtable_free(Hashtable* ht){
void __Hashtable_free(void* _ht){
Hashtable* ht=_ht;
for(uint16 i=0;i<HT_HEIGHTS[ht->hein];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){

View File

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

View File

@@ -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("}");
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()!

View File

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

View File

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

View File

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

View File

@@ -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<size; i++)
((char*)to)[i]=((char*)from)[i];
}
char* __cptr_concat(uint16 n, ...){
char** strs=(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, n);
for(uint16 i=0; i<n; i++){
char* str=va_arg(vl,char*);
int16 length=cptr_length(str);
strs[i]=str;
lengths[i]=length;
totalLength+=length;
}
va_end(vl);
// allocating memory for output value
char* totality=malloc(totalLength+1);
const char* output=totality;
totality[totalLength]=0;
// copying content of all strings to rezult
for(uint16 k=0; k<n; k++){
memcopy(strs[k], totality, lengths[k]);
totality+=lengths[k];
}
free(strs);
free(lengths);
return output;
}

View File

@@ -4,7 +4,7 @@
extern "C" {
#endif
#include "types.h"
#include "std.h"
// returns length of char buffer (without \0)
uint32 cptr_length(char* str);
@@ -18,6 +18,15 @@ bool cptr_compare(char* key0, char* key1);
// multiplies char n times
char* char_multiply(char c, uint32 n);
bool cptr_startsWith(char* ptr, char* fragment);
bool cptr_endsWith(char* ptr, char* fragment);
void memcopy(void* from, void* to, uint32 size);
char* __cptr_concat(uint16 n, ...);
#define cptr_concat(STR...) __cptr_concat(count_args(STR), STR)
#if __cplusplus
}
#endif

View File

@@ -1,6 +1,7 @@
#include "std.h"
#include "errors.h"
#include "cptr.h"
#include "../kprint/kprintf.h"
char* errname(ErrorId err){
switch(err){
@@ -12,6 +13,8 @@ char* errname(ErrorId err){
case ERR_NULLPTR: return "ERR_NULLPTR";
case ERR_ENDOFSTR: return "ERR_ENDOFSTR";
case ERR_KEYNOTFOUND: return "ERR_KEYNOTFOUND";
case ERR_FORMAT: return "ERR_FORMAT";
case ERR_UNEXPECTEDVAL: return "ERR_UNEXPECTEDVAL";
default: return "UNKNOWN_ERROR";
}
}
@@ -45,7 +48,7 @@ void Maybe_free(Maybe e){
}
void printMaybe(Maybe e){
if(e.errmsg) printf("%s\n",e.errmsg);
if(e.errmsg) kprintf("%s\n",e.errmsg);
else printuni(e.value);
}

View File

@@ -5,13 +5,13 @@ extern "C" {
#endif
#include "std.h"
#include "types.h"
#include "type_system/unitype.h"
typedef enum ErrorId {
SUCCESS, // not an error
ERR_MAXLENGTH, ERR_WRONGTYPE, ERR_WRONGINDEX,
ERR_NOTIMPLEMENTED, ERR_NULLPTR, ERR_ENDOFSTR,
ERR_KEYNOTFOUND
ERR_KEYNOTFOUND, ERR_FORMAT, ERR_UNEXPECTEDVAL
} ErrorId;
char* errname(ErrorId err);
@@ -36,7 +36,7 @@ void printMaybe(Maybe e);
#define __RETURN_EXCEPTION(ERRMSG) return (Maybe){.errmsg=ERRMSG, .value=UniNull}
#define __EXIT(ERRMSG) ({ printf("\e[91m%s\e[0m \n", ERRMSG); free(ERRMSG); exit(128); })
#define __EXIT(ERRMSG) ({ kprintf("\e[91m%s\e[0m \n", ERRMSG); free(ERRMSG); exit(128); })
char* __doNothing(char* a);
char* __unknownErr( );
@@ -59,12 +59,12 @@ char* __unknownErr( );
freeMem;\
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__);\
return _rezult;\
}else
}
#define tryLast(_funcCall, _rezult) Maybe _rezult=_funcCall; if(_rezult.errmsg){\
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__);\
__EXIT(_rezult.errmsg);\
}else
}
#endif

View File

@@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include "std.h"
// executes codeblock and prints execution time
#ifdef CLOCK_REALTIME // non-standard high-precision clock
@@ -11,7 +11,7 @@
(codeblock);\
clock_gettime(CLOCK_REALTIME, &stop);\
double t=(double)(stop.tv_sec-start.tv_sec+(double)(stop.tv_nsec-start.tv_nsec)/1000000000)/repeats;\
printf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
})
#else // standard low precision clock
#define optime(opname,repeats,codeblock) ({\
@@ -20,6 +20,6 @@
(codeblock);\
clock_t stop=clock();\
double t=(double)(stop-start)/CLOCKS_PER_SEC/repeats;\
printf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%lf \e[93mseconds\n",opname,t);\
})
#endif

View File

@@ -8,13 +8,23 @@ extern "C" {
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <locale.h>
#include <time.h>
#include <setjmp.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;
#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
}

View File

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

View File

@@ -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("<float>");
}
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<size; bn++){
unsigned char byte=bytes[bn];
for(uint8 i=0; i<8; i++)
str[cn++]='0' + (byte & (char)128>>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; bn<size; bn++){
unsigned char byte=bytes[bn];
str[cn++]=_4bitsHex(byte%16, uppercase);
str[cn++]=_4bitsHex(byte/16, uppercase);
}
str[cn]=0;
return str;
}
#define __toString_int_def(BITS) char* __toString_int##BITS(void* _n, uint32 f){\
switch(kprint_format_dataFormat(f)){\
case kprint_fmtInt: ;\
int##BITS n=*(int##BITS*)_n;\
return toString_int(n);\
case kprint_fmtBin:\
return toString_bin(_n, BITS/8, kprint_format_withPrefix(f));\
case kprint_fmtHex:\
return toString_hex(_n, BITS/8, kprint_format_withPrefix(f), kprint_format_uppercase(f));\
default:\
kprintf("\n%u\n", kprint_format_dataFormat(f));\
throw(ERR_FORMAT);\
return NULL;\
}\
}
__toString_int_def(8)
__toString_int_def(16)
__toString_int_def(32)
__toString_int_def(64)
#define __toString_uint_def(BITS) char* __toString_uint##BITS(void* _n, uint32 f){\
switch(kprint_format_dataFormat(f)){\
case kprint_fmtUInt: ;\
uint##BITS n=*(uint##BITS*)_n;\
return toString_uint(n, kprint_format_withPostfix(f), kprint_format_uppercase(f));\
case kprint_fmtBin:\
return toString_bin(_n, BITS/8, kprint_format_withPrefix(f));\
case kprint_fmtHex:\
return toString_hex(_n, BITS/8, kprint_format_withPrefix(f), kprint_format_uppercase(f));\
default:\
kprintf("\n%u\n", kprint_format_dataFormat(f));\
throw(ERR_FORMAT);\
return NULL;\
}\
}
__toString_uint_def(8)
__toString_uint_def(16)
__toString_uint_def(32)
__toString_uint_def(64)
#define __toString_float_def(BITS) char* __toString_float##BITS(void* _n, uint32 f){\
switch(kprint_format_dataFormat(f)){\
case kprint_fmtFloat: ;\
float##BITS n=*(float##BITS*)_n;\
return toString_float(n, kprint_format_withPostfix(f), kprint_format_uppercase(f));\
case kprint_fmtBin:\
return toString_bin(_n, BITS/8, kprint_format_withPrefix(f));\
case kprint_fmtHex:\
return toString_hex(_n, BITS/8, kprint_format_withPrefix(f), kprint_format_uppercase(f));\
default:\
kprintf("\n%u\n", kprint_format_dataFormat(f));\
throw(ERR_FORMAT);\
return NULL;\
}\
}
__toString_float_def(32)
__toString_float_def(64)

View File

@@ -0,0 +1,36 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../errors.h"
// functions for base types
char* __toString_char(void* c, uint32 fmt);
char* __toString_charPtr(void* c, uint32 fmt);
char* __toString_bool(void* c, uint32 fmt);
char* toString_int(int64 n);
char* __toString_int8(void* n, uint32 fmt);
char* __toString_int16(void* n, uint32 fmt);
char* __toString_int32(void* n, uint32 fmt);
char* __toString_int64(void* n, uint32 fmt);
char* toString_uint(uint64 n, bool withPostfix, bool uppercase);
char* __toString_uint8(void* n, uint32 fmt);
char* __toString_uint16(void* n, uint32 fmt);
char* __toString_uint32(void* n, uint32 fmt);
char* __toString_uint64(void* n, uint32 fmt);
char* toString_float(float64 n, bool withPostfix, bool uppercase); // very bad implimentation
char* __toString_float32(void* n, uint32 fmt);
char* __toString_float64(void* n, uint32 fmt);
// universal functions
char* toString_bin(void* bytes, uint32 size, bool withPrefix);
char* toString_hex(void* bytes, uint32 size, bool withPrefix, bool uppercase);
#if __cplusplus
}
#endif

134
src/base/type_system/init.c Normal file
View File

@@ -0,0 +1,134 @@
#include "../base.h"
#include "../../Array/Array.h"
#include "../../Autoarr/Autoarr.h"
#include "../../SearchTree/SearchTree.h"
#include "../../Hashtable/Hashtable.h"
#include "../../String/StringBuilder.h"
#include "base_toString.h"
void ktDescriptors_initKerepTypes(){
// null
kt_register(NULL, ktId_Null, NULL, NULL);
// base types
kt_register(char, ktId_Char, NULL, __toString_char);
kt_register(bool, ktId_Bool, NULL, __toString_bool);
kt_register(float32, ktId_Float32, NULL, __toString_float32);
kt_register(float64, ktId_Float64, NULL, __toString_float64);
kt_register(int8, ktId_Int8, NULL, __toString_int8);
kt_register(uint8, ktId_UInt8, NULL, __toString_uint8);
kt_register(int16, ktId_Int16, NULL, __toString_int16);
kt_register(uint16, ktId_UInt16, NULL, __toString_uint16);
kt_register(int32, ktId_Int32, NULL, __toString_int32);
kt_register(uint32, ktId_UInt32, NULL, __toString_uint32);
kt_register(int64, ktId_Int64, NULL, __toString_int64);
kt_register(uint64, ktId_UInt64, NULL, __toString_uint64);
// base type pointers
kt_register(char*, ktId_CharPtr, NULL, __toString_charPtr);
kt_register(bool*, ktId_BoolPtr, NULL, NULL);
kt_register(float32*, ktId_Float32Ptr, NULL, NULL);
kt_register(float64*, ktId_Float64Ptr, NULL, NULL);
kt_register(int8*, ktId_Int8Ptr, NULL, NULL);
kt_register(uint8*, ktId_UInt8Ptr, NULL, NULL);
kt_register(int16*, ktId_Int16Ptr, NULL, NULL);
kt_register(uint16*, ktId_UInt16Ptr, NULL, NULL);
kt_register(int32*, ktId_Int32Ptr, NULL, NULL);
kt_register(uint32*, ktId_UInt32Ptr, NULL, NULL);
kt_register(int64*, ktId_Int64Ptr, NULL, NULL);
kt_register(uint64*, ktId_UInt64Ptr, NULL, NULL);
// ktDescriptor
kt_register(ktDescriptor, ktId_ktDescriptor, NULL, NULL);
kt_register(ktDescriptor*, ktId_ktDescriptorPtr, NULL, NULL);
// base type arrays
kt_register(Array_char, ktId_ArrayChar, Array_char_freeValues, NULL);
kt_register(Array_bool, ktId_ArrayBool, Array_bool_freeValues, NULL);
kt_register(Array_float32, ktId_ArrayFloat32, Array_float32_freeValues, NULL);
kt_register(Array_float64, ktId_ArrayFloat64, Array_float64_freeValues, NULL);
kt_register(Array_int8, ktId_ArrayInt8, Array_int8_freeValues, NULL);
kt_register(Array_uint8, ktId_ArrayUInt8, Array_uint8_freeValues, NULL);
kt_register(Array_int16, ktId_ArrayInt16, Array_int16_freeValues, NULL);
kt_register(Array_uint16, ktId_ArrayUInt16, Array_uint16_freeValues, NULL);
kt_register(Array_int32, ktId_ArrayInt32, Array_int32_freeValues, NULL);
kt_register(Array_uint32, ktId_ArrayUInt32, Array_uint32_freeValues, NULL);
kt_register(Array_int64, ktId_ArrayInt64, Array_int64_freeValues, NULL);
kt_register(Array_uint64, ktId_ArrayUInt64, Array_uint64_freeValues, NULL);
// base type array pointers
kt_register(Array_char*, ktId_ArrayCharPtr, Array_char_freeValues, NULL);
kt_register(Array_bool*, ktId_ArrayBoolPtr, Array_bool_freeValues, NULL);
kt_register(Array_float32*, ktId_ArrayFloat32Ptr, Array_float32_freeValues, NULL);
kt_register(Array_float64*, ktId_ArrayFloat64Ptr, Array_float64_freeValues, NULL);
kt_register(Array_int8*, ktId_ArrayInt8Ptr, Array_int8_freeValues, NULL);
kt_register(Array_uint8*, ktId_ArrayUInt8Ptr, Array_uint8_freeValues, NULL);
kt_register(Array_int16*, ktId_ArrayInt16Ptr, Array_int16_freeValues, NULL);
kt_register(Array_uint16*, ktId_ArrayUInt16Ptr, Array_uint16_freeValues, NULL);
kt_register(Array_int32*, ktId_ArrayInt32Ptr, Array_int32_freeValues, NULL);
kt_register(Array_uint32*, ktId_ArrayUInt32Ptr, Array_uint32_freeValues, NULL);
kt_register(Array_int64*, ktId_ArrayInt64Ptr, Array_int64_freeValues, NULL);
kt_register(Array_uint64*, ktId_ArrayUInt64Ptr, Array_uint64_freeValues, NULL);
// base type autoarrs
kt_register(Autoarr_char, ktId_AutoarrChar, ____Autoarr_free_char, NULL);
kt_register(Autoarr_bool, ktId_AutoarrBool, ____Autoarr_free_bool, NULL);
kt_register(Autoarr_float32, ktId_AutoarrFloat32, ____Autoarr_free_float32, NULL);
kt_register(Autoarr_float64, ktId_AutoarrFloat64, ____Autoarr_free_float64, NULL);
kt_register(Autoarr_int8, ktId_AutoarrInt8, ____Autoarr_free_int8, NULL);
kt_register(Autoarr_uint8, ktId_AutoarrUInt8, ____Autoarr_free_uint8, NULL);
kt_register(Autoarr_int16, ktId_AutoarrInt16, ____Autoarr_free_int16, NULL);
kt_register(Autoarr_uint16, ktId_AutoarrUInt16, ____Autoarr_free_uint16, NULL);
kt_register(Autoarr_int32, ktId_AutoarrInt32, ____Autoarr_free_int32, NULL);
kt_register(Autoarr_uint32, ktId_AutoarrUInt32, ____Autoarr_free_uint32, NULL);
kt_register(Autoarr_int64, ktId_AutoarrInt64, ____Autoarr_free_int64, NULL);
kt_register(Autoarr_uint64, ktId_AutoarrUInt64, ____Autoarr_free_uint64, NULL);
// base type autoarr pointers
kt_register(Autoarr_char*, ktId_AutoarrCharPtr, ____Autoarr_free_char, NULL);
kt_register(Autoarr_bool*, ktId_AutoarrBoolPtr, ____Autoarr_free_bool, NULL);
kt_register(Autoarr_float32*, ktId_AutoarrFloat32Ptr, ____Autoarr_free_float32, NULL);
kt_register(Autoarr_float64*, ktId_AutoarrFloat64Ptr, ____Autoarr_free_float64, NULL);
kt_register(Autoarr_int8*, ktId_AutoarrInt8Ptr, ____Autoarr_free_int8, NULL);
kt_register(Autoarr_uint8*, ktId_AutoarrUInt8Ptr, ____Autoarr_free_uint8, NULL);
kt_register(Autoarr_int16*, ktId_AutoarrInt16Ptr, ____Autoarr_free_int16, NULL);
kt_register(Autoarr_uint16*, ktId_AutoarrUInt16Ptr, ____Autoarr_free_uint16, NULL);
kt_register(Autoarr_int32*, ktId_AutoarrInt32Ptr, ____Autoarr_free_int32, NULL);
kt_register(Autoarr_uint32*, ktId_AutoarrUInt32Ptr, ____Autoarr_free_uint32, NULL);
kt_register(Autoarr_int64*, ktId_AutoarrInt64Ptr, ____Autoarr_free_int64, NULL);
kt_register(Autoarr_uint64*, ktId_AutoarrUInt64Ptr, ____Autoarr_free_uint64, NULL);
// Unitype
kt_register(Unitype, ktId_Unitype, __UnitypePtr_free, NULL);
kt_register(Unitype*, ktId_UnitypePtr, __UnitypePtr_free, NULL);
kt_register(Autoarr_Unitype, ktId_AutoarrUnitype, ____Autoarr_free_Unitype_, NULL);
kt_register(Autoarr_Unitype*, ktId_AutoarrUnitypePtr, ____Autoarr_free_Unitype_, NULL);
// replacing autogenerated freear() function to custom
Autoarr_Unitype* _uar=Autoarr_create(Unitype, 1, 1);
_uar->functions->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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,5 @@
#include "init.h"
#include "ktId.h"
#include "ktDescriptor.h"
#include "kt_functions.h"
#include "unitype.h"

View File

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

View File

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

View File

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

View File

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

36
src/kprint/README.md Normal file
View File

@@ -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<char*> | kprint_format, void*, kprint_format, void*... |
| kfprint | Maybe<void> | 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: <span style="color:blue">Maybe:</span> <span style="color:lightgreen">{value={0, ktId_Null}}</span>

168
src/kprint/kprint.c Normal file
View File

@@ -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<n; i++){
try(__next_toString(formats[i], &objects[i]),mStr,;);
StringBuilder_append_cptr(strb, mStr.value.VoidPtr);
Unitype_free(mStr.value);
}
char* rezult=StringBuilder_build(strb).ptr;
return SUCCESS(UniHeap(ktId_CharPtr, rezult));
}
Maybe __kfprint(FILE* file, uint8 n, kprint_format* formats, __kprint_value_union* objects){
n/=2;
for(uint8 i=0; i<n; i++){
try(__next_toString(formats[i], &objects[i]),maybeStr,;);
if(fputs(maybeStr.value.VoidPtr, file)==EOF)
safethrow("can't write string to file", Unitype_free(maybeStr.value));
Unitype_free(maybeStr.value);
}
fflush(file);
return MaybeNull;
}
void __kprint(uint8 n, kprint_format* formats, __kprint_value_union* objects){
n/=2;
for(uint8 i=0; i<n; i++){
kprint_format fmt=formats[i];
kprint_setColor(fmt);
tryLast(__next_toString(fmt, &objects[i]),maybeStr);
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF)\
throw("can't write string to stdout");
//, Unitype_free(maybeStr.value)
Unitype_free(maybeStr.value);
}
fflush(stdout);
}
#if defined(_WIN32)|| defined(_WIN64)
#include <windows.h>
#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
DWORD 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<count; e++){
StringBuilder_append_char(strb, ' ');
char* elStr=typeDesc.toString(array+typeDesc.size*e, &format);
StringBuilder_append_cptr(strb, elStr);
StringBuilder_append_char(strb, ',');
}
StringBuilder_rmchar(strb);
StringBuilder_append_char(strb, ' ');
StringBuilder_append_char(strb, ']');
} */

73
src/kprint/kprint.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/errors.h"
#include "kprint_colors.h"
#include "kprint_format.h"
typedef union {
int64 i64;
uint64 u64;
float64 f64;
void* ptr;
} __kprint_value_union;
#define __kprintVU(value) (__kprint_value_union){ value }
#define __kprint_argsToFormats8(\
a0, a1, a2, a3, a4, a5, a6, a7,...)\
((int32[]){ a0,a2,a4,a6 })
#define __kprint_argsToObjects8(\
a0, a1, a2, a3, a4, a5, a6, a7,...)\
((__kprint_value_union[]){ __kprintVU(a1),__kprintVU(a3),__kprintVU(a5),__kprintVU(a7) })
#define __kprint_argsToFormats16(\
a0, a1, a2, a3, a4, a5, a6, a7,\
a8, a9, a10,a11,a12,a13,a14,a15,...)\
((int32[]){ a0,a2,a4,a6,a8,a10,a12,a14 })
#define __kprint_argsToObjects16(\
a0, a1, a2, a3, a4, a5, a6, a7,\
a8, a9, a10,a11,a12,a13,a14,a15,...)\
((__kprint_value_union[]){ __kprintVU(a1),__kprintVU(a3),__kprintVU(a5),__kprintVU(a7),__kprintVU(a9),__kprintVU(a11),__kprintVU(a13),__kprintVU(a15) })
#define __kprint_argsToFormats32(\
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,...)\
((int32[]){ a0,a2,a4,a6,a8,a10,a12,a14,a16,a18,a20,a22,a24,a26,a28,a30 })
#define __kprint_argsToObjects32(\
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,...)\
((__kprint_value_union[]){ __kprintVU(a1),__kprintVU(a3),__kprintVU(a5),__kprintVU(a7),__kprintVU(a9),__kprintVU(a11),__kprintVU(a13),__kprintVU(a15),__kprintVU(a17),__kprintVU(a19),__kprintVU(a21),__kprintVU(a23),__kprintVU(a25),__kprintVU(a27),__kprintVU(a29),__kprintVU(a31) })
#define __32zeroes 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
#define __kprint_argsToArrs(COUNT,ARGS...)\
(kprint_format*)(COUNT<=8 ? __kprint_argsToFormats8(ARGS) :\
COUNT<=16 ? __kprint_argsToFormats16(ARGS) :\
__kprint_argsToFormats32(ARGS)),\
(__kprint_value_union*)(COUNT<=8 ? __kprint_argsToObjects8(ARGS) :\
COUNT<=16 ? __kprint_argsToObjects16(ARGS) :\
__kprint_argsToObjects32(ARGS))
Maybe __ksprint(uint8 n, kprint_format* formats, __kprint_value_union* objects);
#define ksprint(ARGS...) __ksprint(count_args(ARGS), __kprint_argsToArrs(count_args(ARGS),ARGS, __32zeroes))
Maybe __kfprint(FILE* fd, uint8 n, kprint_format* formats, __kprint_value_union* objects);
#define kfprint(FD, ARGS...) __kfprint(FD, count_args(ARGS), __kprint_argsToArrs(count_args(ARGS),ARGS, __32zeroes))
void __kprint(uint8 n, kprint_format* formats, __kprint_value_union* objects);
#define kprint(ARGS...) __kprint(count_args(ARGS), __kprint_argsToArrs(count_args(ARGS),ARGS, __32zeroes))
// can take (bgColor | fgColor)
void kprint_setColor(kprint_format f);
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,55 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
typedef enum kprint_fgColor{
// 10000000 00000000 00000000 00000000
// ^ ^^^^
// | color num
// fgColorChanged flag
kprint_fgBlack = 0x80000000,
kprint_fgDarkRed = 0x81000000,
kprint_fgDarkGreen = 0x82000000,
kprint_fgDarkYellow = 0x83000000,
kprint_fgDarkBlue = 0x84000000,
kprint_fgDarkMagenta= 0x85000000,
kprint_fgDarkCyan = 0x86000000,
kprint_fgGray = 0x87000000,
kprint_fgDarkGray = 0x88000000,
kprint_fgRed = 0x89000000,
kprint_fgGreen = 0x8a000000,
kprint_fgYellow = 0x8b000000,
kprint_fgBlue = 0x8c000000,
kprint_fgMagenta = 0x8d000000,
kprint_fgCyan = 0x8e000000,
kprint_fgWhite = 0x8f000000
} kprint_fgColor;
typedef enum kprint_bgColor{
// 01000000 00000000 00000000 00000000
// ^ ^^^^
// bgColorChanged flag color num
kprint_bgBlack = 0x40000000,
kprint_bgDarkRed = 0x40100000,
kprint_bgDarkGreen = 0x40200000,
kprint_bgDarkYellow = 0x40300000,
kprint_bgDarkBlue = 0x40400000,
kprint_bgDarkMagenta= 0x40500000,
kprint_bgDarkCyan = 0x40600000,
kprint_bgGray = 0x40700000,
kprint_bgDarkGray = 0x40800000,
kprint_bgRed = 0x40900000,
kprint_bgGreen = 0x40a00000,
kprint_bgYellow = 0x40b00000,
kprint_bgBlue = 0x40c00000,
kprint_bgMagenta = 0x40d00000,
kprint_bgCyan = 0x40e00000,
kprint_bgWhite = 0x40f00000
} kprint_bgColor;
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,48 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/std.h"
#include "../base/type_system/ktId.h"
typedef enum kprint_dataFormat{
// 00000000 00000000 00000000 00000000
// ^^^^
// type
kprint_fmtInt = 0x00000000,
kprint_fmtUInt = 0x00010000,
kprint_fmtHex = 0x00020000,
kprint_fmtBin = 0x00030000,
kprint_fmtFloat = 0x00040000,
kprint_fmtChar = 0x00050000,
kprint_fmtString = 0x00060000,
// 00100000 00000000 00000000 00000000
// ^
// prefix/postfix flag
kprint_fmtWithPrefix=0x20000000,
kprint_fmtWithPostfix=kprint_fmtWithPrefix,
// 00010000 00000000 00000000 00000000
// ^
// uppercase flag
kprint_fmtUppercase=0x10000000
} kprint_dataFormat;
typedef uint32 kprint_format;
#define kprint_format_fgColorChanged(FMT) (FMT&0x80000000)
#define kprint_format_bgColorChanged(FMT) (FMT&0x40000000)
#define kprint_format_withPrefix(FMT) (FMT&kprint_fmtWithPrefix)
#define kprint_format_withPostfix(FMT) (FMT&kprint_fmtWithPostfix)
#define kprint_format_uppercase(FMT) (FMT&kprint_fmtUppercase)
#define kprint_format_fgColor(FMT) (kprint_fgColor)(FMT&0x8f000000)
#define kprint_format_bgColor(FMT) (kprint_bgColor)(FMT&0x40f00000)
#define kprint_format_dataFormat(FMT) (kprint_dataFormat)(FMT&0x000f0000)
#define kprint_format_ktId(FMT) (kprint_dataFormat)(FMT&0x0000ffff)
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,72 @@
# kerep_format
```
00000000 00000000 00000000 00000000
fgColorSet┘│││└┼┴┘ └┼┴┘└┴┴┤ ktId
bgColorSet─┘││ │ bgColor └data format
prefix┬────┘│ └fgColor
postfix └uppercase
```
## Console colors
### *Foreground*
| kprint_fg | hex | bin |
|-----------|-----|-----|
| Black | 0x80000000 | 10000000 00000000... |
| DarkRed | 0x81000000 | 10000001 00000000... |
| DarkGreen | 0x82000000 | 10000010 00000000... |
| DarkYellow | 0x83000000 | 10000011 00000000... |
| DarkBlue | 0x84000000 | 10000100 00000000... |
| DarkMagenta | 0x85000000 | 10000101 00000000... |
| DarkCyan | 0x86000000 | 10000110 00000000... |
| Gray | 0x87000000 | 10000111 00000000... |
| DarkGray | 0x88000000 | 10001000 00000000... |
| Red | 0x89000000 | 10001001 00000000... |
| Green | 0x8a000000 | 10001010 00000000... |
| Yellow | 0x8b000000 | 10001011 00000000... |
| Blue | 0x8c000000 | 10001100 00000000... |
| Magenta | 0x8d000000 | 10001101 00000000... |
| Cyan | 0x8e000000 | 10001110 00000000... |
| White | 0x8f000000 | 10001111 00000000... |
### *Background*
| kprint_bg | hex | bin |
|-----------|-----|-----|
| Black | 0x40000000 | 01000000 00000000... |
| DarkRed | 0x40100000 | 01000000 00010000... |
| DarkGreen | 0x40200000 | 01000000 00100000... |
| DarkYellow | 0x40300000 | 01000000 00110000... |
| DarkBlue | 0x40400000 | 01000000 01000000... |
| DarkMagenta | 0x40500000 | 01000000 01010000... |
| DarkCyan | 0x40600000 | 01000000 01100000... |
| Gray | 0x40700000 | 01000000 01110000... |
| DarkGray | 0x40800000 | 01000000 10000000... |
| Red | 0x40900000 | 01000000 10010000... |
| Green | 0x40a00000 | 01000000 10100000... |
| Yellow | 0x40b00000 | 01000000 10110000... |
| Blue | 0x40c00000 | 01000000 11000000... |
| Magenta | 0x40d00000 | 01000000 11010000... |
| Cyan | 0x40e00000 | 01000000 11100000... |
| White | 0x40f00000 | 01000000 11110000... |
## Data format
| kprint_fmt | possible flags | data types | hex value | bin value |
|------------|----------------|------------|-----------|-----------|
| Int | | int8... int64 | 0x00000000 | 00000000 00000000... |
| UInt | WithPostfix, Uppercase | uint8... uint64 | 0x00010000 | 00000000 00000001... |
| Hex | WithPrefix, Uppercase | any | 0x00020000 | 00000000 00000010... |
| Bin | WithPrefix, | any | 0x00030000 | 00000000 00000011... |
| Float | WithPostfix, Uppercase | float32, float64 | 0x00040000 | 00000000 00000100... |
| Char | | char | 0x00050000 | 00000000 00000101... |
| String | | char* | 0x00060000 | 00000000 00000110... |
### *Flags*
| kprint_fmt | hex value | bin value |
|-------------|------------|-----------|
| withPrefix | 0x20000000 | 00100000 00000000... |
| withPostfix | 0x20000000 | 00100000 00000000... |
| upperase | 0x10000000 | 00010000 00000000... |

147
src/kprint/kprintf.c Normal file
View File

@@ -0,0 +1,147 @@
#include "kprintf.h"
#include "../base/base.h"
#include "../base/type_system/base_toString.h"
#if defined(_WIN64) || defined(_WIN32)
#include <windows.h>
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="<nullstr>";
if(*cptr)
fputs(cptr, stdout);
break;
case 'c':
argstr=malloc(2);
argstr[0]=(char)va_arg(vl,int);
argstr[1]=0;
break;
default:
putc('\n',stdout);
putc('<',stdout);
putc(c,stdout);
putc('>',stdout);
throw(ERR_FORMAT);
}
if(argstr){
fputs(argstr, stdout);
free(argstr);
}
} 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);
}

12
src/kprint/kprintf.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
// cross-platform kprintf analog
void kprintf(const char* format, ...);
#if __cplusplus
}
#endif

72
src/random/krandom.h Normal file
View File

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

View File

@@ -0,0 +1,34 @@
#include "splitmix64.h"
/*
This is a fixed-increment version of Java 8's SplittableRandom generator
See http://dx.doi.org/10.1145/2714064.2660195 and
http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
It is a very fast generator passing BigCrush, and it can be useful if
for some reason you absolutely want 64 bits of state; otherwise, we
rather suggest to use a xoroshiro128+ (for moderately parallel
computations) or xorshift1024* (for massively parallel computations)
generator.
*/
// The state can be seeded with any (upto) 64 bit integer value.
void* splitmix64_init(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);
}

View File

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

View File

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

View File

@@ -0,0 +1,49 @@
/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoroshiro64.h"
/*
This is xoroshiro64* 1.0, our best and fastest 32-bit small-state
generator for 32-bit floating-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;
}

View File

@@ -0,0 +1,37 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoroshiro64.h"
/* This is xoroshiro64** 1.0, our 32-bit all-purpose, rock-solid,
small-state generator. It is extremely fast and it passes all tests we
are aware of, but its state space is not large enough for any parallel
application.
For generating just single-precision (i.e., 32-bit) floating-point
numbers, xoroshiro64* is even faster.
The state must be seeded so that it is not everywhere zero. */
static inline 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;
}

View File

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

View File

@@ -0,0 +1,59 @@
/* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoroshiro128.h"
/* This is xoroshiro128+ 1.0, our best and fastest small-state generator
for floating-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;
}

View File

@@ -0,0 +1,39 @@
/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoroshiro128.h"
/* This is xoroshiro128++ 1.0, one of our all-purpose, rock-solid,
small-state generators. It is extremely (sub-ns) fast and it passes all
tests we are aware of, but its state space is large enough only for
mild parallelism.
For generating just floating-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;
}

View File

@@ -0,0 +1,39 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoroshiro128.h"
/* This is xoroshiro128** 1.0, one of our all-purpose, rock-solid,
small-state generators. It is extremely (sub-ns) fast and it passes all
tests we are aware of, but its state space is large enough only for
mild parallelism.
For generating just floating-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;
}

View File

@@ -0,0 +1,2 @@
#include "32bitValue/xoroshiro64.h"
#include "64bitValue/xoroshiro128.h"

View File

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

View File

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

View File

@@ -0,0 +1,54 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro128.h"
/* This is xoshiro128+ 1.0, our best and fastest 32-bit generator for 32-bit
floating-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;
}

View File

@@ -0,0 +1,42 @@
/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro128.h"
/* This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid
generators. It has excellent speed, a state size (128 bits) that is
large enough for mild parallelism, and it passes all tests we are aware
of.
For generating just single-precision (i.e., 32-bit) floating-point
numbers, xoshiro128+ is even faster.
The state must be seeded so that it is not everywhere zero. */
static inline 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;
}

View File

@@ -0,0 +1,45 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro128.h"
/* This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid
generators. It has excellent speed, a state size (128 bits) that is
large enough for mild parallelism, and it passes all tests we are aware
of.
Note that version 1.0 had mistakenly state->s[0] instead of state->s[1] as state
word passed to the scrambler.
For generating just single-precision (i.e., 32-bit) floating-point
numbers, xoshiro128+ is even faster.
The state must be seeded so that it is not everywhere zero. */
static inline 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;
}

View File

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

View File

@@ -0,0 +1,58 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro256.h"
/* This is xoshiro256+ 1.0, our best and fastest generator for floating-point
numbers. We suggest to use its upper bits for floating-point
generation, as it is slightly faster than xoshiro256++/xoshiro256**. It
passes all tests we are aware of except for the lowest three bits,
which might fail linearity tests (and just those), so if low linear
complexity is not considered an issue (as it is usually the case) it
can be used to generate 64-bit outputs, too.
We suggest to use a sign test to extract a random Boolean value, and
right shifts to extract subsets of bits.
The state must be seeded so that it is not everywhere zero. If you have
a 64-bit seed, we suggest to seed a splitmix64 generator and use its
output to fill s. */
static inline 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;
}

View File

@@ -0,0 +1,37 @@
/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro256.h"
/* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
It has excellent (sub-ns) speed, a state (256 bits) that is large
enough for any parallel application, and it passes all tests we are
aware of.
For generating just floating-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;
}

View File

@@ -0,0 +1,42 @@
/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "xoshiro256.h"
/* This is xoshiro256** 1.0, one of our all-purpose, rock-solid
generators. It has excellent (sub-ns) speed, a state (256 bits) that is
large enough for any parallel application, and it passes all tests we
are aware of.
For generating just floating-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;
}

View File

@@ -0,0 +1,2 @@
#include "32bitValue/xoshiro128.h"
#include "64bitValue/xoshiro256.h"