core: Add pointer box / RAII impl

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-05-23 06:03:23 -04:00
parent 32635789dc
commit f99c1d678f
4 changed files with 212 additions and 0 deletions
+132
View File
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause
*/
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "cescal/ptrbox.h"
/*
* Allocate a pointer box entry to be used
*/
static struct ptrbox_entry *
ptrbox_alloc_entry(void)
{
struct ptrbox_entry *entry;
if ((entry = malloc(sizeof(*entry))) == NULL) {
return NULL;
}
entry->data = NULL;
entry->next = NULL;
return entry;
}
static int
ptrbox_push_entry(struct ptrbox *ptrbox, struct ptrbox_entry *entry)
{
if (ptrbox == NULL || entry == NULL) {
errno = EINVAL;
return -1;
}
if (ptrbox->head == NULL || ptrbox->tail == NULL) {
ptrbox->head = entry;
ptrbox->tail = entry;
} else {
ptrbox->head->next = entry;
ptrbox->head = entry;
}
return 0;
}
int
ptrbox_init(struct ptrbox *ptrbox)
{
if (ptrbox == NULL) {
errno = EINVAL;
return -1;
}
ptrbox->head = NULL;
ptrbox->tail = NULL;
return 0;
}
void *
ptrbox_alloc(struct ptrbox *ptrbox, size_t len)
{
struct ptrbox_entry *entry;
void *p;
if (ptrbox == NULL || len == 0) {
errno = EINVAL;
return NULL;
}
if ((p = malloc(len)) == NULL) {
return NULL;
}
if ((entry = ptrbox_alloc_entry()) == NULL) {
free(p);
return NULL;
}
entry->data = p;
if (ptrbox_push_entry(ptrbox, entry) < 0) {
free(p);
free(entry);
return NULL;
}
return 0;
}
char *
ptrbox_strdup(struct ptrbox *ptrbox, const char *s)
{
char *sdup;
size_t slen;
if (ptrbox == NULL || s == NULL) {
errno = EINVAL;
return NULL;
}
slen = strlen(s) + 1;
if ((sdup = ptrbox_alloc(ptrbox, slen)) == NULL) {
return NULL;
}
memcpy(sdup, s, slen);
return sdup;
}
void
ptrbox_destroy(struct ptrbox *ptrbox)
{
struct ptrbox_entry *entry, *tmp;
if (ptrbox == NULL) {
return;
}
if ((entry = ptrbox->tail) == NULL) {
return;
}
while (entry != NULL) {
tmp = entry;
entry = entry->next;
free(tmp->data);
free(tmp);
}
}
+6
View File
@@ -33,6 +33,11 @@ state_init(struct cescal_state *state, const char *pathname)
return -1;
}
if (ptrbox_init(&state->ptrbox) < 0) {
close(state->in_fd);
return -1;
}
return 0;
}
@@ -41,4 +46,5 @@ state_close(struct cescal_state *state)
{
close(state->in_fd);
state->in_fd = -1;
ptrbox_destroy(&state->ptrbox);
}
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause
*/
#ifndef CESCAL_PTRBOX_H
#define CESCAL_PTRBOX_H 1
/*
* Represents a pointer box entry in which allocated data can
* be stored within
*
* @data: Allocated data backed by entry
* @next: Next pointer box entry
*/
struct ptrbox_entry {
void *data;
struct ptrbox_entry *next;
};
/*
* Represents a pointer box that enables RAII like behavior
*
* @head: Pointer box head
* @tail: Pointer box tail
*/
struct ptrbox {
struct ptrbox_entry *head;
struct ptrbox_entry *tail;
};
/*
* Initialize a pointer box
*
* @ptrbox: Pointer box to initialize
*
* Returns zero on success
*/
int ptrbox_init(struct ptrbox *ptrbox);
/*
* Allocate memory and save the reference within a pointer box
*
* @ptrbox: Pointer box to save reference within
* @len: Length of memory to allocate
*
* Returns the base of the allocated memory on success, otherwise
* NULL.
*/
void *ptrbox_alloc(struct ptrbox *ptrbox, size_t len);
/*
* Duplicate a string and store the reference within a
* pointer box
*
* @ptrbox: Pointer box to store reference within
* @s: String to duplicate
*
* Returns the duplicated string on success, otherwise NULL.
*/
char *ptrbox_strdup(struct ptrbox *ptrbox, const char *s);
/*
* Destroy a pointer box along with all references stored
* within
*
* @ptrbox: Pointer box to destroy
*/
void ptrbox_destroy(struct ptrbox *ptrbox);
#endif /* !CESCAL_PTRBOX_H */
+3
View File
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "cescal/readbuf.h"
#include "cescal/tokbuf.h"
#include "cescal/ptrbox.h"
/*
* Compiler state machine
@@ -16,11 +17,13 @@
* @in_fd: Input file descriptor
* @rb: Read buffer
* @tokbuf: Token buffer
* @ptrbox: Global pointer box
*/
struct cescal_state {
int in_fd;
struct readbuf rb;
struct tokbuf tokbuf;
struct ptrbox ptrbox;
};
/*