Compare commits

...

13 Commits

Author SHA1 Message Date
885ef7fea6 Hashtable 2023-10-27 14:21:29 +06:00
b6088845d9 removed elements freeing in autoarr 2023-10-27 14:21:10 +06:00
5ddc96e1b4 StringBuilder 2023-10-27 13:37:18 +06:00
e7280038fb typeof 2023-10-12 14:01:39 +06:00
14630e509d Autuarr 2023-07-10 18:31:16 +06:00
28169450cf LinearAllocator improved 2023-06-08 21:29:47 +06:00
8d36fd8042 string and StringBuilder 2023-06-08 18:41:05 +06:00
32ce7d3a70 some fixes 2023-06-08 15:59:52 +06:00
080bbb28fd random 2023-06-08 15:15:50 +06:00
c5585bbb0c refactoring 2023-06-08 15:15:38 +06:00
a983df1ac6 memory allocators 2023-06-05 14:10:00 +06:00
490d450a82 changed Autoarr field names 2023-06-05 13:56:14 +06:00
61da9ad161 memcpy 2023-06-05 13:55:00 +06:00
117 changed files with 1735 additions and 1773 deletions

4
.gitignore vendored
View File

@@ -4,6 +4,10 @@ obj/
# user files # user files
.old*/ .old*/
[Tt]mp/
[Tt]emp/
.[Tt]mp/
.[Tt]emp/
.vs/ .vs/
.vshistory/ .vshistory/
.editorconfig .editorconfig

10
.vscode/launch.json vendored
View File

@@ -42,16 +42,6 @@
"pipeArgs": ["-c"], "pipeArgs": ["-c"],
"pipeCwd": "${workspaceFolder}" "pipeCwd": "${workspaceFolder}"
} }
},
{
"name": "(msvc) Debug",
"type": "cppvsdbg",
"request": "launch",
"preLaunchTask": "build_dbg",
"program": "${workspaceFolder}\\bin\\kerep",
"cwd": "${workspaceFolder}\\bin",
"stopAtEntry": false,
"console": "integratedTerminal"
} }
] ]
} }

3
.vscode/tasks.json vendored
View File

@@ -23,8 +23,7 @@
"reveal": "always", "reveal": "always",
"focus": true, "focus": true,
"panel": "shared", "panel": "shared",
"showReuseMessage": false, "showReuseMessage": false
"clean": true
} }
} }
] ]

29
TODO.md Normal file
View File

@@ -0,0 +1,29 @@
## Allocators
- replace all malloc() and free() with allocator_alloc() and allocator_free()
- replace allocating constructors with Type_construct(var_ptr, ...)
- replace Struct_free functions with Struct_destruct which will not call free() on the struct ptr
- store in resizable structs their buffer allocators and free them with Struct_destruct()
- check allocator_free call order
- deal with StackingAllocator_free not freing memory sometimes
- replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize)
- use LinkedList instead of complicated LinearAllocator logic
- configurable LinearAllocator chunk size (static/growing)
## Autoarr
- store length and max_length inside the struct instead of calculating them by macro
- keep Autoarr_length() and Autoarr_maxLength() to old code compatibility
- toString()
## Hashtable
- store hash in KVPair
- don't use Autoarr in Hashtable
- make Hashtable generic struct
## Unitype
- replace UniPtrHeap with UniPtrStack
- do something with VoidPtr ownership
## String
- add `bool zero_terminated`
- rewrite all code to use `string` instead of `char*`
- rewrite `StringBuilder`

2
cbuild

Submodule cbuild updated: ef6a3f82c4...60fa8c11c2

View File

@@ -1,27 +0,0 @@
#include "Array.h"
Array_define(char)
Array_define(bool)
Array_define(f32)
Array_define(f64)
Array_define(i8)
Array_define(u8)
Array_define(i16)
Array_define(u16)
Array_define(i32)
Array_define(u32)
Array_define(i64)
Array_define(u64)
Array_define(Pointer)
Array_define(Unitype)
void Array_Unitype_free_(Array_Unitype* array, bool freeMembers){
if(freeMembers) for (u32 i=0; i<array->length; i++)
Unitype_free(array->values[i]);
if(array->allocatedOnHeap)
free(array->values);
}
void __Array_Unitype_free_(void* ar)
{ Array_Unitype_free_(ar, true); }

View File

@@ -1,32 +0,0 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "Array_declare.h"
#include "Array_define.h"
Array_declare(char)
Array_declare(bool)
Array_declare(f32)
Array_declare(f64)
Array_declare(i8)
Array_declare(u8)
Array_declare(i16)
Array_declare(u16)
Array_declare(i32)
Array_declare(u32)
Array_declare(i64)
Array_declare(u64)
Array_declare(Pointer)
Array_declare(Unitype)
/// use this function instead of auto generated
void Array_Unitype_free_(Array_Unitype* array, bool freeMembers);
void __Array_Unitype_free_(void* ar);
#if __cplusplus
}
#endif

View File

@@ -1,39 +0,0 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
#define Array_declare(type) \
STRUCT(Array_##type, \
type* values; \
u32 length; \
bool allocatedOnHeap; \
) \
\
static inline Array_##type Array_##type##_allocValues(u32 length){ \
return (Array_##type) { \
.values=(type*)malloc(sizeof(type)*length), \
.length=length, \
.allocatedOnHeap=true \
}; \
} \
\
static inline Array_##type Array_##type##_fromBuffer(type* buffer, u32 bufferLength, bool allocatedOnHeap){ \
return (Array_##type) { \
.values=buffer, \
.length=bufferLength, \
.allocatedOnHeap=allocatedOnHeap \
}; \
} \
\
static inline void Array_##type##_free(Array_##type* array){ \
if(array->allocatedOnHeap) \
free(array->values); \
}
#if __cplusplus
}
#endif

View File

@@ -1,14 +0,0 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/base.h"
#define Array_define(type) \
kt_define(Array_##type, (freeMembers_t)Array_##type##_free, NULL);
#if __cplusplus
}
#endif

View File

@@ -1,2 +0,0 @@
# 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` and defined in source file by `Array_define`.

View File

@@ -1,17 +1,17 @@
#include "Autoarr.h" #include "Autoarr.h"
Autoarr_define(Pointer, true) Autoarr_define(Pointer)
Autoarr_define(char, false) Autoarr_define(char)
Autoarr_define(bool, false) Autoarr_define(bool)
Autoarr_define(f32, false) Autoarr_define(f32)
Autoarr_define(f64, false) Autoarr_define(f64)
Autoarr_define(u8, false) Autoarr_define(u8)
Autoarr_define(i8, false) Autoarr_define(i8)
Autoarr_define(u16, false) Autoarr_define(u16)
Autoarr_define(i16, false) Autoarr_define(i16)
Autoarr_define(u32, false) Autoarr_define(u32)
Autoarr_define(i32, false) Autoarr_define(i32)
Autoarr_define(u64, false) Autoarr_define(u64)
Autoarr_define(i64, false) Autoarr_define(i64)
Autoarr_define(Unitype, false) Autoarr_define(Unitype)

View File

@@ -23,21 +23,6 @@ Autoarr_declare(u64)
Autoarr_declare(Unitype) Autoarr_declare(Unitype)
#define Autoarr_foreach(ar, elem, codeblock...) { \
if(ar->blocks_count>0) { \
typeof(**ar->values) elem; \
for(u16 blockI=0;blockI<ar->blocks_count-1;blockI++) \
for(u32 elemI=0;elemI<ar->max_block_length;elemI++){ \
elem=ar->values[blockI][elemI]; \
{ codeblock; } \
} \
for(u16 elemI=0;elemI<ar->block_length;elemI++){ \
elem=ar->values[ar->blocks_count-1][elemI]; \
{ codeblock; } \
} \
} \
}
#if __cplusplus #if __cplusplus
} }
#endif #endif

View File

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

View File

@@ -4,12 +4,12 @@ extern "C" {
#include "Autoarr.h" #include "Autoarr.h"
EXPORT void CALL kerep_Autoarr_Unitype_create(u16 max_blocks_count, u16 max_block_length, Autoarr_Unitype** output){ EXPORT void CALL kerep_Autoarr_Unitype_create(u16 max_chunks_count, u16 max_chunk_length, Autoarr_Unitype** output){
*output=Autoarr_create(Unitype, max_blocks_count, max_block_length); *output=Autoarr_construct(Unitype, max_chunks_count, max_chunk_length);
} }
EXPORT void CALL kerep_Autoarr_Unitype_free(Autoarr_Unitype* ar){ EXPORT void CALL kerep_Autoarr_Unitype_destruct(Autoarr_Unitype* ar){
Autoarr_free(ar, true); Autoarr_destruct(ar, true);
} }
EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, u32 index, Unitype* output){ EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, u32 index, Unitype* output){

View File

@@ -6,67 +6,60 @@ extern "C" {
#include "../base/base.h" #include "../base/base.h"
#define Autoarr_declare(type) \ #define Autoarr_declare(TYPE) \
\ \
struct Autoarr_##type; \ typedef struct Autoarr_##TYPE Autoarr_##TYPE; \
\ \
typedef struct __Autoarr_##type##_functions_list_t { \ typedef struct __Autoarr_##TYPE##_functions_list_t { \
void (*add)(struct Autoarr_##type* ar, type element); \ void (*add)(Autoarr_##TYPE* ar, TYPE element); \
type (*get)(struct Autoarr_##type* ar, u32 index); \ TYPE (*get)(Autoarr_##TYPE* ar, u32 index); \
type* (*getPtr)(struct Autoarr_##type* ar, u32 index); \ TYPE* (*getPtr)(Autoarr_##TYPE* ar, u32 index); \
void (*set)(struct Autoarr_##type* ar, u32 index, type element); \ void (*set)(Autoarr_##TYPE* ar, u32 index, TYPE element); \
void (*freeWithMembers)(struct Autoarr_##type* ar, bool freePtr); \ TYPE* (*toArray)(Autoarr_##TYPE* ar, allocator_ptr array_holder); \
void (*freeWithoutMembers)(struct Autoarr_##type* ar, bool freePtr); \ } __Autoarr_##TYPE##_functions_list_t; \
type* (*toArray)(struct Autoarr_##type* ar); \
} __Autoarr_##type##_functions_list_t; \
\ \
extern __Autoarr_##type##_functions_list_t __Autoarr_##type##_functions_list; \ STRUCT(Autoarr_##TYPE, \
\ InternalAllocator_declare(LinearAllocator); \
STRUCT(Autoarr_##type, \ __Autoarr_##TYPE##_functions_list_t* functions; \
u16 blocks_count; \ ktDescriptor* type; \
u16 max_blocks_count; \ u32 length; \
u16 block_length; \ TYPE* _typeof_target; \
u16 max_block_length; \
type** values; \
__Autoarr_##type##_functions_list_t* functions; \
) \ ) \
\ \
Autoarr_##type* __Autoarr_##type##_create(u16 max_blocks_count, u16 max_block_length); \ void __Autoarr_##TYPE##_construct(Autoarr_##TYPE* ar, alloc_size_t starting_size, allocator_ptr external_al); \
void __Autoarr_##type##_freeWithMembers(Autoarr_##type* ar, bool freePtr); \ void __Autoarr_##TYPE##_destruct(Autoarr_##TYPE* ar); \
void ____Autoarr_##type##_freeWithMembers(void* ar);
#define Autoarr(type) Autoarr_##type #define Autoarr(TYPE) Autoarr_##TYPE
#define Autoarr_create(type, max_blocks_count, max_block_length) \ #define Autoarr_construct(ptr, TYPE, starting_size, data_allocator) \
__Autoarr_##type##_create(max_blocks_count, max_block_length) __Autoarr_##TYPE##_construct(ptr, starting_size, data_allocator)
#define Autoarr_add(autoarr, element) \ #define Autoarr_destruct(autoarr) (autoarr)->type->destruct(autoarr)
autoarr->functions->add(autoarr, element) #define Autoarr_add(autoarr, element) (autoarr)->functions->add(autoarr, element)
#define Autoarr_get(autoarr, index) \ #define Autoarr_get(autoarr, index) (autoarr)->functions->get(autoarr,index)
autoarr->functions->get(autoarr,index) #define Autoarr_getPtr(autoarr, index) (autoarr)->functions->getPtr(autoarr,index)
#define Autoarr_getPtr(autoarr, index) \ #define Autoarr_set(autoarr, index, element) (autoarr)->functions->set(autoarr, index, element)
autoarr->functions->getPtr(autoarr,index) #define Autoarr_toArray(autoarr, array_alloctr) (autoarr)->functions->toArray(autoarr, array_alloctr)
#define Autoarr_set(autoarr, index, element) \ #define Autoarr_length(autoarr) (autoarr)->length
autoarr->functions->set(autoarr, index, element) #define Autoarr_pop(autoarr) { \
#define Autoarr_free(autoarr, freePtr) \ u32 new_len=(autoarr)->length-1; \
autoarr->functions->freeWithMembers(autoarr, freePtr) allocator_free(InternalAllocator_getPtr((autoarr)), Autoarr_getPtr((autoarr), new_len)); \
#define Autoarr_freeWithoutMembers(autoarr, freePtr) \ (autoarr)->length=new_len; \
autoarr->functions->freeWithoutMembers(autoarr, freePtr) }
#define Autoarr_toArray(autoarr) \
autoarr->functions->toArray(autoarr)
#define Autoarr_length(autoarr) \ #define Autoarr_foreach(ar, elem, codeblock...) { \
(u32)(!autoarr->blocks_count ? 0 : \ if((ar)->length > 0) { \
autoarr->max_block_length*(autoarr->blocks_count-1)+autoarr->block_length) typeof(*((ar)->_typeof_target)) elem; \
#define Autoarr_max_length(autoarr) \ LinearAllocator* al=(LinearAllocator*)InternalAllocator_getPtr(ar); \
(u32)(autoarr->max_block_length*autoarr->max_blocks_count) for(u16 chunk_i=0; chunk_i <= al->curr_chunk_i; chunk_i++) { \
MemoryChunk chunk = al->chunks[chunk_i]; \
#define Autoarr_pop(AR){ \ alloc_size_t chunk_elem_count = chunk.occupied_size/sizeof(elem); \
if(AR->block_length==1){ \ typeof((ar)->_typeof_target) chunk_data = (void*)chunk.data; \
AR->blocks_count--; \ for(u32 elem##_i=0; elem##_i < chunk_elem_count; elem##_i++) { \
AR->block_length=AR->max_block_length; \ elem = chunk_data[elem##_i]; \
free(AR->values[AR->blocks_count]); \ { codeblock; } \
} \
} \
} \ } \
else AR->block_length--; \
} }
#if __cplusplus #if __cplusplus

View File

@@ -6,94 +6,72 @@ extern "C" {
#include "../base/base.h" #include "../base/base.h"
#define Autoarr_define(type, TYPE_IS_PTR) \ #define Autoarr_define(TYPE) \
\ \
kt_define(Autoarr_##type, ____Autoarr_##type##_freeWithMembers, NULL); \ void __Autoarr_##TYPE##_add(Autoarr_##TYPE* ar, TYPE element){ \
TYPE* ptr = allocator_alloc(InternalAllocator_getPtr(ar), sizeof(element)); \
*ptr=element; \
ar->length++; \
} \
\ \
void __Autoarr_##type##_add(Autoarr_##type* ar, type element){ \ TYPE* __Autoarr_##TYPE##_getPtr(Autoarr_##TYPE* ar, u32 index){ \
if(!ar->values){ \ if(index >= Autoarr_length(ar)) \
ar->values=malloc(ar->max_blocks_count*sizeof(type*)); \ throw(ERR_WRONGINDEX); \
goto create_block; \ u32 elem_count_sum=0; \
LinearAllocator* al=(LinearAllocator*)InternalAllocator_getPtr(ar); \
for(u16 chunk_i=0; chunk_i <= al->curr_chunk_i; chunk_i++) { \
MemoryChunk chunk = al->chunks[chunk_i]; \
alloc_size_t chunk_elem_count = chunk.occupied_size/sizeof(TYPE); \
alloc_size_t chunk_elem_i = index - elem_count_sum; \
if(chunk_elem_i < chunk_elem_count){ \
return chunk.data + chunk_elem_i*sizeof(TYPE); \
} \ } \
if(ar->block_length==ar->max_block_length){ \ elem_count_sum += chunk_elem_count; \
if (ar->blocks_count>=ar->max_blocks_count) throw(ERR_MAXLENGTH); \
ar->block_length=0; \
create_block: \
ar->values[ar->blocks_count]=malloc(ar->max_block_length*sizeof(type)); \
ar->blocks_count++; \
} \ } \
ar->values[ar->blocks_count-1][ar->block_length]=element; \ return NULL; \
ar->block_length++; \
} \ } \
\ \
type __Autoarr_##type##_get(Autoarr_##type* ar, u32 index){ \ TYPE __Autoarr_##TYPE##_get(Autoarr_##TYPE* ar, u32 index){ \
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \ TYPE* ptr=__Autoarr_##TYPE##_getPtr(ar, index); \
return ar->values[index/ar->max_block_length][index%ar->max_block_length]; \ return *ptr; \
} \ } \
\ \
type* __Autoarr_##type##_getPtr(Autoarr_##type* ar, u32 index){ \ void __Autoarr_##TYPE##_set(Autoarr_##TYPE* ar, u32 index, TYPE value){ \
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \ TYPE* ptr=__Autoarr_##TYPE##_getPtr(ar, index); \
return ar->values[index/ar->max_block_length]+(index%ar->max_block_length); \ *ptr=value; \
} \ } \
\ \
void __Autoarr_##type##_set(Autoarr_##type* ar, u32 index, type element){ \ void __Autoarr_##TYPE##_destruct(Autoarr_##TYPE* ar){ \
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \ InternalAllocator_destructIfInternal(LinearAllocator, ar); \
ar->values[index/ar->max_block_length][index%ar->max_block_length]=element; \
} \ } \
\ \
void __Autoarr_##type##_freeWithoutMembers(Autoarr_##type* ar, bool freePtr){ \ TYPE* __Autoarr_##TYPE##_toArray(Autoarr_##TYPE* ar, allocator_ptr array_alloctr){ \
for(u16 i=0; i<ar->blocks_count;i++) \
free(ar->values[i]); \
free(ar->values); \
if(freePtr) free(ar); \
} \
\
void __Autoarr_##type##_freeWithMembers(Autoarr_##type* ar, bool freePtr){ \
if(ktDescriptor_##type.freeMembers!=NULL) { \
Autoarr_foreach(ar, el, \
void* members_ptr=&el; \
if(TYPE_IS_PTR) members_ptr=*(type**)members_ptr; \
ktDescriptor_##type.freeMembers(members_ptr); \
); \
} \
__Autoarr_##type##_freeWithoutMembers(ar, freePtr);\
} \
void ____Autoarr_##type##_freeWithMembers(void* ar){ \
__Autoarr_##type##_freeWithMembers((Autoarr_##type*)ar, false); \
} \
\
type* __Autoarr_##type##_toArray(Autoarr_##type* ar){ \
u32 length=Autoarr_length(ar); \ u32 length=Autoarr_length(ar); \
if(length==0) \ if(length==0) \
return NULL; \ return NULL; \
type* array=malloc(length * sizeof(type)); \ TYPE* array=allocator_alloc(array_alloctr, length); \
for(u32 i=0; i<length; i++) \ Autoarr_foreach(ar, el, { \
array[i]=__Autoarr_##type##_get(ar, i); \ array[el_i]=el; \
}); \
return array; \ return array; \
} \ } \
\ \
__Autoarr_##type##_functions_list_t __Autoarr_##type##_functions_list={ \ __Autoarr_##TYPE##_functions_list_t __Autoarr_##TYPE##_functions_list={ \
&__Autoarr_##type##_add, \ &__Autoarr_##TYPE##_add, \
&__Autoarr_##type##_get, \ &__Autoarr_##TYPE##_get, \
&__Autoarr_##type##_getPtr, \ &__Autoarr_##TYPE##_getPtr, \
&__Autoarr_##type##_set, \ &__Autoarr_##TYPE##_set, \
&__Autoarr_##type##_freeWithMembers, \ &__Autoarr_##TYPE##_toArray \
&__Autoarr_##type##_freeWithoutMembers, \
&__Autoarr_##type##_toArray \
}; \ }; \
\ \
Autoarr_##type* __Autoarr_##type##_create(u16 max_blocks_count, u16 max_block_length){ \ void __Autoarr_##TYPE##_construct(Autoarr_##TYPE* ar, alloc_size_t starting_size, allocator_ptr data_allocator){ \
Autoarr_##type* ar=malloc(sizeof(Autoarr_##type)); \ InternalAllocator_setExternalOrConstruct(ar, data_allocator, LinearAllocator, starting_size); \
*ar=(Autoarr_##type){ \ ar->functions=&__Autoarr_##TYPE##_functions_list; \
.max_blocks_count=max_blocks_count, \ ar->type = &ktDescriptor_name(TYPE); \
.blocks_count=0, \ ar->length=0; \
.max_block_length=max_block_length, \ } \
.block_length=0, \ \
.values=NULL, \ kt_define(Autoarr_##TYPE, (destruct_t)__Autoarr_##TYPE##_destruct, NULL);
.functions=&__Autoarr_##type##_functions_list \
}; \
return ar; \
}
#if __cplusplus #if __cplusplus
} }

View File

@@ -25,6 +25,6 @@ bool DtsodV24_remove(Hashtable* dtsod, char* key){
} }
// frees memory including memory of elements (hashtables, autoarrs, etc.) // frees memory including memory of elements (hashtables, autoarrs, etc.)
void DtsodV24_free(Hashtable* dtsod){ void DtsodV24_destruct(Hashtable* dtsod){
Hashtable_free(dtsod); Hashtable_destruct(dtsod);
} }

View File

