Skip to content
Growable Memory Buffer for C99
C Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore
Makefile
README.md
UNLICENSE
buf.h
tests.c

README.md

Growable Memory Buffers for C99

This C99 header library provides a simple, portable interface to growable buffers of homogeneous values of any type, similar to a std::vector in C++. The user need not use any particular struct, and the buffer need only initialize to NULL.

Each "function" in the interface is actually a macro, and its usage is reflected by these hypothetical prototypes:

/* Returns the number of elements in the buffer (for push and pop).
*/
size_t buf_size(type *v);

/* Returns the total capacity of the buffer.
*/
size_t buf_capacity(type *v);

/* Destroy and free the buffer, effectively resetting it.
 * Potentially assigns a new V pointer.
*/
void buf_free(type *v);

/* Append an element E to the end of the buffer, growing if necessary.
 * Potentially increases the capacity and assigns a new V pointer.
*/
void buf_push(type *v, type e);

/* Remove an element E from the end of the buffer.
 * Neither the capacity nor the V pointer will change. Popping when the
 * size is zero has undefined results.
 */
type buf_pop(type *v);

/* Increase buffer capactity by N elements.
 * Potentially assigns a new V pointer while also returning it.
 */
type *buf_grow(type *v, ptrdiff_t n);

/* Set buffer capactity to exactly N elements.
 * Potentially assigns a new V pointer while also returning it. A
 * negative capacity has undefined results.
 */
type *buf_trunc(type *v, ptrdiff_t n);

/* Set buffer size to zero.
 * Only affects push and pop. The capacity and buffer contents are
 * unchanged.
 */
void buf_clear(type *v);

Note: buf_push(), buf_grow(), buf_trunc(), and buf_free() may change the buffer pointer, and any previously-taken pointers should be considered invalidated. This has important consequences that must be considered.

The BUF_INIT_CAPACITY determines the initial capacity for buffers receiving their first push.

The BUF_ABORT macro is evaluated when the system runs out of memory. It defaults to abort(), but you may override it to run your own abort code instead.

Example usage:

float *values = 0;

/* Append 25 values */
for (size_t i = 0; i < 25; i++)
    buf_push(values, rand() / (float)RAND_MAX);

/* Access 25 values using the normal [] operator */
for (size_t i = 0; i < buf_size(values); i++)
    printf("values[%zu] = %f\n", i, values[i]);

/* Destroy/reset the buffer */
buf_free(values);

Purpose

This library is inspired by stb stretchy_buffer.h. The difference is that it's written in C99 so that it doesn't need to rely on undefined behavior. This does so by using a flexible array member and the offsetof() macro. It also checks for integer overflows before allocating any memory, making it safer.

You can’t perform that action at this time.