skip to content
==> include/mesh/buf.h <==
1/* @ajax/mesh-buf: a growable byte buffer for building strings and messages.
2 *
3 * What Rust's String and Vec<u8> do for meshd's host code: append bytes, text
4 * and printf output, keep a NUL after the last byte (so data is always a C
5 * string when it holds text), hand the bytes over. Allocation failure aborts:
6 * meshd never continues with half a message. */
7#ifndef MESH_BUF_H
8#define MESH_BUF_H
9
10#include <stdarg.h>
11#include <stddef.h>
12#include <stdint.h>
13
14typedef struct {
15    char *data; /* NULL until something is added; data[len] == 0 after any append */
16    size_t len;
17    size_t cap;
18} mesh_buf;
19
20#define MESH_BUF_INIT {NULL, 0, 0}
21
22void mesh_buf_reserve(mesh_buf *b, size_t extra);
23void mesh_buf_put(mesh_buf *b, const void *p, size_t n);
24void mesh_buf_puts(mesh_buf *b, const char *s);
25void mesh_buf_putc(mesh_buf *b, char c);
26void mesh_buf_printf(mesh_buf *b, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
27void mesh_buf_vprintf(mesh_buf *b, const char *fmt, va_list ap);
28/* Little-endian integers (wire formats). */
29void mesh_buf_u32le(mesh_buf *b, uint32_t v);
30void mesh_buf_u64le(mesh_buf *b, uint64_t v);
31/* n zero bytes. */
32void mesh_buf_zeros(mesh_buf *b, size_t n);
33/* The text so far ("" when empty): never NULL. */
34const char *mesh_buf_str(const mesh_buf *b);
35/* Takes the bytes (NUL-terminated; free() them); the buffer is empty again. */
36char *mesh_buf_take(mesh_buf *b);
37void mesh_buf_truncate(mesh_buf *b, size_t len);
38void mesh_buf_clear(mesh_buf *b);
39void mesh_buf_free(mesh_buf *b);
40
41/* Allocation helpers that abort on failure. */
42void *mesh_xmalloc(size_t n);
43void *mesh_xcalloc(size_t n, size_t size);
44void *mesh_xrealloc(void *p, size_t n);
45char *mesh_xstrdup(const char *s);
46char *mesh_xstrndup(const char *s, size_t n);
47/* A new string from printf. */
48char *mesh_buf_fmt(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
49
50#endif