diff --git a/core/ptrbox.c b/core/ptrbox.c new file mode 100644 index 0000000..b6af1ee --- /dev/null +++ b/core/ptrbox.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include "rifle/ptrbox.h" + +int +ptrbox_init(struct ptrbox *res) +{ + if (res == NULL) { + errno = -EINVAL; + return -1; + } + + TAILQ_INIT(&res->entries); + res->entry_count = 0; + return 0; +} + +void * +ptrbox_alloc(struct ptrbox *ptrbox, size_t sz) +{ + struct ptrbox_entry *entry; + + if (ptrbox == NULL || sz == 0) { + return NULL; + } + + if ((entry = malloc(sizeof(*entry))) == NULL) { + return NULL; + } + + if ((entry->data = malloc(sz)) == NULL) { + free(entry); + return NULL; + } + + TAILQ_INSERT_TAIL(&ptrbox->entries, entry, link); + ++ptrbox->entry_count; + return entry->data; +} + +void * +ptrbox_strdup(struct ptrbox *ptrbox, const char *s) +{ + struct ptrbox_entry *entry; + + if (ptrbox == NULL || s == 0) { + return NULL; + } + + if ((entry = malloc(sizeof(*entry))) == NULL) { + return NULL; + } + + if ((entry->data = strdup(s)) == NULL) { + free(entry); + return NULL; + } + + TAILQ_INSERT_TAIL(&ptrbox->entries, entry, link); + ++ptrbox->entry_count; + return entry->data; +} + +void +ptrbox_destroy(struct ptrbox *ptrbox) +{ + struct ptrbox_entry *entry; + + if (ptrbox == NULL) { + return; + } + + if ((entry = TAILQ_FIRST(&ptrbox->entries)) == NULL) { + return; + } + + do { + TAILQ_REMOVE(&ptrbox->entries, entry, link); + free(entry->data); + free(entry); + entry = TAILQ_FIRST(&ptrbox->entries); + } while (entry != NULL); +} diff --git a/inc/rifle/ptrbox.h b/inc/rifle/ptrbox.h new file mode 100644 index 0000000..97ef3bf --- /dev/null +++ b/inc/rifle/ptrbox.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2026, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef RIFLE_PTRBOX_H +#define RIFLE_PTRBOX_H + +#include +#include +#include + +/* + * Represents a pointer box entry which stores a reference + * to allocated memory + * + * @data: Allocated memory + * @link: Queue link + */ +struct ptrbox_entry { + void *data; + TAILQ_ENTRY(ptrbox_entry) link; +}; + +/* + * A pointer box stores one or more references to allocated memory + * so that it can be cleaned up in one sweep when usage is complete. + * + * @entries: Pointer box entries + * @entry_count: Number of entries in pointer box + */ +struct ptrbox { + TAILQ_HEAD(, ptrbox_entry) entries; + size_t entry_count; +}; + +/* + * Allocate memory and save it in a pointer box + * + * @ptrbox: Pointer box to save reference in + * @sz: Allocation size + * + * Returns the base of the allocated memory on success + */ +void *ptrbox_alloc(struct ptrbox *ptrbox, size_t sz); + +/* + * Perform a strdup() operation and save the reference in + * a pointer box + * + * @ptrbox: Ptrbox to save reference within + * @s: String to dup + * + * Returns dupped string on success + */ +void *ptrbox_strdup(struct ptrbox *ptrbox, const char *s); + +/* + * Destroy a pointer box + * + * @ptrbox: Pointer box to destory + */ +void ptrbox_destroy(struct ptrbox *ptrbox); + +/* + * Initialize a pointer box + * + * @res: Pointer box to initialize + * + * Returns zero on success + */ +int ptrbox_init(struct ptrbox *res); + +#endif /* !RIFLE_PTRBOX_H */