Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

lib/split.x

String field splitting and repeatable typed cursors.

Primary API

FunctionSummary
Split.iterReturns an iterator over a lazy String cursor.
Split.try_nextYields the next field and advances a caller-owned position on success.
String.linesReturns a lazy cursor over lines in str, with endings removed.
String.splitSplits str on every occurrence of sep into a List of Strings.
String.split_linesSplits str into a List of lines.
String.split_nSplits str at no more than max_splits separators.
String.splitsReturns a lazy cursor over fields separated by sep.
String.wordsReturns a lazy cursor over whitespace-delimited words in str.

Split

Split.iter

Iter Split.iter(Split split, Iter dest)

Returns an iterator over a lazy String cursor. This adapter over Split.try_next boxes each field into a Var and keeps the Iter state in step. Use the typed cursor in hot code and this method when you need the Iter protocol.

The cursor descriptor is Scope-owned; dest is caller-supplied iterator storage. Every iterator keeps its own byte position, so cursors can be nested or traversed concurrently. The Split descriptor, its borrowed input Strings, and dest must remain live until iteration ends.

Constructing the iterator does not raise. Pulling may raise <alloc-fail> as Split.try_next does. A null dest returns NULL.

Source: lib/split.x:269

Split.try_next

int Split.try_next(Split split, int *cursor, String *out)

Yields the next field and advances a caller-owned position on success. Position must start at zero and thereafter retain only values written by this method. Both it and out are written only on success, so an empty String field stays distinct from exhaustion and a walk that has ended leaves the last field in place. The position belongs to the caller, so one descriptor supports repeated, nested, and concurrent walks, including alongside a Split.iter iterator over the same descriptor. A yielded canonical String remains live until its actual owning pool is released.

Split words = %"ada lovelace".words();
int cursor = 0;
String word;
while (words.try_next(&cursor, &word)) printf("%s\n", word);

This is what foreach(String word, split) lowers to; Split.iter is the boxing adapter for every other binder.

Raises: <alloc-fail> while canonicalizing a nonempty field. Null arguments produce exhaustion without raising.

Source: lib/split.x:243

String

String.lines

Split String.lines(String str)

Returns a lazy cursor over lines in str, with endings removed. LF, CR, and CRLF end a line, with CRLF counted as one ending. The yielded fields agree with str.split_lines(0), including empty interior lines and the rule that a trailing ending does not add a final empty line.

Each yielded field is a canonical String. Distinct fields remain resident in the active String pool; bracket bulk traversal with String.pool_retain / String.pool_release and promote retained values when that residency should be temporary. The cursor borrows str, whose actual owning pool must remain live through traversal.

Raises: <alloc-fail> when the cursor descriptor cannot be allocated. An empty String produces an exhausted cursor.

Source: lib/split.x:206

String.split

List String.split(String str, String sep)

Splits str on every occurrence of sep into a List of Strings. Separators are not coalesced, so adjacent ones produce empty fields and the result holds one more element than the number of separators found. An empty field is the empty String, the null pointer. An empty or null sep yields a one-element List holding str, and splitting the empty String yields the empty List. The canonical fields and List remain live until their actual String and List pools are released.

printf("%s\n", %"a:b:c".split(":").repr());
printf("%s\n", %"a::b".split(":").repr());

Raises: the same causes as String.split_n.

Source: lib/split.x:110

String.split_lines

List String.split_lines(String str, int keep_ends)

Splits str into a List of lines. LF, CR, and CRLF all end a line, and CRLF counts as one ending. A nonzero keep_ends leaves each line’s ending attached to it. A trailing line ending does not produce a final empty line, so text that ends in a newline yields as many lines as it has endings. A null or empty str returns nil. The canonical fields and List remain live until their actual String and List pools are released.

Raises: <alloc-fail> or <size-limit> while constructing fields or the result.

Source: lib/split.x:123

String.split_n

List String.split_n(String str, String sep, int max_splits)

Splits str at no more than max_splits separators. A negative limit splits every occurrence; zero returns str as one field. A null str returns nil. A null or empty sep returns str as one field. The canonical fields and List remain live until their actual String and List pools are released.

Raises: <alloc-fail> or <size-limit> while constructing the result.

Source: lib/split.x:80

String.splits

Split String.splits(String str, String sep)

Returns a lazy cursor over fields separated by sep. Separators are not coalesced, so adjacent separators produce empty fields. The yielded fields agree with str.split(sep). A null or empty separator yields str once, while an empty str yields nothing.

Each yielded field is a canonical String. Distinct fields remain resident in the active String pool; bracket bulk traversal with String.pool_retain / String.pool_release and promote retained values when that residency should be temporary. The cursor borrows str and sep; both actual owning pools must remain live through traversal.

Raises: <alloc-fail> when the cursor descriptor cannot be allocated.

Source: lib/split.x:220

String.words

Split String.words(String str)

Returns a lazy cursor over whitespace-delimited words in str. Runs of C isspace bytes are coalesced, leading and trailing whitespace is ignored, and no empty String is yielded. str.splits(" ") instead preserves empty fields around every explicit separator.

Each yielded field is a canonical String. Distinct fields remain resident in the active String pool; bracket bulk traversal with String.pool_retain / String.pool_release and promote retained values when that residency should be temporary. The cursor borrows str, whose actual owning pool must remain live through traversal.

Raises: <alloc-fail> when the cursor descriptor cannot be allocated. An empty String produces an exhausted cursor.

Source: lib/split.x:191

Public types

TypeKindSummary
SplitstructDescribes an immutable, repeatable lazy traversal of a borrowed String.

Split

typedef struct Split *Split

Describes an immutable, repeatable lazy traversal of a borrowed String. The descriptor is Scope-owned and keeps no position; each caller or Iter keeps its own cursor. The input and separator are not retained, so their actual String pools must remain live through every traversal. No cleanup is needed before the descriptor’s Scope is released.

Source: lib/split.x:22

Design notes

A Split description is immutable and Scope-owned. It keeps no position; the caller holds the cursor, so one Split supports repeated, nested, and concurrent walks. Eager and lazy splitting share the same separator and line-ending scans.

Tests and examples

make verify (unittest/test-split.x).