@@ -25,7 +25,7 @@ bool DtsodV24_contains(Hashtable* dtsod, char* key);
bool DtsodV24_remove(Hashtable* dtsod, char* key); bool DtsodV24_remove(Hashtable* dtsod, char* key);
// frees memory including memory of elements (hashtables, autoarrs, etc.) // frees memory including memory of elements (hashtables, autoarrs, etc.)
void DtsodV24_free(Hashtable* dtsod); void DtsodV24_destruct(Hashtable* dtsod);
#if __cplusplus #if __cplusplus
} }

View File

@@ -1,8 +1,7 @@
#include "DtsodV24.h" #include "DtsodV24.h"
#include "../String/StringBuilder.h" #include "../String/StringBuilder.h"
#define ARR_BC 64 #define ARR_SZ_START 64
#define ARR_BL 1024
typedef struct DeserializeSharedData{ typedef struct DeserializeSharedData{
@@ -10,11 +9,13 @@ typedef struct DeserializeSharedData{
char* sh_text; char* sh_text;
bool sh_partOfDollarList; bool sh_partOfDollarList;
bool sh_calledRecursively; bool sh_calledRecursively;
allocator_ptr sh_tmp_al;
} DeserializeSharedData; } DeserializeSharedData;
#define text shared->sh_text #define text shared->sh_text
#define partOfDollarList shared->sh_partOfDollarList #define partOfDollarList shared->sh_partOfDollarList
#define calledRecursively shared->sh_calledRecursively #define calledRecursively shared->sh_calledRecursively
#define tmp_al shared->sh_tmp_al
// special func for throwing error messages about wrong characters in deserializing text // special func for throwing error messages about wrong characters in deserializing text
@@ -44,16 +45,10 @@ Maybe ERROR_WRONGCHAR(const char c, char* _text, char* text_first, const char* s
if(!_c) break; if(!_c) break;
} }
char errmsg[1024]; char errmsg[1024];
IFMSC( sprintf_s(errmsg, sizeof(errmsg), "unexpected <%c> at:\n"
sprintf_s(errmsg,1024, "unexpected <%c> at:\n"
" \"%s\"\n" " \"%s\"\n"
"\\___[%s:%d] %s()", "\\___[%s:%d] %s()",
c,errBuf, srcfile,line,funcname), c,errBuf, srcfile,line,funcname);
sprintf(errmsg, "unexpected <%c> at:\n"
" \"%s\"\n"
" \\___[%s:%d] %s()",
c,errBuf, srcfile,line,funcname)
);
safethrow(errmsg,;); safethrow(errmsg,;);
} }
#define safethrow_wrongchar(C, freeMem) { freeMem; return ERROR_WRONGCHAR(C, text, shared->sh_text_first, __FILE__,__LINE__,__func__); } #define safethrow_wrongchar(C, freeMem) { freeMem; return ERROR_WRONGCHAR(C, text, shared->sh_text_first, __FILE__,__LINE__,__func__); }
@@ -100,7 +95,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
safethrow_wrongchar(c,;); safethrow_wrongchar(c,;);
return SUCCESS(UniHeapPtr(char,NULL)); return SUCCESS(UniHeapPtr(char,NULL));
case ':': case ':':
return SUCCESS(UniHeapPtr(char,string_extract(nameStr))); return SUCCESS(UniHeapPtr(char,string_extract(tmp_al, nameStr)));
case '$': case '$':
if(nameStr.length!=0) if(nameStr.length!=0)
safethrow_wrongchar(c,;); safethrow_wrongchar(c,;);
@@ -117,7 +112,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
} }
#define ReadName() __ReadName(shared) #define ReadName() __ReadName(shared)
Maybe __deserialize(char** _text, bool _calledRecursively); Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al);
Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList); Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
#define ReadValue(rL) __ReadValue(shared, rL) #define ReadValue(rL) __ReadValue(shared, rL)
@@ -125,7 +120,9 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
Maybe __ReadString(DeserializeSharedData* shared){ Maybe __ReadString(DeserializeSharedData* shared){
char c; char c;
bool prevIsBackslash=false; bool prevIsBackslash=false;
StringBuilder* b=StringBuilder_create(); StringBuilder _sb;
StringBuilder* b=&_sb;
StringBuilder_construct(b, tmp_al);
while ((c=*++text)){ while ((c=*++text)){
if(c=='"') { if(c=='"') {
@@ -146,24 +143,25 @@ Maybe __ReadString(DeserializeSharedData* shared){
} }
} }
safethrow(ERR_ENDOFSTR, StringBuilder_free(b)); safethrow(ERR_ENDOFSTR, StringBuilder_destruct(b));
} }
#define ReadString() __ReadString(shared) #define ReadString() __ReadString(shared)
Maybe __ReadList(DeserializeSharedData* shared){ Maybe __ReadList(DeserializeSharedData* shared){
Autoarr(Unitype)* list=Autoarr_create(Unitype,ARR_BC,ARR_BL); Autoarr(Unitype) list;
Autoarr_construct(&list, Unitype, ARR_SZ_START, NULL);
bool readingList=true; bool readingList=true;
while (true){ while (true){
try(ReadValue((&readingList)), m_val, Autoarr_free(list, true)) try(ReadValue((&readingList)), m_val, Autoarr_destruct(&list))
Autoarr_add(list,m_val.value); Autoarr_add(&list, m_val.value);
if (!readingList){ if (!readingList){
if(Unitype_isUniNull(m_val.value)) if(Unitype_isUniNull(m_val.value))
Autoarr_pop(list); Autoarr_pop(&list);
break; break;
} }
} }
return SUCCESS(UniHeapPtr(Autoarr_Unitype,list)); return SUCCESS(UniHeapPtr(Autoarr_Unitype, &list));
}; };
#define ReadList() __ReadList(shared) #define ReadList() __ReadList(shared)
@@ -181,40 +179,34 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){
else safethrow_wrongchar(*str.ptr,;); else safethrow_wrongchar(*str.ptr,;);
// Float64 // Float64
case 'f': { case 'f': {
char* _c=string_extract(str); char* _c=string_extract(tmp_al, str);
Unitype rez=UniFloat64(strtod(_c,NULL)); Unitype rez=UniFloat64(strtod(_c,NULL));
free(_c); // allocator_free(tmp_al,_c);
return SUCCESS(rez); return SUCCESS(rez);
} }
// UInt64 // UInt64
case 'u': { case 'u': {
u64 lu=0; u64 lu=0;
char* _c=string_extract(str); char* _c=string_extract(tmp_al, str);
if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){ if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){
char err[64]; char err[64];
IFMSC( sprintf_s(err, sizeof(err), "can't parse to int: <%s>", _c);
sprintf_s(err,64,"can't parse to int: <%s>",_c), safethrow(err, /*allocator_free(tmp_al, _c)*/);
sprintf(err,"can't parse to int: <%s>",_c)
);
safethrow(err,free(_c));
} }
free(_c); // allocator_free(tmp_al, _c);
return SUCCESS(UniUInt64(lu)); return SUCCESS(UniUInt64(lu));
} }
// Int64 // Int64
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': { case '5': case '6': case '7': case '8': case '9': {
i64 li=0; i64 li=0;
char* _c=string_extract(str); char* _c=string_extract(tmp_al, str);
if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){ if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){
char err[64]; char err[64];
IFMSC( sprintf_s(err, sizeof(err),"can't parse to int: <%s>",_c);
sprintf_s(err,64,"can't parse to int: <%s>",_c), // safethrow(err,allocator_free(tmp_al, _c));
sprintf(err,"can't parse to int: <%s>",_c)
);
safethrow(err,free(_c));
} }
free(_c); // allocator_free(tmp_al, _c);
return SUCCESS(UniInt64(li)); return SUCCESS(UniInt64(li));
} }
// wrong type // wrong type
@@ -242,35 +234,35 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
case '=': case ':': case '=': case ':':
case '}': case '$': case '}': case '$':
case '\'': case '\'':
safethrow_wrongchar(c,Unitype_free(value)); safethrow_wrongchar(c,Unitype_destruct(&value));
case '#':; case '#':;
char _c=c; char _c=c;
char* _text=text; char* _text=text;
try(SkipComment(),_,;); try(SkipComment(),_,;);
if(valueStr.length!=0){ if(valueStr.length!=0){
text=_text; text=_text;
safethrow_wrongchar(_c,Unitype_free(value)); safethrow_wrongchar(_c,Unitype_destruct(&value));
} }
valueStr.ptr=text+1; // skips '\n' valueStr.ptr=text+1; // skips '\n'
break; break;
case '"': case '"':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value)); if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
try(ReadString(),maybeString,;) try(ReadString(),maybeString,;)
value=maybeString.value; value=maybeString.value;
break; break;
case '{': case '{':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value)); if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
++text; // skips '{' ++text; // skips '{'
try(__deserialize(&text,true), val,Unitype_free(value)) try(__deserialize(&text,true,tmp_al), val, Unitype_destruct(&value))
value=val.value; value=val.value;
break; break;
case '[': case '[':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value)); if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
try(ReadList(),maybeList,Unitype_free(value)) try(ReadList(),maybeList,Unitype_destruct(&value))
value=maybeList.value; value=maybeList.value;
break; break;
case ']': case ']':
if(!readingList) safethrow_wrongchar(c,Unitype_free(value)); if(!readingList) safethrow_wrongchar(c,Unitype_destruct(&value));
*readingList=false; *readingList=false;
goto return_value; goto return_value;
case ';': case ';':
@@ -278,14 +270,14 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
return_value: return_value:
if(valueStr.length!=0){ if(valueStr.length!=0){
if(!Unitype_isUniNull(value)) if(!Unitype_isUniNull(value))
safethrow_wrongchar(c,Unitype_free(value)); safethrow_wrongchar(c,Unitype_destruct(&value));
try(ParseValue(valueStr),maybeParsed,;) try(ParseValue(valueStr),maybeParsed,;)
value=maybeParsed.value; value=maybeParsed.value;
} }
return SUCCESS(value); return SUCCESS(value);
default: default:
if(spaceAfterVal) if(spaceAfterVal)
safethrow_wrongchar(c,Unitype_free(value)); safethrow_wrongchar(c,Unitype_destruct(&value));
valueStr.length++; valueStr.length++;
break; break;
} }
@@ -294,25 +286,29 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
} }
Maybe __deserialize(char** _text, bool _calledRecursively) { Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al) {
DeserializeSharedData _shared={ DeserializeSharedData _shared={
.sh_text_first=*_text, .sh_text_first=*_text,
.sh_text=*_text, .sh_text=*_text,
.sh_partOfDollarList=false, .sh_partOfDollarList=false,
.sh_calledRecursively=_calledRecursively .sh_calledRecursively=_calledRecursively,
.sh_tmp_al=_tmp_al
}; };
DeserializeSharedData* shared=&_shared; DeserializeSharedData* shared=&_shared;
Hashtable* dict=Hashtable_create(); Hashtable _dict;
Hashtable* dict = &_dict;
Hashtable_construct(dict, _tmp_al);
text--; text--;
while(true){ while(true){
try(ReadName(), maybeName, Hashtable_free(dict)) try(ReadName(), maybeName, Hashtable_destruct(dict))
if(!maybeName.value.VoidPtr) // end of file or '}' in recursive call if(!maybeName.value.VoidPtr) // end of file or '}' in recursive call
goto END; goto END;
char* nameCPtr=maybeName.value.VoidPtr; char* nameCPtr=maybeName.value.VoidPtr;
try(ReadValue(NULL), val, { try(ReadValue(NULL), val, {
Hashtable_free(dict); Hashtable_destruct(dict);
free(nameCPtr); // do not use, free call order is incorrect
// allocator_free(tmp_al, nameCPtr);
}) { }) {
if(partOfDollarList){ if(partOfDollarList){
partOfDollarList=false; partOfDollarList=false;
@@ -322,10 +318,12 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
list=(Autoarr(Unitype)*)lu.VoidPtr; list=(Autoarr(Unitype)*)lu.VoidPtr;
// Key is not used in that case, because it is already added // Key is not used in that case, because it is already added
// to the table with the first dollar list item. // to the table with the first dollar list item.
free(nameCPtr); // do not use, free call order is incorrect
// allocator_free(tmp_al, nameCPtr);
} }
else{ else{
list=Autoarr_create(Unitype,ARR_BC,ARR_BL); list=allocator_alloc(tmp_al, sizeof(*list));
Autoarr_construct(list, Unitype, ARR_SZ_START, NULL);
Hashtable_add(dict,nameCPtr,UniHeapPtr(Autoarr_Unitype,list)); Hashtable_add(dict,nameCPtr,UniHeapPtr(Autoarr_Unitype,list));
} }
Autoarr_add(list,val.value); Autoarr_add(list,val.value);
@@ -340,5 +338,9 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
} }
Maybe DtsodV24_deserialize(char* _text) { Maybe DtsodV24_deserialize(char* _text) {
return __deserialize(&_text, false); LinearAllocator _tmp_al;
LinearAllocator_construct(&_tmp_al, 1024);
Maybe m=__deserialize(&_text, false, (allocator_ptr)&_tmp_al);
LinearAllocator_destruct(&_tmp_al);
return m;
} }

View File

@@ -1,62 +0,0 @@
//
// I planned to export functions from DtsodV24.h,
// but C# P/Invoke can't get returned values for some reason.
// Following functions return values by pointer, which looks in C# like out parameter
//
#if __cplusplus
extern "C" {
#endif
#include "DtsodV24.h"
// parses text to binary values
EXPORT void CALL kerep_DtsodV24_deserialize(char* text, Hashtable** output, char** errmsg){
Maybe r=DtsodV24_deserialize(text);
*errmsg=r.errmsg;
*output=r.value.VoidPtr;
}
// creates text representation of dtsod
EXPORT void CALL kerep_DtsodV24_serialize(Hashtable* dtsod, char** output, char** errmsg){
Maybe r=DtsodV24_serialize(dtsod);
*errmsg=r.errmsg;
*output=r.value.VoidPtr;
}
// returns value or UniNull if key not found
EXPORT void CALL kerep_DtsodV24_get(Hashtable* dtsod, char* key, Unitype* output){
*output=DtsodV24_get(dtsod, key);
}
// adds or sets the value
EXPORT void CALL kerep_DtsodV24_addOrSet(Hashtable* dtsod, char* key, Unitype value){
DtsodV24_addOrSet(dtsod, key, value);
}
// checks for dtsod contains value or dont
EXPORT void CALL kerep_DtsodV24_contains(Hashtable* dtsod, char* key, bool* output){
*output=DtsodV24_contains(dtsod, key);
}
// replaces value with UniNull if key exists in dtsod
EXPORT void CALL kerep_DtsodV24_remove(Hashtable* dtsod, char* key, bool* output){
*output=DtsodV24_remove(dtsod, key);
}
// replaces value with UniNull if key exists in dtsod
EXPORT void CALL kerep_DtsodV24_free(Hashtable* dtsod){
DtsodV24_free(dtsod);
}
EXPORT void CALL kerep_DtsodV24_height(Hashtable* dtsod, u16* heigth){
*heigth=Hashtable_height(dtsod);
}
EXPORT void CALL kerep_DtsodV24_getrow(Hashtable* dtsod, u16 h, Autoarr_KVPair** row){
*row=dtsod->rows[h];
}
#if __cplusplus
}
#endif

View File

@@ -123,8 +123,13 @@ Maybe __serialize(StringBuilder* _b, u8 _tabs, Hashtable* dtsod){
} }
Maybe DtsodV24_serialize(Hashtable* dtsod){ Maybe DtsodV24_serialize(Hashtable* dtsod){
StringBuilder* sb=StringBuilder_create(); LinearAllocator _al; allocator_ptr al=(allocator_ptr)&_al;
try(__serialize(sb,0,dtsod),__, StringBuilder_free(sb)); LinearAllocator_construct(&_al, 512);
StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
try(__serialize(sb,0,dtsod),__, StringBuilder_destruct(sb); LinearAllocator_destruct(&_al););
char* str=StringBuilder_build(sb).ptr; char* str=StringBuilder_build(sb).ptr;
LinearAllocator_destruct(&_al);
return SUCCESS(UniHeapPtr(char, str)); return SUCCESS(UniHeapPtr(char, str));
} }

View File

@@ -26,9 +26,10 @@ bool dir_exists(const char* path){
Maybe dir_create(const char* path){ Maybe dir_create(const char* path){
if (dir_exists(path)) if (dir_exists(path))
return MaybeNull; return MaybeNull;
char* parentDir=path_parentDir(path); LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
char* parentDir=path_parentDir(al, path);
dir_create(parentDir); dir_create(parentDir);
free(parentDir);
#if KFS_USE_WINDOWS_H #if KFS_USE_WINDOWS_H
if(!CreateDirectory(path, NULL)) if(!CreateDirectory(path, NULL))
#else #else
@@ -36,12 +37,10 @@ Maybe dir_create(const char* path){
#endif #endif
{ {
char err[512]; char err[512];
IFWIN( sprintf_s(err, sizeof(err), "can't create dicectory <%s>", path);
sprintf_s(err, 512, "can't create dicectory <%s>", path), safethrow(err, LinearAllocator_destruct(&_al));
sprintf(err, "can't create dicectory <%s>", path));
safethrow(err,;);
} }
LinearAllocator_destruct(&_al);
return MaybeNull; return MaybeNull;
} }

View File

@@ -2,9 +2,9 @@
#include "../String/StringBuilder.h" #include "../String/StringBuilder.h"
#include "io_includes.h" #include "io_includes.h"
void __file_freeMembers(void* _f){ fclose((FileHandle)_f); } void __file_destructMembers(void* _f){ fclose((FileHandle)_f); }
kt_define(FileHandle, __file_freeMembers, NULL) kt_define(FileHandle, __file_destructMembers, NULL)
bool file_exists(const char* path){ bool file_exists(const char* path){
if(path[0]=='.'){ if(path[0]=='.'){
@@ -50,8 +50,11 @@ char* FileOpenMode_toStr(FileOpenMode m){
Maybe file_open(const char* path, FileOpenMode mode){ Maybe file_open(const char* path, FileOpenMode mode){
FileHandle file=fopen(path, FileOpenMode_toStr(mode)); FileHandle file=fopen(path, FileOpenMode_toStr(mode));
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
if(!file) if(!file)
safethrow(cptr_concat("can't open file ", (char*)path),;); safethrow(cptr_concat(al, "can't open file ", (char*)path), LinearAllocator_destruct(&_al));
LinearAllocator_destruct(&_al);
return SUCCESS(UniHeapPtr(FileHandle,file)); return SUCCESS(UniHeapPtr(FileHandle,file));
} }
@@ -112,13 +115,15 @@ Maybe file_readAll(FileHandle file, char** allBytes){
i32 rezult=0; i32 rezult=0;
char buffer[256]; char buffer[256];
string bufStr={.ptr=buffer, .length=sizeof(buffer)}; string bufStr={.ptr=buffer, .length=sizeof(buffer)};
StringBuilder* sb=StringBuilder_create(); StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, NULL);
u64 i=0; u64 i=0;
while(true){ while(true){
rezult=fgetc(file); rezult=fgetc(file);
if(rezult==EOF){ if(rezult==EOF){
if(ferror(file)) if(ferror(file))
safethrow(ERR_IO, StringBuilder_free(sb)); safethrow(ERR_IO, StringBuilder_destruct(sb));
break; break;
} }
buffer[i%sizeof(buffer)]=(char)rezult; buffer[i%sizeof(buffer)]=(char)rezult;

View File

@@ -5,7 +5,6 @@ extern "C" {
#endif #endif
#include "../base/base.h" #include "../base/base.h"
#include "../Array/Array.h"
#include "../String/string.h" #include "../String/string.h"
typedef FILE* FileHandle; typedef FILE* FileHandle;

View File

@@ -1,8 +1,8 @@
#include "filesystem.h" #include "filesystem.h"
char* __path_concat(u32 n, ...){ char* __path_concat(allocator_ptr al, u32 n, ...){
char** parts=(char**)malloc(n*sizeof(char*)); char** parts=(char**)allocator_alloc(al, n*sizeof(char*));
u32* lengths=malloc(n*sizeof(u32)); u32* lengths=allocator_alloc(al, n*sizeof(u32));
u32 totalLength=0; u32 totalLength=0;
// reading args from va_list // reading args from va_list
@@ -18,27 +18,27 @@ char* __path_concat(u32 n, ...){
va_end(vl); va_end(vl);
// allocating memory for output value // allocating memory for output value
char* totality=malloc(totalLength+1); char* totality=allocator_alloc(al, totalLength+1);
const char* output=totality; const char* output=totality;
totality[totalLength]=0; totality[totalLength]=0;
// copying content of all strings to rezult // copying content of all strings to rezult
u16 k=0; u16 k=0;
for(; k<n-1; k++){ for(; k<n-1; k++){
memcopy(parts[k], totality, lengths[k]); memcpy(totality, parts[k], lengths[k]);
totality+=lengths[k]; totality+=lengths[k];
*totality=path_sep; *totality=path_sep;
totality++; totality++;
} }
memcopy(parts[k], totality, lengths[k]); memcpy(totality, parts[k], lengths[k]);
free(parts); allocator_free(al, lengths);
free(lengths); allocator_free(al, parts);
return output; return output;
} }
char* path_fixSeparators(const char* path){ char* path_fixSeparators(allocator_ptr al, const char* path){
char* pathCopy=cptr_copy(path); char* pathCopy=cptr_copy(al, path);
char c; char c;
while((c=*pathCopy)){ while((c=*pathCopy)){
if(c==path_notSep) if(c==path_notSep)
@@ -49,13 +49,17 @@ char* path_fixSeparators(const char* path){
} }
Maybe path_throwIfEscapes(const char* path){ Maybe path_throwIfEscapes(const char* path){
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
if(cptr_contains(path,"..")) if(cptr_contains(path,".."))
safethrow(cptr_concat("path <",path,"> uses <..>, that's not allowed"),); safethrow(cptr_concat(al, "path <",path,"> uses <..>, that's not allowed"),
LinearAllocator_destruct(&_al));
LinearAllocator_destruct(&_al);
return MaybeNull; return MaybeNull;
} }
char* path_parentDir(char* dir){ char* path_parentDir(allocator_ptr al, char* dir){
char* copy=cptr_copy(dir); char* copy=cptr_copy(al, dir);
i32 length=cptr_length(copy); i32 length=cptr_length(copy);
i32 i=cptr_lastIndexOfChar(copy,path_sep); i32 i=cptr_lastIndexOfChar(copy,path_sep);
if(i!=-1 && i==length-1){ if(i!=-1 && i==length-1){
@@ -63,8 +67,8 @@ char* path_parentDir(char* dir){
i=cptr_lastIndexOfChar(copy,path_sep); i=cptr_lastIndexOfChar(copy,path_sep);
} }
if(i==-1){ if(i==-1){
free(copy); allocator_free(al, copy);
copy=malloc(2); copy=allocator_alloc(al, 2);
copy[0]='.'; copy[0]='.';
copy[1]=0; copy[1]=0;
} }
@@ -72,7 +76,7 @@ char* path_parentDir(char* dir){
} }
char* path_basename(char* path, bool with_extension){ char* path_basename(allocator_ptr al, char* path, bool with_extension){
i32 nameIndex=cptr_lastIndexOfChar(path, path_sep)+1; i32 nameIndex=cptr_lastIndexOfChar(path, path_sep)+1;
string rezult=string_fromCptr(path+nameIndex); string rezult=string_fromCptr(path+nameIndex);
if(!with_extension){ if(!with_extension){
@@ -80,5 +84,5 @@ char* path_basename(char* path, bool with_extension){
if(extIndex!=0 && extIndex!=-1) if(extIndex!=0 && extIndex!=-1)
rezult.length=extIndex; rezult.length=extIndex;
} }
return string_extract(rezult); return string_extract(al, rezult);
} }

View File

@@ -14,17 +14,17 @@ static const char path_sep='/';
static const char path_notSep='\\'; static const char path_notSep='\\';
#endif #endif
char* __path_concat(u32 n, ...); char* __path_concat(allocator_ptr al, u32 n, ...);
/// @brief merges path parts together and puts <path_sep> between them /// @brief merges path parts together and puts <path_sep> between them
/// @return new cstr /// @return new cstr
#define path_concat(PATH_PARTS...) __path_concat(count_args(PATH_PARTS), PATH_PARTS) #define path_concat(ALLOCATOR, PATH_PARTS...) __path_concat(ALLOCATOR, count_args(PATH_PARTS), PATH_PARTS)
/// @brief fixes path separators /// @brief fixes path separators
/// @param cstr where can be <path_notSep> /// @param cstr where can be <path_notSep>
/// @return new cstr with correct separators /// @return new cstr with correct separators
char* path_fixSeparators(const char* path); char* path_fixSeparators(allocator_ptr al, const char* path);
#define path_resolve(PATH_PARTS...) path_fixSeparators(path_concat(PATH_PARTS)) #define path_resolve(ALLOCATOR, PATH_PARTS...) path_fixSeparators(ALLOCATOR, path_concat(ALLOCATOR, PATH_PARTS))
/// @brief calls safethrow() if finds escape sequense in path /// @brief calls safethrow() if finds escape sequense in path
/// @param path cstr where can be <..> /// @param path cstr where can be <..>
@@ -32,10 +32,10 @@ char* path_fixSeparators(const char* path);
Maybe path_throwIfEscapes(const char* path); Maybe path_throwIfEscapes(const char* path);
///@return path of parent dir ///@return path of parent dir
char* path_parentDir(char* path); char* path_parentDir(allocator_ptr al, char* path);
///@return file name ///@return file name
char* path_basename(char* path, bool with_extension); char* path_basename(allocator_ptr al, char* path, bool with_extension);
#if __cplusplus #if __cplusplus
} }

View File

@@ -1,74 +1,70 @@
#include "Hashtable.h" #include "Hashtable.h"
kt_define(Hashtable, __Hashtable_free, NULL); kt_define(Hashtable, __Hashtable_destruct, NULL);
// amount of rows // amount of rows
static const u16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521}; static const u16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
#define HT_HEIN_MIN 0 #define HT_HEIN_MIN 0
#define HT_HEIN_MAX 6 #define HT_HEIN_MAX 6
#define ARR_BC 2 #define ARR_SIZE_MAX 16
#define ARR_BL 8
Hashtable* Hashtable_create(){ void Hashtable_construct(Hashtable* ht, allocator_ptr external_al){
Hashtable* ht=malloc(sizeof(Hashtable)); InternalAllocator_setExternalOrConstruct(ht, external_al, LinearAllocator, 1024);
ht->hein=HT_HEIN_MIN; ht->hein=HT_HEIN_MIN;
ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*)); ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*));
for(u16 i=0;i<HT_HEIGHTS[HT_HEIN_MIN];i++) allocator_ptr internal_al = InternalAllocator_getPtr(ht);
ht->rows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL); for(u16 i=0; i<HT_HEIGHTS[HT_HEIN_MIN]; i++)
return ht; Autoarr_construct(&ht->rows[i], KVPair, 16, internal_al);
} }
void __Hashtable_free(void* _ht){ u16 __Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
void __Hashtable_destruct(void* _ht){
Hashtable* ht=_ht; Hashtable* ht=_ht;
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++) for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
Autoarr_free(ht->rows[i], true); Autoarr_destruct(&ht->rows[i]);
free(ht->rows); allocator_free(InternalAllocator_getPtr(ht), ht->rows);
InternalAllocator_destructIfInternal(LinearAllocator, ht);
} }
void Hashtable_free(Hashtable* ht){ void Hashtable_destruct(Hashtable* ht){
__Hashtable_free(ht); __Hashtable_destruct(ht);
free(ht);
} }
u16 Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
void Hashtable_expand(Hashtable* ht){ void Hashtable_expand(Hashtable* ht){
if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH); if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH);
Autoarr(KVPair)** newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*)); Autoarr(KVPair)* newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*));
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++) for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
newrows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL); Autoarr_construct(&newrows[i], KVPair, ARR_SIZE_MAX, InternalAllocator_getPtr(ht));
for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){ for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
Autoarr(KVPair)* ar=ht->rows[i]; Autoarr(KVPair)* ar=&ht->rows[i];
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 k=0;k<arlen;k++){ for(u32 k=0;k<arlen;k++){
KVPair p=Autoarr_get(ar,k); KVPair p=Autoarr_get(ar,k);
u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein]; u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein];
Autoarr(KVPair)* newar=newrows[newrown]; Autoarr(KVPair)* newar=&newrows[newrown];
Autoarr_add(newar,p); Autoarr_add(newar,p);
} }
// there is no need to free array values, because they are copied into new array Autoarr_destruct(ar);
// so dont replace this incorrect auto-generated function
Autoarr_freeWithoutMembers(ar, true);
} }
free(ht->rows); free(ht->rows);
ht->rows=newrows; ht->rows = newrows;
} }
Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){ Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){
u32 hash=hashs(hash_sdbm32, key); u32 hash=hashs(hash_sdbm32, key);
Autoarr(KVPair)* ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; Autoarr(KVPair)* ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar)) if(can_expand && Autoarr_length(ar) == ARR_SIZE_MAX)
Hashtable_expand(ht); Hashtable_expand(ht);
ar=ht->rows[hash%HT_HEIGHTS[ht->hein]]; ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
return ar; return ar;
} }
/// @param key must be heap allocated /// @param key must be heap allocated
/// Hashtable_free will free this pointer /// Hashtable_destruct will free this pointer
void Hashtable_add(Hashtable* ht, char* key, Unitype u){ void Hashtable_add(Hashtable* ht, char* key, Unitype u){
KVPair p={ .key=key, .value=u }; KVPair p={ .key=key, .value=u };
Autoarr_add(getrow(ht,key,true),p); Autoarr_add(getrow(ht,key,true),p);
@@ -86,7 +82,8 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair* p=Autoarr_getPtr(ar,i); KVPair* p=Autoarr_getPtr(ar,i);
if(cptr_equals(key,p->key)) return &p->value; if(cptr_equals(key,p->key))
return &p->value;
} }
return NULL; return NULL;
} }
@@ -96,7 +93,8 @@ Unitype Hashtable_get(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair p=Autoarr_get(ar,i); KVPair p=Autoarr_get(ar,i);
if(cptr_equals(key,p.key)) return p.value; if(cptr_equals(key,p.key))
return p.value;
} }
return UniNull; return UniNull;
} }

