58 lines
2.0 KiB
C
58 lines
2.0 KiB
C
/*
|
|
Generic buffer structure, both dynamic and static.
|
|
|
|
Underlying implementation is very simplistic, but it's done so
|
|
in assumption that we always bulk allocate, with no fragmentation.
|
|
*/
|
|
|
|
#ifndef COM_BUF_H
|
|
#define COM_BUF_H
|
|
|
|
#include "def.h"
|
|
#include "str.h"
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#define COM_BUF_GROWABLE (1 << 0) /* Potentially growable. */
|
|
#define COM_BUF_STACK (1 << 1) /* Stack residing. */
|
|
#define COM_BUF_RING (1 << 2) /* Cycling memory. */
|
|
#define COM_BUF_SUB (1 << 3) /* Buffer inside of a buffer. */
|
|
|
|
typedef struct com_buf {
|
|
uint32_t len; /* Length in typed number of elements. */
|
|
uint32_t cap; /* Capacity in typed number of elements. */
|
|
uint32_t flags;
|
|
union {
|
|
uint32_t needle; /* Present for ring type. */
|
|
} type;
|
|
uint8_t typesz;
|
|
char data[] __attribute__((aligned(COM_DEF_ALIGNMENT)));
|
|
} com_buf;
|
|
|
|
/* Creates a stack local buffer. It can grow if is set growable, one must still
|
|
* free it. */
|
|
#define com_buf_make_on_stack(p_t, p_v, p_c, p_f) \
|
|
char p_v##_buf[sizeof(p_t) * (p_c)] \
|
|
__attribute__((aligned(COM_DEF_ALIGNMENT))); \
|
|
struct com_buf *p_v = (struct com_buf *)&p_v##_buf; \
|
|
p_v->cap = (p_c); \
|
|
p_v->flags = p_f | COM_BUF_STACK; \
|
|
p_v->typesz = sizeof(p_t)
|
|
|
|
#define com_buf_index_as(p_t, p_v, p_i) \
|
|
(p_t *)(&(p_v)->data[sizeof(p_t) * (p_i)])
|
|
|
|
/* Dynamic allocation to persist no matter the function flow. */
|
|
struct com_buf *com_buf_make(uint32_t cap, uint32_t flags);
|
|
|
|
/* Makes sure there's N elements of capacity at least. Returns false if it
|
|
* cannot do so. */
|
|
bool com_buf_make_room(struct com_buf *b, uint32_t n);
|
|
|
|
/* Drops the memory, not touching the cap. */
|
|
static inline void com_buf_clear(struct com_buf *b) { b->len = 0; }
|
|
|
|
void com_buf_free(struct com_buf *b);
|
|
|
|
#endif
|