1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#ifndef ZONE_H
#define ZONE_H
#include <stdint.h>
#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);
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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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) {
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) {
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;
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;
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
|