View File

@@ -9,16 +9,14 @@ extern "C" {
#include "KeyValuePair.h" #include "KeyValuePair.h"
STRUCT(Hashtable, STRUCT(Hashtable,
InternalAllocator_declare(LinearAllocator);
u8 hein; // height=HT_HEIGHTS[hein] u8 hein; // height=HT_HEIGHTS[hein]
Autoarr(KVPair)** rows; // Autoarr[height] Autoarr(KVPair)* rows; // Autoarr[height]
) )
Hashtable* Hashtable_create(); void Hashtable_construct(Hashtable* ht, allocator_ptr external_al);
void Hashtable_free(Hashtable* ht); void Hashtable_destruct(Hashtable* ht);
void __Hashtable_free(void* ht); void __Hashtable_destruct(void* ht);
// amount of rows
u16 Hashtable_height(Hashtable* ht);
// don't add pairs with the same keys, // don't add pairs with the same keys,
// or something weird will happen // or something weird will happen
@@ -36,11 +34,13 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key);
Unitype Hashtable_get(Hashtable* ht, char* key); Unitype Hashtable_get(Hashtable* ht, char* key);
bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output); bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output);
u16 __Hashtable_height(Hashtable* ht);
#define Hashtable_foreach(HT, EL, codeblock...) { \ #define Hashtable_foreach(HT, EL, codeblock...) { \
u16 hmax=Hashtable_height(HT); \ u16 hmax=__Hashtable_height(HT); \
for(u16 h=0; h<hmax; h++){ \ for(u16 h=0; h<hmax; h++){ \
Autoarr(KVPair)* AR=HT->rows[h]; \ Autoarr(KVPair)* row=&HT->rows[h]; \
Autoarr_foreach(AR, EL, codeblock); \ Autoarr_foreach(row, EL, codeblock); \
} \ } \
} }

View File

@@ -1,15 +1,8 @@
#include "KeyValuePair.h" #include "KeyValuePair.h"
kt_define(KVPair, __KVPair_free, NULL); kt_define(KVPair, NULL, NULL);
Autoarr_define(KVPair, false) Autoarr_define(KVPair)
// proper way to clean a KVP
void KVPair_free(KVPair p){
free(p.key);
Unitype_free(p.value);
}
void __KVPair_free(void* p){ KVPair_free(*(KVPair*)p); }
void printkvp(KVPair p){ void printkvp(KVPair p){
kprintf("{\"%s\", ",p.key); kprintf("{\"%s\", ",p.key);

View File

@@ -14,9 +14,7 @@ STRUCT(KVPair,
Autoarr_declare(KVPair) Autoarr_declare(KVPair)
// proper way to clean a KVP void __KVPair_destruct(void* p);
void KVPair_free(KVPair p);
void __KVPair_free(void* p);
void printkvp(KVPair p); void printkvp(KVPair p);

View File

@@ -16,7 +16,7 @@ extern "C" {
#define LLNode_create(TYPE, VALUE) LLNode_##TYPE##_create(VALUE) #define LLNode_create(TYPE, VALUE) LLNode_##TYPE##_create(VALUE)
#define LinkedList_create(TYPE) LinkedList_##TYPE##_create() #define LinkedList_create(TYPE) LinkedList_##TYPE##_create()
#define LinkedList_free(LLIST) ({ LLIST->_functions->freeMembers(LLIST); free(LLIST); }) #define LinkedList_destruct(LLIST) ({ LLIST->_functions->destruct(LLIST); free(LLIST); })
void LinkedList_addToBeginning(void* _llist, void* _new_node); void LinkedList_addToBeginning(void* _llist, void* _new_node);

View File

@@ -12,7 +12,7 @@ STRUCT(LLNode(TYPE), \
) \ ) \
\ \
LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value); \ LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value); \
void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value); void LLNode_##TYPE##_destruct(LLNode(TYPE)* node, bool free_value);
#define LinkedList_declare(TYPE)\ #define LinkedList_declare(TYPE)\
@@ -27,7 +27,7 @@ STRUCT(LinkedList(TYPE), \
) \ ) \
\ \
typedef struct LinkedList_##TYPE##_functions_t { \ typedef struct LinkedList_##TYPE##_functions_t { \
freeMembers_t freeMembers; \ destruct_t destruct; \
void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \ void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \
void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \ void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \
} LinkedList_##TYPE##_functions_t; \ } LinkedList_##TYPE##_functions_t; \

View File

@@ -14,19 +14,19 @@ LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value){ \
return node; \ return node; \
} \ } \
\ \
void LLNode_##TYPE##_freeMembers(void* _node){ \ void LLNode_##TYPE##_destructMembers(void* _node){ \
LLNode(TYPE)* node=(LLNode(TYPE)*)_node; \ LLNode(TYPE)* node=(LLNode(TYPE)*)_node; \
void* value_ptr=&node->value; \ void* value_ptr=&node->value; \
if(TYPE_IS_PTR) value_ptr=*(TYPE**)value_ptr; \ if(TYPE_IS_PTR) value_ptr=*(TYPE**)value_ptr; \
ktDescriptor_##TYPE.freeMembers(value_ptr); \ ktDescriptor_##TYPE.destruct(value_ptr); \
} \ } \
\ \
void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value){ \ void LLNode_##TYPE##_destruct(LLNode(TYPE)* node, bool free_value){ \
if(free_value) LLNode_##TYPE##_freeMembers(node); \ if(free_value) LLNode_##TYPE##_destructMembers(node); \
free(node); \ free(node); \
} \ } \
\ \
kt_define(LLNode_##TYPE, LLNode_##TYPE##_freeMembers, NULL) kt_define(LLNode_##TYPE, LLNode_##TYPE##_destructMembers, NULL)
#define LinkedList_define(TYPE, VALUE_IS_PTR)\ #define LinkedList_define(TYPE, VALUE_IS_PTR)\
@@ -41,10 +41,10 @@ LinkedList(TYPE)* LinkedList_##TYPE##_create(){ \
return l; \ return l; \
} \ } \
\ \
void LinkedList_##TYPE##_freeMembers(void* _l){ \ void LinkedList_##TYPE##_destructMembers(void* _l){ \
LinkedList(TYPE)* l=(LinkedList(TYPE)*)_l; \ LinkedList(TYPE)* l=(LinkedList(TYPE)*)_l; \
if(l->first_node!=NULL) \ if(l->first_node!=NULL) \
LinkedList_foreach(l, node, LLNode_##TYPE##_free(node, true)); \ LinkedList_foreach(l, node, LLNode_##TYPE##_destruct(node, true)); \
l->first_node=NULL; l->last_node=NULL; l->count=0; \ l->first_node=NULL; l->last_node=NULL; l->count=0; \
} \ } \
\ \
@@ -55,7 +55,7 @@ void LinkedList_##TYPE##_removePrev(LinkedList(TYPE)* llist, LLNode(TYPE)* nextN
nextNode->prev=prevNode; \ nextNode->prev=prevNode; \
prevNode->next=nextNode; \ prevNode->next=nextNode; \
if(freeRemoved) \ if(freeRemoved) \
LLNode_##TYPE##_free(removedNode, true); \ LLNode_##TYPE##_destruct(removedNode, true); \
} \ } \
\ \
void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved){ \ void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved){ \
@@ -65,16 +65,16 @@ void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevN
prevNode->next=nextNode; \ prevNode->next=nextNode; \
nextNode->prev=prevNode; \ nextNode->prev=prevNode; \
if(freeRemoved) \ if(freeRemoved) \
LLNode_##TYPE##_free(removedNode, true); \ LLNode_##TYPE##_destruct(removedNode, true); \
} \ } \
\ \
LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions={ \ LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions={ \
.freeMembers=LinkedList_##TYPE##_freeMembers, \ .destruct=LinkedList_##TYPE##_destructMembers, \
.removePrev=LinkedList_##TYPE##_removePrev, \ .removePrev=LinkedList_##TYPE##_removePrev, \
.removeNext=LinkedList_##TYPE##_removeNext \ .removeNext=LinkedList_##TYPE##_removeNext \
}; \ }; \
\ \
kt_define(LinkedList_##TYPE, LinkedList_##TYPE##_freeMembers, NULL) kt_define(LinkedList_##TYPE, LinkedList_##TYPE##_destructMembers, NULL)
#if __cplusplus #if __cplusplus

View File

@@ -1,6 +1,6 @@
#include "SearchTree.h" #include "SearchTree.h"
kt_define(STNode, __STNode_free, NULL); kt_define(STNode, __STNode_destruct, NULL);
STNode* STNode_create(){ STNode* STNode_create(){
STNode* node=malloc(sizeof(STNode)); STNode* node=malloc(sizeof(STNode));
@@ -9,7 +9,7 @@ STNode* STNode_create(){
return node; return node;
} }
void __STNode_free(void* _node){ void __STNode_destruct(void* _node){
STNode* node=_node; STNode* node=_node;
if (!node) throw(ERR_NULLPTR); if (!node) throw(ERR_NULLPTR);
if(node->branches){ if(node->branches){
@@ -22,7 +22,7 @@ void __STNode_free(void* _node){
for(u8 rem=0;rem<4;rem++){ for(u8 rem=0;rem<4;rem++){
STNode* ptrrem=ptrn4[rem]; STNode* ptrrem=ptrn4[rem];
if(ptrrem) if(ptrrem)
STNode_free(ptrrem); STNode_destruct(ptrrem);
} }
free(ptrn4); free(ptrn4);
} }
@@ -33,10 +33,10 @@ void __STNode_free(void* _node){
free(node->branches); free(node->branches);
} }
if(node->value.VoidPtr) if(node->value.VoidPtr)
Unitype_free(node->value); Unitype_destruct(&node->value);
} }
void STNode_free(STNode* node){ void STNode_destruct(STNode* node){
__STNode_free(node); __STNode_destruct(node);
free(node); free(node);
} }

View File

@@ -13,8 +13,8 @@ STRUCT(STNode,
) )
STNode* STNode_create(); STNode* STNode_create();
void STNode_free(STNode* node); void STNode_destruct(STNode* node);
void __STNode_free(void* node); void __STNode_destruct(void* node);
void ST_push(STNode* node, char* key, Unitype value); void ST_push(STNode* node, char* key, Unitype value);
void ST_pushString(STNode* node, string key, Unitype value); void ST_pushString(STNode* node, string key, Unitype value);

View File

@@ -1,147 +1,90 @@
#include "StringBuilder.h" #include "StringBuilder.h"
kt_define(StringBuilder, __StringBuilder_free, NULL); kt_define(StringBuilder, (destruct_t)StringBuilder_destruct, NULL);
#define BL_C 32 #define BL_C 32
#define BL_L 1024 #define BL_L 1024
#define createBuffer() (MemoryChunk){.data = allocator_alloc(InternalAllocator_getPtr(b), 512), .size=512, .occupied_size=0}
void complete_buf(StringBuilder* b){ void complete_buf(StringBuilder* b){
if(!b->compl_bufs) if(b->curr_buf.occupied_size == 0)
b->compl_bufs=Autoarr_create(string,BL_C,BL_L); return;
u32 len=Autoarr_length(b->curr_buf); string str={ .length=b->curr_buf.occupied_size, .ptr= b->curr_buf.data };
if(!len) return; Autoarr_add(&b->compl_bufs,str);
string str={.length=len, .ptr=malloc(len)}; b->curr_buf = createBuffer();
u32 i=0;
Autoarr_foreach(b->curr_buf, c,
str.ptr[i++]=c;
);
Autoarr_add(b->compl_bufs,str);
Autoarr_free(b->curr_buf, true);
b->curr_buf=Autoarr_create(i8,BL_C,BL_L);
}
void try_complete_buf(StringBuilder* b){
if(b->curr_buf->blocks_count==BL_C)
complete_buf(b);
} }
StringBuilder* StringBuilder_create(){ void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al){
StringBuilder* b=malloc(sizeof(StringBuilder)); InternalAllocator_setExternalOrConstruct(b, external_al, LinearAllocator, 1024);
b->compl_bufs=NULL; Autoarr_construct(&b->compl_bufs, string, 0, InternalAllocator_getPtr(b));
b->curr_buf=Autoarr_create(i8,BL_C,BL_L); b->curr_buf = createBuffer();
return b; b->total_length = 0;
} }
void __StringBuilder_free(void* _b){ void StringBuilder_destruct(StringBuilder* b){
StringBuilder* b=_b; Autoarr_destruct(&b->compl_bufs);
if(b->compl_bufs) Autoarr_free(b->compl_bufs, true); allocator_free(InternalAllocator_getPtr(b), b->curr_buf.data);
Autoarr_free(b->curr_buf, true); InternalAllocator_destructIfInternal(LinearAllocator, b);
}
void StringBuilder_free(StringBuilder* b){
__StringBuilder_free(b);
free(b);
} }
string StringBuilder_build(StringBuilder* b){ string StringBuilder_build(StringBuilder* b){
complete_buf(b); complete_buf(b);
u32 len=0; string str= {
Autoarr_foreach(b->compl_bufs, cs, .length = b->total_length,
len+=cs.length; .ptr = allocator_alloc(InternalAllocator_getPtr(b), b->total_length+1)
};
str.ptr[b->total_length]='\0';
char* free_space_ptr = str.ptr;
Autoarr_foreach(&b->compl_bufs, buf,
memcpy(free_space_ptr, buf.ptr, buf.length);
free_space_ptr += buf.length;
); );
string str= { .length=len, .ptr=malloc(len+1) }; StringBuilder_destruct(b);
str.ptr[len]='\0';
u32 i=0;
Autoarr_foreach(b->compl_bufs, cs,
for(u32 n=0;n<cs.length;n++)
str.ptr[i++]=cs.ptr[n];
free(cs.ptr);
);
StringBuilder_free(b);
return str; return str;
} }
void StringBuilder_rmchar(StringBuilder* b){ void StringBuilder_rmchar(StringBuilder* b){
if(b->curr_buf->block_length!=0) if(b->curr_buf.occupied_size != 0)
Autoarr_pop(b->curr_buf) b->curr_buf.occupied_size--;
else { else {
if(!b->compl_bufs) throw(ERR_NULLPTR); for(u32 buf_i = Autoarr_length(&b->compl_bufs) - 1; buf_i != (u32)-1; buf_i--){
string* lastcb=Autoarr_getPtr(b->compl_bufs, (Autoarr_length(b->compl_bufs)-1)); string* lastcb = Autoarr_getPtr(&b->compl_bufs, buf_i);
if(lastcb->length != 0){
lastcb->length--; lastcb->length--;
break;
}
}
} }
} }
void StringBuilder_append_char(StringBuilder* b, char c){ void StringBuilder_append_char(StringBuilder* b, char c){
try_complete_buf(b); if(b->curr_buf.occupied_size==b->curr_buf.size)
Autoarr_add(b->curr_buf,c); complete_buf(b);
((char*)b->curr_buf.data)[b->curr_buf.occupied_size] = c;
} }
void StringBuilder_append_string(StringBuilder* b, string s){ void StringBuilder_append_string(StringBuilder* b, string s){
complete_buf(b); complete_buf(b);
Autoarr_add(b->compl_bufs, string_copy(s)); Autoarr_add(&b->compl_bufs, s);
} }
void StringBuilder_append_cptr(StringBuilder* b, char* s){ void StringBuilder_append_cptr(StringBuilder* b, char* s){
string str={ string str={ .ptr=s, .length=cptr_length(s) };
.ptr=s, StringBuilder_append_string(b, str);
.length=cptr_length(s)
};
StringBuilder_append_string(b,str);
}
void curr_buf_add_string(StringBuilder* b, string s){
for(u32 i=0; i<s.length; i++)
Autoarr_add(b->curr_buf,s.ptr[i]);
} }
void StringBuilder_append_i64(StringBuilder* b, i64 a){ void StringBuilder_append_i64(StringBuilder* b, i64 a){
try_complete_buf(b); StringBuilder_append_cptr(b, toString_i64(InternalAllocator_getPtr(b), a));
u8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
return;
}
else if(a<0){
Autoarr_add(b->curr_buf,'-');
a=-a;
}
char buf[24];
while(a!=0){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
} }
void StringBuilder_append_u64(StringBuilder* b, u64 a){ void StringBuilder_append_u64(StringBuilder* b, u64 a){
try_complete_buf(b); StringBuilder_append_cptr(b, toString_u64(InternalAllocator_getPtr(b), a, 0, 0));
u8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
return;
}
char buf[24];
while(a!=0){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
} }
void StringBuilder_append_f64(StringBuilder* b, f64 a){ void StringBuilder_append_f64(StringBuilder* b, f64 a){
try_complete_buf(b); StringBuilder_append_cptr(b, toString_f64(InternalAllocator_getPtr(b), a, toString_f64_max_precision, 0, 0));
char buf[32];
IFMSC(
sprintf_s(buf,32,"%lf",a),
sprintf(buf,"%lf",a)
);
curr_buf_add_string(b, (string){.ptr=buf, .length=cptr_length(buf)});
} }

