MULE 0.0.1
Multi-Use Library Essentials
Loading...
Searching...
No Matches
str.h
1#pragma once
2/**
3 * @defgroup mod_str Str and StrView
4 * @brief Owned, growable byte strings, and borrowed views into them.
5 *
6 * Two types do all the work. A Str owns a heap buffer and can grow. A
7 * StrView borrows bytes that something else owns and never allocates. The
8 * working pattern is to put text into a Str once, then pass StrViews around
9 * to search it, split it and cut it. Copy a view into a new Str only when
10 * the bytes must outlive their owner.
11 *
12 * @snippet{trimleft} test_str.c build
13 *
14 * ## Str
15 *
16 * - `data` is NUL-terminated whenever it is non-null, so str_cstr() can
17 * hand it to C APIs. `len` is still the authority, and embedded NULs are
18 * allowed.
19 * - `capacity` counts content bytes. The allocation is `capacity + 1`
20 * bytes, to hold the terminator.
21 * - A zero-initialised Str (`Str s = { 0 };`) is a valid empty string
22 * that owns no memory. Every function accepts it.
23 * - The first allocation holds 15 bytes, and each growth doubles the
24 * capacity, so appending one byte at a time costs O(1) amortised.
25 * - `alloc` says where the bytes live, and null means the libc heap. Set
26 * it before the first allocation and leave it alone after. str_free()
27 * keeps it.
28 * - Pass a Str to functions as `Str *`. `Str b = a;` copies the pointer,
29 * not the bytes, and freeing both is a double free.
30 *
31 * @snippet{trimleft} test_str.c arena_str
32 *
33 * ## StrView
34 *
35 * - A view is a pointer and a length. Pass it by value.
36 * - It is valid while its owner is alive and has not moved its buffer.
37 * Any call that may grow a Str may move it, and every view into it then
38 * dangles.
39 * - It is not NUL-terminated in general. Print it with `%.*s` and
40 * STR_FMT, never with `%s`.
41 * - No StrView function allocates, so none of them can fail. Make a view
42 * with SV(), sv_from_cstr(), str_view() or sv_slice().
43 *
44 * ## Errors
45 *
46 * A function that may allocate returns `bool`. False means out of memory, a
47 * size that would overflow, or a read error for the file functions. A call
48 * that returns false leaves the Str exactly as it was, so `&&` can chain
49 * calls and stops at the first failure.
50 *
51 * The tutorial [Str and StrView in practice](str-and-strview.html) walks
52 * through all of this with programs you can run, and shows what the common
53 * mistakes look like under AddressSanitizer.
54 * @{
55 */
56
57#include "base/base.h"
58#include "mem/mem.h"
59
60#include <stdarg.h>
61#include <stdio.h>
62
63/** Owned, growable byte string. Zero-initialise before first use. */
64typedef struct Str {
65 char *data; /**< Buffer, or null when nothing is allocated. */
66 size_t len; /**< Bytes of content, excluding the terminator. */
67 size_t capacity; /**< Content bytes that fit before the next realloc. */
68 const Allocator *alloc; /**< Source of `data`. Null means the heap. */
69} Str;
70
71/** Non-owning view of bytes; handy for passing slices and literals around. */
72typedef struct StrView {
73 const char *data; /**< First byte. Not necessarily NUL-terminated. */
74 size_t len; /**< Number of bytes in the view. */
75} StrView;
76
77/** View of a string literal, with its length computed at compile time. Only
78 * a literal compiles, so a `char *` cannot silently get the length of a
79 * pointer. Use sv_from_cstr() for pointers. */
80#define SV(lit) ((StrView){ .data = "" lit "", .len = sizeof(lit) - 1 })
81/** printf helper: `printf("%.*s", STR_FMT(s))` prints exactly len bytes.
82 * Works on a Str and on a StrView.
83 * @par Example
84 * @snippet{trimleft} test_str.c fmt */
85#define STR_FMT(s) (int)(s).len, (s).data
86
87/** @name Lifetime
88 * Initialise a Str with contents, and free it.
89 * @{ */
90
91/** Initialise @p s as empty with room for @p capacity bytes of content.
92 * @param[out] s Overwritten without being freed. Only `alloc` is kept.
93 * @param capacity Content bytes to make room for.
94 * @return False when out of memory.
95 * @warning It does not free what @p s held. Call str_free() first on a Str
96 * that owns memory. */
97MULE_NODISCARD bool str_with_capacity(Str *s, size_t capacity);
98/** Initialise @p s as a copy of @p v.
99 * @param[out] s Overwritten without being freed. Only `alloc` is kept.
100 * @param v The bytes to copy.
101 * @return False when out of memory.
102 * @warning It does not free what @p s held. Call str_free() first on a Str
103 * that owns memory. */
104MULE_NODISCARD bool str_from(Str *s, StrView v);
105/** Initialise @p s as a copy of @p cstr. Null gives an empty string.
106 * @return False when out of memory.
107 * @see str_from() */
108MULE_NODISCARD bool str_from_cstr(Str *s, const char *cstr);
109/** Free the buffer and reset @p s to the zero state. Keeps `alloc`, so the
110 * string can be reused. Safe to call twice.
111 * @par Example
112 * @snippet{trimleft} test_str.c free */
113void str_free(Str *s);
114
115/** @} */
116
117/** @name Capacity
118 * Control allocation when you know more than the doubling policy does.
119 * @{ */
120
121/** Ensure @p additional more bytes fit without another allocation. Reserve
122 * before taking views, and appends within the reserve will not move them.
123 * @return False when out of memory or `len + additional` overflows. */
124MULE_NODISCARD bool str_reserve(Str *s, size_t additional);
125/** Shrink the allocation to exactly `len + 1` bytes.
126 * @return False when the allocator fails. @p s is then unchanged. */
127MULE_NODISCARD bool str_shrink_to_fit(Str *s);
128/** Set the length to zero. Keeps the allocation for reuse, so a loop that
129 * builds one string per pass allocates once.
130 * @par Example
131 * @snippet{trimleft} test_str.c clear */
132void str_clear(Str *s);
133
134/** @} */
135
136/** @name Appending
137 * Add bytes to the end. Each call may move `data`.
138 * @{ */
139
140/** Append the single byte @p c.
141 * @return False when out of memory. @p s is then unchanged. */
142MULE_NODISCARD bool str_push(Str *s, char c);
143/** Append @p v. @p v may point into @p s itself.
144 * @return False when out of memory. @p s is then unchanged.
145 * @par Example
146 * @snippet{trimleft} test_str.c self_append */
147MULE_NODISCARD bool str_append(Str *s, StrView v);
148/** Append @p cstr. A null @p cstr appends nothing.
149 * @return False when out of memory. @p s is then unchanged. */
150MULE_NODISCARD bool str_append_cstr(Str *s, const char *cstr);
151/** Append the printf-style expansion of @p fmt. The compiler checks the
152 * arguments against the format.
153 * @return False when out of memory or the format fails. @p s is then
154 * unchanged.
155 * @par Example
156 * @snippet{trimleft} test_str.c appendf */
157MULE_NODISCARD bool str_appendf(Str *s, const char *fmt, ...) MULE_PRINTF(2, 3);
158/** str_appendf() for a `va_list`, like vprintf.
159 * @param s The string to append to.
160 * @param fmt A printf format for the arguments in @p ap.
161 * @param ap Used up afterwards. va_copy it first to use it again.
162 * @return False when out of memory or the format fails. */
163MULE_NODISCARD bool str_vappendf(Str *s, const char *fmt, va_list ap)
164 MULE_PRINTF(2, 0);
165
166/** @} */
167
168/** @name Reading files
169 * Fill a Str from a `FILE *`.
170 * @{ */
171
172/** Append everything left to read from @p f. When @p s owns no buffer yet,
173 * it takes the read buffer over instead of copying it.
174 * @return False on a read error or out of memory. @p s is then unchanged.
175 * Check ferror(f) before fclose to tell the two apart.
176 * @par Example
177 * @snippet{trimleft} test_str.c append_file */
178MULE_NODISCARD bool str_append_file(Str *s, FILE *f);
179/** Replace the contents of @p s with the next line of @p f, without its
180 * `\n`. A `\r` before it is kept, and embedded NULs are allowed.
181 * @return False at end of input, on a read error (check ferror(f)) or out
182 * of memory. The contents of @p s are then unchanged, though its capacity
183 * may have grown.
184 * @par Example
185 * @snippet{trimleft} test_str.c read_line */
186MULE_NODISCARD bool str_read_line(Str *s, FILE *f);
187
188/** @} */
189
190/** @name Access and comparison
191 * Look at a Str, or turn a C string into a view.
192 * @{ */
193
194/** Borrow the whole of @p s.
195 * @warning Invalidated by any call that may reallocate @p s. */
196MULE_NODISCARD StrView str_view(const Str *s);
197/** NUL-terminated contents of @p s, for C APIs such as fopen and puts.
198 * Never null, even for an empty Str.
199 * @warning Invalidated by any call that may reallocate @p s. */
200MULE_NODISCARD const char *str_cstr(const Str *s);
201/** True when @p a and @p b hold the same bytes.
202 * @par Example
203 * @snippet{trimleft} test_str.c eq
204 * @see sv_cmp() to order strings. */
205MULE_NODISCARD bool str_eq(StrView a, StrView b);
206/** View of @p cstr, measured with strlen. Null gives an empty view. Use it
207 * for `argv[i]`, getenv and other C strings. */
208MULE_NODISCARD StrView sv_from_cstr(const char *cstr);
209
210/** @} */
211
212/** @name Searching and slicing
213 * Inspect a view and cut pieces out of it. Nothing here allocates.
214 * @{ */
215
216/** Returned by the find functions when there is no match. */
217#define SV_NPOS SIZE_MAX
218
219/** Index of the first @p c in @p v.
220 * @return The index, or #SV_NPOS when @p c does not occur. */
221MULE_NODISCARD size_t sv_find_byte(StrView v, char c);
222/** Index of the first @p needle in @p v. An empty needle is at 0.
223 * @return The index, or #SV_NPOS when @p needle does not occur.
224 * @par Example
225 * @snippet{trimleft} test_str.c find */
226MULE_NODISCARD size_t sv_find(StrView v, StrView needle);
227/** Byte order like memcmp. A prefix sorts before the longer string, so it
228 * works as a qsort comparison on views.
229 * @return Negative, zero or positive as @p a sorts before, with or after
230 * @p b. */
231MULE_NODISCARD int sv_cmp(StrView a, StrView b);
232/** True when @p v begins with @p prefix. */
233MULE_NODISCARD bool sv_starts_with(StrView v, StrView prefix);
234/** True when @p v ends with @p suffix. */
235MULE_NODISCARD bool sv_ends_with(StrView v, StrView suffix);
236/** Bytes @p from up to but not including @p to.
237 * @pre `from <= to && to <= v.len`. An assert checks it. */
238MULE_NODISCARD StrView sv_slice(StrView v, size_t from, size_t to);
239/** @p v without leading and trailing ASCII whitespace: space, `\t`, `\n`,
240 * `\v`, `\f` and `\r`. */
241MULE_NODISCARD StrView sv_trim(StrView v);
242
243/** @} */
244
245/** @name Splitting
246 * Walk a view piece by piece. Both functions cut the next piece off the
247 * front of `rest`, and return false when nothing is left.
248 * @{ */
249
250/** Cut the piece before @p sep off @p rest. Empty pieces are kept, so
251 * `a,,b,` splits as `a`, empty, `b`. Use it for fields and lines.
252 * @param[in,out] rest The text still to split. It shrinks on every call.
253 * @param sep The separator. It may be several bytes, such as `"\r\n"`.
254 * @param[out] piece The next piece. Unchanged when the call returns false.
255 * @return False when @p rest is empty.
256 * @pre @p sep is not empty.
257 * @par Example
258 * @snippet{trimleft} test_str.c split
259 * @see sv_token_next() to skip empty pieces. */
260MULE_NODISCARD bool sv_split_next(StrView *rest, StrView sep, StrView *piece);
261/** strtok without the mutation: skip @p delims, then cut the next run of
262 * other bytes. Empty pieces never appear. Use it for words.
263 * @param[in,out] rest The text still to split. It shrinks on every call.
264 * @param delims A set of single bytes, any of which separates tokens.
265 * @param[out] token The next token. Unchanged when the call returns false.
266 * @return False when only delimiters are left.
267 * @par Example
268 * @snippet{trimleft} test_str.c token
269 * @see sv_split_next() to keep empty pieces. */
270MULE_NODISCARD bool sv_token_next(StrView *rest, StrView delims,
271 StrView *token);
272
273/** @} */
274
275/** @name Parsing
276 * Turn a whole view into a number. Partial matches fail.
277 * @{ */
278
279/** Parse all of @p v as a base-10 integer with an optional sign.
280 * @param v The whole text to parse.
281 * @param[out] out The value. Unchanged when the call returns false.
282 * @return False on whitespace, trailing bytes or overflow.
283 * @par Example
284 * @snippet{trimleft} test_str.c parse */
285MULE_NODISCARD bool sv_parse_i64(StrView v, int64_t *out);
286/** Parse all of @p v as a double, in any form strtod accepts in the C
287 * locale.
288 * @param v The whole text to parse.
289 * @param[out] out The value. Unchanged when the call returns false.
290 * @return False on whitespace, trailing bytes, overflow to infinity, or a
291 * view over 255 bytes. */
292MULE_NODISCARD bool sv_parse_f64(StrView v, double *out);
293
294/** @} */
295
296/** @} */
Where a module gets its memory.
Definition mem.h:56
size_t len
Number of bytes in the view.
Definition str.h:74
size_t capacity
Content bytes that fit before the next realloc.
Definition str.h:67
const char * data
First byte.
Definition str.h:73
const Allocator * alloc
Source of data.
Definition str.h:68
size_t len
Bytes of content, excluding the terminator.
Definition str.h:66
char * data
Buffer, or null when nothing is allocated.
Definition str.h:65
const char * str_cstr(const Str *s)
NUL-terminated contents of s, for C APIs such as fopen and puts.
Definition str.c:216
size_t sv_find(StrView v, StrView needle)
Index of the first needle in v.
Definition str.c:237
bool str_shrink_to_fit(Str *s)
Shrink the allocation to exactly len + 1 bytes.
Definition str.c:62
StrView sv_from_cstr(const char *cstr)
View of cstr, measured with strlen.
Definition str.c:224
bool sv_parse_f64(StrView v, double *out)
Parse all of v as a double, in any form strtod accepts in the C locale.
Definition str.c:351
void str_clear(Str *s)
Set the length to zero.
Definition str.c:71
StrView str_view(const Str *s)
Borrow the whole of s.
Definition str.c:212
bool sv_token_next(StrView *rest, StrView delims, StrView *token)
strtok without the mutation: skip delims, then cut the next run of other bytes.
Definition str.c:306
bool str_from(Str *s, StrView v)
Initialise s as a copy of v.
Definition str.c:41
void str_free(Str *s)
Free the buffer and reset s to the zero state.
Definition str.c:50
bool str_append_file(Str *s, FILE *f)
Append everything left to read from f.
Definition str.c:156
bool str_appendf(Str *s, const char *fmt,...)
Append the printf-style expansion of fmt.
Definition str.c:123
bool str_push(Str *s, char c)
Append the single byte c.
Definition str.c:76
StrView sv_trim(StrView v)
v without leading and trailing ASCII whitespace: space, \t, \n, \v, \f and \r.
Definition str.c:279
bool sv_ends_with(StrView v, StrView suffix)
True when v ends with suffix.
Definition str.c:263
bool str_read_line(Str *s, FILE *f)
Replace the contents of s with the next line of f, without its \n.
Definition str.c:185
bool str_reserve(Str *s, size_t additional)
Ensure additional more bytes fit without another allocation.
Definition str.c:56
bool str_append(Str *s, StrView v)
Append v.
Definition str.c:89
bool sv_starts_with(StrView v, StrView prefix)
True when v begins with prefix.
Definition str.c:259
bool str_eq(StrView a, StrView b)
True when a and b hold the same bytes.
Definition str.c:220
bool sv_split_next(StrView *rest, StrView sep, StrView *piece)
Cut the piece before sep off rest.
Definition str.c:286
bool sv_parse_i64(StrView v, int64_t *out)
Parse all of v as a base-10 integer with an optional sign.
Definition str.c:330
bool str_from_cstr(Str *s, const char *cstr)
Initialise s as a copy of cstr.
Definition str.c:46
bool str_with_capacity(Str *s, size_t capacity)
Initialise s as empty with room for capacity bytes of content.
Definition str.c:36
StrView sv_slice(StrView v, size_t from, size_t to)
Bytes from up to but not including to.
Definition str.c:268
int sv_cmp(StrView a, StrView b)
Byte order like memcmp.
Definition str.c:252
size_t sv_find_byte(StrView v, char c)
Index of the first c in v.
Definition str.c:231
bool str_vappendf(Str *s, const char *fmt, va_list ap)
str_appendf() for a va_list, like vprintf.
Definition str.c:131
bool str_append_cstr(Str *s, const char *cstr)
Append cstr.
Definition str.c:119
Owned, growable byte string.
Definition str.h:64
Non-owning view of bytes; handy for passing slices and literals around.
Definition str.h:72