Created
November 24, 2025 11:02
-
-
Save hb3p8/ab58e3fd518ea8dc7d01f3fc692575e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Writen by ChatGPT, you may want to read it before use. | |
| // Example usage: | |
| // fmt_arena_reset(); // once per frame before any usage | |
| // Clay_BeginLayout(); | |
| // ... | |
| // CLAY_TEXT(Clay_WrapStr(fmt_fmt ("%s (%d cores)", gpuName, numCores)), textCfg); | |
| #ifndef FORMAT_ARENA_INIT_CAP | |
| #define FORMAT_ARENA_INIT_CAP 4096 | |
| #endif | |
| typedef struct { | |
| char *base; | |
| size_t cap; | |
| size_t off; | |
| } fmt_arena_t; | |
| static fmt_arena_t g_fmt_arena = { NULL, 0, 0 }; | |
| static void *fmt_arena_alloc(size_t n) { | |
| const size_t align = sizeof(void*); | |
| n = (n + (align - 1)) & ~(align - 1); // align | |
| if (!g_fmt_arena.base) { | |
| g_fmt_arena.cap = FORMAT_ARENA_INIT_CAP; | |
| g_fmt_arena.base = (char*)malloc(g_fmt_arena.cap); | |
| if (!g_fmt_arena.base) return NULL; | |
| g_fmt_arena.off = 0; | |
| } | |
| if (g_fmt_arena.off + n > g_fmt_arena.cap) { | |
| size_t newcap = g_fmt_arena.cap; | |
| while (g_fmt_arena.off + n > newcap) { | |
| if (newcap > SIZE_MAX / 2) { newcap = SIZE_MAX; break; } | |
| newcap *= 2; | |
| } | |
| char *p = (char*)realloc(g_fmt_arena.base, newcap); | |
| if (!p) return NULL; | |
| g_fmt_arena.base = p; | |
| g_fmt_arena.cap = newcap; | |
| } | |
| void *out = g_fmt_arena.base + g_fmt_arena.off; | |
| g_fmt_arena.off += n; | |
| return out; | |
| } | |
| void fmt_arena_reset(void) { g_fmt_arena.off = 0; } | |
| void fmt_arena_free(void) { free(g_fmt_arena.base); g_fmt_arena.base=NULL; g_fmt_arena.cap=g_fmt_arena.off=0; } | |
| const char* fmt_int (int n) | |
| { | |
| char tmp[32]; | |
| int len = snprintf(tmp, sizeof(tmp), "%d", n); | |
| if (len < 0) return NULL; | |
| char *s = (char*)fmt_arena_alloc((size_t)len + 1); | |
| if (!s) return NULL; | |
| memcpy(s, tmp, (size_t)len + 1); // includes NUL | |
| return s; | |
| } | |
| #if defined(__GNUC__) || defined(__clang__) | |
| __attribute__((format(printf,1,2))) | |
| #endif | |
| const char* fmt_fmt(const char* format, ...) | |
| { | |
| va_list ap; | |
| va_start(ap, format); | |
| // First pass: compute required length (excluding NUL) | |
| va_list ap2; | |
| va_copy(ap2, ap); | |
| #if defined(_MSC_VER) | |
| int len = _vscprintf(format, ap2); // MSVC: length only | |
| #else | |
| int len = vsnprintf(NULL, 0, format, ap2); | |
| #endif | |
| va_end(ap2); | |
| if (len < 0) { va_end(ap); return NULL; } | |
| char *s = (char*)fmt_arena_alloc((size_t)len + 1); | |
| if (!s) { va_end(ap); return NULL; } | |
| // Second pass: actually format | |
| vsnprintf(s, (size_t)len + 1, format, ap); | |
| va_end(ap); | |
| return s; // valid until your arena is reset/freed | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment