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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; dup_cases();
|
signalled = 1; dup_cases();
|
||||||
signalled = 42; dupall_cases();
|
signalled = 42; dupall_cases();
|
||||||
@@ -1729,5 +1840,7 @@ export fn main() i32 = {
|
|||||||
signalled = 38; lpad_cases();
|
signalled = 38; lpad_cases();
|
||||||
signalled = 39; rpad_cases();
|
signalled = 39; rpad_cases();
|
||||||
signalled = 44; replace_cases();
|
signalled = 44; replace_cases();
|
||||||
|
signalled = 45; cut_cases();
|
||||||
|
signalled = 46; rcut_cases();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2588,6 +2588,23 @@ export fn remaining_tokens(s: *tokenizer) str = {
|
|||||||
return frombytes(bytes.remaining_tokens(b));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// 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));
|
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
|
// rt_ensure is the runtime slice-growth helper invoked by the
|
||||||
// `append(s, v)` builtin. Direct bind for the same reason as
|
// `append(s, v)` builtin. Direct bind for the same reason as
|
||||||
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
// lib/shlex.shlex (appendstr, 16B): the builtin's expansion stores
|
||||||
|
|||||||
Reference in New Issue
Block a user