View File

@@ -8,20 +8,25 @@ extern "C" {
#include "string.h" #include "string.h"
STRUCT(StringBuilder, STRUCT(StringBuilder,
Autoarr(string)* compl_bufs; InternalAllocator_declare(LinearAllocator);
Autoarr(i8)* curr_buf; Autoarr(string) compl_bufs;
MemoryChunk curr_buf;
u64 total_length;
) )
StringBuilder* StringBuilder_create(void); ///@param external_al if null, creates internal allocator
void StringBuilder_free(StringBuilder* b); void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al);
void __StringBuilder_free(void* b); void StringBuilder_destruct(StringBuilder* b);
// Joins all strings from compl_bufs. // Joins all strings from compl_bufs.
// Returns zero-terminated string. // Returns zero-terminated string.
// No need to call string_extract()! // No need to call string_extract!
// Frees StringBuilder. // Destructs StringBuilder.
string StringBuilder_build(StringBuilder* b); string StringBuilder_build(StringBuilder* b);
// removes last char
/// OBSOLETE! Will be removed later
void StringBuilder_rmchar(StringBuilder* b); void StringBuilder_rmchar(StringBuilder* b);
void StringBuilder_append_char(StringBuilder* b, char c); void StringBuilder_append_char(StringBuilder* b, char c);
void StringBuilder_append_cptr(StringBuilder* b, char* s); void StringBuilder_append_cptr(StringBuilder* b, char* s);
void StringBuilder_append_string(StringBuilder* b, string s); void StringBuilder_append_string(StringBuilder* b, string s);

View File

@@ -1,36 +1,35 @@
#include "string.h" #include "string.h"
kt_define(string, NULL, NULL); kt_define(string, NULL, NULL);
Array_define(string) Autoarr_define(string);
Autoarr_define(string, false)
// copies str content to new char pointer value (adding '\0' at the end) // copies str content to new char pointer value (adding '\0' at the end)
char* string_extract(string str){ char* string_extract(allocator_ptr al, string str){
if(str.length==0) return NULL; if(str.length==0) return NULL;
char* cptr=malloc(str.length*sizeof(char)+1); char* cptr=allocator_alloc(al, str.length+1);
memcpy(cptr, str.ptr, str.length);
cptr[str.length]=0; cptr[str.length]=0;
while(str.length-->0)
cptr[str.length]=str.ptr[str.length];
return cptr; return cptr;
} }
// copies src.ptr content to new string and adds \0 at the end // copies src.ptr content to new string and adds \0 at the end
string string_copy(string src){ string string_copy(allocator_ptr al, string src){
if(!src.ptr) if(!src.ptr)
return src; throw(ERR_NULLPTR);
string nstr; string nstr;
nstr.length=src.length; nstr.length=src.length;
nstr.ptr=malloc(nstr.length+1); nstr.ptr=allocator_alloc(al, nstr.length+1);
for(u32 i=0;i<nstr.length;i++) memcpy(nstr.ptr, src.ptr, nstr.length);
nstr.ptr[i]=src.ptr[i];
nstr.ptr[nstr.length]='\0'; nstr.ptr[nstr.length]='\0';
return nstr; return nstr;
} }
// compares two strings, NullPtr-friendly // compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1){ bool string_compare(string str0, string str1){
if(str0.length!=str1.length) return false; if(str0.length!=str1.length)
if(!str0.ptr) return str1.ptr ? false : true; return false;
if(!str0.ptr)
return str1.ptr ? false : true;
else if(!str1.ptr) return false; else if(!str1.ptr) return false;
while(str0.length-->0) while(str0.length-->0)
if(*str0.ptr++ != *str1.ptr++) if(*str0.ptr++ != *str1.ptr++)
@@ -39,9 +38,12 @@ bool string_compare(string str0, string str1){
} }
// creates new string which is reversed variant of <s> // creates new string which is reversed variant of <s>
string string_reverse(string s){ string string_reverse(allocator_ptr al, string s){
if(s.length==0) return s; if(s.length==0)
string r={malloc(s.length), s.length}; return s;
string r;
r.ptr=allocator_alloc(al, s.length);
r.length=s.length;
for(u32 i=0; i<s.length; i++) for(u32 i=0; i<s.length; i++)
r.ptr[i]=s.ptr[s.length-i-1]; r.ptr[i]=s.ptr[s.length-i-1];
return r; return r;

View File

@@ -5,7 +5,6 @@ extern "C" {
#endif #endif
#include "../base/base.h" #include "../base/base.h"
#include "../Array/Array.h"
#include "../Autoarr/Autoarr.h" #include "../Autoarr/Autoarr.h"
// my fixed length string struct // my fixed length string struct
@@ -15,7 +14,6 @@ STRUCT(string,
u64 length; // amount of chars in ptr value u64 length; // amount of chars in ptr value
) )
Array_declare(string)
Autoarr_declare(string) Autoarr_declare(string)
static const string stringNull={NULL,0}; static const string stringNull={NULL,0};
@@ -24,16 +22,16 @@ static const string stringNull={NULL,0};
#define string_fromCptr(CPTR) (string){ .ptr=CPTR, .length=cptr_length(CPTR) } #define string_fromCptr(CPTR) (string){ .ptr=CPTR, .length=cptr_length(CPTR) }
// copies str content to new char pointer value (adding '\0' at the end) // copies str content to new char pointer value (adding '\0' at the end)
char* string_extract(string str); char* string_extract(allocator_ptr al, string str);
// copies src.ptr content to new string and adds \0 at the end // copies src.ptr content to new string and adds \0 at the end
string string_copy(string src); string string_copy(allocator_ptr al, string src);
// compares two strings, NullPtr-friendly // compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1); bool string_compare(string str0, string str1);
// creates new string which is reversed variant of <s> // creates new string which is reversed variant of <s>
string string_reverse(string s); string string_reverse(allocator_ptr al, string s);
#if __cplusplus #if __cplusplus
} }

View File

@@ -11,6 +11,7 @@ extern "C" {
#include "type_system/type_system.h" #include "type_system/type_system.h"
#include "../kprint/kprintf.h" #include "../kprint/kprintf.h"
#include "endian.h" #include "endian.h"
#include "memory/memory.h"
#if __cplusplus #if __cplusplus
} }

View File

@@ -11,17 +11,16 @@ u32 cptr_length(const char* str){
} }
// allocates new char[] and copies src there // allocates new char[] and copies src there
char* cptr_copy(const char* src){ char* cptr_copy(allocator_ptr al, const char* src){
u32 len=cptr_length(src)+1; u32 len=cptr_length(src)+1;
char* dst=malloc(len); char* dst=allocator_alloc(al, len);
while(len--!=0) memcpy(dst, src, len);
dst[len]=src[len];
return dst; return dst;
} }
// multiplies char n times // multiplies char n times
char* char_multiply(char c, u32 n){ char* char_multiply(allocator_ptr al, char c, u32 n){
char* rez=malloc(n+1); char* rez=allocator_alloc(al, n+1);
rez[n]=0; rez[n]=0;
while(n--!=0) while(n--!=0)
rez[n]=c; rez[n]=c;
@@ -131,16 +130,9 @@ i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 see
return -1; return -1;
} }
void memcopy(void* from, void* to, u32 size){ char* __cptr_concat(allocator_ptr al, u32 n, ...){
if(from==NULL || to==NULL) char** strs=(char**)allocator_alloc(al, n*sizeof(char*));
throw(ERR_NULLPTR); u32* lengths=allocator_alloc(al, n*sizeof(u32));
for(u32 i=0; i<size; i++)
((char*)to)[i]=((char*)from)[i];
}
char* __cptr_concat(u32 n, ...){
char** strs=(char**)malloc(n*sizeof(char*));
u32* lengths=malloc(n*sizeof(u32));
u32 totalLength=0; u32 totalLength=0;
// reading args from va_list // reading args from va_list
@@ -156,41 +148,41 @@ char* __cptr_concat(u32 n, ...){
va_end(vl); va_end(vl);
// allocating memory for output value // allocating memory for output value
char* totality=malloc(totalLength+1); char* totality=allocator_alloc(al, totalLength+1);
char* output=totality; char* output=totality;
totality[totalLength]=0; totality[totalLength]=0;
// copying content of all strings to rezult // copying content of all strings to rezult
for(u16 k=0; k<n; k++){ for(u16 k=0; k<n; k++){
memcopy(strs[k], totality, lengths[k]); memcpy(totality, strs[k], lengths[k]);
totality+=lengths[k]; totality+=lengths[k];
} }
free(strs); allocator_free(al, lengths);
free(lengths); allocator_free(al, strs);
return output; return output;
} }
char* cptr_toLower(const char* src) { char* cptr_toLower(allocator_ptr al, const char* src) {
u32 length=cptr_length(src); u32 length=cptr_length(src);
char *p=malloc(length+1); char *p=allocator_alloc(al, length+1);
p[length]=0; p[length]=0;
for(u32 i=0; i<length; i++) for(u32 i=0; i<length; i++)
p[i]=tolower(src[i]); p[i]=tolower(src[i]);
return p; return p;
} }
char* cptr_toUpper(const char* src) { char* cptr_toUpper(allocator_ptr al, const char* src) {
u32 length=cptr_length(src); u32 length=cptr_length(src);
char *p=malloc(length+1); char *p=allocator_alloc(al, length+1);
p[length]=0; p[length]=0;
for(u32 i=0; i<length; i++) for(u32 i=0; i<length; i++)
p[i]=toupper(src[i]); p[i]=toupper(src[i]);
return p; return p;
} }
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){ char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){
char* rzlt=cptr_copy(src); char* rzlt=cptr_copy(al, src);
for(u32 i=startIndex; i!=seekLength && src[i]!=0; i++){ for(u32 i=startIndex; i!=seekLength && src[i]!=0; i++){
if(src[i]==c_old) if(src[i]==c_old)
rzlt[i]=c_new; rzlt[i]=c_new;
@@ -198,8 +190,10 @@ char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex
return rzlt; return rzlt;
} }
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength){ char* cptr_replaceIn(allocator_ptr al, const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength){
StringBuilder* sb=StringBuilder_create(); StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
const u32 str_old_len=cptr_length(str_old); const u32 str_old_len=cptr_length(str_old);
const u32 str_new_len=cptr_length(str_new); const u32 str_new_len=cptr_length(str_new);
i32 i=startIndex; i32 i=startIndex;

View File

@@ -5,12 +5,13 @@ extern "C" {
#endif #endif
#include "std.h" #include "std.h"
#include "memory/allocator_base.h"
// returns length of char buffer (without \0) // returns length of char buffer (without \0)
u32 cptr_length(const char* str); u32 cptr_length(const char* str);
// allocates new char[] and copies src there // allocates new char[] and copies src there
char* cptr_copy(const char* src); char* cptr_copy(allocator_ptr al, const char* src);
bool cptr_equals(const char* key0, const char* key1); bool cptr_equals(const char* key0, const char* key1);
@@ -19,7 +20,7 @@ bool cptr_startsWith(const char* src, const char* fragment);
bool cptr_endsWith(const char* src, const char* fragment); bool cptr_endsWith(const char* src, const char* fragment);
// multiplies char n times // multiplies char n times
char* char_multiply(char c, u32 n); char* char_multiply(allocator_ptr al, char c, u32 n);
/// @param startIndex 0 ... src length /// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1 /// @param seekLength 0 ... -1
@@ -66,28 +67,26 @@ static inline bool cptr_contains(const char* src, const char* fragment){
return cptr_seek(src, fragment, 0, -1) +1; return cptr_seek(src, fragment, 0, -1) +1;
} }
void memcopy(void* from, void* to, u32 size); char* __cptr_concat(allocator_ptr al, u32 n, ...);
#define cptr_concat(ALLOCATOR, STR...) __cptr_concat(ALLOCATOR, count_args(STR), STR)
char* __cptr_concat(u32 n, ...); char* cptr_toLower(allocator_ptr al, const char* src);
#define cptr_concat(STR...) __cptr_concat(count_args(STR), STR) char* cptr_toUpper(allocator_ptr al, const char* src);
char* cptr_toLower(const char* src);
char* cptr_toUpper(const char* src);
/// @param startIndex 0 ... src length /// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1 /// @param seekLength 0 ... -1
/// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found /// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength); char* cptr_replaceIn(allocator_ptr al, const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength);
/// @param startIndex 0 ... src length /// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1 /// @param seekLength 0 ... -1
/// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found /// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength); char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength);
static inline char* cptr_replace(const char* src, const char* str_old, const char* str_new) static inline char* cptr_replace(allocator_ptr al, const char* src, const char* str_old, const char* str_new)
{ return cptr_replaceIn(src, str_old, str_new, 0, -1); } { return cptr_replaceIn(al, src, str_old, str_new, 0, -1); }
static inline char* cptr_replaceChar(const char* src, char c_old, char c_new) static inline char* cptr_replaceChar(allocator_ptr al, const char* src, char c_old, char c_new)
{ return cptr_replaceCharIn(src, c_old, c_new, 0, -1); } { return cptr_replaceCharIn(al, src, c_old, c_new, 0, -1); }
#if __cplusplus #if __cplusplus
} }

View File

@@ -26,27 +26,21 @@ char* errname(ErrorId err){
char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){ char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
size_t bufsize=ERRMSG_MAXLENGTH; size_t bufsize=ERRMSG_MAXLENGTH;
char* rezult=malloc(bufsize); char* rezult=malloc(bufsize);
IFMSC( sprintf_s(rezult,bufsize,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg);
sprintf_s(rezult,bufsize,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg),
sprintf(rezult,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg)
);
return rezult; return rezult;
} }
char* __extendErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){ char* __extendErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH; size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH;
char* rezult=malloc(bufsize); char* rezult=malloc(bufsize);
IFMSC( sprintf_s(rezult,bufsize,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname);
sprintf_s(rezult,bufsize,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname),
sprintf(rezult,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname)
);
free(errmsg); free(errmsg);
return rezult; return rezult;
} }
void Maybe_free(Maybe e){ void Maybe_destruct(Maybe e){
free(e.errmsg); free(e.errmsg);
Unitype_free(e.value); Unitype_destruct(&e.value);
} }
void printMaybe(Maybe e){ void printMaybe(Maybe e){

View File

@@ -29,7 +29,7 @@ STRUCT(Maybe,
// .value .errmsg // .value .errmsg
#define MaybeNull (Maybe){UniNull, NULL} #define MaybeNull (Maybe){UniNull, NULL}
void Maybe_free(Maybe e); void Maybe_destruct(Maybe e);
void printMaybe(Maybe e); void printMaybe(Maybe e);

View File

@@ -0,0 +1,15 @@
#include "allocators_internal.h"
void* CstdAllocator_alloc(allocator_ptr self, alloc_size_t size){
// assert(size>0);
return malloc(size);
}
void CstdAllocator_free(allocator_ptr self, void* ptr){
// assert(ptr!=NULL);
free(ptr);
}
kt_define(CstdAllocator, NULL, NULL);
CstdAllocator CstdAllocator_instance=(CstdAllocator){.base.alloc_f=CstdAllocator_alloc, .base.free_f=CstdAllocator_free};

View File

@@ -0,0 +1,102 @@
#include "allocators_internal.h"
#include <stdio.h>
#define default_chunks_per_allocation 16
// growing chunk array size
#define new_max_chunks_count ( default_chunks_per_allocation*(self->chunks_count/16 == 0) + \
default_chunks_per_allocation*add_padding(self->chunks_count/2)/4 )
#define default_chunk_size 1024
// growing chunk size
#define new_chunk_size ( default_chunk_size*(self->chunks_count/16 == 0) + \
default_chunk_size*add_padding(self->chunks_count/8) )
#define chunk_alloc(SZ, OCCUPIED) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=OCCUPIED }
#define curr_chunk (self->chunks+self->curr_chunk_i)
__attribute__ ((noinline)) void* ___alloc_realloc_chunk(LinearAllocator* self, alloc_size_t alloc_size){
free(curr_chunk->data);
*curr_chunk=chunk_alloc(alloc_size, alloc_size);
return curr_chunk->data;
}
__attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, alloc_size_t alloc_size){
self->curr_chunk_i++;
// next chunk has been already allocated
if(self->curr_chunk_i < self->chunks_count)
return curr_chunk->data;
// self->chunks array is full
if(self->chunks_count == self->max_chunks_count){
self->max_chunks_count = new_max_chunks_count;
self->chunks = realloc(self->chunks, sizeof(MemoryChunk) * self->max_chunks_count);
}
// new chunk allocation
self->chunks_count++;
alloc_size_t _new_chunk_size= alloc_size > new_chunk_size ? alloc_size : new_chunk_size;
*curr_chunk=chunk_alloc(_new_chunk_size, alloc_size);
return curr_chunk->data;
}
void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t alloc_size){
// assert(_self!=NULL);
// assert(alloc_size>0);
LinearAllocator* self = (LinearAllocator*)_self;
alloc_size=add_padding(alloc_size);
// aligned alloc_size can fit into the current chunk
if(curr_chunk->occupied_size + alloc_size <= curr_chunk->size){
void* data_ptr=curr_chunk->data + curr_chunk->occupied_size;
curr_chunk->occupied_size += alloc_size;
return data_ptr;
}
// reallocation of current chunk because it is clean
if(curr_chunk->occupied_size == 0){
// It is very unefficient operation.
// If it happens not only in the first chunk, code have to be refactored
assert(self->curr_chunk_i==0);
return ___alloc_realloc_chunk(self, alloc_size);
}
// creation of a new chunk
else {
return __alloc_new_chunk(self, alloc_size);
}
}
void LinearAllocator_free(allocator_ptr _self, void* ptr){
// LinearAllocator can't free pointers
}
void LinearAllocator_destruct(LinearAllocator* self){
// assert(_self!=NULL);
u32 size=0;
u32 oc_size=0;
for(u32 chunk_i=0; chunk_i < self->chunks_count; chunk_i++){
free(self->chunks[chunk_i].data);
size+=self->chunks[chunk_i].size;
oc_size+=self->chunks[chunk_i].occupied_size;
}
printf("\e[35m%u/%u\n",oc_size,size);
free(self->chunks);
self->chunks=NULL;
self->chunks_count=0;
self->curr_chunk_i=0;
self->max_chunks_count=0;
}
void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size){
assert(self!=NULL);
assert(starting_size>0);
self->base.alloc_f=LinearAllocator_alloc;
self->base.free_f=LinearAllocator_free;
self->curr_chunk_i=0;
self->chunks_count=1;
self->max_chunks_count=new_max_chunks_count;
self->chunks=malloc(sizeof(MemoryChunk) * new_max_chunks_count);
self->chunks[0]=chunk_alloc(starting_size, 0);
}
kt_define(LinearAllocator, (destruct_t)LinearAllocator_destruct, NULL)

