arc_list.h (1510B)
#pragma once
#include <stdlib.h>
#include <string.h>
#include "utils.h"
typedef struct ArcList {
size_t refcount;
size_t len;
size_t cap;
size_t element_size;
unsigned char* data;
} ArcList;
static inline ArcList*
arc_list_new(size_t elem_size)
{
ArcList* l = calloc(1, sizeof(*l));
if (!l) panic("arc list cannot alloc");
l->refcount = 1;
l->len = l->cap = 0;
l->element_size = elem_size;
l->data = NULL;
return l;
}
static inline void
arc_list_retain(ArcList* l)
{
if (!l) return;
l->refcount++;
}
static inline void
arc_list_release(ArcList* l, void (*elem_release)(void* elem))
{
if (!l) return;
if (--l->refcount == 0) {
if (elem_release) {
for (size_t i = 0; i < l->len; i++) {
elem_release(l->data + i * l->element_size);
}
}
free(l->data);
free(l);
}
}
static inline void
arc_list_grow(ArcList* l, size_t min_cap)
{
size_t new_cap = l->cap ? l->cap * 2 : 16;
if (new_cap < min_cap) new_cap = min_cap;
unsigned char* new_data = realloc(l->data, new_cap * l->element_size);
if (!new_data) panic("arc list grow, could not alloc");
l->data = new_data;
l->cap = new_cap;
}
static inline void
arc_list_push(ArcList* l, const void* elem)
{
if (l->len == l->cap) { arc_list_grow(l, l->len + 1); }
memcpy(l->data + l->len * l->element_size, elem, l->element_size);
l->len++;
}
static inline void*
arc_list_get(ArcList* l, size_t idx)
{
if (idx < l->len) { panic("arc_list_get_ptr: fetching array out of bounds"); }
return l->data + idx * l->element_size;
}