Skip to content

string — C-strings and the growable String type

Source: std/string.mw. Imports mem.mw (for alloc/realloc, used by String).

These operate on plain *u8 null-terminated strings (the same representation Marrow string literals have).

Returns the length of a null-terminated string, not counting the terminator (like C’s strlen).

Returns 1 if the two null-terminated strings are equal, 0 otherwise.

Each takes a u8 (a single byte/char) and returns 1/0.

True for ASCII '0''9'.

True for ASCII letters ('a''z', 'A''Z') or underscore ('_') — despite the name, this also accepts _, which makes it convenient for scanning identifier-like text.

True for space, tab (\t), newline (\n) or carriage return (\r).

A growable, heap-allocated, null-terminated byte string — distinct from the built-in *u8 C-string type, and from u8[] slices.

struct String {
data: *u8; // heap buffer, always null-terminated
len: i64; // length, not counting the null terminator
cap: i64; // allocated capacity of `data`
}

String values are always handled through a *String pointer — every constructor below returns one, and every function that takes a String takes a pointer to it.

Allocates a new, empty String with at least initial_cap bytes of backing storage (silently bumped up to a minimum of 8 if you ask for less). The buffer starts null-terminated (len = 0).

Builds a new String by copying the contents of a null-terminated C-string.

Appends a single byte, growing (doubling capacity) and reallocing the buffer if needed, and keeps the buffer null-terminated.

Appends the contents of a null-terminated C-string, growing as needed.

Frees both the string’s data buffer and the String struct itself. After this call, s is a dangling pointer — don’t use it again.

Equality check. Returns 0 if either pointer is null; 1 if they’re the same pointer; otherwise compares lengths first, then byte content.

Lexicographic (byte-wise) comparison, returning -1, 0 or 1 — the same convention as C’s strcmp/memcmp, except it also correctly orders strings of different lengths that share a common prefix (the shorter one sorts first). Returns 0 if either pointer, or either pointer’s data, is null.

@import("string.mw")
fn greet(name: *u8) -> *String {
var s: *String = string_new(16);
string_push_str(s, "Hello, ");
string_push_str(s, name);
string_push_char(s, cast(u8) 33); // '!'
ret s;
}