lib/strings+test: 0-arg trim strips ASCII whitespace per Hare

The 0-arg ltrim/rtrim/trim used to return input unchanged. Hare's
0-arg form strips [' ', '\n', '\t', '\r'] (ref/hare/strings/trim.ha:6).
Aligned by delegating to bytes.ltrim/bytes.rtrim with the whitespace
set spread inline at the call site — the obvious `let ws = whitespace[0:4]`
shape produces a slice whose ptr does NOT alias storage (#40).
N-arg forms (strip-specific-runes) untouched.

Test rows retargeted to Hare's canonical inputs from trim.ha:78/85
so '\r' is exercised alongside ' '/'\t'/'\n'.
This commit is contained in:
2026-05-19 22:52:23 +09:00
parent f827429215
commit 18fe1a7a31
5 changed files with 105 additions and 54 deletions

View File

@@ -3,10 +3,6 @@
//
// Documented divergences from Hare:
//
// - `trim` / `ltrim` / `rtrim` 0-arg returns the input unchanged.
// Hare strips ASCII whitespace via `bytes::ltrim(input,
// whitespace...)`; that needs `lib/bytes` variadic graduation
// (future commit).
// - `byteindex` / `rbyteindex` rune arms encode via
// `utf8.encoderune`; the legacy impls scanned for `r: u8` (an
// undocumented ASCII-only restriction that silently dropped
@@ -402,12 +398,21 @@ export fn trimsuffix(input: str, suffix: str) str = {
return r;
};
// whitespace — ASCII whitespace set used by the 0-arg ltrim/rtrim/trim
// branches (#9). ref/hare/strings/trim.ha:6.
let whitespace: [4]u8 = [0x20u8, 0x0Au8, 0x09u8, 0x0Du8];
// ltrim — strip leading runes that occur in `trim`. Borrowed view.
// Empty `trim` returns input unchanged (Hare's no-rune branch strips
// ASCII whitespace via `bytes::ltrim`; needs lib/bytes variadic
// graduation). ref/hare/strings/trim.ha:11.
// 0-arg strips ASCII whitespace via [[bytes.ltrim]] (#9).
// ref/hare/strings/trim.ha:11. The spread expression is inlined
// because `let ws: []u8 = whitespace[0:4]` produces a slice whose
// ptr doesn't track the module-level array storage (filed as #40);
// `b.flush = flushdefault[0:1]` in lib/bufio is the same shape via
// the working field-assign path.
export fn ltrim(input: str, trim: rune...) str = {
if (trim.len == 0) { return input; };
if (trim.len == 0) {
return fromutf8_unsafe(bytes.ltrim(toutf8(input), whitespace[0:4]...));
};
let it: iterator = iter(input);
for (true) {
match (next(&it)) {
@@ -433,9 +438,13 @@ export fn ltrim(input: str, trim: rune...) str = {
};
// rtrim — strip trailing runes that occur in `trim`. Borrowed view.
// 0-arg strips ASCII whitespace via [[bytes.rtrim]] (#9). Spread is
// inlined to dodge #40 — see [[ltrim]].
// ref/hare/strings/trim.ha:32.
export fn rtrim(input: str, trim: rune...) str = {
if (trim.len == 0) { return input; };
if (trim.len == 0) {
return fromutf8_unsafe(bytes.rtrim(toutf8(input), whitespace[0:4]...));
};
let it: iterator = riter(input);
for (true) {
match (next(&it)) {