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;
bool sh_partOfDollarList;
bool sh_calledRecursively;
allocator_ptr sh_tmp_al;
} DeserializeSharedData;
#define text shared->sh_text
#define partOfDollarList shared->sh_partOfDollarList
#define calledRecursively shared->sh_calledRecursively
#define tmp_al shared->sh_tmp_al
// special func for throwing error messages about wrong characters in deserializing text
@ -94,7 +96,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
safethrow_wrongchar(c,;);
return SUCCESS(UniHeapPtr(char,NULL));
case ':':
return SUCCESS(UniHeapPtr(char,string_extract(nameStr)));
return SUCCESS(UniHeapPtr(char,string_extract(tmp_al, nameStr)));
case '$':
if(nameStr.length!=0)
safethrow_wrongchar(c,;);
@ -111,7 +113,7 @@ Maybe __ReadName(DeserializeSharedData* 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);
#define ReadValue(rL) __ReadValue(shared, rL)
@ -119,7 +121,9 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
Maybe __ReadString(DeserializeSharedData* shared){
char c;
bool prevIsBackslash=false;
StringBuilder* b=StringBuilder_create();
StringBuilder _sb;
StringBuilder* b=&_sb;
StringBuilder_construct(b, tmp_al);
while ((c=*++text)){
if(c=='"') {
@ -175,34 +179,34 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){
else safethrow_wrongchar(*str.ptr,;);
// Float64
case 'f': {
char* _c=string_extract(str);
char* _c=string_extract(tmp_al, str);
Unitype rez=UniFloat64(strtod(_c,NULL));
free(_c);
// allocator_free(tmp_al,_c);
return SUCCESS(rez);
}
// UInt64
case 'u': {
u64 lu=0;
char* _c=string_extract(str);
char* _c=string_extract(tmp_al, str);
if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){
char err[64];
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));
}
// Int64
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
i64 li=0;
char* _c=string_extract(str);
char* _c=string_extract(tmp_al, str);
if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){
char err[64];
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));
}
// wrong type
@ -249,7 +253,7 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
case '{':
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
++text; // skips '{'
try(__deserialize(&text,true), val,Unitype_destruct(&value))
try(__deserialize(&text,true,tmp_al), val, Unitype_destruct(&value))
value=val.value;
break;
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={
.sh_text_first=*_text,
.sh_text=*_text,
.sh_partOfDollarList=false,
.sh_calledRecursively=_calledRecursively
.sh_calledRecursively=_calledRecursively,
.sh_tmp_al=_tmp_al
};
DeserializeSharedData* shared=&_shared;
Hashtable* dict=Hashtable_create();
@ -300,7 +305,8 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
char* nameCPtr=maybeName.value.VoidPtr;
try(ReadValue(NULL), val, {
Hashtable_destruct(dict);
free(nameCPtr);
// do not use, free call order is incorrect
// allocator_free(tmp_al, nameCPtr);
}) {
if(partOfDollarList){
partOfDollarList=false;
@ -310,7 +316,8 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
list=(Autoarr(Unitype)*)lu.VoidPtr;
// Key is not used in that case, because it is already added
// 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{
list=Autoarr_create(Unitype,ARR_BC,ARR_BL);
@ -328,5 +335,9 @@ Maybe __deserialize(char** _text, bool _calledRecursively) {
}
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){
StringBuilder* sb=StringBuilder_create();
try(__serialize(sb,0,dtsod),__, StringBuilder_destruct(sb));
LinearAllocator _al; allocator_ptr al=(allocator_ptr)&_al;
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;
LinearAllocator_destruct(&_al);
return SUCCESS(UniHeapPtr(char, str));
}

View File

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

View File

@ -53,7 +53,7 @@ Maybe file_open(const char* path, FileOpenMode mode){
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
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);
return SUCCESS(UniHeapPtr(FileHandle,file));
}
@ -115,7 +115,9 @@ Maybe file_readAll(FileHandle file, char** allBytes){
i32 rezult=0;
char buffer[256];
string bufStr={.ptr=buffer, .length=sizeof(buffer)};
StringBuilder* sb=StringBuilder_create();
StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, NULL);
u64 i=0;
while(true){
rezult=fgetc(file);

View File

@ -52,7 +52,8 @@ Maybe path_throwIfEscapes(const char* path){
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
allocator_ptr al=&_al.base;
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);
return MaybeNull;
}
@ -83,5 +84,5 @@ char* path_basename(allocator_ptr al, char* path, bool with_extension){
if(extIndex!=0 && extIndex!=-1)
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 { \
freeMembers_t freeMembers; \
destruct_t freeMembers; \
void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \
void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \
} LinkedList_##TYPE##_functions_t; \

View File

@ -1,6 +1,6 @@
#include "StringBuilder.h"
kt_define(StringBuilder, __StringBuilder_destruct, NULL);
kt_define(StringBuilder, (destruct_t)StringBuilder_destruct, NULL);
#define BL_C 32
#define BL_L 1024
@ -10,7 +10,8 @@ void complete_buf(StringBuilder* b){
if(!b->compl_bufs)
b->compl_bufs=Autoarr_create(string,BL_C,BL_L);
u32 len=Autoarr_length(b->curr_buf);
if(!len) return;
if(len==0)
return;
string str={.length=len, .ptr=malloc(len)};
u32 i=0;
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);
}
void try_complete_buf(StringBuilder* b){
if(b->curr_buf->chunks_count==BL_C)
complete_buf(b);
}
StringBuilder* StringBuilder_create(){
StringBuilder* b=malloc(sizeof(StringBuilder));
void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al){
InternalAllocator_setExternalOrConstruct(b, external_al, LinearAllocator, 1024);
b->compl_bufs=NULL;
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){
__StringBuilder_destruct(b);
free(b);
if(b->compl_bufs)
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){
@ -52,11 +45,10 @@ string StringBuilder_build(StringBuilder* b){
);
string str= { .length=len, .ptr=malloc(len+1) };
str.ptr[len]='\0';
u32 i=0;
u32 l=0;
Autoarr_foreach(b->compl_bufs, cs,
for(u32 n=0;n<cs.length;n++)
str.ptr[i++]=cs.ptr[n];
free(cs.ptr);
memcpy(str.ptr+l, cs.ptr, cs.length);
l+=cs.length;
);
StringBuilder_destruct(b);
return str;
@ -75,14 +67,15 @@ void StringBuilder_rmchar(StringBuilder* b){
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);
}
void StringBuilder_append_string(StringBuilder* b, string s){
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){
@ -93,13 +86,7 @@ void StringBuilder_append_cptr(StringBuilder* b, char* 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){
try_complete_buf(b);
u8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
@ -114,13 +101,11 @@ void StringBuilder_append_i64(StringBuilder* b, i64 a){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
string rev=string_reverse(InternalAllocator_getPtr(b), (string){buf,i});
StringBuilder_append_string(b, rev);
}
void StringBuilder_append_u64(StringBuilder* b, u64 a){
try_complete_buf(b);
u8 i=0;
if(a==0){
Autoarr_add(b->curr_buf,'0');
@ -131,14 +116,12 @@ void StringBuilder_append_u64(StringBuilder* b, u64 a){
buf[i++]='0'+a%10;
a/=10;
}
string rev=string_reverse((string){buf,i});
curr_buf_add_string(b,rev);
free(rev.ptr);
string rev=string_reverse(InternalAllocator_getPtr(b), (string){buf,i});
StringBuilder_append_string(b, rev);
}
void StringBuilder_append_f64(StringBuilder* b, f64 a){
try_complete_buf(b);
char buf[32];
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"
STRUCT(StringBuilder,
InternalAllocator_decl(LinearAllocator);
Autoarr(string)* compl_bufs;
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(void* b);
// Joins all strings from compl_bufs.
// Returns zero-terminated string.
// No need to call string_extract()!
// Frees StringBuilder.
// No need to call string_extract!
// Destructs StringBuilder.
string StringBuilder_build(StringBuilder* b);
// removes last char
void StringBuilder_rmchar(StringBuilder* b);

View File

@ -4,32 +4,32 @@ kt_define(string, NULL, NULL);
Autoarr_define(string, false);
// 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;
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;
while(str.length-->0)
cptr[str.length]=str.ptr[str.length];
return cptr;
}
// 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)
return src;
throw(ERR_NULLPTR);
string nstr;
nstr.length=src.length;
nstr.ptr=malloc(nstr.length+1);
for(u32 i=0;i<nstr.length;i++)
nstr.ptr[i]=src.ptr[i];
nstr.ptr=allocator_alloc(al, nstr.length+1);
memcpy(nstr.ptr, src.ptr, nstr.length);
nstr.ptr[nstr.length]='\0';
return nstr;
}
// compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1){
if(str0.length!=str1.length) return false;
if(!str0.ptr) return str1.ptr ? false : true;
if(str0.length!=str1.length)
return false;
if(!str0.ptr)
return str1.ptr ? false : true;
else if(!str1.ptr) return false;
while(str0.length-->0)
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>
string string_reverse(string s){
if(s.length==0) return s;
string r={malloc(s.length), s.length};
string string_reverse(allocator_ptr al, string s){
if(s.length==0)
return s;
string r;
r.ptr=allocator_alloc(al, s.length);
r.length=s.length;
for(u32 i=0; i<s.length; i++)
r.ptr[i]=s.ptr[s.length-i-1];
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) }
// 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
string string_copy(string src);
string string_copy(allocator_ptr al, string src);
// compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1);
// creates new string which is reversed variant of <s>
string string_reverse(string s);
string string_reverse(allocator_ptr al, string s);
#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){
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_new_len=cptr_length(str_new);
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);
}
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;
}
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*)
// 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_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 \
};
typedef void (*freeMembers_t)(void*);
typedef void (*destruct_t)(void*);
typedef char* (*toString_t)(allocator_ptr al, void* obj, u32 fmt);
STRUCT(ktDescriptor,
char* name;
ktid id;
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
)

