Skip to content

String 0.3 (legacy)

A heap-owned, NUL-terminated byte string. charAt(i) returns the i-th byte — on this surface a “char” is a u8, exactly as in C.

String* s = String.withCString(" Hello, World ");
String* t = s.trimmed(); // "Hello, World"
if (t.hasPrefix(String.withCString("Hello"))) { … }
Array* fields = String.withCString("a,b,,c").split((u8)','); // 4 parts — the gap counts
String* back = String.join(fields, String.withCString("-")); // "a-b--c"
BuildString.withCString(p), withString(s), withBytes(p, n)
NumbersString.withI32(v), withU32(v), withI16(v), withU16(v), withFloat(v)
Readlength(), isEmpty(), charAt(i), cString(), copyCString()
SearchindexOf(needle), indexOfChar(c), lastIndexOfChar(c), contains(s), hasPrefix(s), hasSuffix(s)
Slicesubstring(from, len), substringFrom(from), substringTo(to)
Mutateappend(s), appendChar(c), appendCString(p) — and appending(s), which returns a new String instead
Caseuppercased(), lowercased(), caseInsensitiveCompare(s), equalsIgnoringCase(s)
Othertrimmed(), split(sep)Array*, String.join(parts, sep), replacing(find, sub), description()
Valueequals(other), compare(other), hash() — FNV-1a over the bytes

Out-of-range slicing clamps to empty rather than faulting — substringFrom(999) is an empty String, the same choice Foundation makes for a clamped range.

split yields empty components for consecutive, leading or trailing separators, so "a,,b" is three fields. That is what a CSV needs; filter the empties out if you want tokens.

Ordering is lexicographic by unsigned byte, then by length — so a prefix sorts before its extension ("go" before "gone").

cString() is a borrow. It returns a pointer into the String’s own buffer, and any mutation that grows the String — append, appendChar, appendCString, appendFormat, insert — may reallocate that buffer and free the old one. The pointer is valid until the String is next grown; after that it dangles, and it usually still appears to work, which is exactly the failure that survives testing. A string is not a class pointer, so holding one neither retains the String nor stops it growing. If the bytes must outlive the next mutation, take a copy: copyCString() returns a fresh heap copy that the caller owns (and frees with delete).

So that byte-only code can be written once for every target, the xt6502 String also accepts the 0.4 spellings, each a thin alias for the method above it:

0.4 spelling (alias)xt6502 implementation
byteLength()length()
byteAt(i)charAt(i)
appendByte(c)appendChar(c)
byteIndexOf(needle[, from])indexOf(…)
indexOfByte(c) / lastIndexOfByte(c)indexOfChar(c) / lastIndexOfChar(c)
substringBytes(from, len) / substringFromByte(from) / substringToByte(to)substring(…) / substringFrom(…) / substringTo(…)
insertAtByte(at, s) / insertByte(at, c) / insertCStringAtByte(at, p)insert(…) / insertChar(…) / insertCString(…)
deleteByteRange(at, len) / replaceByteRange(at, len, s)deleteRange(…) / replaceRange(…)
byteIndexOfSet(cs) / lastByteIndexOfSet(cs) / containsByteFromSet(cs)indexOfCharacterFrom(cs) / lastIndexOfCharacterFrom(cs) / containsCharacterFrom(cs)
splitOnSet(cs) / splitOnByte(sep)split(cs) / split(sep)

There is no character layer on xt6502 — no charCount, no code-point charAt, no encodings. A UTF-8 decoder is the wrong tax on a 6502.