View File

@@ -0,0 +1,58 @@
#include "allocators_internal.h"
#define chunk_alloc(SZ) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=0 }
#define linear self->base
#define curr_chunk (linear.chunks+linear.curr_chunk_i)
typedef struct {
alloc_size_t data_size;
} AllocationHeader;
void* StackingAllocator_alloc(allocator_ptr _self, alloc_size_t size){
assert(_self!=NULL);
assert(size>0);
StackingAllocator* self = (StackingAllocator*)_self;
size=add_padding(size);
// allocates memory with header struct before data
AllocationHeader* header_ptr=LinearAllocator_alloc(_self, sizeof(AllocationHeader) + size);
void* data_ptr = (void*)header_ptr + sizeof(AllocationHeader);
header_ptr->data_size = size;
self->allocations_count++;
return data_ptr;
}
void StackingAllocator_free(allocator_ptr _self, void* data_ptr){
assert(_self!=NULL);
assert(data_ptr!=NULL);
StackingAllocator* self = (StackingAllocator*)_self;
AllocationHeader* header_ptr = data_ptr - sizeof(AllocationHeader);
// TODO check is data_ptr pointer to the last allocation
// chunk is empty
if(curr_chunk->occupied_size==0){
// isn't the first chunk
assert(linear.curr_chunk_i>0);
linear.curr_chunk_i--;
}
alloc_size_t allocation_size=header_ptr->data_size+sizeof(*header_ptr);
// data must fit in chunk
assert(allocation_size <= curr_chunk->occupied_size);
curr_chunk->occupied_size -= allocation_size;
}
void StackingAllocator_destruct(StackingAllocator* self){
LinearAllocator_destruct(&self->base);
}
void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size){
assert(self!=NULL);
assert(starting_size>0);
LinearAllocator_construct(&linear, starting_size);
linear.base.alloc_f=StackingAllocator_alloc;
linear.base.free_f=StackingAllocator_free;
self->allocations_count=0;
}
kt_define(StackingAllocator, (destruct_t)StackingAllocator_destruct, NULL)

View File

@@ -0,0 +1,36 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "../std.h"
///////////////////////////////////////////
// MemoryAllocator interface //
///////////////////////////////////////////
typedef u32 alloc_size_t;
typedef struct MemoryAllocator MemoryAllocator;
typedef MemoryAllocator* allocator_ptr;
typedef void* (*alloc_t)(allocator_ptr, alloc_size_t size);
typedef void (*free_t)(allocator_ptr, void* ptr);
typedef struct MemoryAllocator {
alloc_t alloc_f;
free_t free_f;
} MemoryAllocator;
#define allocator_alloc(ALLOCATOR, SIZE) \
((allocator_ptr)ALLOCATOR)->alloc_f(ALLOCATOR, SIZE)
#define allocator_free(ALLOCATOR, PTR) \
((allocator_ptr)ALLOCATOR)->free_f(ALLOCATOR, PTR)
#define allocator_destruct(ALLOCATOR) \
((allocator_ptr)ALLOCATOR)->destruct_f(ALLOCATOR)
void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,9 @@
#include "memory.h"
void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size)
{
void* transfered=allocator_alloc(dest, data_size);
memcpy(transfered, data, data_size);
allocator_free(src, data);
return transfered;
}

View File

@@ -0,0 +1,69 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../std.h"
#include "../type_system/ktDescriptor.h"
#include "allocator_base.h"
///////////////////////////////////////////
// CstdAllocator //
///////////////////////////////////////////
// Just wrapper for malloc() and free() //
///////////////////////////////////////////
STRUCT(CstdAllocator,
MemoryAllocator base;
);
extern CstdAllocator CstdAllocator_instance;
#define CstdAllocator_instPtr (allocator_ptr)(&CstdAllocator_instance)
///////////////////////////////////////////
// LinearAllocator //
///////////////////////////////////////////
// Can't free allocated memory. //
// Allocates new memory chunk when the //
// current is full. //
///////////////////////////////////////////
typedef struct MemoryChunk {
void* data;
alloc_size_t size;
alloc_size_t occupied_size; /* free memory position in the current chunk. */
} MemoryChunk;
STRUCT(LinearAllocator,
MemoryAllocator base;
MemoryChunk* chunks; /* MemoryChunk[max_chunks_count] */
u32 chunks_count; /* allocated chunks */
u32 max_chunks_count; /* chunks that can be allocated without reallocating .chunks */
u32 curr_chunk_i; /* index of current chunk in .chunks, can be < .chunks_count */
);
void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size);
void LinearAllocator_destruct(LinearAllocator* self);
///////////////////////////////////////////
// StackingAllocator //
///////////////////////////////////////////
// The same as Linear, but can free //
// allocations in reverse order //
///////////////////////////////////////////
STRUCT(StackingAllocator,
LinearAllocator base;
u32 allocations_count;
);
void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size);
void StackingAllocator_destruct(StackingAllocator* self);
#if __cplusplus
}
#endif

View File

@@ -0,0 +1,4 @@
#include <assert.h>
#include "memory.h"
void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t size);

44
src/base/memory/memory.h Normal file
View File

@@ -0,0 +1,44 @@
#include "allocators.h"
// addresses must be aligned to this value
#define memory_align sizeof(void*)
// adds padding if memory_align if N isn't a multiple of memory_aligh
#define add_padding(N) (N + (N%memory_align != 0)*(memory_align - N%memory_align))
///////////////////////////////////////////
// NOT AN ALLOCATOR //
///////////////////////////////////////////
// Macros to embed internal allocator //
// into some collection struct. //
///////////////////////////////////////////
/// call this macro inside struct declaration
#define InternalAllocator_declare(AL_TYPE) \
AL_TYPE _internal_al; \
allocator_ptr _internal_al_ptr;
/// get pointer to allocator
#define InternalAllocator_getPtr(STRUCT_PTR) ((STRUCT_PTR)->_internal_al_ptr)
/// true if allocator is stored inside the struct, otherwise false
#define InternalAllocator_isInternal(STRUCT_PTR) (bool)((STRUCT_PTR)->_internal_al_ptr == (allocator_ptr)&(STRUCT_PTR)->_internal_al)
/// set ptr to external allocator
#define InternalAllocator_setExternal(STRUCT_PTR, EXT_AL_PTR) ((STRUCT_PTR)->_internal_al_ptr = EXT_AL_PTR);
/// create internal allocator and set ptr to it
#define InternalAllocator_construct(STRUCT_PTR, TYPE, CTOR_ARGS...) { \
TYPE##_construct(&(STRUCT_PTR)->_internal_al, CTOR_ARGS); \
(STRUCT_PTR)->_internal_al_ptr = (allocator_ptr)&(STRUCT_PTR)->_internal_al; \
}
/// if EXT_AL_PTR isn't null, set external allocator, otherwise create new
#define InternalAllocator_setExternalOrConstruct(STRUCT_PTR, EXT_AL_PTR, TYPE, CTOR_ARGS...) \
if(EXT_AL_PTR!=NULL) InternalAllocator_setExternal(STRUCT_PTR, EXT_AL_PTR) \
else InternalAllocator_construct(STRUCT_PTR, TYPE, CTOR_ARGS)
#define InternalAllocator_destructIfInternal(TYPE, STRUCT_PTR) {\
if(InternalAllocator_isInternal(STRUCT_PTR)) \
TYPE##_destruct((TYPE*)InternalAllocator_getPtr(STRUCT_PTR)); \
}

View File

@@ -13,7 +13,8 @@
tni=1; \ tni=1; \
} else tni=2; \ } else tni=2; \
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%f \e[93m%s\n", \ kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%f \e[93m%s\n", \
opname, t, tnames[tni]); opname, t, tnames[tni]); \
fflush(stdout);
#ifdef CLOCK_REALTIME #ifdef CLOCK_REALTIME
/// executes codeblock and prints execution time /// executes codeblock and prints execution time

View File

@@ -25,7 +25,7 @@ typedef int64_t i64;
typedef uint64_t u64; typedef uint64_t u64;
typedef float f32; typedef float f32;
typedef double f64; typedef double f64;
/// anonymous pointer without specified freeMembers() func /// anonymous pointer without specified destruct() func
typedef void* Pointer; typedef void* Pointer;
// Usually bool from stdbool.h is defined as macro, // Usually bool from stdbool.h is defined as macro,
@@ -38,6 +38,14 @@ typedef u8 bool;
#define false 0 #define false 0
#endif #endif
#ifndef memcpy
extern void* memcpy(void *dest, const void * src, size_t n);
#endif
#ifndef typeof
#define typeof __typeof__
#endif
#define dbg(N) kprintf("\e[95m%d\n",N) #define dbg(N) kprintf("\e[95m%d\n",N)
#define nameof(V) #V #define nameof(V) #V

View File

@@ -22,7 +22,7 @@ and register it.
## type descriptors ## 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`). 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`, `destruct`).
## type registration ## type registration

View File

@@ -5,14 +5,14 @@
// accepts char* (ptr to char) and char* (ptr to string) // accepts char* (ptr to char) and char* (ptr to string)
// uses format kp_s and kp_c to determine what type is <c> argument // uses format kp_s and kp_c to determine what type is <c> argument
char* __toString_char(void* c, u32 fmt) { char* __toString_char(allocator_ptr al, void* c, u32 fmt) {
// *c=char* // *c=char*
if(kp_fmt_dataFormat(fmt)==kp_s){ if(kp_fmt_dataFormat(fmt)==kp_s){
return cptr_copy((char*)c); // to avoid segmentation fault on free() when *c allocalet on stack return cptr_copy(al, (char*)c); // to avoid segmentation fault on free() when *c allocalet on stack
} }
// *c=char // *c=char
if(kp_fmt_dataFormat(fmt)==kp_c){ if(kp_fmt_dataFormat(fmt)==kp_c){
char* cc=malloc(2); char* cc=allocator_alloc(al, 2);
cc[0]=*(char*)c; cc[0]=*(char*)c;
cc[1]=0; cc[1]=0;
return cc; return cc;
@@ -20,10 +20,10 @@ char* __toString_char(void* c, u32 fmt) {
else throw(ERR_FORMAT); else throw(ERR_FORMAT);
} }
char* __toString_bool(void* c, u32 fmt) { char* __toString_bool(allocator_ptr al, void* c, u32 fmt) {
static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" }; static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" };
u8 strind=*(bool*)c==1 + kp_fmt_isUpper(fmt)*2; u8 strind=*(bool*)c==1 + kp_fmt_isUpper(fmt)*2;
char* rez=malloc(6); char* rez=allocator_alloc(al, 6);
rez[0]=_strbool[strind][0]; rez[0]=_strbool[strind][0];
rez[1]=_strbool[strind][1]; rez[1]=_strbool[strind][1];
rez[2]=_strbool[strind][2]; rez[2]=_strbool[strind][2];
@@ -33,7 +33,7 @@ char* __toString_bool(void* c, u32 fmt) {
return rez; return rez;
} }
char* toString_i64(i64 n){ char* toString_i64(allocator_ptr al, i64 n){
i64 d=n<0 ? -1*n : n; i64 d=n<0 ? -1*n : n;
char str[32]; char str[32];
u8 i=sizeof(str); u8 i=sizeof(str);
@@ -46,10 +46,10 @@ char* toString_i64(i64 n){
} }
if(n<0) if(n<0)
str[--i]='-'; str[--i]='-';
return cptr_copy((char*)str+i); return cptr_copy(al, (char*)str+i);
} }
char* toString_u64(u64 n, bool withPostfix, bool uppercase){ char* toString_u64(allocator_ptr al, u64 n, bool withPostfix, bool uppercase){
char str[32]; char str[32];
u8 i=sizeof(str); u8 i=sizeof(str);
str[--i]=0; str[--i]=0;
@@ -61,33 +61,30 @@ char* toString_u64(u64 n, bool withPostfix, bool uppercase){
str[--i]='0' + n%10; str[--i]='0' + n%10;
n/=10; n/=10;
} }
return cptr_copy((char*)str+i); return cptr_copy(al, (char*)str+i);
} }
#define _toString_float_impl(bufsize, maxPrecision) { \ #define _toString_float_impl(al, bufsize, maxPrecision) { \
char str[bufsize]; \ char str[bufsize]; \
if(precision>maxPrecision) \ if(precision>maxPrecision) \
throw("too big precision"); \ throw("too big precision"); \
if(precision==0) \ if(precision==0) \
precision=toString_float_default_precision; \ precision=toString_float_default_precision; \
i32 cn=IFMSC( \ i32 cn=sprintf_s(str, bufsize, "%.*f", precision, n); \
sprintf_s(str, bufsize, "%.*f", precision, n), \
sprintf(str, "%.*f", precision, n) \
); \
/* remove trailing zeroes except .0*/ \ /* remove trailing zeroes except .0*/ \
while(str[cn-1]=='0' && str[cn-2]!='.') \ while(str[cn-1]=='0' && str[cn-2]!='.') \
cn--; \ cn--; \
if(withPostfix) \ if(withPostfix) \
str[cn++]= uppercase ? 'F' : 'f'; \ str[cn++]= uppercase ? 'F' : 'f'; \
str[cn]='\0'; \ str[cn]='\0'; \
return cptr_copy(str); \ return cptr_copy(al, str); \
} }
char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase) char* toString_f32(allocator_ptr al, f32 n, u8 precision, bool withPostfix, bool uppercase)
_toString_float_impl(48, toString_f32_max_precision) _toString_float_impl(al, 48, toString_f32_max_precision)
char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase) char* toString_f64(allocator_ptr al, f64 n, u8 precision, bool withPostfix, bool uppercase)
_toString_float_impl(512, toString_f64_max_precision) _toString_float_impl(al, 512, toString_f64_max_precision)
#define byte_to_bits(byte) { \ #define byte_to_bits(byte) { \
str[cn++]='0' + (u8)((byte>>7)&1); /* 8th bit */ \ str[cn++]='0' + (u8)((byte>>7)&1); /* 8th bit */ \
@@ -100,9 +97,9 @@ char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase)
str[cn++]='0' + (u8)((byte>>0)&1); /* 1th bit */ \ str[cn++]='0' + (u8)((byte>>0)&1); /* 1th bit */ \
} }
char* toString_bin(void* _bytes, u32 size, bool inverse, bool withPrefix){ char* toString_bin(allocator_ptr al, void* _bytes, u32 size, bool inverse, bool withPrefix){
char* bytes=_bytes; char* bytes=_bytes;
char* str=malloc(size*8 + (withPrefix?2:0) +1); char* str=allocator_alloc(al, size*8 + (withPrefix?2:0) +1);
u32 cn=0; // char number u32 cn=0; // char number
if(withPrefix){ if(withPrefix){
str[cn++]='0'; str[cn++]='0';
@@ -132,13 +129,13 @@ char _4bitsHex(u8 u, bool uppercase){
default: default:
dbg(u); dbg(u);
throw("incorrect number"); throw("incorrect number");
return 219; return (char)219;
} }
} }
char* toString_hex(void* _bytes, u32 size, bool inverse, bool withPrefix, bool uppercase){ char* toString_hex(allocator_ptr al, void* _bytes, u32 size, bool inverse, bool withPrefix, bool uppercase){
char* bytes=_bytes; char* bytes=_bytes;
char* str=malloc(size*2 + (withPrefix?2:0) + 1); char* str=allocator_alloc(al, size*2 + (withPrefix?2:0) + 1);
u32 cn=0; // char number u32 cn=0; // char number
if(withPrefix){ if(withPrefix){
str[cn++]='0'; str[cn++]='0';
@@ -166,67 +163,58 @@ char* toString_hex(void* _bytes, u32 size, bool inverse, bool withPrefix, bool u
} }
#define __toString_i32_def(BITS) char* __toString_i##BITS(void* _n, u32 f){ \ #define __toString_i_def(BITS) char* __toString_i##BITS(allocator_ptr al, void* _n, u32 f){ \
switch(kp_fmt_dataFormat(f)){ \ switch(kp_fmt_dataFormat(f)){ \
case kp_i: ; \ case kp_i: ; \
i##BITS n=*(i##BITS*)_n; \ i##BITS n=*(i##BITS*)_n; \
return toString_i64(n); \ return toString_i64(al,n); \
case kp_b: \ case kp_b: \
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \ return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
case kp_h: \ case kp_h: \
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \ return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
default: \ default: \
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \ kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
throw(ERR_FORMAT); \ throw(ERR_FORMAT); \
return NULL; \ return NULL; \
} \ } \
} }
__toString_i32_def(8)
__toString_i32_def(16)
__toString_i32_def(32)
__toString_i32_def(64)
#define __toString_u_def(BITS) char* __toString_u##BITS(void* _n, u32 f){ \ __toString_i_def(8)
__toString_i_def(16)
__toString_i_def(32)
__toString_i_def(64)
#define __toString_u_def(BITS) char* __toString_u##BITS(allocator_ptr al, void* _n, u32 f){ \
switch(kp_fmt_dataFormat(f)){ \ switch(kp_fmt_dataFormat(f)){ \
case kp_u: ; \ case kp_u: ; \
u##BITS n=*(u##BITS*)_n; \ u##BITS n=*(u##BITS*)_n; \
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \ return toString_u64(al, n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
case kp_b: \ case kp_b: \
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \ return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
case kp_h: \ case kp_h: \
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \ return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
default: \ default: \
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \ kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
throw(ERR_FORMAT); \ throw(ERR_FORMAT); \
return NULL; \ return NULL; \
} \ } \
} }
__toString_u_def(8) __toString_u_def(8)
__toString_u_def(16) __toString_u_def(16)
__toString_u_def(32) __toString_u_def(32)
// __toString_u_def(64) __toString_u_def(64)
char* __toString_u64(void* _n, u32 f){
switch(kp_fmt_dataFormat(f)){
case kp_u: ;
u64 n=*(u64*)_n;
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f));
case kp_b:
return toString_bin(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f));
case kp_h:
return toString_hex(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f));
default:
kprintf("\n%u\n", kp_fmt_dataFormat(f)); throw(ERR_FORMAT); return NULL; }
}
#define __toString_float_def(BITS) char* __toString_f##BITS(void* _n, u32 f){ \
#define __toString_f_def(BITS) char* __toString_f##BITS(allocator_ptr al, void* _n, u32 f){ \
switch(kp_fmt_dataFormat(f)){ \ switch(kp_fmt_dataFormat(f)){ \
case kp_f: ; \ case kp_f: ; \
f##BITS n=*(f##BITS*)_n; \ f##BITS n=*(f##BITS*)_n; \
return toString_f64(n, toString_float_default_precision, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \ return toString_f64(al, n, toString_float_default_precision, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
case kp_b: \ case kp_b: \
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \ return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
case kp_h: \ case kp_h: \
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \ return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
default: \ default: \
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \ kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
throw(ERR_FORMAT); \ throw(ERR_FORMAT); \
@@ -234,5 +222,5 @@ char* __toString_u64(void* _n, u32 f){
} \ } \
} }
__toString_float_def(32) __toString_f_def(32)
__toString_float_def(64) __toString_f_def(64)

View File

@@ -5,42 +5,43 @@ extern "C" {
#endif #endif
#include "../errors.h" #include "../errors.h"
#include "../memory/allocator_base.h"
// accepts char* (ptr to char) and char* (ptr to string) // accepts char* (ptr to char) and char* (ptr to string)
// uses format kp_s and kp_c to determine what type is <c> argument // uses format kp_s and kp_c to determine what type is <c> argument
char* __toString_char(void* c, u32 fmt); char* __toString_char(allocator_ptr al, void* c, u32 fmt);
// bool // bool
char* __toString_bool(void* c, u32 fmt); char* __toString_bool(allocator_ptr al, void* c, u32 fmt);
// signed int // signed int
char* toString_i64(i64 n); char* toString_i64(allocator_ptr al, i64 n);
char* __toString_i8(void* n, u32 fmt); char* __toString_i8(allocator_ptr al, void* n, u32 fmt);
char* __toString_i16(void* n, u32 fmt); char* __toString_i16(allocator_ptr al, void* n, u32 fmt);
char* __toString_i32(void* n, u32 fmt); char* __toString_i32(allocator_ptr al, void* n, u32 fmt);
char* __toString_i64(void* n, u32 fmt); char* __toString_i64(allocator_ptr al, void* n, u32 fmt);
// unsigned int // unsigned int
char* toString_u64(u64 n, bool withPostfix, bool uppercase); char* toString_u64(allocator_ptr al, u64 n, bool withPostfix, bool uppercase);
char* __toString_u8(void* n, u32 fmt); char* __toString_u8(allocator_ptr al, void* n, u32 fmt);
char* __toString_u16(void* n, u32 fmt); char* __toString_u16(allocator_ptr al, void* n, u32 fmt);
char* __toString_u32(void* n, u32 fmt); char* __toString_u32(allocator_ptr al, void* n, u32 fmt);
char* __toString_u64(void* n, u32 fmt); char* __toString_u64(allocator_ptr al, void* n, u32 fmt);
// float // float
#define toString_f32_max_precision 6 #define toString_f32_max_precision 6
#define toString_f64_max_precision 15 #define toString_f64_max_precision 15
#define toString_float_default_precision 6 #define toString_float_default_precision 6
char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf char* toString_f32(allocator_ptr al, f32 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf char* toString_f64(allocator_ptr al, f64 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
char* __toString_f32(void* n, u32 fmt); char* __toString_f32(allocator_ptr al, void* n, u32 fmt);
char* __toString_f64(void* n, u32 fmt); char* __toString_f64(allocator_ptr al, void* n, u32 fmt);
///@param inverse set to true for little endian numbers (their bytes are in reverse order) ///@param inverse set to true for little endian numbers (their bytes are in reverse order)
char* toString_bin(void* bytes, u32 size, bool inverse, bool withPrefix); char* toString_bin(allocator_ptr al, void* bytes, u32 size, bool inverse, bool withPrefix);
///@param inverse set to true for little endian numbers (their bytes are in reverse order) ///@param inverse set to true for little endian numbers (their bytes are in reverse order)
char* toString_hex(void* bytes, u32 size, bool inverse, bool withPrefix, bool uppercase); char* toString_hex(allocator_ptr al, void* bytes, u32 size, bool inverse, bool withPrefix, bool uppercase);
#if __cplusplus #if __cplusplus
} }

View File

@@ -1,5 +1,4 @@
#include "../base.h" #include "../base.h"
#include "../../Array/Array.h"
#include "../../Autoarr/Autoarr.h" #include "../../Autoarr/Autoarr.h"
#include "../../SearchTree/SearchTree.h" #include "../../SearchTree/SearchTree.h"
#include "../../Hashtable/Hashtable.h" #include "../../Hashtable/Hashtable.h"
@@ -29,21 +28,6 @@ void kt_initKerepTypes(){
// ktDescriptor // ktDescriptor
kt_register(ktDescriptor); kt_register(ktDescriptor);
// base type arrays
kt_register(Array_char);
kt_register(Array_bool);
kt_register(Array_f32);
kt_register(Array_f64);
kt_register(Array_i8);
kt_register(Array_u8);
kt_register(Array_i16);
kt_register(Array_u16);
kt_register(Array_i32);
kt_register(Array_u32);
kt_register(Array_i64);
kt_register(Array_u64);
kt_register(Array_Pointer);
// base type autoarrs // base type autoarrs
kt_register(Autoarr_Pointer); kt_register(Autoarr_Pointer);
kt_register(Autoarr_char); kt_register(Autoarr_char);
@@ -61,7 +45,6 @@ void kt_initKerepTypes(){
// Unitype // Unitype
kt_register(Unitype); kt_register(Unitype);
kt_register(Array_Unitype);
kt_register(Autoarr_Unitype); kt_register(Autoarr_Unitype);
// STNode // STNode
@@ -76,12 +59,16 @@ void kt_initKerepTypes(){
// string // string
kt_register(string); kt_register(string);
kt_register(Array_string);
kt_register(Autoarr_string); kt_register(Autoarr_string);
// StringBuilder // StringBuilder
kt_register(StringBuilder); kt_register(StringBuilder);
//File // File
kt_register(FileHandle); kt_register(FileHandle);
// Allocators
kt_register(CstdAllocator);
kt_register(LinearAllocator);
kt_register(StackingAllocator);
} }

View File

@@ -7,6 +7,7 @@ extern "C" {
#include "../std.h" #include "../std.h"
#include "ktid.h" #include "ktid.h"
#include "typedef_macros.h" #include "typedef_macros.h"
#include "../memory/allocator_base.h"
#define kt_declare(TYPE)\ #define kt_declare(TYPE)\
ktid_declare(TYPE);\ ktid_declare(TYPE);\
@@ -19,25 +20,25 @@ extern "C" {
.name=#TYPE, \ .name=#TYPE, \
.id=ktid_undefined, \ .id=ktid_undefined, \
.size=sizeof(TYPE), \ .size=sizeof(TYPE), \
.freeMembers=FREE_MEMBERS_F, \ .destruct=FREE_MEMBERS_F, \
.toString=TOSTRING_F \ .toString=TOSTRING_F \
}; \ }; \
ktDescriptor ktDescriptor_##TYPE##_Ptr={\ ktDescriptor ktDescriptor_##TYPE##_Ptr={\
.name=#TYPE "_Ptr", \ .name=#TYPE "_Ptr", \
.id=ktid_undefined, \ .id=ktid_undefined, \
.size=sizeof(TYPE), \ .size=sizeof(TYPE), \
.freeMembers=FREE_MEMBERS_F, \ .destruct=FREE_MEMBERS_F, \
.toString=TOSTRING_F \ .toString=TOSTRING_F \
}; };
typedef void (*freeMembers_t)(void*); typedef void (*destruct_t)(void*);
typedef char* (*toString_t)(void* obj, u32 fmt); typedef char* (*toString_t)(allocator_ptr al, void* obj, u32 fmt);
STRUCT(ktDescriptor, STRUCT(ktDescriptor,
char* name; char* name;
ktid id; ktid id;
u16 size; u16 size;
freeMembers_t freeMembers; // NULL or function which frees all struct members destruct_t destruct; // NULL or function which frees all struct members
toString_t toString; // NULL or function which generates string representaion of object toString_t toString; // NULL or function which generates string representaion of object
) )

View File

@@ -17,27 +17,27 @@ kt_define(i64, NULL, __toString_i64);
kt_define(u64, NULL, __toString_u64); kt_define(u64, NULL, __toString_u64);
char* ktDescriptor_toString(ktDescriptor* d){ char* ktDescriptor_toString(allocator_ptr al, ktDescriptor* d){
const char* n="null"; const char* n="null";
char *s0 = toString_u64(d->id, 0,0); char *s0 = toString_u64(al, d->id, 0,0);
char *s1 = toString_u64(d->size, 0,0); char *s1 = toString_u64(al, d->size, 0,0);
char *s2 = d->toString ? toString_hex(d->toString, sizeof(void*), 0,1,0) : n; char *s2 = d->toString ? toString_hex(al, d->toString, sizeof(void*), 0,1,0) : n;
char *s3 = d->freeMembers ? toString_hex(d->freeMembers, sizeof(void*), 0,1,0) : n; char *s3 = d->destruct ? toString_hex(al, d->destruct, sizeof(void*), 0,1,0) : n;
char *rez=cptr_concat("ktDescriptor {" char *rez=cptr_concat(al, "ktDescriptor {"
" name:", d->name, " name:", d->name,
" id:",s0, " id:",s0,
" size:",s1, " size:",s1,
" toString:",s2, " toString:",s2,
" freeMembers:",s3, " destruct:",s3,
" }"); " }");
free(s0); if(s3!=n) allocator_free(al, s3);
free(s1); if(s2!=n) allocator_free(al, s2);
if(s2!=n) free(s2); allocator_free(al, s1);
if(s3!=n) free(s3); allocator_free(al, s0);
return rez; return rez;
} }
char* _ktDescriptor_toString(void* _d, u32 fmt) { return ktDescriptor_toString(_d); } char* _ktDescriptor_toString(allocator_ptr al, void* _d, u32 fmt) { return ktDescriptor_toString(al, _d); }
kt_define(ktDescriptor, NULL, _ktDescriptor_toString); kt_define(ktDescriptor, NULL, _ktDescriptor_toString);
@@ -56,15 +56,16 @@ ktDescriptorsState initState=NotInitialized;
void kt_beginInit(){ void kt_beginInit(){
kprintf("\e[94mtype descriptors initializing...\n"); kprintf("\e[94mtype descriptors initializing...\n");
__descriptorPointers=Autoarr_create(Pointer, 256, 256); Autoarr_construct(__descriptorPointers, Pointer, 256, NULL);
} }
void kt_endInit(){ void kt_endInit(){
if(__descriptorPointers==NULL) if(__descriptorPointers==NULL)
throw(ERR_NULLPTR); throw(ERR_NULLPTR);
typeDescriptors=(ktDescriptor**)Autoarr_toArray(__descriptorPointers); typeDescriptors=(ktDescriptor**)Autoarr_toArray(__descriptorPointers, CstdAllocator_instPtr);
Autoarr_free(__descriptorPointers,true); Autoarr_destruct(__descriptorPointers);
if(typeDescriptors==NULL) throw(ERR_NULLPTR); if(typeDescriptors==NULL)
throw(ERR_NULLPTR);
kprintf("\e[92minitialized %u type descriptors\n", ktid_last); kprintf("\e[92minitialized %u type descriptors\n", ktid_last);
} }
@@ -81,6 +82,6 @@ ktDescriptor* ktDescriptor_get(ktid id){
return typeDescriptors[id]; return typeDescriptors[id];
} }
void kt_free(){ void kt_deinit(){
free(typeDescriptors); free(typeDescriptors);
} }