View File

@ -8,6 +8,10 @@
ENUM_MEMBERS \
} __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; \
typedef struct STRUCT_NAME { \
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);
}
kt_define(Unitype, (freeMembers_t)Unitype_destruct, __Unitype_toString);
kt_define(Unitype, (destruct_t)Unitype_destruct, __Unitype_toString);
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){
try(check_argsN(n), _,;);
n/=2;
StringBuilder* strb=StringBuilder_create();
StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
for(u8 i=0; i<n; i++){
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);
}
char* rezult=StringBuilder_build(strb).ptr;
char* rezult=StringBuilder_build(sb).ptr;
return SUCCESS(UniHeapPtr(char, rezult));
}
@ -173,17 +175,19 @@ void kprint_setColor(kp_fmt f){
ktDescriptor* type=ktDescriptor_get(format.typeId);
if(!type->toString)
safethrow("type descriptor doesnt have toString() func",;);
StringBuilder* strb=StringBuilder_create();
StringBuilder_append_char(strb, '[');
StringBuilder _sb;
StringBuilder* sb=&_sb;
StringBuilder_construct(sb, al);
StringBuilder_append_char(sb, '[');
for (u16 e=1; e<count; e++){
StringBuilder_append_char(strb, ' ');
StringBuilder_append_char(sb, ' ');
char* elStr=type->toString(array+type->size*e, &format);
StringBuilder_append_cptr(strb, elStr);
StringBuilder_append_char(strb, ',');
StringBuilder_append_cptr(sb, elStr);
StringBuilder_append_char(sb, ',');
}
StringBuilder_rmchar(strb);
StringBuilder_append_char(strb, ' ');
StringBuilder_append_char(strb, ']');
StringBuilder_rmchar(sb);
StringBuilder_append_char(sb, ' ');
StringBuilder_append_char(sb, ']');
} */
static const char* _kp_colorNames[16]={

View File

@ -5,8 +5,7 @@ Maybe dont_throw(){
}
Maybe throw_error(){
char* k=malloc(64);
safethrow("test exception",free(k));
safethrow("test exception", kprintf("\e[94on_safethrow_free called\n"));
}
Maybe throw_errcode(){

View File

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