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 is_whitespace(c: char): bool
Helper: checks if character is whitespace
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): char
Returns character at index with bounds checking Returns null character '\0' if index is out of bounds
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 is_digit(c: char): bool
Returns true if character is a digit (0-9)
fn is_alpha(c: char): bool
Returns true if character is a letter (a-z, A-Z)
fn is_alnum(c: char): bool
Returns true if character is alphanumeric (letter or digit)
fn index_of(s: string, needle: string): int
Returns the index of the first occurrence of needle in s, or -1 if not found Pure Reef implementation (replaces strstr)
fn last_index_of(s: string, needle: string): int
Returns the index of the last occurrence of needle in s, or -1 if not found Pure Reef implementation
fn index_of_char(s: string, c: char): int
Returns the index of the first occurrence of character c in s, or -1 if not found
fn last_index_of_char(s: string, c: char): int
Returns the index of the last occurrence of character c in s, or -1 if not found
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, result: [string], max_parts: int): int
Splits string s by delimiter character into result array Returns the number of parts written to result max_parts limits how many parts to extract (0 = no limit up to array size) Example: split("a,b,c", ',', result, 10) -> returns 3, result = ["a", "b", "c"]
fn join(parts: [string], count: int, delim: string): string
Joins array of strings with delimiter using a single allocation (O(n) time) count specifies how many elements to join from parts array Example: join(["a", "b", "c"], 3, ",") -> "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 format(template: string, args: [string], arg_count: int): string
Formats a string by replacing %s placeholders with arguments Supports: %s (string substitution), %% (literal percent) Arguments are provided as a string array Returns the formatted string
Example: format("Hello %s, you have %s messages", ["Alice", "5"], 2) -> "Hello Alice, you have 5 messages"
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
fn from_int(n: int): string
Converts an integer to its decimal string representation. Handles zero, positive, and negative values. INT_MIN safe. Note: core.convert.to_string is the symmetric numeric API; this is the discoverable str-namespace alias and currently has its own impl to avoid a circular import (convert.reef imports core.str).
fn to_int(s: string): result.Result[int, error.Error]
Parses a string as a signed decimal integer. Returns Ok(n) on success, Err(msg) on empty input or any non-digit character (including trailing garbage; "12x" is rejected). Leading whitespace not skipped; callers should str.trim_ws first if needed. Accepts optional leading '+' or '-'. Note: core.convert.toInt also returns Result[int, Error], but is permissive about trailing garbage — it stops at the first non-digit and returns Ok on the parsed prefix (e.g. toInt("123abc") returns Ok(123)). Use str.to_int when trailing non-digit characters should make the whole parse fail.
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