Module: core.str
Source: ./core/str.reef
Overview
core.str - String manipulation functions
Provides fundamental string operations including length, comparison, concatenation, substring extraction, trimming, and character classification. Uses FFI to C standard library where appropriate.
BUG-147 (v0.8.2): length() and safe-context s[i] bounds checks are O(1) -
they read a logical length (str_len) stored in the string's heap-block
header instead of scanning to the NUL. The runtime keeps str_len correct
for every stdlib-facing operation automatically. The one place this is NOT
automatic is unsafe code that moves a string's NUL terminator by hand
(e.g. building a string with hand-indexed writes past its allocator-set
length, or handing a buffer to external C to fill): that code must call
set_length()/sync_length() below to keep str_len truthful, or length()
and bounds checks will report the stale value. See
docs/language/reference/100_UNSAFE.md for the full contract and
docs/superpowers/specs/2026-07-31-string-logical-length-design.md for the
design.
Functions
fn length(s: string): int
Returns the length of a string. BUG-147: O(1) - reads the logical length from the heap-block header instead of scanning to the NUL. Was a strlen-equivalent unsafe loop, which made every caller (substring, split, trim_ws, ...) quadratic in the input length.
fn equals(s1: string, s2: string): bool
Checks if two strings are equal (pure Reef implementation) Replaces: strcmp from libc
fn compare(s1: string, s2: string): int
Compares two strings lexicographically (pure Reef implementation) Returns: <0 if s1 < s2, 0 if s1 == s2, >0 if s1 > s2 Replaces: strcmp from libc
fn contains(haystack: string, needle: string): bool
Checks if a string contains a substring (pure Reef implementation) Replaces: strstr from libc
fn starts_with(s: string, prefix: string): bool
Checks if a string starts with a given prefix (pure Reef implementation) Replaces: strncmp from libc
fn ends_with(s: string, suffix: string): bool
Checks if a string ends with a given suffix (pure Reef implementation)
fn concat(s1: string, s2: string): string
Concatenates two strings (pure Reef implementation) Replaces: strcpy + strcat from libc
Warning: Using concat() or + in a loop is O(n^2) because each call
allocates a new string and copies all previous content. For joining
many strings, use str.join() or text.stringbuilder instead.
fn substring(s: string, start: int, len: int): string
Extracts a substring from start index with given length (pure Reef implementation) Replaces: strncpy from libc
fn trim_left(s: string, c: char): string
Removes all occurrences of character c from the beginning of string
fn trim_right(s: string, c: char): string
Removes all occurrences of character c from the end of string
fn trim(s: string, c: char): string
Removes all occurrences of character c from both ends of string
fn trim_ws(s: string): string
Removes all whitespace (space, tab, newline, carriage return) from both ends
fn chomp(s: string): string
Removes trailing newline character(s) from string (like Ruby's chomp) Handles both Unix (\n) and Windows (\r\n) line endings
fn is_empty(s: string): bool
Returns true if string is empty (length 0)
fn char_at(s: string, index: int): option.Option[char]
Returns character at index with bounds checking. OOB → None (no '\0' sentinel).
fn reverse(s: string): string
Returns a reversed copy of the string
fn repeat(s: string, n: int): string
Returns string repeated n times If n <= 0, returns empty string
fn pad_left(s: string, width: int, pad_char: char): string
Left-pads string to specified width with pad_char If string is already >= width, returns original string
fn pad_right(s: string, width: int, pad_char: char): string
Right-pads string to specified width with pad_char If string is already >= width, returns original string
fn index_of(s: string, needle: string): option.Option[int]
Returns Some(index) of the first occurrence of needle in s, None if absent. An empty needle matches at 0. Pure Reef implementation (replaces strstr).
fn last_index_of(s: string, needle: string): option.Option[int]
Returns Some(index) of the last occurrence of needle in s, None if absent. An empty needle matches at length(s). Pure Reef implementation.
fn index_of_char(s: string, c: char): option.Option[int]
Returns Some(index) of the first occurrence of c in s, None if absent.
fn last_index_of_char(s: string, c: char): option.Option[int]
Returns Some(index) of the last occurrence of c in s, None if absent.
fn to_upper(s: string): string
Converts string to uppercase (pure Reef implementation)
fn to_lower(s: string): string
Converts string to lowercase (pure Reef implementation)
fn replace(s: string, old: string, new_str: string): string
Replaces all occurrences of old with new_str in s (pure Reef implementation)
fn replace_char(s: string, old: char, new_char: char): string
Replaces all occurrences of old character with new_char in s
fn count_char(s: string, c: char): int
Counts occurrences of character c in string s
fn split(s: string, delim: char): [string]
Splits s on delim and returns the parts.
The callee sizes the result, so there is no caller buffer and no count to thread back: split("a,b,c", ',') is ["a", "b", "c"]. An empty input yields zero parts. Adjacent delimiters and a trailing delimiter both produce empty fields, so the number of parts is always count_char(s, delim) + 1 for a non-empty s -- splitting is total, and join(split(x, d), d) == x.
0.9.2 C14: the old form took a max_parts cap whose last part absorbed
the entire remainder -- split("a,b,c,d", ',', buf, 2) gave ["a", "b,c,d"].
That rule is GONE, not reimplemented. A caller that wants it should split
fully and rejoin the tail.
fn join(parts: [string], delim: string): string
Joins array of strings with delimiter using a single allocation (O(n) time) Example: join(["a", "b", "c"], ",") -> "a,b,c"
Performance: This is the recommended way to combine many strings.
Concatenating strings in a loop with + or concat() is O(n^2)
because each iteration allocates a new string and copies all
previous characters. For large inputs this causes severe slowdowns.
Use join() instead, or see text.stringbuilder for incremental building.
fn glob_match(pattern: string, text: string): bool
Matches a string against a glob pattern Supports:
-
- matches zero or more characters ? - matches exactly one character Returns true if the text matches the pattern
Examples: glob_match(".txt", "file.txt") -> true glob_match("test_??.reef", "test_01.reef") -> true glob_match("hello", "hello world") -> true
fn glob_match_helper(pattern: string, pi: int, text: string, ti: int): bool
Helper function for recursive glob matching
Procedures
proc set_length(s: string, n: int)
Sets the logical length of a mutable string buffer (BUG-147). For unsafe code that moved the NUL; panics on literals and out-of-range n.
proc sync_length(s: string)
Re-derives the logical length from the NUL terminator (one O(n) scan). For buffers filled by external C code; panics on literals.
Generated by reefc doc