==> src/buf.c <==1/* A growable byte buffer; allocation failure aborts. */
2#include "mesh/buf.h"
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8static _Noreturn void oom(void) {
9 fputs("out of memory\n", stderr);
10 abort();
11}
12
13void *mesh_xmalloc(size_t n) {
14 void *p = malloc(n ? n : 1);
15 if (!p) oom();
16 return p;
17}
18
19void *mesh_xcalloc(size_t n, size_t size) {
20 void *p = calloc(n ? n : 1, size ? size : 1);
21 if (!p) oom();
22 return p;
23}
24
25void *mesh_xrealloc(void *p, size_t n) {
26 p = realloc(p, n ? n : 1);
27 if (!p) oom();
28 return p;
29}
30
31char *mesh_xstrndup(const char *s, size_t n) {
32 char *d = mesh_xmalloc(n + 1);
33 memcpy(d, s, n);
34 d[n] = 0;
35 return d;
36}
37
38char *mesh_xstrdup(const char *s) { return mesh_xstrndup(s, strlen(s)); }
39
40void mesh_buf_reserve(mesh_buf *b, size_t extra) {
41 if (b->len + extra + 1 <= b->cap) return;
42 size_t cap = b->cap ? b->cap : 64;
43 while (cap < b->len + extra + 1) cap *= 2;
44 b->data = mesh_xrealloc(b->data, cap);
45 b->cap = cap;
46 b->data[b->len] = 0;
47}
48
49void mesh_buf_put(mesh_buf *b, const void *p, size_t n) {
50 mesh_buf_reserve(b, n);
51 if (n) memcpy(b->data + b->len, p, n);
52 b->len += n;
53 b->data[b->len] = 0;
54}
55
56void mesh_buf_puts(mesh_buf *b, const char *s) { mesh_buf_put(b, s, strlen(s)); }
57
58void mesh_buf_putc(mesh_buf *b, char c) { mesh_buf_put(b, &c, 1); }
59
60void mesh_buf_vprintf(mesh_buf *b, const char *fmt, va_list ap) {
61 va_list copy;
62 va_copy(copy, ap);
63 int n = vsnprintf(NULL, 0, fmt, copy);
64 va_end(copy);
65 if (n < 0) return;
66 mesh_buf_reserve(b, (size_t)n);
67 vsnprintf(b->data + b->len, (size_t)n + 1, fmt, ap);
68 b->len += (size_t)n;
69}
70
71void mesh_buf_printf(mesh_buf *b, const char *fmt, ...) {
72 va_list ap;
73 va_start(ap, fmt);
74 mesh_buf_vprintf(b, fmt, ap);
75 va_end(ap);
76}
77
78void mesh_buf_u32le(mesh_buf *b, uint32_t v) {
79 uint8_t x[4] = {(uint8_t)v, (uint8_t)(v >> 8), (uint8_t)(v >> 16), (uint8_t)(v >> 24)};
80 mesh_buf_put(b, x, 4);
81}
82
83void mesh_buf_u64le(mesh_buf *b, uint64_t v) {
84 mesh_buf_u32le(b, (uint32_t)v);
85 mesh_buf_u32le(b, (uint32_t)(v >> 32));
86}
87
88void mesh_buf_zeros(mesh_buf *b, size_t n) {
89 mesh_buf_reserve(b, n);
90 memset(b->data + b->len, 0, n);
91 b->len += n;
92 b->data[b->len] = 0;
93}
94
95const char *mesh_buf_str(const mesh_buf *b) { return b->data ? b->data : ""; }
96
97char *mesh_buf_take(mesh_buf *b) {
98 mesh_buf_reserve(b, 0);
99 char *s = b->data;
100 b->data = NULL;
101 b->len = b->cap = 0;
102 return s;
103}
104
105void mesh_buf_truncate(mesh_buf *b, size_t len) {
106 if (len >= b->len) return;
107 b->len = len;
108 b->data[len] = 0;
109}
110
111void mesh_buf_clear(mesh_buf *b) {
112 b->len = 0;
113 if (b->data) b->data[0] = 0;
114}
115
116void mesh_buf_free(mesh_buf *b) {
117 free(b->data);
118 b->data = NULL;
119 b->len = b->cap = 0;
120}
121
122char *mesh_buf_fmt(const char *fmt, ...) {
123 mesh_buf b = MESH_BUF_INIT;
124 va_list ap;
125 va_start(ap, fmt);
126 mesh_buf_vprintf(&b, fmt, ap);
127 va_end(ap);
128 return mesh_buf_take(&b);
129}