skip to content
==> 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)); }