View File

@@ -23,10 +23,10 @@ void kt_endInit();
/// @param id id of registered type /// @param id id of registered type
ktDescriptor* ktDescriptor_get(ktid id); ktDescriptor* ktDescriptor_get(ktid id);
char* ktDescriptor_toString(ktDescriptor* d); char* ktDescriptor_toString(allocator_ptr al, ktDescriptor* d);
// call it to free heap-allocated ktDescriptors array // call it to free heap-allocated ktDescriptors array
void kt_free(); void kt_deinit();
kt_declare(Pointer); kt_declare(Pointer);
kt_declare(char); kt_declare(char);

View File

@@ -8,6 +8,10 @@
ENUM_MEMBERS \ ENUM_MEMBERS \
} __attribute__((__packed__)) ENUM_NAME; } __attribute__((__packed__)) ENUM_NAME;
#define PACKED_STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME { \
STRUCT_MEMBERS \
} __attribute__((__packed__)) STRUCT_NAME;
#define STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME STRUCT_NAME; \ #define STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME STRUCT_NAME; \
typedef struct STRUCT_NAME { \ typedef struct STRUCT_NAME { \
STRUCT_MEMBERS \ STRUCT_MEMBERS \

View File

@@ -1,40 +1,36 @@
#include "../../kprint/kprint_format.h" #include "../../kprint/kprint_format.h"
#include "../base.h" #include "../base.h"
char *__Unitype_toString(void *_u, u32 fmt) char *__Unitype_toString(allocator_ptr al, void *_u, u32 fmt)
{ {
return Unitype_toString(*(Unitype *)_u, fmt); return Unitype_toString(al, *(Unitype *)_u, fmt);
} }
kt_define(Unitype, __UnitypePtr_free, __Unitype_toString); kt_define(Unitype, (destruct_t)Unitype_destruct, __Unitype_toString);
void Unitype_free(Unitype u) void Unitype_destruct(Unitype* u)
{ {
if (u.typeId == ktid_undefined) if (u->typeId == ktid_undefined)
{ {
if (u.VoidPtr != NULL) if (u->VoidPtr != NULL)
throw("unitype with undefined typeId has value"); throw("unitype with undefined typeId has value");
return; return;
} }
ktDescriptor *type = ktDescriptor_get(u.typeId); ktDescriptor *type = ktDescriptor_get(u->typeId);
if (type->freeMembers) if (type->destruct)
type->freeMembers(u.VoidPtr); type->destruct(u->VoidPtr);
if (u.allocatedInHeap) if (u->allocatedInHeap)
free(u.VoidPtr); free(u->VoidPtr);
}
void __UnitypePtr_free(void *u)
{
Unitype_free(*(Unitype *)u);
} }
char *Unitype_toString(Unitype u, u32 fmt) char *Unitype_toString(allocator_ptr al, Unitype u, u32 fmt)
{ {
if (u.typeId == ktid_undefined) if (u.typeId == ktid_undefined)
{ {
if (u.VoidPtr != NULL) if (u.VoidPtr != NULL)
throw("unitype with undefined typeId has value"); throw("unitype with undefined typeId has value");
return cptr_copy("{ERROR_TYPE}"); return cptr_copy(al, "{ERROR_TYPE}");
} }
if (fmt == 0) if (fmt == 0)
@@ -74,7 +70,7 @@ char *Unitype_toString(Unitype u, u32 fmt)
else if (u.typeId == ktid_name(Pointer)) else if (u.typeId == ktid_name(Pointer))
{ {
if (u.VoidPtr == NULL) if (u.VoidPtr == NULL)
return cptr_copy("{ UniNull }"); return cptr_copy(al, "{ UniNull }");
fmt = kp_h; fmt = kp_h;
} }
} }
@@ -82,19 +78,22 @@ char *Unitype_toString(Unitype u, u32 fmt)
ktDescriptor *type = ktDescriptor_get(u.typeId); ktDescriptor *type = ktDescriptor_get(u.typeId);
char *valuestr; char *valuestr;
if (type->toString) if (type->toString)
valuestr = type->toString(u.VoidPtr, fmt); valuestr = type->toString(al, u.VoidPtr, fmt);
else else
valuestr = "ERR_NO_TOSTRING_FUNC"; valuestr = "ERR_NO_TOSTRING_FUNC";
char *rezult = cptr_concat("{ type: ", type->name, ", allocated on heap: ", (u.allocatedInHeap ? "true" : "false"), char *rezult = cptr_concat(al, "{ type: ", type->name, ", allocated on heap: ", (u.allocatedInHeap ? "true" : "false"),
", value:", valuestr, " }"); ", value:", valuestr, " }");
if (type->toString) if (type->toString)
free(valuestr); allocator_free(al, valuestr);
return rezult; return rezult;
} }
void printuni(Unitype v) void printuni(Unitype v)
{ {
char *s = Unitype_toString(v, 0); LinearAllocator _al;
LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
char *s = Unitype_toString(al, v, 0);
fputs(s, stdout); fputs(s, stdout);
free(s); LinearAllocator_destruct(&_al);
} }

View File

@@ -17,7 +17,7 @@ STRUCT(Unitype,
char Bytes[8]; char Bytes[8];
}; };
ktid typeId; ktid typeId;
bool allocatedInHeap; // should Unitype_free call free() to VoidPtr* bool allocatedInHeap; // should Unitype_destruct call free() to VoidPtr*
) )
@@ -45,9 +45,8 @@ STRUCT(Unitype,
#define UniCheckTypePtr(UNI, TYPE) UniCheckTypeId(UNI, ktid_ptrName(TYPE)) #define UniCheckTypePtr(UNI, TYPE) UniCheckTypeId(UNI, ktid_ptrName(TYPE))
// frees VoidPtr value or does nothing if type isn't pointer // frees VoidPtr value or does nothing if type isn't pointer
void Unitype_free(Unitype u); void Unitype_destruct(Unitype* u);
void __UnitypePtr_free(void* u); char* Unitype_toString(allocator_ptr al, Unitype v, u32 fmt);
char* Unitype_toString(Unitype v, u32 fmt);
void printuni(Unitype v); void printuni(Unitype v);
#if __cplusplus #if __cplusplus

View File

@@ -23,7 +23,7 @@ ktid __typeFromFormat(kp_fmt f){
} }
} }
Maybe __next_toString(kp_fmt f, void* object){ Maybe __next_toString(allocator_ptr al, kp_fmt f, void* object){
// detecting type // detecting type
ktid typeId=__typeFromFormat(f); ktid typeId=__typeFromFormat(f);
if(typeId==ktid_undefined) if(typeId==ktid_undefined)
@@ -35,7 +35,7 @@ Maybe __next_toString(kp_fmt f, void* object){
ktDescriptor* type=ktDescriptor_get(typeId); ktDescriptor* type=ktDescriptor_get(typeId);
if(!type->toString) if(!type->toString)
safethrow("type descriptor doesnt have toString() func",;); safethrow("type descriptor doesnt have toString() func",;);
return SUCCESS(UniHeapPtr(char, type->toString(object, f))); return SUCCESS(UniHeapPtr(char, type->toString(al, object, f)));
} }
Maybe check_argsN(u8 n){ Maybe check_argsN(u8 n){
@@ -44,45 +44,53 @@ Maybe check_argsN(u8 n){
return MaybeNull; return MaybeNull;
} }
Maybe __ksprint(u8 n, kp_fmt* formats, __kp_value_union* objects){ Maybe __ksprint(allocator_ptr al, u8 n, kp_fmt* formats, __kp_value_union* objects){
try(check_argsN(n), _,;); try(check_argsN(n), _,;);
n/=2; n/=2;
StringBuilder* strb=StringBuilder_create(); StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
for(u8 i=0; i<n; i++){ for(u8 i=0; i<n; i++){
try(__next_toString(formats[i], &objects[i]),mStr,;); try(__next_toString(al, formats[i], &objects[i]),mStr,;);
StringBuilder_append_cptr(strb, mStr.value.VoidPtr); StringBuilder_append_cptr(sb, mStr.value.VoidPtr);
Unitype_free(mStr.value); allocator_free(al, mStr.value.VoidPtr);
} }
char* rezult=StringBuilder_build(strb).ptr; char* rezult=StringBuilder_build(sb).ptr;
return SUCCESS(UniHeapPtr(char, rezult)); return SUCCESS(UniHeapPtr(char, rezult));
} }
Maybe __kfprint(FILE* file, u8 n, kp_fmt* formats, __kp_value_union* objects){ Maybe __kfprint(FILE* file, u8 n, kp_fmt* formats, __kp_value_union* objects){
try(check_argsN(n), _,;); try(check_argsN(n), _,;);
n/=2; n/=2;
LinearAllocator _al;
LinearAllocator_construct(&_al, 256);
allocator_ptr al=&_al.base;
for(u8 i=0; i<n; i++){ for(u8 i=0; i<n; i++){
try(__next_toString(formats[i], &objects[i]),maybeStr,;); try(__next_toString(al, formats[i], &objects[i]),maybeStr, LinearAllocator_destruct(&_al));
if(fputs(maybeStr.value.VoidPtr, file)==EOF) if(fputs(maybeStr.value.VoidPtr, file)==EOF)
safethrow("can't write string to file", Unitype_free(maybeStr.value)); safethrow("can't write string to file", LinearAllocator_destruct(&_al));
Unitype_free(maybeStr.value);
} }
fflush(file); fflush(file);
LinearAllocator_destruct(&_al);
return MaybeNull; return MaybeNull;
} }
void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){ void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
tryLast(check_argsN(n), _,;); tryLast(check_argsN(n), _,;);
n/=2; n/=2;
LinearAllocator _al;
LinearAllocator_construct(&_al, 256);
allocator_ptr al=&_al.base;
for(u8 i=0; i<n; i++){ for(u8 i=0; i<n; i++){
kp_fmt fmt=formats[i]; kp_fmt fmt=formats[i];
kprint_setColor(fmt); kprint_setColor(fmt);
tryLast(__next_toString(fmt, &objects[i]),maybeStr, kprint_setColor(kp_bgBlack|kp_fgGray)); tryLast(__next_toString(al, fmt, &objects[i]), maybeStr,
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF) \ kprint_setColor(kp_bgBlack|kp_fgGray););
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF)
throw("can't write string to stdout"); throw("can't write string to stdout");
//, Unitype_free(maybeStr.value)
Unitype_free(maybeStr.value);
} }
fflush(stdout); fflush(stdout);
LinearAllocator_destruct(&_al);
} }
#if defined(_WIN32)|| defined(_WIN64) #if defined(_WIN32)|| defined(_WIN64)
@@ -167,17 +175,19 @@ void kprint_setColor(kp_fmt f){
ktDescriptor* type=ktDescriptor_get(format.typeId); ktDescriptor* type=ktDescriptor_get(format.typeId);
if(!type->toString) if(!type->toString)
safethrow("type descriptor doesnt have toString() func",;); safethrow("type descriptor doesnt have toString() func",;);
StringBuilder* strb=StringBuilder_create(); StringBuilder _sb;
StringBuilder_append_char(strb, '['); StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
StringBuilder_append_char(sb, '[');
for (u16 e=1; e<count; e++){ for (u16 e=1; e<count; e++){
StringBuilder_append_char(strb, ' '); StringBuilder_append_char(sb, ' ');
char* elStr=type->toString(array+type->size*e, &format); char* elStr=type->toString(array+type->size*e, &format);
StringBuilder_append_cptr(strb, elStr); StringBuilder_append_cptr(sb, elStr);
StringBuilder_append_char(strb, ','); StringBuilder_append_char(sb, ',');
} }
StringBuilder_rmchar(strb); StringBuilder_rmchar(sb);
StringBuilder_append_char(strb, ' '); StringBuilder_append_char(sb, ' ');
StringBuilder_append_char(strb, ']'); StringBuilder_append_char(sb, ']');
} */ } */
static const char* _kp_colorNames[16]={ static const char* _kp_colorNames[16]={
@@ -199,12 +209,12 @@ static const char* _kp_colorNames[16]={
"white" "white"
}; };
char* kp_bgColor_toString(kp_fmt c){ char* kp_bgColor_toString(allocator_ptr al, kp_bgColor c){
u32 color_index=(c&0x00f00000)>>20; u32 color_index=(c&0x00f00000)>>20;
if(color_index>15) throw(ERR_WRONGINDEX); if(color_index>15) throw(ERR_WRONGINDEX);
return _kp_colorNames[color_index]; return _kp_colorNames[color_index];
} }
char* kp_fgColor_toString(kp_fmt c){ char* kp_fgColor_toString(allocator_ptr al, kp_fgColor c){
u32 color_index=(c&0x00f00000)>>24; u32 color_index=(c&0x00f00000)>>24;
if(color_index>15) throw(ERR_WRONGINDEX); if(color_index>15) throw(ERR_WRONGINDEX);
return _kp_colorNames[color_index]; return _kp_colorNames[color_index];

View File

@@ -70,12 +70,12 @@ static inline __kp_value_union __kpVU_i(i64 f) { return (__kp_value_union){ .i64
__kp_argsToObjs32(ARGS)) __kp_argsToObjs32(ARGS))
Maybe __ksprint(u8 n, kp_fmt* formats, __kp_value_union* objects); Maybe __ksprint(allocator_ptr al, u8 n, kp_fmt* formats, __kp_value_union* objects);
/// @param ARGS kp_fmt, value, kp_fmt, value... /// @param ARGS kp_fmt, value, kp_fmt, value...
///@returns Maybe<char*> ///@returns Maybe<char*>
#define ksprint(ARGS...) WARNING_DISABLE( W_INT_CONVERSION, \ #define ksprint(ALLOCATOR, ARGS...) WARNING_DISABLE( W_INT_CONVERSION, \
__ksprint(count_args(ARGS), __kp_argsToArrs(count_args(ARGS),ARGS, __32zeroes)) \ __ksprint(ALLOCATOR, count_args(ARGS), __kp_argsToArrs(count_args(ARGS),ARGS, __32zeroes)) \
) )
/*-Wint-conversion warning was produced during value to __kp_value_union conversion*/ /*-Wint-conversion warning was produced during value to __kp_value_union conversion*/

View File

@@ -4,6 +4,8 @@
extern "C" { extern "C" {
#endif #endif
#include "../base/memory/allocator_base.h"
// 10000000 00000000 00000000 00000000 // 10000000 00000000 00000000 00000000
// ^ ^^^^ // ^ ^^^^
// | color num // | color num
@@ -81,8 +83,8 @@ PACKED_ENUM(kp_bgColor,
kp_bgWhite = 0x40f00000 kp_bgWhite = 0x40f00000
) )
char* kp_bgColor_toString(kp_bgColor c); char* kp_bgColor_toString(allocator_ptr al, kp_bgColor c);
char* kp_fgColor_toString(kp_fgColor c); char* kp_fgColor_toString(allocator_ptr al, kp_fgColor c);
#if __cplusplus #if __cplusplus
} }

