aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/_alloc_fn.h7
-rw-r--r--include/_allocator.h22
-rw-r--r--include/alloc.h125
-rw-r--r--include/array.h63
-rw-r--r--include/dynarr.h81
-rw-r--r--include/unicode/string.h51
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;