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