#ifndef CGC_H_ #define CGC_H_ #include #define GC_DEFAULT_CAP 16 typedef struct { void * ptr; size_t id; } GCItem; typedef struct { GCItem * items; size_t size; size_t capacity; } GC; typedef size_t GCIndex; GC gcInit(void); void gcDeinit(GC gc); void gcGrowBuffer(GC * gc); GCIndex gcAddItem(GC * gc, void * ptr); void * gcAlloc(GC * gc, size_t n); void gcUpdateItem(GC * gc, GCIndex id, void * ptr); void * gcGetPtrAt(GC gc, GCIndex id); #ifdef CGC_IMPLEMENTATION GC gcInit() { void * items = calloc(GC_DEFAULT_CAP, sizeof(GCItem)); if (items == NULL) { fprintf(stderr, "ERROR: Failed to allocate GC!\n"); exit(1); } return (GC) { .items = items, .size = 0, .capacity = GC_DEFAULT_CAP, }; } void gcDeinit(GC gc) { for (size_t i = 0; i < gc.size; ++i) free(gc.items[i].ptr); free(gc.items); } void gcGrowBuffer(GC * gc) { if (gc->items == NULL) { fprintf(stderr, "ERROR: GC is not initialized!\n"); exit(1); } size_t newCap = (size_t) (gc->capacity * 1.5); void * items = calloc(newCap, sizeof(GCItem)); if (items == NULL) { fprintf(stderr, "ERROR: Failed to allocate GC!\n"); exit(1); } memcpy(items, gc->items, gc->capacity * sizeof(GCItem)); free(gc->items); gc->items = items; gc->capacity = newCap; } GCIndex gcAddItem(GC * gc, void * ptr) { if (gc->size >= gc->capacity) gcGrowBuffer(gc); gc->size += 1; gc->items[gc->size - 1] = (GCItem) { .id = gc->size - 1, .ptr = ptr, }; return gc->size - 1; } void * gcAlloc(GC * gc, size_t n) { void * ptr = calloc(1, n); if (ptr == NULL) return NULL; gcAddItem(gc, ptr); return ptr; } void gcUpdateItem(GC * gc, GCIndex id, void * ptr) { free(gc->items[id].ptr); gc->items[id].ptr = ptr; } void * gcGetPtrAt(GC gc, GCIndex id) { return gc.items[id].ptr; } #endif // CGC_IMPLEMENTATION #endif // CGC_H_