#ifndef ZONE_H #define ZONE_H #include #define ZONE_FRAME_CAPACITY_DEFAULT 1024 typedef struct ZoneFrame ZoneFrame; struct ZoneFrame { ZoneFrame *prev, *next; size_t length, capacity; uintptr_t data[]; }; typedef struct { ZoneFrame *tail, *here; } Zone; void zn_free(Zone *z); void zn_clear(Zone *z); void *zn_alloc(Zone *z, size_t n); char *zn_strdup(Zone *z, const char *s); #ifdef ZONE_IMPL #include #include #include #include "zone.h" static ZoneFrame *zn_new_frame(size_t capacity) { ZoneFrame *zf = malloc(sizeof *zf + capacity * sizeof(uintptr_t)); if (!zf) { fprintf(stderr, "failed to allocate memory zone frame\n"); abort(); } zf->prev = NULL; zf->next = NULL; zf->length = 0; zf->capacity = capacity; return zf; } void *zn_alloc(Zone *z, size_t n) { ZoneFrame *zf = NULL; size_t wordsz = (n + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); for (ZoneFrame *f = z->here; f; f = f->next) { if (f->capacity - f->length >= wordsz) { zf = f; break; } } if (!zf) { size_t cap = ZONE_FRAME_CAPACITY_DEFAULT; while (wordsz >= cap) cap <<= 1; zf = zn_new_frame(cap); zf->prev = z->tail; if (z->tail) z->tail->next = zf; z->tail = zf; } void *ptr = &zf->data[zf->length]; zf->length += wordsz; z->here = zf; return ptr; } void zn_free(Zone *z) { ZoneFrame *p, *t; t = z->tail; while (t) { p = t->prev; free(t); t = p; } } void zn_clear(Zone *z) { ZoneFrame *zf = z->here; if (!zf) return; for (;;) { zf->length = 0; if (zf->prev) zf = zf->prev; else break; } z->tail = zf; } char *zn_strdup(Zone *z, const char *s) { size_t n = strlen(s) + 1; char *d = zn_alloc(z, n); memcpy(d, s, n); return d; } #endif #endif