#include "mem.h" #include #include #include #include #ifdef TOBI_SAN_BUILD const char *__asan_default_options(void) { return "detect_leaks=0:abort_on_error=1"; } #endif static void oom(void) { fputs("tobi: out of memory\n", stderr); abort(); } void *tobi_xmalloc(size_t n) { void *p = malloc(n == 0 ? 1 : n); if (!p) { oom(); } return p; } void *tobi_xcalloc(size_t count, size_t size) { if (size != 0 && count > SIZE_MAX / size) { oom(); } void *p = calloc(count == 0 ? 1 : count, size == 0 ? 1 : size); if (!p) { oom(); } return p; } void *tobi_xrealloc(void *ptr, size_t n) { void *p = realloc(ptr, n == 0 ? 1 : n); if (!p) { oom(); } return p; } size_t tobi_xadd_size(size_t a, size_t b) { if (a > SIZE_MAX - b) { oom(); } return a + b; } size_t tobi_xmul_size(size_t a, size_t b) { if (b != 0 && a > SIZE_MAX / b) { oom(); } return a * b; } size_t tobi_xgrow_cap(size_t current, size_t required, size_t initial) { size_t cap = current ? current : (initial ? initial : 1u); while (cap < required) { if (cap > SIZE_MAX / 2u) { cap = required; break; } cap *= 2u; } return cap; } char *tobi_xstrdup(const char *s) { size_t n = strlen(s); char *out = tobi_xmalloc(n + 1); memcpy(out, s, n + 1); return out; } char *tobi_xstrndup(const char *s, size_t n) { char *out = tobi_xmalloc(n + 1); memcpy(out, s, n); out[n] = '\0'; return out; }