ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

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;
}