lib/bytes+test: Hare port (equal / index / rindex / contains / has{prefix,suffix} / reverse / zero)
Mirrors ref/hare/bytes/{equal,index,contains,reverse,zero}.ha for
the in-tree subset used by lib/encoding, lib/bufio, lib/memio;
converts 4 hextest sites from local beq to bytes.equal and drops
the now-dead beq in utf8test.
Surface:
- equal(a, b: []u8) bool
- index(s: []u8, needle: (u8 | []u8)) (i32 | void)
- rindex(s: []u8, needle: (u8 | []u8)) (i32 | void)
- contains(s: []u8, needle: (u8 | []u8)) bool
- hasprefix(s, pre: []u8) bool
- hassuffix(s, suf: []u8) bool
- reverse(s: []u8) void (already present, citation added)
- zero(s: []u8) void (already present, citation added)
Two documented Hare-fidelity gaps (cited in lib/bytes/bytes.ww
header, no in-tree caller demands them yet):
- index_slice / rindex_slice use naive O(n·m). Hare specialises
2/3/4-byte needles + falls back to Crochemore-Perrin two-way
(ref/hare/bytes/two_way.ha). Correctness equivalent.
- contains takes a single needle. Hare uses variadic
needle: (u8 | []u8)... (ref/hare/bytes/contains.ha:5).
Tests: 967_bytes_run drives lib/bytes/bytestest.ww via ww run.
Eight @test fns × table-driven row sets: equal (5), index_byte
(5), index_slice (10), rindex_byte (3), rindex_slice (3),
contains (4), hasprefix (6 verbatim from contains.ha:25),
hassuffix (6 verbatim from contains.ha:40).
Call-site conversions in the same commit (the conversions are
the proof the API is wired): lib/encoding/hex/hextest.ww drops
the local beq helper and 4 callers switch to bytes.equal;
lib/encoding/utf8/utf8test.ww drops the dead beq helper.
91/91 ok. 995_self_rebuild stays green (ww2==ww3==ww4 byte-id).
This commit is contained in:
@@ -1,18 +1,31 @@
|
||||
// bytes — slice operations over []u8.
|
||||
// bytes — slice operations over []u8. Mirrors Hare's bytes module
|
||||
// (ref/hare/bytes/) for the in-tree subset: search/equality/prefix
|
||||
// helpers used by lib/encoding, lib/bufio, lib/memio.
|
||||
//
|
||||
// Documented divergences from Hare:
|
||||
// - index_slice / rindex_slice use naive O(n·m); Hare specialises
|
||||
// 2/3/4-byte needles and falls back to two_way (Crochemore-Perrin)
|
||||
// for longer (ref/hare/bytes/index.ha:61, ref/hare/bytes/two_way.ha).
|
||||
// Correctness equivalent.
|
||||
// - contains takes a single needle; Hare's contains is variadic
|
||||
// `(u8 | []u8)...` (ref/hare/bytes/contains.ha:5). No caller needs
|
||||
// the variadic shape yet; graduate when one does.
|
||||
|
||||
// equal — true iff `a` and `b` have the same length and contents.
|
||||
// ref/hare/bytes/equal.ha:9.
|
||||
export fn equal(a: []u8, b: []u8) bool = {
|
||||
if (a.len != b.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
for (i < a.len) {
|
||||
if (i >= b.len) { return false; };
|
||||
if (a[i] != b[i]) { return false; };
|
||||
i += 1;
|
||||
};
|
||||
return i == b.len;
|
||||
return true;
|
||||
};
|
||||
|
||||
// index — first index of `needle` in `s`. Mirrors Hare's bytes::index:
|
||||
// `u8` needle scans for the byte, `[]u8` needle scans for the
|
||||
// substring. Returns void if absent.
|
||||
// index — first offset of `needle` in `s`. u8 needle scans for the
|
||||
// byte; []u8 needle scans for the substring. void if absent.
|
||||
// ref/hare/bytes/index.ha:6.
|
||||
export fn index(s: []u8, needle: (u8 | []u8)) (i32 | void) = {
|
||||
match (needle) {
|
||||
case let c: u8 => {
|
||||
@@ -44,8 +57,9 @@ export fn index(s: []u8, needle: (u8 | []u8)) (i32 | void) = {
|
||||
return;
|
||||
};
|
||||
|
||||
// rindex — last index of `needle` in `s`. Mirrors Hare's bytes::rindex.
|
||||
// Empty []u8 needle matches at s.len.
|
||||
// rindex — last offset of `needle` in `s`. Empty []u8 needle returns
|
||||
// s.len (ref/hare/bytes/index.ha:103 — Hare's loop yields r-0 at i=0).
|
||||
// ref/hare/bytes/index.ha:86.
|
||||
export fn rindex(s: []u8, needle: (u8 | []u8)) (i32 | void) = {
|
||||
match (needle) {
|
||||
case let c: u8 => {
|
||||
@@ -76,18 +90,18 @@ export fn rindex(s: []u8, needle: (u8 | []u8)) (i32 | void) = {
|
||||
return;
|
||||
};
|
||||
|
||||
// contains — true iff `sub` appears in `s`. Mirrors Hare's
|
||||
// bytes::contains for the slice case.
|
||||
export fn contains(s: []u8, sub: []u8) bool = {
|
||||
let r: (i32 | void) = index(s, sub);
|
||||
match (r) {
|
||||
// contains — true iff `needle` (byte or sub-slice) appears in `s`.
|
||||
// ref/hare/bytes/contains.ha:5 (variadic subset; see header note).
|
||||
export fn contains(s: []u8, needle: (u8 | []u8)) bool = {
|
||||
match (index(s, needle)) {
|
||||
case let i: i32 => return true;
|
||||
case void => return false;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// hasprefix — `s` starts with `pre`. Mirrors Hare's bytes::hasprefix.
|
||||
// hasprefix — true iff `s` starts with `pre`.
|
||||
// ref/hare/bytes/contains.ha:21.
|
||||
export fn hasprefix(s: []u8, pre: []u8) bool = {
|
||||
if (pre.len > s.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
@@ -98,7 +112,8 @@ export fn hasprefix(s: []u8, pre: []u8) bool = {
|
||||
return true;
|
||||
};
|
||||
|
||||
// hassuffix — `s` ends with `suf`. Mirrors Hare's bytes::hassuffix.
|
||||
// hassuffix — true iff `s` ends with `suf`.
|
||||
// ref/hare/bytes/contains.ha:35.
|
||||
export fn hassuffix(s: []u8, suf: []u8) bool = {
|
||||
if (suf.len > s.len) { return false; };
|
||||
let off: i32 = s.len - suf.len;
|
||||
@@ -110,7 +125,7 @@ export fn hassuffix(s: []u8, suf: []u8) bool = {
|
||||
return true;
|
||||
};
|
||||
|
||||
// reverse — in-place reverse of `s`. Mirrors Hare's bytes::reverse.
|
||||
// reverse — in-place reverse of `s`. ref/hare/bytes/reverse.ha:5.
|
||||
export fn reverse(s: []u8) void = {
|
||||
let i: i32 = 0;
|
||||
let j: i32 = s.len - 1;
|
||||
@@ -123,7 +138,7 @@ export fn reverse(s: []u8) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// zero — set every byte of `s` to 0. Mirrors Hare's bytes::zero.
|
||||
// zero — set every byte of `s` to 0. ref/hare/bytes/zero.ha:5.
|
||||
export fn zero(s: []u8) void = {
|
||||
let i: i32 = 0;
|
||||
for (i < s.len) {
|
||||
|
||||
Reference in New Issue
Block a user