string and StringBuilder

This commit is contained in:
timerix 2023-06-08 18:34:42 +06:00
parent 32ce7d3a70
commit 8d36fd8042
21 changed files with 186 additions and 109 deletions

25
TODO.md Normal file
View File

@ -0,0 +1,25 @@
## General refactoring
- replace all malloc() and free() with allocator_alloc() and allocator_free()
- replace allocating constructors with Type_init(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
- replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize)
## Autoarr
- store lenght and max_lenght inside the struct instead of calculating them by macro
- keep Autoarr_length() and Autoarr_maxLength() to old code compatibility
## 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`

View File

@ -10,11 +10,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
@ -94,7 +96,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,;);
@ -111,7 +113,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)
@ -119,7 +121,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=='"') {
@ -175,34 +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];
sprintf_s(err, sizeof(err), "can't parse to int: <%s>", _c); sprintf_s(err, sizeof(err), "can't parse to int: <%s>", _c);
safethrow(err,free(_c)); safethrow(err, /*allocator_free(tmp_al, _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];
sprintf_s(err, sizeof(err),"can't parse to int: <%s>",_c); sprintf_s(err, sizeof(err),"can't parse to int: <%s>",_c);
safethrow(err,free(_c)); // safethrow(err,allocator_free(tmp_al, _c));
} }
free(_c); // allocator_free(tmp_al, _c);
return SUCCESS(UniInt64(li)); return SUCCESS(UniInt64(li));
} }
// wrong type // wrong type
@ -249,7 +253,7 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
case '{': case '{':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value)); if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
++text; // skips '{' ++text; // skips '{'
try(__deserialize(&text,true), val,Unitype_destruct(&value)) try(__deserialize(&text,true,tmp_al), val, Unitype_destruct(&value))
value=val.value; value=val.value;
break; break;
case '[': case '[':
@ -282,12 +286,13 @@ 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_create();
@ -300,7 +305,8 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
char* nameCPtr=maybeName.value.VoidPtr; char* nameCPtr=maybeName.value.VoidPtr;
try(ReadValue(NULL), val, { try(ReadValue(NULL), val, {
Hashtable_destruct(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;
@ -310,7 +316,8 @@ 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=Autoarr_create(Unitype,ARR_BC,ARR_BL);
@ -328,5 +335,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

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

@ -38,7 +38,7 @@ Maybe dir_create(const char* path){
{ {
char err[512]; char err[512];
sprintf_s(err, sizeof(err), "can't create dicectory <%s>", path); sprintf_s(err, sizeof(err), "can't create dicectory <%s>", path);
safethrow(err,;); safethrow(err, LinearAllocator_destruct(&_al));
} }
LinearAllocator_destruct(&_al); LinearAllocator_destruct(&_al);
return MaybeNull; return MaybeNull;

View File

@ -53,7 +53,7 @@ Maybe file_open(const char* path, FileOpenMode mode){
LinearAllocator _al; LinearAllocator_construct(&_al, 128); LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base; allocator_ptr al=&_al.base;
if(!file) if(!file)
safethrow(cptr_concat(al, "can't open file ", (char*)path),;); safethrow(cptr_concat(al, "can't open file ", (char*)path), LinearAllocator_destruct(&_al));
LinearAllocator_destruct(&_al); LinearAllocator_destruct(&_al);
return SUCCESS(UniHeapPtr(FileHandle,file)); return SUCCESS(UniHeapPtr(FileHandle,file));
} }
@ -115,7 +115,9 @@ 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);

View File

@ -52,7 +52,8 @@ Maybe path_throwIfEscapes(const char* path){
LinearAllocator _al; LinearAllocator_construct(&_al, 128); LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base; allocator_ptr al=&_al.base;
if(cptr_contains(path,"..")) if(cptr_contains(path,".."))
safethrow(cptr_concat(al, "path <",path,"> uses <..>, that's not allowed"),); safethrow(cptr_concat(al, "path <",path,"> uses <..>, that's not allowed"),
LinearAllocator_destruct(&_al));
LinearAllocator_destruct(&_al); LinearAllocator_destruct(&_al);
return MaybeNull; return MaybeNull;
} }
@ -83,5 +84,5 @@ char* path_basename(allocator_ptr al, 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

@ -27,7 +27,7 @@ STRUCT(LinkedList(TYPE), \
) \ ) \
\ \
typedef struct LinkedList_##TYPE##_functions_t { \ typedef struct LinkedList_##TYPE##_functions_t { \
freeMembers_t freeMembers; \ destruct_t freeMembers; \
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

@ -1,6 +1,6 @@
#include "StringBuilder.h" #include "StringBuilder.h"
kt_define(StringBuilder, __StringBuilder_destruct, 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
@ -10,7 +10,8 @@ void complete_buf(StringBuilder* b){
if(!b->compl_bufs) if(!b->compl_bufs)
b->compl_bufs=Autoarr_create(string,BL_C,BL_L); b->compl_bufs=Autoarr_create(string,BL_C,BL_L);
u32 len=Autoarr_length(b->curr_buf); u32 len=Autoarr_length(b->curr_buf);
if(!len) return; if(len==0)
return;
string str={.length=len, .ptr=malloc(len)}; string str={.length=len, .ptr=malloc(len)};
u32 i=0; u32 i=0;
Autoarr_foreach(b->curr_buf, c, Autoarr_foreach(b->curr_buf, c,
@ -21,27 +22,19 @@ void complete_buf(StringBuilder* b){
b->curr_buf=Autoarr_create(i8,BL_C,BL_L); b->curr_buf=Autoarr_create(i8,BL_C,BL_L);
} }
void try_complete_buf(StringBuilder* b){
if(b->curr_buf->chunks_count==BL_C)
complete_buf(b);
}
void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al){
StringBuilder* StringBuilder_create(){ InternalAllocator_setExternalOrConstruct(b, external_al, LinearAllocator, 1024);
StringBuilder* b=malloc(sizeof(StringBuilder));
b->compl_bufs=NULL; b->compl_bufs=NULL;
b->curr_buf=Autoarr_create(i8,BL_C,BL_L); b->curr_buf=Autoarr_create(i8,BL_C,BL_L);
return b;
} }
void __StringBuilder_destruct(void* _b){
StringBuilder* b=_b;
if(b->compl_bufs) Autoarr_destruct(b->compl_bufs, true);
Autoarr_destruct(b->curr_buf, true);
}
void StringBuilder_destruct(StringBuilder* b){ void StringBuilder_destruct(StringBuilder* b){
__StringBuilder_destruct(b); if(b->compl_bufs)
free(b); Autoarr_destruct(b->compl_bufs, true);
Autoarr_destruct(b->curr_buf, true);
if(InternalAllocator_isInternal(b))
LinearAllocator_destruct((LinearAllocator*)InternalAllocator_getPtr(b));
} }
string StringBuilder_build(StringBuilder* b){ string StringBuilder_build(StringBuilder* b){
@ -52,11 +45,10 @@ string StringBuilder_build(StringBuilder* b){
); );
string str= { .length=len, .ptr=malloc(len+1) }; string str= { .length=len, .ptr=malloc(len+1) };
str.ptr[len]='\0'; str.ptr[len]='\0';
u32 i=0; u32 l=0;
Autoarr_foreach(b->compl_bufs, cs, Autoarr_foreach(b->compl_bufs, cs,
for(u32 n=0;n<cs.length;n++) memcpy(str.ptr+l, cs.ptr, cs.length);
str.ptr[i++]=cs.ptr[n]; l+=cs.length;
free(cs.ptr);
); );
StringBuilder_destruct(b); StringBuilder_destruct(b);
return str; return str;
@ -75,14 +67,15 @@ void StringBuilder_rmchar(StringBuilder* b){
void StringBuilder_append_char(StringBuilder* b, char c){ void StringBuilder_append_char(StringBuilder* b, char c){
try_complete_buf(b); if(b->curr_buf->chunks_count==BL_C)
complete_buf(b);
Autoarr_add(b->curr_buf,c); Autoarr_add(b->curr_buf,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)); // TODO remove copying
Autoarr_add(b->compl_bufs, string_copy(InternalAllocator_getPtr(b), s));
} }
void StringBuilder_append_cptr(StringBuilder* b, char* s){ void StringBuilder_append_cptr(StringBuilder* b, char* s){
@ -93,13 +86,7 @@ void StringBuilder_append_cptr(StringBuilder* b, char* s){
StringBuilder_append_string(b, str); 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);
u8 i=0; u8 i=0;
if(a==0){ if(a==0){
Autoarr_add(b->curr_buf,'0'); Autoarr_add(b->curr_buf,'0');
@ -114,13 +101,11 @@ void StringBuilder_append_i64(StringBuilder* b, i64 a){
buf[i++]='0'+a%10; buf[i++]='0'+a%10;
a/=10; a/=10;
} }
string rev=string_reverse((string){buf,i}); string rev=string_reverse(InternalAllocator_getPtr(b), (string){buf,i});
curr_buf_add_string(b,rev); StringBuilder_append_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);
u8 i=0; u8 i=0;
if(a==0){ if(a==0){
Autoarr_add(b->curr_buf,'0'); Autoarr_add(b->curr_buf,'0');
@ -131,14 +116,12 @@ void StringBuilder_append_u64(StringBuilder* b, u64 a){
buf[i++]='0'+a%10; buf[i++]='0'+a%10;
a/=10; a/=10;
} }
string rev=string_reverse((string){buf,i}); string rev=string_reverse(InternalAllocator_getPtr(b), (string){buf,i});
curr_buf_add_string(b,rev); StringBuilder_append_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);
char buf[32]; char buf[32];
sprintf_s(buf, sizeof(buf), "%lf", a); sprintf_s(buf, sizeof(buf), "%lf", a);
curr_buf_add_string(b, (string){.ptr=buf, .length=cptr_length(buf)}); StringBuilder_append_string(b, (string){.ptr=buf, .length=cptr_length(buf)});
} }

View File

@ -8,17 +8,19 @@ extern "C" {
#include "string.h" #include "string.h"
STRUCT(StringBuilder, STRUCT(StringBuilder,
InternalAllocator_decl(LinearAllocator);
Autoarr(string)* compl_bufs; Autoarr(string)* compl_bufs;
Autoarr(i8)* curr_buf; Autoarr(i8)* curr_buf;
) )
StringBuilder* StringBuilder_create(void); ///@param external_al if null, creates internal allocator
void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al);
void StringBuilder_destruct(StringBuilder* b); void StringBuilder_destruct(StringBuilder* b);
void __StringBuilder_destruct(void* 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 // removes last char
void StringBuilder_rmchar(StringBuilder* b); void StringBuilder_rmchar(StringBuilder* b);

View File

@ -4,32 +4,32 @@ kt_define(string, NULL, NULL);
Autoarr_define(string, false); 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++)
@ -38,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

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

@ -191,7 +191,9 @@ char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_n
} }
char* cptr_replaceIn(allocator_ptr al, 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

@ -81,4 +81,4 @@ void LinearAllocator_construct(LinearAllocator* self, size_t starting_size){
self->chunks[0]=chunk_alloc(starting_size, 0); self->chunks[0]=chunk_alloc(starting_size, 0);
} }
kt_define(LinearAllocator, (freeMembers_t)LinearAllocator_destruct, NULL) kt_define(LinearAllocator, (destruct_t)LinearAllocator_destruct, NULL)

View File

@ -55,4 +55,4 @@ void StackingAllocator_construct(StackingAllocator* self, size_t starting_size){
self->allocations_count=0; self->allocations_count=0;
} }
kt_define(StackingAllocator, (freeMembers_t)StackingAllocator_destruct, NULL) kt_define(StackingAllocator, (destruct_t)StackingAllocator_destruct, NULL)

View File

@ -4,3 +4,36 @@
#define memory_align sizeof(void*) #define memory_align sizeof(void*)
// adds padding if memory_align if N isn't a multiple of memory_aligh // 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)) #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_decl(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)

View File

@ -31,14 +31,14 @@ extern "C" {
.toString=TOSTRING_F \ .toString=TOSTRING_F \
}; };
typedef void (*freeMembers_t)(void*); typedef void (*destruct_t)(void*);
typedef char* (*toString_t)(allocator_ptr al, 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 freeMembers; // 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

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

@ -6,7 +6,7 @@ char *__Unitype_toString(allocator_ptr al, void *_u, u32 fmt)
return Unitype_toString(al, *(Unitype *)_u, fmt); return Unitype_toString(al, *(Unitype *)_u, fmt);
} }
kt_define(Unitype, (freeMembers_t)Unitype_destruct, __Unitype_toString); kt_define(Unitype, (destruct_t)Unitype_destruct, __Unitype_toString);
void Unitype_destruct(Unitype* u) void Unitype_destruct(Unitype* u)
{ {

View File

@ -47,13 +47,15 @@ Maybe check_argsN(u8 n){
Maybe __ksprint(allocator_ptr al, 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(al, 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);
allocator_free(al, mStr.value.VoidPtr); 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));
} }
@ -173,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]={

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

View File

@ -4,11 +4,14 @@
void test_string(){ void test_string(){
optime(__func__,1, optime(__func__,1,
kprintf("\e[96m-------------[test_string]------------\n"); kprintf("\e[96m-------------[test_string]------------\n");
LinearAllocator _al;
LinearAllocator_construct(&_al, 64);
allocator_ptr al=(allocator_ptr)&_al;
char c[]="0123456789abcdef"; char c[]="0123456789abcdef";
string s={.ptr=c, .length=cptr_length(c)}; string s={.ptr=c, .length=cptr_length(c)};
if(s.length!=sizeof(c)-1) throw("string created with incorrect length"); if(s.length!=sizeof(c)-1) throw("string created with incorrect length");
char* p=string_extract(s); char* p=string_extract(al, s);
kprintf("\e[94mstring_extract() -> \e[92m\"%s\"\n",p); kprintf("\e[94mstring_extract -> \e[92m\"%s\"\n",p);
free(p); LinearAllocator_destruct(&_al);
); );
} }