summary refs log tree commit diff
diff options
context:
space:
mode:
authorWormHeamer2025-02-28 17:45:34 -0500
committerWormHeamer2025-02-28 17:45:34 -0500
commitc2995c57c4a8a97c7a456e63d9f847b2809a31aa (patch)
tree4909c1b15e6890cce0212436765af07a1e566313
parent7794a719c0114153ccbf009339e0f354eff8c1f5 (diff)
add zn_zf_alloc, zn_zf_realloc
-rw-r--r--zone.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/zone.h b/zone.h
index 4daa2fa..71ad926 100644
--- a/zone.h
+++ b/zone.h
@@ -20,6 +20,8 @@ void zn_free(Zone *z);
 void zn_clear(Zone *z);
 
 void *zn_alloc(Zone *z, size_t n);
+void *zn_zf_alloc(Zone *z, ZoneFrame **zf, size_t n);
+void *zn_zf_realloc(Zone *z, ZoneFrame **zf, void *ptr, size_t oldsz, size-t newsz);
 char *zn_strdup(Zone *z, const char *s);
 
 #ifdef ZONE_IMPL
@@ -43,6 +45,10 @@ static ZoneFrame *zn_new_frame(size_t capacity) {
 }
 
 void *zn_alloc(Zone *z, size_t n) {
+	return zn_zf_alloc(z, NULL, n);
+}
+
+void *zn_zf_alloc(Zone *z, ZoneFrame **zfo, 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) {
@@ -62,9 +68,25 @@ void *zn_alloc(Zone *z, size_t n) {
 	void *ptr = &zf->data[zf->length];
 	zf->length += wordsz;
 	z->here = zf;
+	if (zfo) *zfo = zf;
 	return ptr;
 }
 
+void *zn_zf_realloc(Zone *z, ZoneFrame **zfo, void *old, size_t oldsz, size_t newsz) {
+	ZoneFrame *zf = *zfo;
+	size_t old_wordsz = (oldsz + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+	size_t new_wordsz = (newsz + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+	if (&zf->data[zf->length - old_wordsz] == old && zf->length + new_wordsz - old_wordsz <= zf->capacity) {
+		zf->length = zf->length + new_wordsz - old_wordsz;
+		return old;
+	} else {
+		void *new = zn_zf_alloc(z, zfo, newsz);
+		zf->length -= old_wordsz;
+		memcpy(new, old, oldsz);
+		return new;
+	}
+}
+
 void zn_free(Zone *z) {
 	ZoneFrame *p, *t;
 	t = z->tail;