|
MULE 0.0.1
Multi-Use Library Essentials
|
Owned, growable byte strings, and borrowed views into them.
Two types do all the work. A Str owns a heap buffer and can grow. A StrView borrows bytes that something else owns and never allocates. The working pattern is to put text into a Str once, then pass StrViews around to search it, split it and cut it. Copy a view into a new Str only when the bytes must outlive their owner.
A function that may allocate returns bool. False means out of memory, a size that would overflow, or a read error for the file functions. A call that returns false leaves the Str exactly as it was, so && can chain calls and stops at the first failure.
The tutorial Str and StrView in practice walks through all of this with programs you can run, and shows what the common mistakes look like under AddressSanitizer.
Data Structures | |
| struct | Str |
| Owned, growable byte string. More... | |
| struct | StrView |
| Non-owning view of bytes; handy for passing slices and literals around. More... | |
Macros | |
| #define | SV(lit) |
| View of a string literal, with its length computed at compile time. | |
| #define | STR_FMT(s) |
| printf helper: printf("%.*s", STR_FMT(s)) prints exactly len bytes. | |
Lifetime | |
Initialise a Str with contents, and free it. | |
| bool | str_with_capacity (Str *s, size_t capacity) |
Initialise s as empty with room for capacity bytes of content. | |
| bool | str_from (Str *s, StrView v) |
Initialise s as a copy of v. | |
| bool | str_from_cstr (Str *s, const char *cstr) |
Initialise s as a copy of cstr. | |
| void | str_free (Str *s) |
Free the buffer and reset s to the zero state. | |
Capacity | |
Control allocation when you know more than the doubling policy does. | |
| bool | str_reserve (Str *s, size_t additional) |
Ensure additional more bytes fit without another allocation. | |
| bool | str_shrink_to_fit (Str *s) |
| Shrink the allocation to exactly len + 1 bytes. | |
| void | str_clear (Str *s) |
| Set the length to zero. | |
Appending | |
Add bytes to the end. Each call may move data. | |
| bool | str_push (Str *s, char c) |
Append the single byte c. | |
| bool | str_append (Str *s, StrView v) |
Append v. | |
| bool | str_append_cstr (Str *s, const char *cstr) |
Append cstr. | |
| bool | str_appendf (Str *s, const char *fmt,...) |
Append the printf-style expansion of fmt. | |
| bool | str_vappendf (Str *s, const char *fmt, va_list ap) |
| str_appendf() for a va_list, like vprintf. | |
Reading files | |
Fill a Str from a FILE *. | |
| bool | str_append_file (Str *s, FILE *f) |
Append everything left to read from f. | |
| bool | str_read_line (Str *s, FILE *f) |
Replace the contents of s with the next line of f, without its \n. | |
Access and comparison | |
Look at a Str, or turn a C string into a view. | |
| StrView | str_view (const Str *s) |
Borrow the whole of s. | |
| const char * | str_cstr (const Str *s) |
NUL-terminated contents of s, for C APIs such as fopen and puts. | |
| bool | str_eq (StrView a, StrView b) |
True when a and b hold the same bytes. | |
| StrView | sv_from_cstr (const char *cstr) |
View of cstr, measured with strlen. | |
Searching and slicing | |
Inspect a view and cut pieces out of it. Nothing here allocates. | |
| size_t | sv_find_byte (StrView v, char c) |
Index of the first c in v. | |
| size_t | sv_find (StrView v, StrView needle) |
Index of the first needle in v. | |
| int | sv_cmp (StrView a, StrView b) |
| Byte order like memcmp. | |
| bool | sv_starts_with (StrView v, StrView prefix) |
True when v begins with prefix. | |
| bool | sv_ends_with (StrView v, StrView suffix) |
True when v ends with suffix. | |
| StrView | sv_slice (StrView v, size_t from, size_t to) |
Bytes from up to but not including to. | |
| StrView | sv_trim (StrView v) |
v without leading and trailing ASCII whitespace: space, \t, \n, \v, \f and \r. | |
| #define | SV_NPOS SIZE_MAX |
| Returned by the find functions when there is no match. | |
Splitting | |
Walk a view piece by piece. Both functions cut the next piece off the front of rest, and return false when nothing is left. | |
| bool | sv_split_next (StrView *rest, StrView sep, StrView *piece) |
Cut the piece before sep off rest. | |
| bool | sv_token_next (StrView *rest, StrView delims, StrView *token) |
strtok without the mutation: skip delims, then cut the next run of other bytes. | |
Parsing | |
Turn a whole view into a number. Partial matches fail. | |
| bool | sv_parse_i64 (StrView v, int64_t *out) |
Parse all of v as a base-10 integer with an optional sign. | |
| bool | sv_parse_f64 (StrView v, double *out) |
Parse all of v as a double, in any form strtod accepts in the C locale. | |
| struct Str |
Owned, growable byte string.
Zero-initialise before first use.
| Data Fields | ||
|---|---|---|
| char * | data | Buffer, or null when nothing is allocated. |
| size_t | len | Bytes of content, excluding the terminator. |
| size_t | capacity | Content bytes that fit before the next realloc. |
| const Allocator * | alloc |
Source of data. Null means the heap. |
| struct StrView |
Non-owning view of bytes; handy for passing slices and literals around.
| Data Fields | ||
|---|---|---|
| const char * | data |
First byte. Not necessarily NUL-terminated. |
| size_t | len | Number of bytes in the view. |
| #define SV | ( | lit | ) |
View of a string literal, with its length computed at compile time.
Only a literal compiles, so a char * cannot silently get the length of a pointer. Use sv_from_cstr() for pointers.
| #define STR_FMT | ( | s | ) |
printf helper: printf("%.*s", STR_FMT(s)) prints exactly len bytes.
Works on a Str and on a StrView.
| #define SV_NPOS SIZE_MAX |
Returned by the find functions when there is no match.
| bool str_with_capacity | ( | Str * | s, |
| size_t | capacity ) |
Initialise s as empty with room for capacity bytes of content.
| [out] | s | Overwritten without being freed. Only alloc is kept. |
| capacity | Content bytes to make room for. |
s held. Call str_free() first on a Str that owns memory. Initialise s as a copy of v.
| [out] | s | Overwritten without being freed. Only alloc is kept. |
| v | The bytes to copy. |
s held. Call str_free() first on a Str that owns memory. | bool str_from_cstr | ( | Str * | s, |
| const char * | cstr ) |
Initialise s as a copy of cstr.
Null gives an empty string.
| void str_free | ( | Str * | s | ) |
Free the buffer and reset s to the zero state.
Keeps alloc, so the string can be reused. Safe to call twice.
| bool str_reserve | ( | Str * | s, |
| size_t | additional ) |
| bool str_shrink_to_fit | ( | Str * | s | ) |
| void str_clear | ( | Str * | s | ) |
Set the length to zero.
Keeps the allocation for reuse, so a loop that builds one string per pass allocates once.
| bool str_push | ( | Str * | s, |
| char | c ) |
Append v.
v may point into s itself.
s is then unchanged. | bool str_append_cstr | ( | Str * | s, |
| const char * | cstr ) |
| bool str_appendf | ( | Str * | s, |
| const char * | fmt, | ||
| ... ) |
Append the printf-style expansion of fmt.
The compiler checks the arguments against the format.
s is then unchanged. | bool str_vappendf | ( | Str * | s, |
| const char * | fmt, | ||
| va_list | ap ) |
str_appendf() for a va_list, like vprintf.
| s | The string to append to. |
| fmt | A printf format for the arguments in ap. |
| ap | Used up afterwards. va_copy it first to use it again. |
| bool str_append_file | ( | Str * | s, |
| FILE * | f ) |
Append everything left to read from f.
When s owns no buffer yet, it takes the read buffer over instead of copying it.
s is then unchanged. Check ferror(f) before fclose to tell the two apart. | bool str_read_line | ( | Str * | s, |
| FILE * | f ) |
Replace the contents of s with the next line of f, without its \n.
A \r before it is kept, and embedded NULs are allowed.
s are then unchanged, though its capacity may have grown. | const char * str_cstr | ( | const Str * | s | ) |
| StrView sv_from_cstr | ( | const char * | cstr | ) |
| size_t sv_find_byte | ( | StrView | v, |
| char | c ) |
Index of the first needle in v.
An empty needle is at 0.
needle does not occur. Cut the piece before sep off rest.
Empty pieces are kept, so a,,b, splits as a, empty, b. Use it for fields and lines.
| [in,out] | rest | The text still to split. It shrinks on every call. |
| sep | The separator. It may be several bytes, such as "\r\n". | |
| [out] | piece | The next piece. Unchanged when the call returns false. |
rest is empty. sep is not empty. strtok without the mutation: skip delims, then cut the next run of other bytes.
Empty pieces never appear. Use it for words.
| [in,out] | rest | The text still to split. It shrinks on every call. |
| delims | A set of single bytes, any of which separates tokens. | |
| [out] | token | The next token. Unchanged when the call returns false. |
| bool sv_parse_i64 | ( | StrView | v, |
| int64_t * | out ) |
Parse all of v as a base-10 integer with an optional sign.
| v | The whole text to parse. | |
| [out] | out | The value. Unchanged when the call returns false. |
| bool sv_parse_f64 | ( | StrView | v, |
| double * | out ) |