Files
quip/core/ptrbox.c
2026-03-21 19:01:30 -04:00

137 lines
2.4 KiB
C

/*
* Copyright (c) 2026, Mirocom Laboratories
* Provided under the BSD-3 clause
*
* Abtract:
* This file implements pointer boxes used to provide RAII-like
* allocation behavior.
* Author:
* Ian M. Moffett <ian@mirocom.org>
*/
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include "common/ptrbox.h"
/*
* Allocate a new entry from a reference to some
* data.
*
* @data: Data reference to associate pointer box entry with
*/
static struct ptrbox_entry *
entry_from_data(void *data)
{
struct ptrbox_entry *entry;
if ((entry = malloc(sizeof(*entry))) == NULL) {
return NULL;
}
entry->data = data;
entry->next = NULL;
return entry;
}
/*
* Add an entry to a pointer box
*
* @ptrbox: Pointer box to add entry to
* @entry: Entry to add to pointer box
*/
static void
ptrbox_add_entry(struct ptrbox *ptrbox, struct ptrbox_entry *entry)
{
struct ptrbox_entry *ep;
if (ptrbox == NULL || entry == NULL) {
return;
}
if (ptrbox->head == NULL || ptrbox->tail == NULL) {
ptrbox->head = entry;
ptrbox->tail = entry;
} else {
ep = ptrbox->tail;
ep->next = entry;
ptrbox->tail = entry;
}
}
char *
ptrbox_strdup(struct ptrbox *ptrbox, const char *s)
{
struct ptrbox_entry *entry;
char *p;
if (ptrbox == NULL || s == NULL) {
return NULL;
}
if ((p = strdup(s)) == NULL) {
return NULL;
}
if ((entry = entry_from_data(p)) == NULL) {
return NULL;
}
ptrbox_add_entry(ptrbox, entry);
return p;
}
void *
ptrbox_malloc(struct ptrbox *ptrbox, size_t length)
{
struct ptrbox_entry *entry;
void *mem;
if (ptrbox == NULL) {
return NULL;
}
if ((mem = malloc(length)) == NULL) {
return NULL;
}
if ((entry = entry_from_data(mem)) == NULL) {
return NULL;
}
ptrbox_add_entry(ptrbox, entry);
return mem;
}
int
ptrbox_init(struct ptrbox *ptrbox)
{
if (ptrbox == NULL) {
errno = -EINVAL;
return -1;
}
ptrbox->entry_count = 0;
ptrbox->head = NULL;
ptrbox->tail = NULL;
return 0;
}
void
ptrbox_destroy(struct ptrbox *ptrbox)
{
struct ptrbox_entry *entry, *tmp;
entry = ptrbox->head;
while (entry != NULL) {
if (entry->data != NULL)
free(entry->data);
tmp = entry;
entry = entry->next;
free(tmp);
}
}