==> include/mesh/mt.h <==1/* @ajax/mesh-mt: growable strings and string lists, the containers the fleet's Rust used
2 * (`String`, `Vec<String>`) and its splitting (`split`, `split_whitespace`, `split_once`).
3 *
4 * Allocation failure aborts (the Rust aborts too): callers never check for NULL. */
5#ifndef MESH_MT_H
6#define MESH_MT_H
7
8#include <stdarg.h>
9#include <stdbool.h>
10#include <stddef.h>
11
12/* ---- strings */
13
14void *mt_alloc(size_t n); /* zeroed */
15void *mt_realloc(void *p, size_t n);
16char *mt_strdup(const char *s);
17char *mt_strndup(const char *s, size_t n);
18char *mt_fmt(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
19char *mt_vfmt(const char *fmt, va_list ap);
20bool mt_eq(const char *a, const char *b); /* both NULL, or equal */
21bool mt_starts(const char *s, const char *prefix);
22bool mt_ends(const char *s, const char *suffix);
23bool mt_contains(const char *s, const char *needle);
24/* Replaces *dst with src (a copy), freeing what was there. */
25void mt_set(char **dst, const char *src);
26
27/* ---- a growable string (always NUL-terminated once anything was added) */
28
29typedef struct {
30 char *s;
31 size_t len, cap;
32} mt_buf;
33
34void mt_putn(mt_buf *b, const char *s, size_t n);
35void mt_puts(mt_buf *b, const char *s);
36void mt_putc(mt_buf *b, char c);
37void mt_printf(mt_buf *b, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
38const char *mt_str(mt_buf *b); /* "" when empty */
39char *mt_take(mt_buf *b); /* the string (never NULL), b emptied */
40void mt_buf_free(mt_buf *b);
41
42/* ---- a list of strings */
43
44typedef struct {
45 char **v;
46 size_t n, cap;
47} mt_strs;
48
49void mt_push(mt_strs *l, const char *s); /* a copy */
50void mt_push_own(mt_strs *l, char *s); /* takes s */
51void mt_strs_free(mt_strs *l);
52mt_strs mt_strs_clone(const mt_strs *l);
53bool mt_strs_eq(const mt_strs *a, const mt_strs *b);
54bool mt_strs_has(const mt_strs *l, const char *s);
55long mt_strs_find(const mt_strs *l, const char *s); /* index, or -1 */
56void mt_strs_remove(mt_strs *l, size_t i);
57char *mt_join(const mt_strs *l, const char *sep); /* new string; "" for none */
58/* Rust's `s.split(c)`: "a,,b" is ["a", "", "b"], "" is [""]. */
59mt_strs mt_split(const char *s, char c);
60/* Rust's `s.split_whitespace()`: ASCII whitespace runs, no empty items. */
61mt_strs mt_words(const char *s);
62/* Rust's `s.lines()`: split on "\n" (a trailing "\r" removed), no final empty line. */
63mt_strs mt_lines(const char *s);
64/* Rust's `s.split_once(c)`: false when c is absent; else *a and *b are new strings. */
65bool mt_split_once(const char *s, char c, char **a, char **b);
66/* Rust's `s.trim()` (ASCII whitespace): a new string. */
67char *mt_trim(const char *s);
68
69#endif