mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
// charCodeAt at counted-loop counters and other proven integers: in-range
|
|
// reads, negative and past-the-end indices, non-ASCII and surrogate text,
|
|
// and counters near the 2^31 and 2^53 bounds. (4990-lone-surrogates covers
|
|
// lone surrogates.)
|
|
const texts = ["", "a", "plain ascii text", "caf\u00e9 cr\u00e8me", "emoji \ud83d\ude00 pair", "\u4e2d\u6587\u5b57"];
|
|
|
|
function codes(s: string): string {
|
|
let out = "";
|
|
for (let i = 0; i < s.length; i++) out += s.charCodeAt(i) + ",";
|
|
return out;
|
|
}
|
|
function inclusive(s: string): string {
|
|
let out = "";
|
|
for (let i = 0; i <= s.length; i++) out += s.charCodeAt(i) + ",";
|
|
return out;
|
|
}
|
|
function neighbours(s: string): string {
|
|
let out = "";
|
|
for (let i = 0; i < s.length; i++) out += `${s.charCodeAt(i - 1)}/${s.charCodeAt(i + 1)}/${s.charCodeAt(i * 2)},`;
|
|
return out;
|
|
}
|
|
function backwards(s: string): string {
|
|
let out = "";
|
|
for (let i = s.length - 1; i >= -2; i--) out += s.charCodeAt(i) + ",";
|
|
return out;
|
|
}
|
|
function hash(s: string): number {
|
|
let h = 0x811c9dc5 | 0;
|
|
for (let i = 0; i < s.length; i++) h = Math.imul(h ^ s.charCodeAt(i), 0x01000193);
|
|
return h >>> 0;
|
|
}
|
|
for (const s of texts) {
|
|
console.log(JSON.stringify(s), s.length, codes(s), inclusive(s), neighbours(s), backwards(s), hash(s));
|
|
}
|
|
|
|
// A counter that starts negative or at -0.
|
|
function fromStart(s: string, start: number): string {
|
|
let out = "";
|
|
for (let i = start; i < 3; i++) out += `${Object.is(i, -0) ? "-0" : i}:${s.charCodeAt(i)},`;
|
|
return out;
|
|
}
|
|
for (const start of [-3, -0, 0, 1]) console.log("start", start, fromStart("xyz", start), fromStart("", start));
|
|
|
|
// Counters far beyond any string length.
|
|
function wide(s: string, start: number): string {
|
|
let out = "";
|
|
let steps = 0;
|
|
for (let i = start; i < start + 4; i++) {
|
|
out += `${i}:${s.charCodeAt(i)}:${s.charCodeAt(i - start)},`;
|
|
if (++steps === 4) break;
|
|
}
|
|
return out;
|
|
}
|
|
for (const start of [2147483646, 4294967294, 9007199254740989]) console.log("wide", wide("abcd", start));
|
|
|
|
// Bounds derived from indexOf and length.
|
|
function afterSlash(path: string): number {
|
|
let sum = 0;
|
|
for (let i = path.indexOf("/") + 1; i < path.length; i++) sum += path.charCodeAt(i);
|
|
return sum;
|
|
}
|
|
function countDots(path: string): number {
|
|
const n = path.length;
|
|
let dots = 0;
|
|
for (let i = 0; i < n; i++) if (path.charCodeAt(i) === 46) dots++;
|
|
return dots;
|
|
}
|
|
for (const path of ["a/b.c", "/x/./y/../z", "no-slash", "", "\u00e9/\u00e8.\u00ea"]) {
|
|
console.log("path", JSON.stringify(path), afterSlash(path), countDots(path), path.indexOf("."), path.length);
|
|
}
|
|
|
|
// The receiver changes inside the loop.
|
|
function changing(seed: string): string {
|
|
let s = seed;
|
|
let out = "";
|
|
for (let i = 0; i < 6; i++) {
|
|
out += s.charCodeAt(i) + ",";
|
|
s = i % 2 === 0 ? s + "\u00df" : s.slice(1);
|
|
}
|
|
return out;
|
|
}
|
|
console.log("changing", changing("ab"), changing(""));
|