Scratch arena, in-place temporary gebs_fmt() macro
This commit is contained in:
190
gebs.h
190
gebs.h
@ -62,22 +62,48 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
void *(*malloc)(size_t size);
|
||||
void (*free)(void *memory);
|
||||
void *(*realloc)(void *memory, size_t prev_size, size_t new_size);
|
||||
void *(*malloc)(void *self, size_t size);
|
||||
void (*free)(void *self, void *memory);
|
||||
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||
} Gebs_Allocator;
|
||||
|
||||
// Wrapper macros
|
||||
#define gebs_malloc(alloc, size) ((alloc)->malloc((size)))
|
||||
#define gebs_free(alloc, memory) ((alloc)->free((memory)))
|
||||
#define gebs_malloc(alloc, size) ((alloc)->malloc((void *)(alloc), (size)))
|
||||
#define gebs_free(alloc, memory) ((alloc)->free((void *)(alloc), (memory)))
|
||||
#define gebs_realloc(alloc, memory, prev_size, new_size) \
|
||||
((alloc)->realloc((memory), (prev_size), (new_size)))
|
||||
((alloc)->realloc((void *)(alloc), (memory), (prev_size), (new_size)))
|
||||
|
||||
extern Gebs_Allocator gebs_default_allocator;
|
||||
|
||||
void *gebs_default_allocator_malloc(size_t size);
|
||||
void gebs_default_allocator_free(void *memory);
|
||||
void *gebs_default_allocator_realloc(void *memory, size_t prev_size, size_t new_size);
|
||||
void *gebs_default_allocator_malloc(void *self, size_t size);
|
||||
void gebs_default_allocator_free(void *self, void *memory);
|
||||
void *gebs_default_allocator_realloc(void *self, void *memory,
|
||||
size_t prev_size, size_t new_size);
|
||||
|
||||
typedef struct Gebs_Arena_Allocation {
|
||||
size_t index;
|
||||
size_t size;
|
||||
char *ptr;
|
||||
struct Gebs_Arena_Allocation *next;
|
||||
} Gebs_Arena_Allocation;
|
||||
|
||||
typedef struct {
|
||||
void *(*malloc)(void *self, size_t size);
|
||||
void (*free)(void *self, void *memory);
|
||||
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||
|
||||
char *region;
|
||||
size_t index;
|
||||
size_t size;
|
||||
} Gebs_Arena;
|
||||
|
||||
void gebs_arena_reset(Gebs_Arena *a);
|
||||
void gebs_arena_destroy(Gebs_Arena *a);
|
||||
Gebs_Arena *gebs_arena_make(size_t size);
|
||||
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size);
|
||||
void *gebs_arena_malloc(void *self, size_t size);
|
||||
void gebs_arena_free(void *self, void *memory);
|
||||
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Dynamic list
|
||||
@ -210,6 +236,24 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
|
||||
sizeof(__argv)/sizeof(__argv[0]), (char**)__argv, __FILE__); \
|
||||
} while(0)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scratch arena
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef GEBS_SCRATCH_ARENA_SIZE
|
||||
# define GEBS_SCRATCH_ARENA_SIZE 4096
|
||||
#endif
|
||||
|
||||
extern Gebs_Arena *gebs_scratch_arena;
|
||||
|
||||
#define gebs_fmt(fmt, ...) \
|
||||
({ \
|
||||
size_t __size = snprintf(NULL, 0, (fmt), ##__VA_ARGS__); \
|
||||
char *__buf = gebs_malloc(gebs_scratch_arena, __size+1); \
|
||||
sprintf(__buf, (fmt), ##__VA_ARGS__); \
|
||||
__buf; \
|
||||
})
|
||||
|
||||
#ifdef GEBS_IMPLEMENTATION
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -273,22 +317,144 @@ Gebs_Allocator gebs_default_allocator = {
|
||||
.realloc = &gebs_default_allocator_realloc,
|
||||
};
|
||||
|
||||
void *gebs_default_allocator_malloc(size_t size)
|
||||
void *gebs_default_allocator_malloc(void *self, size_t size)
|
||||
{
|
||||
(void)self;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void gebs_default_allocator_free(void *memory)
|
||||
void gebs_default_allocator_free(void *self, void *memory)
|
||||
{
|
||||
(void)self;
|
||||
free(memory);
|
||||
}
|
||||
|
||||
void *gebs_default_allocator_realloc(void *memory, size_t prev_size, size_t new_size)
|
||||
void *gebs_default_allocator_realloc(void *self, void *memory,
|
||||
size_t prev_size, size_t new_size)
|
||||
{
|
||||
(void)self;
|
||||
void *p = realloc(memory, new_size);
|
||||
return p;
|
||||
}
|
||||
|
||||
Gebs_Arena *gebs_arena_make(size_t size)
|
||||
{
|
||||
Gebs_Arena *a;
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = malloc(sizeof(*a));
|
||||
if (a == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->malloc = &gebs_arena_malloc;
|
||||
a->free = &gebs_arena_free;
|
||||
a->realloc = &gebs_arena_realloc;
|
||||
|
||||
a->region = malloc(size);
|
||||
if (a->region == NULL) {
|
||||
free(a);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->index = 0;
|
||||
a->size = size;
|
||||
return a;
|
||||
}
|
||||
|
||||
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size)
|
||||
{
|
||||
if (a == NULL || new_size <= a->size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->region = realloc(a->region, new_size);
|
||||
if (a->region == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->size = new_size;
|
||||
return a;
|
||||
}
|
||||
|
||||
void *gebs_arena_malloc(void *self, size_t size)
|
||||
{
|
||||
Gebs_Arena *a = (Gebs_Arena *)self;
|
||||
unsigned int offset;
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (a == NULL || a->region == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
if (a->size - (a->index + offset) < size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->index += size;
|
||||
return a->region + (a->index - size);
|
||||
}
|
||||
|
||||
void gebs_arena_free(void *self, void *memory)
|
||||
{
|
||||
(void)self;
|
||||
(void)memory;
|
||||
}
|
||||
|
||||
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size)
|
||||
{
|
||||
(void)prev_size;
|
||||
(void)memory;
|
||||
gebs_arena_expand((Gebs_Arena *)self, new_size);
|
||||
return memory;
|
||||
}
|
||||
|
||||
void gebs_arena_reset(Gebs_Arena *a)
|
||||
{
|
||||
if (a == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
a->index = 0;
|
||||
}
|
||||
|
||||
void gebs_arena_destroy(Gebs_Arena *a)
|
||||
{
|
||||
if (a == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (a->region != NULL) {
|
||||
free(a->region);
|
||||
}
|
||||
|
||||
free(a);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scratch arena
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Gebs_Arena *gebs_scratch_arena;
|
||||
|
||||
__attribute__((constructor))
|
||||
void gebs_scratch_areana_init(void)
|
||||
{
|
||||
gebs_scratch_arena = gebs_arena_make(GEBS_SCRATCH_ARENA_SIZE);
|
||||
}
|
||||
|
||||
__attribute__((destructor))
|
||||
void gebs_scratch_areana_free(void)
|
||||
{
|
||||
gebs_arena_destroy(gebs_scratch_arena);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Filesystem operations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user