lib/bytes+test: port ltrim/rtrim/trim from Hare (u8... variadic)

This commit is contained in:
2026-05-19 16:19:12 +09:00
parent e5c1d6baa4
commit 8683202a4c
5 changed files with 240 additions and 0 deletions

View File

@@ -1023,6 +1023,40 @@ export fn contains(s: []u8, needles: (u8 | []u8)...) bool = {
return false;
};
// ltrim — borrowed view of `in` with leading bytes in `trim` stripped.
// `trim` must be non-empty. ref/hare/bytes/trim.ha:7.
export fn ltrim(in: []u8, trim: u8...) []u8 = {
os.assert(trim.len > 0, "bytes.ltrim called with empty trim set");
let i: i32 = 0;
for (i < in.len && contains(trim, in[i])) { i += 1; };
let r: []u8;
r.ptr = in.ptr + (i: u64);
r.len = in.len - i;
r.cap = r.len;
return r;
};
// rtrim — borrowed view of `in` with trailing bytes in `trim` stripped.
// `trim` must be non-empty. ref/hare/bytes/trim.ha:17. Hare's loop uses
// `size` underflow at i==0 to terminate; ww indices are signed i32, so
// the equivalent termination is spelled `i >= 0` explicitly.
export fn rtrim(in: []u8, trim: u8...) []u8 = {
os.assert(trim.len > 0, "bytes.rtrim called with empty trim set");
let i: i32 = in.len - 1;
for (i >= 0 && contains(trim, in[i])) { i -= 1; };
let r: []u8;
r.ptr = in.ptr;
r.len = i + 1;
r.cap = r.len;
return r;
};
// trim — borrowed view of `in` with both ends in `trim` stripped.
// ref/hare/bytes/trim.ha:27.
export fn trim(in: []u8, trim: u8...) []u8 = {
return ltrim(rtrim(in, trim...), trim...);
};
// hasprefix — true iff `s` starts with `pre`.
// ref/hare/bytes/contains.ha:21.
export fn hasprefix(s: []u8, pre: []u8) bool = {

View File

@@ -1023,6 +1023,40 @@ export fn contains(s: []u8, needles: (u8 | []u8)...) bool = {
return false;
};
// ltrim — borrowed view of `in` with leading bytes in `trim` stripped.
// `trim` must be non-empty. ref/hare/bytes/trim.ha:7.
export fn ltrim(in: []u8, trim: u8...) []u8 = {
os.assert(trim.len > 0, "bytes.ltrim called with empty trim set");
let i: i32 = 0;
for (i < in.len && contains(trim, in[i])) { i += 1; };
let r: []u8;
r.ptr = in.ptr + (i: u64);
r.len = in.len - i;
r.cap = r.len;
return r;
};
// rtrim — borrowed view of `in` with trailing bytes in `trim` stripped.
// `trim` must be non-empty. ref/hare/bytes/trim.ha:17. Hare's loop uses
// `size` underflow at i==0 to terminate; ww indices are signed i32, so
// the equivalent termination is spelled `i >= 0` explicitly.
export fn rtrim(in: []u8, trim: u8...) []u8 = {
os.assert(trim.len > 0, "bytes.rtrim called with empty trim set");
let i: i32 = in.len - 1;
for (i >= 0 && contains(trim, in[i])) { i -= 1; };
let r: []u8;
r.ptr = in.ptr;
r.len = i + 1;
r.cap = r.len;
return r;
};
// trim — borrowed view of `in` with both ends in `trim` stripped.
// ref/hare/bytes/trim.ha:27.
export fn trim(in: []u8, trim: u8...) []u8 = {
return ltrim(rtrim(in, trim...), trim...);
};
// hasprefix — true iff `s` starts with `pre`.
// ref/hare/bytes/contains.ha:21.
export fn hasprefix(s: []u8, pre: []u8) bool = {