lib/strings: add cut and rcut
This commit is contained in:
@@ -720,6 +720,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -1685,6 +1685,117 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// ---- cut / rcut -------------------------------------------------------
|
||||
// ref/hare/strings/tokenize.ha:316 (@test fn cut). str wrappers over
|
||||
// bytes.cut/rcut. The `let (a, b) = cut(...)` destructure drives the
|
||||
// over-cap tuple-return (sret) path end-to-end (a 2nd #10 witness).
|
||||
|
||||
@test fn cut_cases() void = {
|
||||
// both halves present.
|
||||
signalled = 1830;
|
||||
let (a0, b0) = strings.cut("hello=world", "=");
|
||||
if (!streq(a0, "hello")) { fail(); };
|
||||
if (!streq(b0, "world")) { fail(); };
|
||||
|
||||
// only first instance is cut; rest stays in the second half.
|
||||
signalled = 1831;
|
||||
let (a1, b1) = strings.cut("hello=world=foobar", "=");
|
||||
if (!streq(a1, "hello")) { fail(); };
|
||||
if (!streq(b1, "world=foobar")) { fail(); };
|
||||
|
||||
// delim absent -> (whole input, "").
|
||||
signalled = 1832;
|
||||
let (a2, b2) = strings.cut("hello world", "=");
|
||||
if (!streq(a2, "hello world")) { fail(); };
|
||||
if (!streq(b2, "")) { fail(); };
|
||||
|
||||
// delim at start -> empty before.
|
||||
signalled = 1833;
|
||||
let (a3, b3) = strings.cut("=world", "=");
|
||||
if (!streq(a3, "")) { fail(); };
|
||||
if (!streq(b3, "world")) { fail(); };
|
||||
|
||||
// delim at end -> empty after.
|
||||
signalled = 1834;
|
||||
let (a4, b4) = strings.cut("hello=", "=");
|
||||
if (!streq(a4, "hello")) { fail(); };
|
||||
if (!streq(b4, "")) { fail(); };
|
||||
|
||||
// empty input -> ("", "").
|
||||
signalled = 1835;
|
||||
let (a5, b5) = strings.cut("", "=");
|
||||
if (!streq(a5, "")) { fail(); };
|
||||
if (!streq(b5, "")) { fail(); };
|
||||
|
||||
// multi-byte delim present.
|
||||
signalled = 1836;
|
||||
let (a6, b6) = strings.cut("aXYbXYc", "XY");
|
||||
if (!streq(a6, "a")) { fail(); };
|
||||
if (!streq(b6, "bXYc")) { fail(); };
|
||||
|
||||
// multi-byte delim absent.
|
||||
signalled = 1837;
|
||||
let (a7, b7) = strings.cut("abc", "XY");
|
||||
if (!streq(a7, "abc")) { fail(); };
|
||||
if (!streq(b7, "")) { fail(); };
|
||||
|
||||
// borrowed, not copied: first half aliases the input bytes.
|
||||
signalled = 1838;
|
||||
let in: str = "hello=world";
|
||||
let (a8, b8) = strings.cut(in, "=");
|
||||
if (a8.ptr != in.ptr) { fail(); };
|
||||
};
|
||||
|
||||
@test fn rcut_cases() void = {
|
||||
// rcut splits along the LAST instance.
|
||||
signalled = 1840;
|
||||
let (a0, b0) = strings.rcut("hello=world=foobar", "=");
|
||||
if (!streq(a0, "hello=world")) { fail(); };
|
||||
if (!streq(b0, "foobar")) { fail(); };
|
||||
|
||||
// single instance == cut.
|
||||
signalled = 1841;
|
||||
let (a1, b1) = strings.rcut("hello=world", "=");
|
||||
if (!streq(a1, "hello")) { fail(); };
|
||||
if (!streq(b1, "world")) { fail(); };
|
||||
|
||||
// delim absent -> (whole input, "").
|
||||
signalled = 1842;
|
||||
let (a2, b2) = strings.rcut("hello world", "=");
|
||||
if (!streq(a2, "hello world")) { fail(); };
|
||||
if (!streq(b2, "")) { fail(); };
|
||||
|
||||
// delim at end -> empty after.
|
||||
signalled = 1843;
|
||||
let (a3, b3) = strings.rcut("hello=", "=");
|
||||
if (!streq(a3, "hello")) { fail(); };
|
||||
if (!streq(b3, "")) { fail(); };
|
||||
|
||||
// delim at start -> empty before.
|
||||
signalled = 1844;
|
||||
let (a4, b4) = strings.rcut("=world", "=");
|
||||
if (!streq(a4, "")) { fail(); };
|
||||
if (!streq(b4, "world")) { fail(); };
|
||||
|
||||
// empty input -> ("", "").
|
||||
signalled = 1845;
|
||||
let (a5, b5) = strings.rcut("", "=");
|
||||
if (!streq(a5, "")) { fail(); };
|
||||
if (!streq(b5, "")) { fail(); };
|
||||
|
||||
// multi-byte delim, two instances -> cut at LAST.
|
||||
signalled = 1846;
|
||||
let (a6, b6) = strings.rcut("XYaXYb", "XY");
|
||||
if (!streq(a6, "XYa")) { fail(); };
|
||||
if (!streq(b6, "b")) { fail(); };
|
||||
|
||||
// multi-byte delim absent.
|
||||
signalled = 1847;
|
||||
let (a7, b7) = strings.rcut("abc", "XY");
|
||||
if (!streq(a7, "abc")) { fail(); };
|
||||
if (!streq(b7, "")) { fail(); };
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
signalled = 1; dup_cases();
|
||||
signalled = 42; dupall_cases();
|
||||
@@ -1729,5 +1840,7 @@ export fn main() i32 = {
|
||||
signalled = 38; lpad_cases();
|
||||
signalled = 39; rpad_cases();
|
||||
signalled = 44; replace_cases();
|
||||
signalled = 45; cut_cases();
|
||||
signalled = 46; rcut_cases();
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -2588,6 +2588,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -2588,6 +2588,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -2697,6 +2697,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -2588,6 +2588,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -4105,6 +4105,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
@@ -4105,6 +4105,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
||||
return frombytes(bytes.remaining_tokens(b));
|
||||
};
|
||||
|
||||
// cut — split `in` along the first instance of `delim`, returning the
|
||||
// portions before and after it. When `delim` is absent the whole input
|
||||
// is the first half and the second is empty. Both halves are borrowed
|
||||
// from `in`; caller ensures `delim` is non-empty.
|
||||
// ref/hare/strings/tokenize.ha:288.
|
||||
export fn cut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.cut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rcut — like [[cut]] but split along the LAST instance of `delim`.
|
||||
// ref/hare/strings/tokenize.ha:302.
|
||||
export fn rcut(in: str, delim: str) (str, str) = {
|
||||
let (a, b) = bytes.rcut(toutf8(in), toutf8(delim));
|
||||
return (frombytes(a), frombytes(b));
|
||||
};
|
||||
|
||||
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||
|
||||
Reference in New Issue
Block a user