Start writing new string-slicing module.

Start: string basic alloc.

Fortune for naka's current commit: Small blessing − 小吉
strings
Avril 3 years ago
parent aa94ab1622
commit 152e0aa8e7
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -130,6 +130,7 @@ _mixin void _drain_val(void* x, ...) { IGNORE(x); } // This compiles to no-op on
#define box(t) aligned_alloc(_Alignof(t), sizeof(t)) #define box(t) aligned_alloc(_Alignof(t), sizeof(t))
#define box_value(v) ({ let _box = box(var(v)); *_box = (v); _box; }) #define box_value(v) ({ let _box = box(var(v)); *_box = (v); _box; })
#define unbox_value(v) ({ let _v = (v); let _res = *_v; free(_v); _res; }
#define stackalloc(t) __builtin_alloca_with_align(sizeof(t), _Alignof(t)) #define stackalloc(t) __builtin_alloca_with_align(sizeof(t), _Alignof(t))
// Function macros // Function macros

@ -21,24 +21,10 @@ enum str_ownership {
STR_DERRIVED_STACK, STR_DERRIVED_STACK,
}; };
//TODO: Complete rework typedef struct string str_t;
typedef struct string {
usize len, cap; str_t* str_alloc(usize cap) _callconv(alloc);
struct str_meta { char* str_new(const char* pIN cstr) _callconv(alloc);
struct string* _shared derrived;
_Atomic usize refs;
void (*m_free)(void*);
enum str_ownership owned;
} meta;
union {
char* slice;
char str[];
};
} *str_t;
str_t* str_alloc(usize cap) _cconv(alloc);
char* str_new(const char* pIN cstr) _cconv(alloc);
void str_free(str_t* restrict str); void str_free(str_t* restrict str);

@ -5,62 +5,63 @@
#include <str.h> #include <str.h>
static str_t _str_alloc_new(usize reserve) struct string {
usize len, cap;
struct str_meta {
enum str_ownership owned;
union _str_meta_inner {
// `STRF_OWNED`
struct {
_Atomic usize refs; // Number of derrivations from this
void (*m_free)(void*); // How to free (when `_MALLOC`).
} owned;
// `STRF_DERRIVED`
struct {
// String this is derrived from, can be either owned or derrived.
struct string* _shared parent;
// `str`'s offset from `parent->str`.
usize offset;
} derrived;
} _inner;
} meta;
// The start of this string slice. Regardless of slicing
char* str;
};
//TODO: We can use offsetof() to reverse the result of `str_new()` from char* (str field) to str_t*.
inline static bool _str_meta_is_owned(enum str_ownership owned)
{ {
return aligned_alloc(_Alignof(struct string), sizeof(struct string) + reserve + 1); return AS(owned, u32) & AS(STRF_OWNED, u32);
} }
inline static str_t _str_unbox(str_t* restrict boxed) inline static bool _str_is_owned(const str_t*pIN str)
{ {
str_t unboxed = *boxed; return _str_meta_is_owned(str->meta.owned);
free(boxed);
return unboxed;
} }
_cconv(alloc) str_t* str_alloc(usize cap) static union _str_meta_inner _str_default_meta(enum str_ownership oship)
{ {
str_t unboxed = _str_alloc_new(cap); bool owned = _str_meta_is_owned(oship);
unboxed->cap = cap; switch(oship)
unboxed->len = 0; {
unboxed->meta = (struct str_meta){
.derrived = NULL, }
.refs = 0, TODO("default str metadata");
.m_free = &free,
.owned = STR_OWNED_MALLOC,
};
memset(unboxed->str, 0, cap+1);
return box_value(unboxed);
} }
void str_free(str_t* restrict str) static str_t _str_alloc_bare(usize cap, enum str_ownership owned)
{ {
str_t ub = _str_unbox(str); bool is_owned = _str_meta_is_owned(owned);
struct str_meta meta = {
void* to_free = (void*)ub; .owned = owned,
let _cont[] = { &&_done, &&_finish_free_derrived }; ._inner = _str_default_meta(owned),
usize cont = 0; };
switch(ub->meta.owned) { str_t str = {
case STR_DERRIVED_MALLOC: .len = 0,
ub->meta.derrived->meta.refs -=1; .cap = cap,
to_free = NULL; .meta = meta,
cont = 1; };
case STR_OWNED_MALLOC: str.str = is_owned ? calloc(cap+1, 1) : NULL;
//TODO: How to handle this refcounting? return str;
if(ub->meta.refs > 0) WARN("Freeing referenced string");
//if(ub->meta.refs == 0)
if(to_free)
(ub->meta.m_free ?: &free)(to_free);
/*else {
ub->meta.refs -=1;
break;
}*/
goto _cont[cont];
_finish_free_derrived:
free(ub);
default:
_done:
break;
}
} }

Loading…
Cancel
Save