string and StringBuilder
This commit is contained in:
parent
32ce7d3a70
commit
8d36fd8042
25
TODO.md
Normal file
25
TODO.md
Normal 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`
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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; \
|
||||||
|
|||||||
@ -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){
|
||||||
@ -90,16 +83,10 @@ void StringBuilder_append_cptr(StringBuilder* b, char* s){
|
|||||||
.ptr=s,
|
.ptr=s,
|
||||||
.length=cptr_length(s)
|
.length=cptr_length(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)});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -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 \
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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]={
|
||||||
|
|||||||
@ -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(){
|
||||||
|
|||||||
@ -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);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user