diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-10-03 00:36:26 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-10-03 00:36:26 +0200 |
commit | d874d01e8e9a30f0073a6e559cbae07244dec7bf (patch) | |
tree | dbde18d7ada337b74fe6cfb8ccc35b52008e6aa0 /include | |
parent | 1e721a413f1d4fc7f7f4e1e691a0a37168f3b302 (diff) |
Huge library overhaul
Diffstat (limited to 'include')
-rw-r--r-- | include/_alloc_fn.h | 7 | ||||
-rw-r--r-- | include/_allocator.h | 22 | ||||
-rw-r--r-- | include/alloc.h | 125 | ||||
-rw-r--r-- | include/array.h | 63 | ||||
-rw-r--r-- | include/dynarr.h | 81 | ||||
-rw-r--r-- | include/unicode/string.h | 51 |
6 files changed, 186 insertions, 163 deletions
diff --git a/include/_alloc_fn.h b/include/_alloc_fn.h deleted file mode 100644 index aae4bd0..0000000 --- a/include/_alloc_fn.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MLIB__ALLOC_FN_H -#define MLIB__ALLOC_FN_H - -typedef void *(*alloc_fn)(void *ctx, void *ptr, size_t old, size_t new, - size_t elemsz, size_t align); - -#endif /* !MLIB__ALLOC_FN_H */ diff --git a/include/_allocator.h b/include/_allocator.h new file mode 100644 index 0000000..3bd78b2 --- /dev/null +++ b/include/_allocator.h @@ -0,0 +1,22 @@ +#ifndef MLIB__ALLOCATOR_H +#define MLIB__ALLOCATOR_H + +#include <setjmp.h> +#include <stddef.h> + +typedef enum { + ALLOC_NEW, + ALLOC_RESIZE, + ALLOC_FREE, + ALLOC_FREEALL, +} alloc_mode_t; + +typedef struct allocator { + void *(*alloc)(struct allocator mem, alloc_mode_t mode, void *ptr, + ptrdiff_t oldnmemb, ptrdiff_t newnmemb, ptrdiff_t elemsz, + ptrdiff_t align); + jmp_buf *err; + void *ctx; +} allocator_t; + +#endif /* !MLIB__ALLOCATOR_H */ diff --git a/include/alloc.h b/include/alloc.h index 8004cd0..2786757 100644 --- a/include/alloc.h +++ b/include/alloc.h @@ -1,60 +1,95 @@ #ifndef MLIB_ALLOC_H #define MLIB_ALLOC_H -#include <setjmp.h> -#include <stddef.h> - +#include "_allocator.h" #include "_attrs.h" -#ifndef MLIB_ARENA_BLKSIZE -# define MLIB_ARENA_BLKSIZE (8 * 1024) -#endif +typedef enum { + ALLOC_OOM, +} alloc_err_t; + +typedef struct arena_blk arena_blk_t; -struct _region { - size_t len, cap; - void *data, *last; - struct _region *next; -}; +typedef struct { + ptrdiff_t blksz; + struct arena_blk *_head; +} arena_ctx_t; typedef struct { - struct _region *_head; - size_t _init; -} arena; + void *buf; + ptrdiff_t len; +} st_buf_t; -/* Heap allocation functions */ -[[nodiscard, gnu::returns_nonnull]] void *bufalloc(void *, size_t, size_t); -[[nodiscard]] void *bufalloc_noterm(void *, size_t, size_t); +#define new(mem, T, n) \ + ((typeof(T) *)((mem).alloc((mem), \ + ALLOC_NEW, \ + nullptr, \ + 0, \ + (n), \ + sizeof(T), \ + alignof(T)))) +#define resz(mem, p, o, n) \ + ((typeof(p))((mem).alloc((mem), \ + ALLOC_RESIZE, \ + (p), \ + (o), \ + (n), \ + sizeof(*(p)), \ + alignof(typeof(*(p)))))) +#define delete(mem, p, sz) \ + (mem).alloc((mem), \ + ALLOC_FREE, \ + (p), \ + (sz), \ + 0, \ + sizeof(*(p)), \ + alignof(typeof(*p))) +#define deleteall(mem) \ + ((mem).alloc((mem), \ + ALLOC_FREEALL, \ + nullptr, \ + 0, \ + 0, \ + 0, \ + 0)) -[[_mlib_pure, _mlib_inline]] -static inline arena -mkarena(size_t n) +void *arena_alloc(allocator_t mem, alloc_mode_t mode, void *ptr, + ptrdiff_t oldnmemb, ptrdiff_t newnmemb, ptrdiff_t elemsz, + ptrdiff_t align); +void *heap_alloc(allocator_t mem, alloc_mode_t mode, void *ptr, + ptrdiff_t oldnmemb, ptrdiff_t newnmemb, ptrdiff_t elemsz, + ptrdiff_t align); +void *static_scratch_alloc(allocator_t mem, alloc_mode_t mode, void *ptr, + ptrdiff_t oldnmemb, ptrdiff_t newnmemb, ptrdiff_t elemsz, + ptrdiff_t align); + +[[_mlib_inline]] static inline allocator_t +init_arena_allocator(arena_ctx_t *ctx, jmp_buf *jmp) { - return (arena){._init = n ? n : MLIB_ARENA_BLKSIZE}; + return (allocator_t){ + .alloc = arena_alloc, + .err = jmp, + .ctx = ctx, + }; } -/* Arena allocation functions */ -[[nodiscard, gnu::malloc, gnu::alloc_size(2, 3), gnu::alloc_align(4)]] -void *arena_alloc(arena *, size_t, size_t, size_t); -[[nodiscard]] -void *arena_realloc(arena *, void *, size_t, size_t, size_t, size_t); -void arena_zero(arena *); -void arena_free(arena *); - -/* Arena allocation macro wrappers */ -#define arena_new(a, T, n) ((T *)arena_alloc((a), (n), sizeof(T), alignof(T))) -#define arena_resz(a, T, p, n) \ - ((T *)arena_realloc((a), (p), (n), sizeof(T), alignof(T))) - -/* Memory allocator callbacks for memory-allocating functions */ -struct arena_ctx { - arena *a; - jmp_buf *jmp; -}; -struct heap_ctx { - jmp_buf *jmp; -}; - -[[nodiscard]] void *alloc_arena(void *, void *, size_t, size_t, size_t, size_t); -[[nodiscard]] void *alloc_heap(void *, void *, size_t, size_t, size_t, size_t); +[[_mlib_inline]] static inline allocator_t +init_heap_allocator(jmp_buf *jmp) +{ + return (allocator_t){ + .alloc = heap_alloc, + .err = jmp, + }; +} + +[[_mlib_inline]] static inline allocator_t +init_static_scratch_allocator(st_buf_t *ctx, jmp_buf *jmp) +{ + return (allocator_t){ + .alloc = static_scratch_alloc, + .err = jmp, + .ctx = ctx, + }; +} #endif /* !MLIB_ALLOC_H */ diff --git a/include/array.h b/include/array.h new file mode 100644 index 0000000..de45a65 --- /dev/null +++ b/include/array.h @@ -0,0 +1,63 @@ +#ifndef MLIB_ARRAY_H +#define MLIB_ARRAY_H + +#include <stddef.h> +#include <string.h> + +#include "_allocator.h" +#include "_attrs.h" + +typedef struct { + ptrdiff_t len, cap; + allocator_t mem; +} _mlib_arr_hdr_t; + +[[_mlib_inline]] +static inline _mlib_arr_hdr_t * +_mlib_array_hdr(void *p, ptrdiff_t align) +{ + ptrdiff_t pad = -sizeof(_mlib_arr_hdr_t) & (align - 1); + return (_mlib_arr_hdr_t *)((char *)p - pad - sizeof(_mlib_arr_hdr_t)); +} + +#define array_hdr(p) (_mlib_array_hdr(p, alignof(typeof(*(p))))) +#define array_len(p) (_mlib_array_hdr(p, alignof(typeof(*(p))))->len) +#define array_cap(p) (_mlib_array_hdr(p, alignof(typeof(*(p))))->cap) + +#define array_new(mem, T, n) \ + ((T *)array_new((mem), (n), sizeof(T), alignof(T))) +#define array_resz(p, cap) \ + ((typeof(p))array_resz((p), (cap), sizeof(*(p)), alignof(typeof(*(p))))) +#define array_free(p) \ + array_free((p), sizeof(*(p)), alignof(typeof(*(p)))) + +#define array_push(p, x) \ + do { \ + _mlib_arr_hdr_t *hdr = _mlib_array_hdr(*(p), alignof(typeof(**(p)))); \ + if (hdr->len == hdr->cap) { \ + *(p) = array_resz(*(p), hdr->len * 2); \ + hdr = _mlib_array_hdr(*(p), alignof(typeof(**(p)))); \ + } \ + (*(p))[hdr->len++] = (x); \ + } while (false) + +/* TODO: Make the resizing not bad */ +#define array_extend(p, xs, n) \ + do { \ + _mlib_arr_hdr_t *hdr = _mlib_array_hdr((p), alignof(typeof(*(p)))); \ + if (hdr->len + (n) <= hdr->cap) { \ + (p) = array_resz((p), hdr->len * 2 + (n)); \ + hdr = _mlib_array_hdr((p), alignof(typeof(*(p)))); \ + } \ + memcpy(&(p)[hdr->len], (xs), (n) * sizeof(*xs)); \ + hdr->len += (n); \ + } while (false) + +#define array_foreach(p, i) for (typeof(p) i = (p); i < (p) + array_len(p); i++) + +void *(array_new)(allocator_t mem, ptrdiff_t nmemb, ptrdiff_t elemsz, + ptrdiff_t align); +void *(array_resz)(void *ptr, ptrdiff_t ncap, ptrdiff_t elemsz, ptrdiff_t align); +void (array_free)(void *ptr, ptrdiff_t elemsz, ptrdiff_t align); + +#endif /* !MLIB_ARRAY_H */ diff --git a/include/dynarr.h b/include/dynarr.h deleted file mode 100644 index 75bdcc8..0000000 --- a/include/dynarr.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MLIB_DYNARR_H -#define MLIB_DYNARR_H - -#include <stdbit.h> -#include <string.h> - -#include "_alloc_fn.h" -#include "alloc.h" - -/* This is required because alignof() only portably works with types and not - expressions… */ -/* clang-format off */ -#ifdef __GNUC__ -# define _mlib_da_alignof(expr) __extension__ alignof(expr) -#else -# include <stddef.h> -# define _mlib_da_alignof(expr) \ - ((size_t) &((struct {char x; typeof(expr) y;} *)0)->y) -#endif -/* clang-format on */ - -#define dafields(T) \ - T *buf; \ - size_t len, cap; \ - alloc_fn alloc; \ - void *ctx - -#define dynarr(T) \ - struct { \ - dafields(T); \ - } - -#define DAPUSH(da, x) \ - do { \ - if (++(da)->len > (da)->cap) { \ - size_t ncap = stdc_bit_ceil((da)->len); \ - (da)->buf = (da)->alloc((da)->ctx, (da)->buf, (da)->cap, ncap, \ - sizeof(*(da)->buf), \ - _mlib_da_alignof(*(da)->buf)); \ - (da)->cap = ncap; \ - } \ - (da)->buf[(da)->len - 1] = (x); \ - } while (false) - -#define DAEXTEND(da, xs, n) \ - do { \ - if (((da)->len += (n)) > (da)->cap) { \ - size_t ncap = stdc_bit_ceil((da)->len); \ - (da)->buf = (da)->alloc((da)->ctx, (da)->buf, (da)->cap, ncap, \ - sizeof(*(da)->buf), \ - _mlib_da_alignof(*(da)->buf)); \ - (da)->cap = ncap; \ - } \ - memcpy((da)->buf + (da)->len - (n), (xs), (n) * sizeof(*(da)->buf)); \ - } while (false) - -#define DAGROW(da, n) \ - do { \ - if ((n) > (da)->cap) { \ - (da)->buf = (da)->alloc((da)->ctx, (da)->buf, (da)->cap, (n), \ - sizeof(*(da)->buf), \ - _mlib_da_alignof(*(da)->buf)); \ - (da)->cap = (n); \ - } \ - } while (false) - -#define DAPOP(da) ((da)->buf[--(da)->len]) - -#define DAREMOVE(da, i) DA_REMOVE_RANGE((da), (i), (i) + 1) - -#define DA_REMOVE_RANGE(da, i, j) \ - do { \ - memmove((da)->buf + (i), (da)->buf + (j), \ - ((da)->len - (j)) * sizeof(*(da)->buf)); \ - (da)->len -= j - i; \ - } while (false) - -#define da_foreach(da, p) \ - for (auto p = (da).buf; (size_t)(p - (da).buf) < (da).len; p++) - -#endif /* !MLIB_DYNARR_H */ diff --git a/include/unicode/string.h b/include/unicode/string.h index 7d62171..077a45a 100644 --- a/include/unicode/string.h +++ b/include/unicode/string.h @@ -3,22 +3,22 @@ #include <stddef.h> -#include "_alloc_fn.h" +#include "_allocator.h" #include "_charN_t.h" #include "_uNview.h" /* clang-format off */ -enum [[clang::flag_enum]] caseflags { +typedef enum [[clang::flag_enum]] { CF_LANG_AZ = 1 << 0, /* Azeri; alias for CF_LANG_TR */ CF_LANG_TR = 1 << 0, /* Turkish; alias for CF_LANG_AZ */ CF_LANG_LT = 1 << 1, /* Lithuanian */ CF_LANG_NL = 1 << 2, /* Dutch */ CF_SS = 1 << 3, /* Use ‘ẞ’ as the uppercase of ‘ß’; alias for CF_ẞ */ CF_ẞ = 1 << 3, /* Use ‘ẞ’ as the uppercase of ‘ß’; alias for CF_SS */ -}; +} caseflags_t; -enum normform { +typedef enum { /* If bit 0 is set, then composition is performed after decomposition. If bit-1 is set then compatibility (de)composition is used as opposed to canonical (de)composition. */ @@ -26,7 +26,7 @@ enum normform { NF_NFC = 0b01, NF_NFKD = 0b10, NF_NFKC = 0b11, -}; +} normform_t; /* clang-format on */ @@ -37,16 +37,11 @@ enum normform { size_t u8gnext(u8view_t *, u8view_t *); size_t u8wnext(u8view_t *, u8view_t *); size_t u8wnext_human(u8view_t *, u8view_t *); -[[nodiscard]] char8_t *u8casefold(size_t *, u8view_t, enum caseflags, - alloc_fn, void *); -[[nodiscard]] char8_t *u8lower(size_t *, u8view_t, enum caseflags, - alloc_fn, void *); -[[nodiscard]] char8_t *u8title(size_t *, u8view_t, enum caseflags, - alloc_fn, void *); -[[nodiscard]] char8_t *u8upper(size_t *, u8view_t, enum caseflags, - alloc_fn, void *); -[[nodiscard]] char8_t *u8norm(size_t *, u8view_t, alloc_fn, void *, - enum normform); +[[nodiscard]] char8_t *u8casefold(size_t *, u8view_t, caseflags_t, allocator_t); +[[nodiscard]] char8_t *u8lower(size_t *, u8view_t, caseflags_t, allocator_t); +[[nodiscard]] char8_t *u8title(size_t *, u8view_t, caseflags_t, allocator_t); +[[nodiscard]] char8_t *u8upper(size_t *, u8view_t, caseflags_t, allocator_t); +[[nodiscard]] char8_t *u8norm(size_t *, u8view_t, allocator_t, normform_t); /* Encoding-generic macros */ #define ucswdth(sv, ts) _Generic((sv), u8view_t: u8wdth)((sv), (ts)) @@ -55,22 +50,18 @@ size_t u8wnext_human(u8view_t *, u8view_t *); #define ucswcnt_human(sv) _Generic((sv), u8view_t: u8wcnt_human)((sv)) #define ucsgnext(g, sv) _Generic((sv), u8view_t *: u8gnext)((g), (sv)) #define ucswnext(g, sv) _Generic((sv), u8view_t *: u8wnext)((g), (sv)) -#define ucswnext_human(g, sv) \ +#define ucswnext_human(g, sv) \ _Generic((sv), u8view_t *: u8wnext_human)((g), (sv)) -#define ucscasefold(dstn, sv, flags, alloc, ctx) \ - _Generic((sv), u8view_t: u8casefold)((dstn), (sv), (flags), (alloc), \ - (ctx)) -#define ucslower(dstn, sv, flags, alloc, ctx) \ - _Generic((sv), u8view_t: u8lower)((dstn), (sv), (flags), (alloc), \ - (ctx)) -#define ucstitle(dstn, sv, flags, alloc, ctx) \ - _Generic((sv), u8view_t: u8title)((dstn), (sv), (flags), (alloc), \ - (ctx)) -#define ucsupper(dstn, sv, flags, alloc, ctx) \ - _Generic((sv), u8view_t: u8upper)((dstn), (sv), (flags), (alloc), \ - (ctx)) -#define ucsnorm(dstn, sv, alloc, ctx, nf) \ - _Generic((sv), u8view_t: u8norm)((dstn), (sv), (alloc), (ctx), (nf)) +#define ucscasefold(dstn, sv, flags, mem) \ + _Generic((sv), u8view_t: u8casefold)((dstn), (sv), (flags), (mem)) +#define ucslower(dstn, sv, flags, mem) \ + _Generic((sv), u8view_t: u8lower)((dstn), (sv), (flags), (mem)) +#define ucstitle(dstn, sv, flags, mem) \ + _Generic((sv), u8view_t: u8title)((dstn), (sv), (flags), (mem)) +#define ucsupper(dstn, sv, flags, mem) \ + _Generic((sv), u8view_t: u8upper)((dstn), (sv), (flags), (mem)) +#define ucsnorm(dstn, sv, mem, nf) \ + _Generic((sv), u8view_t: u8norm)((dstn), (sv), (mem), (nf)) constexpr double U8CASEFOLD_SCALE = 3; constexpr double U8LOWER_SCALE = 1.5; |