==> src/strbuf.c <==1/* @ajax/mesh-strbuf: growable buffers and formatted strings. */
2#include "mesh/strbuf.h"
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8static void oom(void) {
9 fputs("mesh-strbuf: out of memory\n", stderr);
10 abort();
11}
12
13void *mxalloc(size_t n) {
14 void *p = calloc(1, n ? n : 1);
15 if (!p) oom();
16 return p;
17}
18
19void *mxrealloc(void *p, size_t n) {
20 p = realloc(p, n ? n : 1);
21 if (!p) oom();
22 return p;
23}
24
25void msb_reserve(msb *b, size_t extra) {
26 if (b->n + extra + 1 <= b->cap) return;
27 size_t cap = b->cap ? b->cap : 64;
28 while (cap < b->n + extra + 1) cap *= 2;
29 b->p = mxrealloc(b->p, cap);
30 b->cap = cap;
31 b->p[b->n] = 0;
32}
33
34void msb_put(msb *b, const void *data, size_t n) {
35 msb_reserve(b, n);
36 if (n) memcpy(b->p + b->n, data, n);
37 b->n += n;
38 b->p[b->n] = 0;
39}
40
41void msb_puts(msb *b, const char *s) { msb_put(b, s, strlen(s)); }
42void msb_putc(msb *b, char c) { msb_put(b, &c, 1); }
43
44void msb_vprintf(msb *b, const char *fmt, va_list ap) {
45 va_list cp;
46 va_copy(cp, ap);
47 int n = vsnprintf(NULL, 0, fmt, cp);
48 va_end(cp);
49 if (n < 0) return;
50 msb_reserve(b, (size_t)n);
51 vsnprintf(b->p + b->n, (size_t)n + 1, fmt, ap);
52 b->n += (size_t)n;
53}
54
55void msb_printf(msb *b, const char *fmt, ...) {
56 va_list ap;
57 va_start(ap, fmt);
58 msb_vprintf(b, fmt, ap);
59 va_end(ap);
60}
61
62const char *msb_str(msb *b) { return b->p ? b->p : ""; }
63
64char *msb_take(msb *b) {
65 msb_reserve(b, 0);
66 char *s = b->p;
67 *b = (msb){0};
68 return s;
69}
70
71void msb_clear(msb *b) {
72 b->n = 0;
73 if (b->p) b->p[0] = 0;
74}
75
76void msb_free(msb *b) {
77 free(b->p);
78 *b = (msb){0};
79}
80
81char *mvfmt(const char *fmt, va_list ap) {
82 msb b = {0};
83 msb_vprintf(&b, fmt, ap);
84 return msb_take(&b);
85}
86
87char *mfmt(const char *fmt, ...) {
88 va_list ap;
89 va_start(ap, fmt);
90 char *s = mvfmt(fmt, ap);
91 va_end(ap);
92 return s;
93}
94
95char *mstrndup(const char *s, size_t n) {
96 char *d = mxalloc(n + 1);
97 memcpy(d, s, n);
98 return d;
99}
100
101char *mstrdup(const char *s) { return mstrndup(s, strlen(s)); }