ww: import toolchain — C bootstrap + ww-side self-host (phases 0-10)
C bootstrap (phases 0-9):
cmd/wwc, cmd/6c, cmd/6a, cmd/6l, cmd/ww, rt, lib/*.
ww-side self-host (phase 10):
selfhost/cmd/wwc — ww-cgen frontend; bootstrap fixed point.
selfhost/cmd/6a — assembler; byte-identical to C 6a (test 991).
selfhost/cmd/6l — linker w/ archive (.a) support; byte-identical
to C 6l (test 992).
selfhost/cmd/ww — driver (build/run/version); byte-identical to
C ww (test 993).
make test: 15/15. make bootstrap: ww2.s == ww3.s, ww2.o == ww3.o,
ww2 == ww3 byte-identical, with the full ww-tooled chain.
This commit is contained in:
95
lib/strings/strings.ww
Normal file
95
lib/strings/strings.ww
Normal file
@@ -0,0 +1,95 @@
|
||||
// strings — operations over the immutable str type ({ *u8, len }).
|
||||
|
||||
use os;
|
||||
|
||||
export fn len(s: str) i32 = {
|
||||
return s.len;
|
||||
};
|
||||
|
||||
export fn isempty(s: str) bool = {
|
||||
return s.len == 0;
|
||||
};
|
||||
|
||||
export fn equal(a: str, b: str) bool = {
|
||||
if (a.len != b.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
for (i < a.len) {
|
||||
if (a[i] != b[i]) { return false; };
|
||||
i += 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
export fn hasprefix(s: str, p: str) bool = {
|
||||
if (p.len > s.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
for (i < p.len) {
|
||||
if (s[i] != p[i]) { return false; };
|
||||
i += 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
export fn hassuffix(s: str, suf: str) bool = {
|
||||
if (suf.len > s.len) { return false; };
|
||||
let off: i32 = s.len - suf.len;
|
||||
let i: i32 = 0;
|
||||
for (i < suf.len) {
|
||||
if (s[off + i] != suf[i]) { return false; };
|
||||
i += 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
// indexbyte — first index of `c` in `s`, or -1 if absent. Plan 9-
|
||||
// style sentinel return; callers that prefer a fallible shape can
|
||||
// wrap this in their own (i32 | str). No allocation.
|
||||
export fn indexbyte(s: str, c: u8) i32 = {
|
||||
let i: i32 = 0;
|
||||
for (i < s.len) {
|
||||
if (s[i] == c) { return i; };
|
||||
i += 1;
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
// index — first index of `sub` in `s`, or -1. Naive scan; fine for
|
||||
// short patterns and small strings, which dominate config and CLI
|
||||
// parsing. Empty `sub` matches at 0.
|
||||
export fn index(s: str, sub: str) i32 = {
|
||||
if (sub.len == 0) { return 0; };
|
||||
if (sub.len > s.len) { return -1; };
|
||||
let last: i32 = s.len - sub.len;
|
||||
let i: i32 = 0;
|
||||
for (i <= last) {
|
||||
let j: i32 = 0;
|
||||
let ok: bool = true;
|
||||
for (j < sub.len) {
|
||||
if (s[i + j] != sub[j]) { ok = false; j = sub.len; }
|
||||
else { j += 1; };
|
||||
};
|
||||
if (ok) { return i; };
|
||||
i += 1;
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
export fn contains(s: str, sub: str) bool = {
|
||||
return index(s, sub) >= 0;
|
||||
};
|
||||
|
||||
// concat — joins two strings into a fresh str. Caller owns the
|
||||
// returned str's storage; release via `os.free(r.ptr, r.len)`. Mirrors
|
||||
// Hare's strings::concat shape.
|
||||
export fn concat(a: str, b: str) str = {
|
||||
let total: i32 = a.len + b.len;
|
||||
let buf: *u8 = os.alloc(total: u64): *u8;
|
||||
let i: i32 = 0;
|
||||
for (i < a.len) { buf[i] = a[i]; i += 1; };
|
||||
let j: i32 = 0;
|
||||
for (j < b.len) { buf[a.len + j] = b[j]; j += 1; };
|
||||
let r: str;
|
||||
r.ptr = buf;
|
||||
r.len = total;
|
||||
return r;
|
||||
};
|
||||
Reference in New Issue
Block a user