View File

@@ -49,6 +49,9 @@ void kprintf(const char* format, ...){
va_list vl; va_list vl;
va_start(vl, format); va_start(vl, format);
u32 i=0; u32 i=0;
LinearAllocator _al;
LinearAllocator_construct(&_al, 128);
allocator_ptr al=(allocator_ptr)&_al;
for(char c=format[i++]; c!=0; c=format[i++]){ for(char c=format[i++]; c!=0; c=format[i++]){
// value format specifiers // value format specifiers
if(c=='%'){ if(c=='%'){
@@ -58,18 +61,18 @@ void kprintf(const char* format, ...){
format_escape_seq: format_escape_seq:
switch (c) { switch (c) {
case 'u': case 'u':
argstr=toString_u64( argstr=toString_u64(al,
l ? va_arg(vl, u64) : va_arg(vl, u32) l ? va_arg(vl, u64) : va_arg(vl, u32)
,0,0); ,0,0);
break; break;
case 'i': case 'd': case 'i': case 'd':
argstr=toString_i64( argstr=toString_i64(al,
l ? va_arg(vl, i64) : va_arg(vl, i32) l ? va_arg(vl, i64) : va_arg(vl, i32)
); );
break; break;
case 'f': case 'f':
// f32 is promoted to f64 when passed through '...' // f32 is promoted to f64 when passed through '...'
argstr=toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0); argstr=toString_f64(al, va_arg(vl, f64), toString_float_default_precision,0,0);
break; break;
case 'l': case 'l':
l=true; l=true;
@@ -78,16 +81,16 @@ void kprintf(const char* format, ...){
break; break;
case 'p': ; case 'p': ;
void* phex=va_arg(vl, void*); void* phex=va_arg(vl, void*);
argstr=toString_hex(&phex,getEndian()==LittleEndian,sizeof(phex),1,0); argstr=toString_hex(al, &phex,getEndian()==LittleEndian,sizeof(phex),1,0);
break; break;
case 'x': ; case 'x': ;
if(l){ if(l){
u64 xhex=va_arg(vl, u64); u64 xhex=va_arg(vl, u64);
argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); argstr=toString_hex(al, &xhex,getEndian()==LittleEndian,sizeof(xhex),0,1);
} }
else { else {
u32 xhex=va_arg(vl, u32); u32 xhex=va_arg(vl, u32);
argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); argstr=toString_hex(al, &xhex,getEndian()==LittleEndian,sizeof(xhex),0,1);
} }
break; break;
case 's': ; case 's': ;
@@ -98,7 +101,7 @@ void kprintf(const char* format, ...){
fputs(cptr, stdout); fputs(cptr, stdout);
break; break;
case 'c': case 'c':
argstr=malloc(2); argstr=allocator_alloc(al, 2);
argstr[0]=(char)va_arg(vl,int); argstr[0]=(char)va_arg(vl,int);
argstr[1]=0; argstr[1]=0;
break; break;
@@ -111,7 +114,6 @@ void kprintf(const char* format, ...){
} }
if(argstr){ if(argstr){
fputs(argstr, stdout); fputs(argstr, stdout);
free(argstr);
} }
} }
// escape sequences // escape sequences
@@ -152,4 +154,5 @@ void kprintf(const char* format, ...){
#endif #endif
} }
va_end(vl); va_end(vl);
LinearAllocator_destruct(&_al);
} }

View File

@@ -1,7 +1,10 @@
# Xoshiro/Xoroshiro RNG algorithms # Random
There are a bunch of versions of xoshiro/xoroshiro algorithms, which are created by [David Blackman and Sebastiano Vigna](https://prng.di.unimi.it/) This directory contains some popular random functions. I recommend you using `splitmix64` initialized with `random_seedFromTime` for fast rng, hoshiro128plus for more accurate 32-bit rng and hoshiro256plus for 64-bit.
## 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 xoroshiro
├── 32bitValue ├── 32bitValue

View File

@@ -1,72 +0,0 @@
#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(u32 seed);
u32 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 i8 krand_next8 (krand_statePtr state, i8 from, i8 to) __krand_next_definition(32)
static inline i16 krand_next16(krand_statePtr state, i16 from, i16 to) __krand_next_definition(32)
static inline i32 krand_next32(krand_statePtr state, i32 from, i32 to) __krand_next_definition(32)
static inline i64 krand_next64(krand_statePtr state, i64 from, i64 to) __krand_next_definition(64)
// divides random number by 2^64 to return a value between 0 and 1
static inline f32 krand_nextFloat32(krand_statePtr state) {return (u32)KRAND_ALG32_next(state)/0xffffffff; }
static inline f64 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){
i32 limit=1/chance + 0.01f;
return KRAND_ALG32_next(state)%limit == 0;
}
#if __cplusplus
}
#endif

33
src/random/random.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#if __cplusplus
extern "C" {
#endif
#include "../base/std.h"
#include "splitmix64/splitmix64.h"
#include "xoroshiro/32bitValue/xoroshiro64.h"
#include "xoroshiro/64bitValue/xoroshiro128.h"
#include "xoshiro/32bitValue/xoshiro128.h"
#include "xoshiro/64bitValue/xoshiro256.h"
#define random_seedFromTime() time(NULL)
/// divides random number by 2^32
/// @return value between 0 and 1
static inline f32 random_toFloat32(u32 random_value) { return (f32)random_value / (f32)0xffff; }
/// divides random number by 2^64
/// @return value between 0 and 1
static inline f64 random_nextFloat64(u64 random_value) { return (f64)random_value / (f64)0xffffffff; }
///@param probability (0-1.0) probability of success
///@return is action sucsessfull or not
static inline bool random_probability(u32 random_value, float probability){
i32 limit=1.0f/probability + 0.0002f;
return random_value%limit == 0;
}
#if __cplusplus
}
#endif

View File

@@ -11,20 +11,11 @@ computations) or xorshift1024* (for massively parallel computations)
generator. generator.
*/ */
// The state can be seeded with any (upto) 64 bit integer value. u64 splitmix64_next(splitmix64_state* state_ptr) {
void* splitmix64_init(u64 seed){
splitmix64_state* state=malloc(sizeof(splitmix64_state));
*state=seed;
return state;
}
u64 splitmix64_next(void* _state) {
splitmix64_state* state=_state;
// increment the state variable // increment the state variable
*state += 0x9e3779b97f4a7c15; *state_ptr += 0x9e3779b97f4a7c15;
// copy the state to a working variable // copy the state to a working variable
u64 z = *state; u64 z = *state_ptr;
// xor the variable with the variable right bit shifted 30 then multiply by a constant // xor the variable with the variable right bit shifted 30 then multiply by a constant
z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9;
// xor the variable with the variable right bit shifted 27 then multiply by a constant // xor the variable with the variable right bit shifted 27 then multiply by a constant

View File

@@ -7,16 +7,13 @@ extern "C" {
#include "../../base/base.h" #include "../../base/base.h"
typedef u64 splitmix64_state; typedef u64 splitmix64_state;
typedef void* splitmix64_statePtr;
splitmix64_statePtr splitmix64_init(u64 seed); static inline void splitmix64_construct(splitmix64_state* state, u64 seed){
static inline splitmix64_statePtr splitmix64_initFromTime(void) { return splitmix64_init(time(NULL)); } *state=seed;
u64 splitmix64_next(splitmix64_statePtr);
static inline void splitmix64_free(splitmix64_statePtr state) {
free(state);
} }
u64 splitmix64_next(splitmix64_state* state_ptr);
#if __cplusplus #if __cplusplus
} }
#endif #endif

View File

@@ -4,31 +4,17 @@
extern "C" { extern "C" {
#endif #endif
#include "../../../base/std.h"
#include "../../splitmix64/splitmix64.h" #include "../../splitmix64/splitmix64.h"
typedef union { typedef union {
u64 merged; u64 merged;
u32 s[2]; u32 s[2];
} xoroshiro64_state; } xoroshiro64_state;
typedef void* xoroshiro64_statePtr;
xoroshiro64_statePtr xoroshiro64_init(u64 seed); void xoroshiro64_construct(xoroshiro64_state* state_ptr, u64 seed);
#define xoroshiro64star_init xoroshiro64_init
#define xoroshiro64starstar_init xoroshiro64_init
static inline xoroshiro64_statePtr xoroshiro64_initFromTime(void) { return xoroshiro64_init(time(NULL)); } u32 xoroshiro64star_next(xoroshiro64_state*);
#define xoroshiro64star_initFromTime xoroshiro64_initFromTime u32 xoroshiro64starstar_next(xoroshiro64_state*);
#define xoroshiro64starstar_initFromTime xoroshiro64_initFromTime
u32 xoroshiro64star_next(xoroshiro64_statePtr);
u32 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 #if __cplusplus
} }

View File

@@ -27,8 +27,7 @@ static inline u32 rotl(const u32 x, i32 k) {
return (x << k) | (x >> (32 - k)); return (x << k) | (x >> (32 - k));
} }
u32 xoroshiro64star_next(void* _state) { u32 xoroshiro64star_next(xoroshiro64_state* state) {
xoroshiro64_state* state=_state;
const u32 s0 = state->s[0]; const u32 s0 = state->s[0];
u32 s1 = state->s[1]; u32 s1 = state->s[1];
const u32 result = s0 * 0x9E3779BB; const u32 result = s0 * 0x9E3779BB;
@@ -40,10 +39,8 @@ u32 xoroshiro64star_next(void* _state) {
return result; return result;
} }
void* xoroshiro64_init(u64 seed){ void xoroshiro64_construct(xoroshiro64_state* state, u64 seed){
xoroshiro64_state* state=malloc(sizeof(xoroshiro64_state)); splitmix64_state sm_state;
splitmix64_state* splitmix=splitmix64_init(seed); splitmix64_construct(&sm_state, seed);
state->merged=splitmix64_next(splitmix); state->merged=splitmix64_next(&sm_state);
splitmix64_free(splitmix);
return state;
} }

View File

@@ -23,8 +23,7 @@ static inline u32 rotl(const u32 x, i32 k) {
return (x << k) | (x >> (32 - k)); return (x << k) | (x >> (32 - k));
} }
u32 xoroshiro64starstar_next(void* _state) { u32 xoroshiro64starstar_next(xoroshiro64_state* state) {
xoroshiro64_state* state=_state;
const u32 s0 = state->s[0]; const u32 s0 = state->s[0];
u32 s1 = state->s[1]; u32 s1 = state->s[1];
const u32 result = rotl(s0 * 0x9E3779BB, 5) * 5; const u32 result = rotl(s0 * 0x9E3779BB, 5) * 5;

View File

@@ -4,35 +4,17 @@
extern "C" { extern "C" {
#endif #endif
#include "../../../base/std.h"
#include "../../splitmix64/splitmix64.h" #include "../../splitmix64/splitmix64.h"
typedef union { typedef union {
u32 s[2]; u32 s[2];
} xoroshiro128_state; } xoroshiro128_state;
typedef void* xoroshiro128_statePtr;
xoroshiro128_statePtr xoroshiro128_init(u64 seed); void xoroshiro128_construct(xoroshiro128_state* state, u64 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)); } u64 xoroshiro128plus_next(xoroshiro128_state*);
#define xoroshiro128plus_initFromTime xoroshiro128_initFromTime u64 xoroshiro128plusplus_next(xoroshiro128_state*);
#define xoroshiro128plusplus_initFromTime xoroshiro128_initFromTime u64 xoroshiro128starstar_next(xoroshiro128_state*);
#define xoroshiro128starstar_initFromTime xoroshiro128_initFromTime
u64 xoroshiro128plus_next(xoroshiro128_statePtr);
u64 xoroshiro128plusplus_next(xoroshiro128_statePtr);
u64 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 #if __cplusplus
} }

View File

