lib/bytes: add cut and rcut (#4)
Port bytes::cut / bytes::rcut from ref/hare/bytes/tokenize.ha:392,413. Both return borrowed (before, after) views split on the first / last delimiter instance; void-case yields (whole input, empty). Needle order is ww's (u8 | []u8), matching index/rindex (bytes.ww:57/91) rather than Hare's ([]u8 | u8). Unblocked by #10 (wide tuple-return / sret): ([]u8, []u8) is 48B, over-cap, returned via sret and received by the call-site destructure the tests exercise. combined.ww amalgamations regenerated (bytes is compiler-imported via strings).
This commit is contained in:
@@ -516,3 +516,57 @@ export fn rsplitn(in: []u8, delim: []u8, n: i32) [][]u8 = {
|
||||
export fn split(in: []u8, delim: []u8) [][]u8 = {
|
||||
return splitn(in, delim, types.I32_MAX);
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portion before and the portion after the delimiter as a borrowed
|
||||
// tuple. When `delim` is absent, the whole input is the first half and
|
||||
// the second is empty. ref/hare/bytes/tokenize.ha:392.
|
||||
//
|
||||
// Delim is spelled (u8 | []u8) to match index/rindex (bytes.ww:57/91);
|
||||
// the tagged union is an unordered set, so this is the same type as
|
||||
// Hare's ([]u8 | u8), not a divergence.
|
||||
export fn cut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = {
|
||||
let ln: i32 = match (delim) {
|
||||
case let c: u8 => yield 1i32;
|
||||
case let sub: []u8 => {
|
||||
os.assert(sub.len > 0,
|
||||
"bytes.cut called with empty delimiter");
|
||||
yield sub.len;
|
||||
};
|
||||
};
|
||||
match (index(in, delim)) {
|
||||
case let i: i32 => {
|
||||
let lo: i32 = i + ln;
|
||||
return (in[0:i], in[lo:in.len]);
|
||||
};
|
||||
case void => {
|
||||
let empty: []u8;
|
||||
empty.ptr = nil; empty.len = 0; empty.cap = 0;
|
||||
return (in, empty);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but splits along the last instance of `delim`.
|
||||
// ref/hare/bytes/tokenize.ha:413.
|
||||
export fn rcut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = {
|
||||
let ln: i32 = match (delim) {
|
||||
case let c: u8 => yield 1i32;
|
||||
case let sub: []u8 => {
|
||||
os.assert(sub.len > 0,
|
||||
"bytes.rcut called with empty delimiter");
|
||||
yield sub.len;
|
||||
};
|
||||
};
|
||||
match (rindex(in, delim)) {
|
||||
case let i: i32 => {
|
||||
let lo: i32 = i + ln;
|
||||
return (in[0:i], in[lo:in.len]);
|
||||
};
|
||||
case void => {
|
||||
let empty: []u8;
|
||||
empty.ptr = nil; empty.len = 0; empty.cap = 0;
|
||||
return (in, empty);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user