@@ -36,8 +36,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
u64 xoroshiro128plus_next(void* _state){ u64 xoroshiro128plus_next(xoroshiro128_state* state){
xoroshiro128_state* state=_state;
const u64 s0 = state->s[0]; const u64 s0 = state->s[0];
u64 s1 = state->s[1]; u64 s1 = state->s[1];
const u64 result = s0 + s1; const u64 result = s0 + s1;
@@ -49,11 +48,9 @@ u64 xoroshiro128plus_next(void* _state){
return result; return result;
} }
void* xoroshiro128_init(u64 seed){ void xoroshiro128_construct(xoroshiro128_state* state, u64 seed){
xoroshiro128_state* state=malloc(sizeof(xoroshiro128_state)); splitmix64_state sm_state;
splitmix64_state* splitmix=splitmix64_init(seed); splitmix64_construct(&sm_state, seed);
state->s[0]=splitmix64_next(splitmix); state->s[0]=splitmix64_next(&sm_state);
state->s[1]=splitmix64_next(splitmix); state->s[1]=splitmix64_next(&sm_state);
splitmix64_free(splitmix);
return state;
} }

View File

@@ -25,8 +25,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
u64 xoroshiro128plusplus_next(void* _state){ u64 xoroshiro128plusplus_next(xoroshiro128_state* state){
xoroshiro128_state* state=_state;
const u64 s0 = state->s[0]; const u64 s0 = state->s[0];
u64 s1 = state->s[1]; u64 s1 = state->s[1];
const u64 result = rotl(s0 + s1, 17) + s0; const u64 result = rotl(s0 + s1, 17) + s0;

View File

@@ -25,8 +25,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
u64 xoroshiro128starstar_next(void* _state){ u64 xoroshiro128starstar_next(xoroshiro128_state* state){
xoroshiro128_state* state=_state;
const u64 s0 = state->s[0]; const u64 s0 = state->s[0];
u64 s1 = state->s[1]; u64 s1 = state->s[1];
const u64 result = rotl(s0 * 5, 7) * 9; const u64 result = rotl(s0 * 5, 7) * 9;

View File

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

View File

@@ -4,36 +4,18 @@
extern "C" { extern "C" {
#endif #endif
#include "../../../base/std.h"
#include "../../splitmix64/splitmix64.h" #include "../../splitmix64/splitmix64.h"
typedef union { typedef union {
u64 merged[2]; u64 merged[2];
u32 s[4]; u32 s[4];
} xoshiro128_state; } xoshiro128_state;
typedef void* xoshiro128_statePtr;
xoshiro128_statePtr xoshiro128_init(u64 seed); void xoshiro128_construct(xoshiro128_state* state, u64 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)); } u32 xoshiro128plus_next(xoshiro128_state*);
#define xoshiro128plus_initFromTime xoshiro128_initFromTime u32 xoshiro128plusplus_next(xoshiro128_state*);
#define xoshiro128plusplus_initFromTime xoshiro128_initFromTime u32 xoshiro128starstar_next(xoshiro128_state*);
#define xoshiro128starstar_initFromTime xoshiro128_initFromTime
u32 xoshiro128plus_next(xoshiro128_statePtr);
u32 xoshiro128plusplus_next(xoshiro128_statePtr);
u32 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 #if __cplusplus
} }

View File

@@ -26,8 +26,7 @@ static inline u32 rotl(const u32 x, i32 k) {
return (x << k) | (x >> (32 - k)); return (x << k) | (x >> (32 - k));
} }
u32 xoshiro128plus_next(void* _state){ u32 xoshiro128plus_next(xoshiro128_state* state){
xoshiro128_state* state=_state;
const u32 result = state->s[0] + state->s[3]; const u32 result = state->s[0] + state->s[3];
const u32 t = state->s[1] << 9; const u32 t = state->s[1] << 9;
@@ -44,11 +43,9 @@ u32 xoshiro128plus_next(void* _state){
return result; return result;
} }
void* xoshiro128_init(u64 seed){ void xoshiro128_construct(xoshiro128_state* state, u64 seed){
xoshiro128_state* state=malloc(sizeof(xoshiro128_state)); splitmix64_state sm_state;
splitmix64_state* splitmix=splitmix64_init(seed); splitmix64_construct(&sm_state, seed);
state->merged[0]=splitmix64_next(splitmix); state->merged[0]=splitmix64_next(&sm_state);
state->merged[1]=splitmix64_next(splitmix); state->merged[1]=splitmix64_next(&sm_state);
splitmix64_free(splitmix);
return state;
} }

View File

@@ -23,8 +23,7 @@ static inline u32 rotl(const u32 x, i32 k) {
return (x << k) | (x >> (32 - k)); return (x << k) | (x >> (32 - k));
} }
u32 xoshiro128plusplus_next(void* _state){ u32 xoshiro128plusplus_next(xoshiro128_state* state){
xoshiro128_state* state=_state;
const u32 result = rotl(state->s[0] + state->s[3], 7) + state->s[0]; const u32 result = rotl(state->s[0] + state->s[3], 7) + state->s[0];
const u32 t = state->s[1] << 9; const u32 t = state->s[1] << 9;

View File

@@ -26,8 +26,7 @@ static inline u32 rotl(const u32 x, i32 k) {
return (x << k) | (x >> (32 - k)); return (x << k) | (x >> (32 - k));
} }
u32 xoshiro128starstar_next(void* _state){ u32 xoshiro128starstar_next(xoshiro128_state* state){
xoshiro128_state* state=_state;
const u32 result = rotl(state->s[1] * 5, 7) * 9; const u32 result = rotl(state->s[1] * 5, 7) * 9;
const u32 t = state->s[1] << 9; const u32 t = state->s[1] << 9;

View File

@@ -4,35 +4,17 @@
extern "C" { extern "C" {
#endif #endif
#include "../../../base/std.h"
#include "../../splitmix64/splitmix64.h" #include "../../splitmix64/splitmix64.h"
typedef union { typedef union {
u64 s[4]; u64 s[4];
} xoshiro256_state; } xoshiro256_state;
typedef void* xoshiro256_statePtr;
xoshiro256_statePtr xoshiro256_init(u64 seed); void xoshiro256_construct(xoshiro256_state* state, u64 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)); } u64 xoshiro256plus_next(xoshiro256_state*);
#define xoshiro256plus_initFromTime xoshiro256_initFromTime u64 xoshiro256plusplus_next(xoshiro256_state*);
#define xoshiro256plusplus_initFromTime xoshiro256_initFromTime u64 xoshiro256starstar_next(xoshiro256_state*);
#define xoshiro256starstar_initFromTime xoshiro256_initFromTime
u64 xoshiro256plus_next(xoshiro256_statePtr);
u64 xoshiro256plusplus_next(xoshiro256_statePtr);
u64 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 #if __cplusplus
} }

View File

@@ -28,8 +28,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
u64 xoshiro256plus_next(void* _state){ u64 xoshiro256plus_next(xoshiro256_state* state){
xoshiro256_state* state=_state;
const u64 result = state->s[0] + state->s[3]; const u64 result = state->s[0] + state->s[3];
const u64 t = state->s[1] << 17; const u64 t = state->s[1] << 17;
@@ -46,13 +45,11 @@ u64 xoshiro256plus_next(void* _state){
return result; return result;
} }
void* xoshiro256_init(u64 seed){ void xoshiro256_construct(xoshiro256_state* state, u64 seed){
xoshiro256_state* state=malloc(sizeof(xoshiro256_state)); splitmix64_state sm_state;
splitmix64_state* splitmix=splitmix64_init(seed); splitmix64_construct(&sm_state, seed);
state->s[0]=splitmix64_next(splitmix); state->s[0]=splitmix64_next(&sm_state);
state->s[1]=splitmix64_next(splitmix); state->s[1]=splitmix64_next(&sm_state);
state->s[2]=splitmix64_next(splitmix); state->s[2]=splitmix64_next(&sm_state);
state->s[3]=splitmix64_next(splitmix); state->s[3]=splitmix64_next(&sm_state);
splitmix64_free(splitmix);
return state;
} }

View File

@@ -23,8 +23,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x>>(64 - k)); return (x << k) | (x>>(64 - k));
} }
u64 xoshiro256plusplus_next(void* _state) { u64 xoshiro256plusplus_next(xoshiro256_state* state) {
xoshiro256_state* state=_state;
const u64 result=rotl(state->s[0] + state->s[3], 23) + state->s[0]; const u64 result=rotl(state->s[0] + state->s[3], 23) + state->s[0];
const u64 t=state->s[1] << 17; const u64 t=state->s[1] << 17;
state->s[2] ^= state->s[0]; state->s[2] ^= state->s[0];

View File

@@ -23,8 +23,7 @@ static inline u64 rotl(const u64 x, i32 k) {
return (x << k) | (x >> (64 - k)); return (x << k) | (x >> (64 - k));
} }
u64 xoshiro256starstar_next(void* _state){ u64 xoshiro256starstar_next(xoshiro256_state* state){
xoshiro256_state* state=_state;
const u64 result = rotl(state->s[1] * 5, 7) * 9; const u64 result = rotl(state->s[1] * 5, 7) * 9;
const u64 t = state->s[1] << 17; const u64 t = state->s[1] << 17;

View File

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

View File

@@ -7,7 +7,7 @@ i32 main(){
kt_initKerepTypes(); kt_initKerepTypes();
kt_endInit(); kt_endInit();
test_all(); test_all();
kt_free(); kt_deinit();
kprintf("\e[0m\n"); kprintf("\e[0m\n");
return 0; return 0;
} }

45
tests/test_allocators.c Normal file
View File

@@ -0,0 +1,45 @@
#include "tests.h"
void _test_allocator(allocator_ptr al){
void* ptr=allocator_alloc(al, 1);
allocator_free(al, ptr);
ptr=allocator_alloc(al, 5);
allocator_free(al, ptr);
ptr=allocator_alloc(al, 41);
allocator_free(al, ptr);
ptr=allocator_alloc(al, 19);
void* ptr1=allocator_alloc(al, 1);
void* ptr2=allocator_alloc(al, 5);
// allocator_free(al, ptr); // temp case
allocator_free(al, ptr2);
allocator_free(al, ptr1);
allocator_free(al, ptr);
ptr=allocator_alloc(al, 500);
ptr1=allocator_alloc(al, 1025);
allocator_free(al, ptr1);
allocator_free(al, ptr);/*
ptr=allocator_alloc(al, 5000);
ptr1=allocator_alloc(al, 5000000);
allocator_free(al, ptr1);
allocator_free(al, ptr);*/
}
void test_allocators(){
kprintf("\e[96m----------[test_allocators]-----------\n");
optime("test CstdAllocator", 10000,
_test_allocator(CstdAllocator_instPtr);
);
optime("test LinearAllocator", 10000,
LinearAllocator al;
LinearAllocator_construct(&al, 4096);
_test_allocator((allocator_ptr)&al);
LinearAllocator_destruct(&al);
);
optime("test StackingAllocator", 10000,
StackingAllocator al;
StackingAllocator_construct(&al, 4096);
_test_allocator((allocator_ptr)&al);
StackingAllocator_destruct(&al);
);
}

View File

@@ -2,10 +2,11 @@
#include "../src/Autoarr/Autoarr.h" #include "../src/Autoarr/Autoarr.h"
#include <vector> #include <vector>
i64 _autoarrVsVector(u16 blockCount, u16 blockLength){ i64 _autoarrVsVector(u32 count){
u32 count=blockLength*blockCount; kprintf("\e[94mcount: %u\n", count);
kprintf("\e[94mblock count: %u block length: %u count: " IFWIN("%llu", "%lu") "\n", blockCount, blockLength, (u64)count); Autoarr_i64 _ar;
Autoarr_i64* ar=Autoarr_create(i64, blockCount, blockLength); Autoarr_i64* ar=&_ar;
Autoarr_construct(ar, i64, count, NULL);
std::vector<i64> vec=std::vector<i64>(); std::vector<i64> vec=std::vector<i64>();
optime("Autoarr_add", count, optime("Autoarr_add", count,
Autoarr_add(ar, op_i)); Autoarr_add(ar, op_i));
@@ -16,19 +17,22 @@ i64 _autoarrVsVector(u16 blockCount, u16 blockLength){
t=Autoarr_get(ar, op_i)); t=Autoarr_get(ar, op_i));
optime("vector_get", count, optime("vector_get", count,
t=vec[op_i]); t=vec[op_i]);
Autoarr_free(ar, true); Autoarr_destruct(ar);
return t; return t;
} }
void test_autoarrVsVector(){ void test_autoarrVsVector(){
optime(__func__, 1, optime(__func__, 1,
kprintf("\e[96m-------[test_autoarr_vs_vector]-------\n"); kprintf("\e[96m-------[test_autoarr_vs_vector]-------\n");
_autoarrVsVector(4, 16); _autoarrVsVector(1);
_autoarrVsVector(16, 64); _autoarrVsVector(4);
_autoarrVsVector(32, 32); _autoarrVsVector(16);
_autoarrVsVector(64, 64); _autoarrVsVector(64);
_autoarrVsVector(32, 1024); _autoarrVsVector(256);
_autoarrVsVector(256, 256); _autoarrVsVector(1024);
_autoarrVsVector(1024, 1024); _autoarrVsVector(4096);
_autoarrVsVector(16384);
_autoarrVsVector(65536);
_autoarrVsVector(524288);
); );
} }

View File

@@ -1,53 +1,45 @@
#include "tests.h" #include "tests.h"
#include "../src/Autoarr/Autoarr.h" #include "../src/Autoarr/Autoarr.h"
#define ARR_SZ 256
static void printautoarr(Autoarr(u16)* ar){ static void printautoarr(Autoarr(u16)* ar){
kprintf("\e[94mAutoarr(u16): " kprintf("\e[94mAutoarr(u16): %lu\n"
IFWIN("%llu", "%lu") " length: %u",
"\n max_blocks_count: %u\n"
" blocks_count: %u\n"
" max_block_length: %u\n"
" block_length: %u\n"
" max_length: %u\n"
" length: %u\n",
sizeof(Autoarr(u16)), sizeof(Autoarr(u16)),
ar->max_blocks_count,
ar->blocks_count,
ar->max_block_length,
ar->block_length,
Autoarr_max_length(ar),
Autoarr_length(ar)); Autoarr_length(ar));
} }
static void fillar(Autoarr(u16)* ar){ static void fillar(Autoarr(u16)* ar){
for (u16 i=0;i<Autoarr_max_length(ar);i++) for (u16 i=0; ARR_SZ; i++)
Autoarr_add(ar,i); Autoarr_add(ar,i);
} }
static void resetar(Autoarr(u16)* ar){ static void resetar(Autoarr(u16)* ar){
for (u16 i=0;i<Autoarr_max_length(ar);i++) for (u16 i=0; ARR_SZ; i++)
Autoarr_set(ar,i,Autoarr_max_length(ar)-i-1); Autoarr_set(ar,i,ARR_SZ-i-1);
} }
static void printallval(Autoarr(u16)* ar){ static void printallval(Autoarr(u16)* ar){
kprintf("\e[90m"); kprintf("\e[90m");
for (u16 i=0;i<Autoarr_length(ar);i++) for (u16 i=0; i<Autoarr_length(ar); i++)
kprintf("%u ",Autoarr_get(ar,i)); kprintf("%u ",Autoarr_get(ar,i));
kprintf("\n"); kprintf("\n");
} }
void test_autoarr(){ void test_autoarr(){
optime("test_autoarr",1, // optime("test_autoarr",1,
kprintf("\e[96m------------[test_autoarr]------------\n"); kprintf("\e[96m------------[test_autoarr]------------\n");
Autoarr(u16)* ar=Autoarr_create(u16,10,16); Autoarr(u16) ar;
Autoarr_construct(&ar, u16, ARR_SZ, NULL);
kprintf("\e[92mautoarr created\n"); kprintf("\e[92mautoarr created\n");
fillar(ar); fillar(&ar);
kprintf("\e[92mautoarr filled up\n"); kprintf("\e[92mautoarr filled up\n");
printautoarr(ar); printautoarr(&ar);
printallval(ar); printallval(&ar);
resetar(ar); resetar(&ar);
kprintf("\e[92mautoarr values reset\n"); kprintf("\e[92mautoarr values reset\n");
printallval(ar); printallval(&ar);
Autoarr_free(ar, true); Autoarr_destruct(&ar);
kprintf("\e[92mautoarr deleted\n"); kprintf("\e[92mautoarr deleted\n");
); // );
} }

View File

@@ -52,7 +52,7 @@ void test_dtsod(){
tryLast(DtsodV24_serialize(dtsod),r,;) tryLast(DtsodV24_serialize(dtsod),r,;)
s=r.value.VoidPtr; s=r.value.VoidPtr;
); );
DtsodV24_free(dtsod); DtsodV24_destruct(dtsod);
kprintf("\e[92m%s",s); kprintf("\e[92m%s",s);
optime("reserialize",10, optime("reserialize",10,
@@ -61,7 +61,7 @@ void test_dtsod(){
free(s); free(s);
tryLast(DtsodV24_serialize(dtsod),rr,;) tryLast(DtsodV24_serialize(dtsod),rr,;)
s=rr.value.VoidPtr; s=rr.value.VoidPtr;
DtsodV24_free(dtsod); DtsodV24_destruct(dtsod);
); );
free(s); free(s);

View File

@@ -1,26 +1,33 @@
#include "tests.h" #include "tests.h"
#include "../src/HashFunctions/hash.h" #include "../src/HashFunctions/hash.h"
#include "../src/Autoarr/Autoarr.h" #include "../src/Autoarr/Autoarr.h"
#include "../src/random/random.h"
#define SPEED_TESTS 1000000
#define COLLISION_TESTS 64000
char data[]="iojihi2ojo8la14nhvi3311pi[jiugbja38mo0ih6gfty88tryf-drh0lanvj03";
#define SPEED_TESTS 100000 #define rng() splitmix64_next(&rng_state)
#define COLLISION_TESTS 16000
char data[]="iojihiojopijiugbjmoihftytryfdrh";
#define test_hashfunc(hasht, hashf) { \ #define test_hashfunc(hasht, hashf) { \
kprintf("\e[94mfunction: \e[92m" #hashf "\n"); \ kprintf("\e[94mfunction: \e[92m" #hashf "\n"); \
hasht h=0; \ hasht h=0; \
optime("speed test", 1, \ optime("speed test", SPEED_TESTS, \
for(u32 i=0; i<SPEED_TESTS; i++) \
h=hashf(h, data, sizeof(data)); \ h=hashf(h, data, sizeof(data)); \
); \ ); \
/*kprintf("\e[94mhash of \"\e[90m%s\e[94m\": \e[92m%x\n",data, h);*/ \ /*kprintf("\e[94mhash of \"\e[90m%s\e[94m\": \e[92m%x\n",data, h);*/ \
Autoarr(hasht)* hashes=Autoarr_create(hasht,512,32768); \ Autoarr(hasht) _hashes; \
Autoarr(hasht)* hashes = &_hashes; \
Autoarr_construct(hashes, hasht, COLLISION_TESTS*sizeof(hasht), NULL); \
splitmix64_state rng_state; \
splitmix64_construct(&rng_state, random_seedFromTime()); \
optime("collision test",1, \ optime("collision test",1, \
u32 collisions=0; \ u32 collisions=0; \
for(u64 i=0;i< COLLISION_TESTS;i++){ \ for(u64 i=0;i< COLLISION_TESTS;i++){ \
hasht h=hashb(hashf, (u8*)&i, sizeof(i)); \ u64 rn[8]; \
rn[0]=rng(); rn[1]=rng(); rn[2]=rng(); rn[3]=rng();\
rn[4]=rng(); rn[5]=rng(); rn[6]=rng(); rn[7]=rng();\
hasht h=hashb(hashf, rn, sizeof(rn)); \
bool col=false; \ bool col=false; \
Autoarr_foreach(hashes,e, \ Autoarr_foreach(hashes,e, \
if(e==h) { \ if(e==h) { \
@@ -33,14 +40,14 @@ char data[]="iojihiojopijiugbjmoihftytryfdrh";
} \ } \
kprintf("\e[93m%u \e[94mcollisions detected in %u hashes\n", collisions, COLLISION_TESTS); \ kprintf("\e[93m%u \e[94mcollisions detected in %u hashes\n", collisions, COLLISION_TESTS); \
); \ ); \
Autoarr_free(hashes, true); \ Autoarr_destruct(hashes); \
kprintf("\e[96m--------------------------------------\n"); \ kprintf("\e[96m--------------------------------------\n"); \
} }
void test_hash_functions(){ void test_hash_functions(){
optime("test_hash_functions",1, optime("test_hash_functions",1,
kprintf("\e[96m--------[test_hash_functions]---------\n"); kprintf("\e[96m--------[test_hash_functions]---------\n");
test_hashfunc(u32, hash_crc32);
test_hashfunc(u32, hash_sdbm32); test_hashfunc(u32, hash_sdbm32);
test_hashfunc(u32, hash_crc32);
); );
} }

View File

@@ -2,60 +2,56 @@
#include "../src/Hashtable/Hashtable.h" #include "../src/Hashtable/Hashtable.h"
void print_hashtable(Hashtable* ht){ void print_hashtable(Hashtable* ht){
kprintf("\e[94mHashtable: " kprintf("\e[94mHashtable: %lu\n"
IFWIN("%llu", "%lu") " hein: %u\n"
"\n hein: %u\n"
" height: %u\n" " height: %u\n"
" rows: %p\n", " rows: %p\n",
sizeof(Hashtable), sizeof(Hashtable),
ht->hein, ht->hein,
Hashtable_height(ht), __Hashtable_height(ht),
ht->rows); ht->rows);
} }
void printrowgraph(Hashtable* ht){ void printrowgraph(allocator_ptr al, Hashtable* ht){
kprintf("\e[94mrow length graph:\n"); kprintf("\e[94mrow length graph:\n");
u16 lgs_l=1000; u16 lgs_l=1000;
u32 lgs[lgs_l]; u32 lgs[lgs_l];
for(u32 i=0; i<lgs_l; i++) for(u32 i=0; i<lgs_l; i++)
lgs[i]=0; lgs[i]=0;
for(u16 h=0;h<Hashtable_height(ht);h++){ for(u16 h=0;h<__Hashtable_height(ht);h++){
Autoarr(KVPair)* ar=ht->rows[h]; Autoarr(KVPair)* ar=&ht->rows[h];
u32 l=Autoarr_length(ar); u32 l=Autoarr_length(ar);
lgs[l]++; lgs[l]++;
} }
for(u32 i=0; i<lgs_l; i++) for(u32 i=0; i<lgs_l; i++)
if(lgs[i]>0) { if(lgs[i]>0) {
char* str0=char_multiply(' ',i>=100?0:(i>=10?1:2)); char* str0=char_multiply(al, ' ',i>=100?0:(i>=10?1:2));
char* str1=char_multiply(' ',lgs[i]>=100?0:(lgs[i]>=10?1:2)); char* str1=char_multiply(al, ' ',lgs[i]>=100?0:(lgs[i]>=10?1:2));
char* str2=char_multiply('#',lgs[i]/100); char* str2=char_multiply(al, '#',lgs[i]/100);
kprintf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2); kprintf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2);
free(str0); allocator_free(al, str2);
free(str1); allocator_free(al, str1);
free(str2); allocator_free(al, str0);
} }
} }
char* genkey(u32 i){ char* genkey(allocator_ptr al, u32 i){
char* key=malloc(12); char* key=allocator_alloc(al, 16);
IFMSC( sprintf_s(key,16,"key_%u",i);
sprintf_s(key,12,"key_%u",i),
sprintf(key,"key_%u",i)
);
return key; return key;
} }
void fill(Hashtable* ht){ void fill(allocator_ptr al, Hashtable* ht){
for(u32 i=0;i<100000;i++) for(u32 i=0;i<100000;i++)
Hashtable_add(ht,genkey(i),UniUInt64(i)); Hashtable_add(ht,genkey(al, i), UniUInt64(i));
} }
Unitype gett(Hashtable* ht){ Unitype gett(allocator_ptr al, Hashtable* ht){
Unitype u; Unitype u;
for(u32 i=0;i<100000;i++){ for(u32 i=0;i<100000;i++){
char* key=genkey(i); char* key=genkey(al, i);
u=Hashtable_get(ht,key); u=Hashtable_get(ht,key);
free(key); allocator_free(al, key);
} }
return u; return u;
} }
@@ -64,14 +60,20 @@ Unitype gett(Hashtable* ht){
void test_hashtable(){ void test_hashtable(){
optime("test_hashtable",1, optime("test_hashtable",1,
kprintf("\e[96m-----------[test_hashtable]-----------\n"); kprintf("\e[96m-----------[test_hashtable]-----------\n");
Hashtable* ht=Hashtable_create(); StackingAllocator _al;
allocator_ptr al=(allocator_ptr)&_al;
StackingAllocator_construct(&_al, 4096);
Hashtable _ht;
Hashtable* ht=&_ht;
Hashtable_construct(ht, al);
kprintf("\e[92mhashtable created\n"); kprintf("\e[92mhashtable created\n");
print_hashtable(ht); print_hashtable(ht);
optime("fill",1,fill(ht)); optime("fill",1,fill(al, ht));
optime("get",1,gett(ht)); optime("get",1,gett(al, ht));
printrowgraph(ht); printrowgraph(al, ht);
print_hashtable(ht); print_hashtable(ht);
Hashtable_free(ht); Hashtable_destruct(ht);
kprintf("\e[92mhashtable freed\n"); kprintf("\e[92mhashtable freed\n");
StackingAllocator_destruct(&_al);
); );
} }

View File

@@ -1,10 +1,10 @@
#include "../src/Hashtable/KeyValuePair.h" #include "../src/Hashtable/KeyValuePair.h"
EXPORT void CALL test_marshalling(char* text, KVPair** kptr){ EXPORT void CALL test_marshalling(char* text, KVPair** kptr){
KVPair* k=malloc(sizeof(KVPair)); KVPair* k=allocator_alloc(CstdAllocator_instPtr, sizeof(KVPair));
k->key="message"; k->key="message";
char* tc=cptr_copy(text); char* tc=cptr_copy(CstdAllocator_instPtr, text);
Unitype u=UniHeapPtr(char,tc); Unitype u=UniHeapPtr(char, tc);
k->value=u; k->value=u;
*kptr=k; *kptr=k;
} }

View File

@@ -1,45 +1,43 @@
#include "tests.h" #include "tests.h"
#include "../src/random/krandom.h" #include "../src/random/random.h"
#define test_alg(ALG, STATE_TYPE, EXPECTED_FROM_ZERO) { \
#define test_alg(ALG, VALUE_SIZE, EXPECTED_FROM_ZERO) { \
kprintf("\e[94mrng algorithm: \e[96m" #ALG "\n"); \ kprintf("\e[94mrng algorithm: \e[96m" #ALG "\n"); \
void* s= ALG##_init(0); \ STATE_TYPE##_state state; \
u##VALUE_SIZE r=ALG##_next(s); \ STATE_TYPE##_construct(&state, 0); \
u64 rn=ALG##_next(&state); \
kprintf("\e[97m next from zero seed:"); \ kprintf("\e[97m next from zero seed:"); \
if(r!=EXPECTED_FROM_ZERO){ \ if(rn != EXPECTED_FROM_ZERO){ \
kprintf("\e[91m " IFWIN("%llu\n","%lu\n"), (u64)r); \ kprintf("\e[91m %lu\n", rn); \
throw(ERR_UNEXPECTEDVAL); \ throw(ERR_UNEXPECTEDVAL); \
} \ } \
kprintf("\e[92m " IFWIN("%llu\n","%lu\n"), (u64)r); \ kprintf("\e[92m %lu\n", rn); \
ALG##_free(s); \ STATE_TYPE##_construct(&state, random_seedFromTime()); \
s= ALG##_initFromTime(); \ rn=ALG##_next(&state); \
r=ALG##_next(s); \ kprintf("\e[97m next from time seed:\e[92m %lu\n", rn); \
ALG##_free(s); \
kprintf("\e[97m next from time seed:\e[92m " IFWIN("%llu\n","%lu\n"), (u64)r); \
} }
void test_rng_algorithms(){ void test_rng_algorithms(){
optime("test_rng_algorithms",1, // optime("test_rng_algorithms",1,
kprintf("\e[96m--------[test_rng_algorithms]---------\n"); kprintf("\e[96m--------[test_rng_algorithms]---------\n");
// for ALG32
// xoroshiro64
test_alg(xoroshiro64star, 32, 932574677ULL)
test_alg(xoroshiro64starstar, 32, 3183060286ULL)
// xoshiro128
test_alg(xoshiro128plus, 32, 3918949401ULL)
test_alg(xoshiro128plusplus, 32, 1179900579ULL)
test_alg(xoshiro128starstar, 32, 3737715805ULL)
// for ALG64
// xoroshiro128
test_alg(xoroshiro128plus, 64, 4778832803ULL)
test_alg(xoroshiro128plusplus, 64, 626373238705583ULL)
test_alg(xoroshiro128starstar, 64, 11897572417920ULL)
// xoshiro256
test_alg(xoshiro256plus, 64, 15757075719729598363ULL)
test_alg(xoshiro256plusplus, 64, 5987356902031041503ULL)
test_alg(xoshiro256starstar, 64, 11091344671253066420ULL)
// splitmix64 // splitmix64
test_alg(splitmix64, 64, 16294208416658607535ULL) test_alg(splitmix64, splitmix64, 16294208416658607535ULL)
); // 32-bit
// xoroshiro64
test_alg(xoroshiro64star, xoroshiro64, 932574677ULL)
test_alg(xoroshiro64starstar, xoroshiro64, 3183060286ULL)
// xoshiro128
test_alg(xoshiro128plus, xoshiro128, 3918949401ULL)
test_alg(xoshiro128plusplus, xoshiro128, 1179900579ULL)
test_alg(xoshiro128starstar, xoshiro128, 3737715805ULL)
// 64-bit
// xoroshiro128
test_alg(xoroshiro128plus, xoroshiro128, 4778832803ULL)
test_alg(xoroshiro128plusplus, xoroshiro128, 626373238705583ULL)
test_alg(xoroshiro128starstar, xoroshiro128, 11897572417920ULL)
// xoshiro256
test_alg(xoshiro256plus, xoshiro256, 15757075719729598363ULL)
test_alg(xoshiro256plusplus, xoshiro256, 5987356902031041503ULL)
test_alg(xoshiro256starstar, xoshiro256, 11091344671253066420ULL)
// );
} }

View File

@@ -5,8 +5,7 @@ Maybe dont_throw(){
} }
Maybe throw_error(){ Maybe throw_error(){
char* k=malloc(64); safethrow("test exception", kprintf("\e[94on_safethrow_free called\n"));
safethrow("test exception",free(k));
} }
Maybe throw_errcode(){ Maybe throw_errcode(){
@@ -34,10 +33,10 @@ void test_safethrow(){
Maybe e=test_maybe(); Maybe e=test_maybe();
kprintf("\e[94mthrow_error:\n\e[92m"); kprintf("\e[94mthrow_error:\n\e[92m");
printMaybe(e); printMaybe(e);
Maybe_free(e); Maybe_destruct(e);
kprintf("\e[94mthrow_errcode:\n\e[92m"); kprintf("\e[94mthrow_errcode:\n\e[92m");
e=a(); e=a();
printMaybe(e); printMaybe(e);
Maybe_free(e); Maybe_destruct(e);
); );
} }

Some files were not shown because too many files have changed in this diff Show More