Skip to content

Commit

Permalink
util: Add withBuffer function
Browse files Browse the repository at this point in the history
  • Loading branch information
remko committed Feb 18, 2024
1 parent c36e001 commit 30de653
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/tests/suite.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
decodeUlz as decodeUlz_,
encodeUlz as encodeUlz_,
withLineBuffer,
withBuffer,
} from "../util/index.js";

function asm(v) {
Expand Down Expand Up @@ -971,6 +972,42 @@ Da ba dee da ba di`,
expect(out).to.eql(["he"]);
});
});

describe("withBuffer", () => {
let writeBuffer;

beforeEach(() => {
out = [];
writeBuffer = withBuffer(writeOut);
});

it("should buffer ascii characters", () => {
writeBuffer("h".charCodeAt(0));
expect(out).to.eql(["h"]);
writeBuffer("e".charCodeAt(0));
expect(out).to.eql(["h", "e"]);
});

it("should buffer 2-byte utf-8 characters", () => {
writeBuffer(0xc3);
expect(out).to.eql([]);
writeBuffer(0xa7);
expect(out).to.eql(["ç"]);
writeBuffer("o".charCodeAt(0));
expect(out).to.eql(["ç", "o"]);
});

it("should buffer 4-byte utf-8 characters", () => {
writeBuffer(0xf0);
expect(out).to.eql([]);
writeBuffer(0x93);
expect(out).to.eql([]);
writeBuffer(0x80);
expect(out).to.eql([]);
writeBuffer(0x80);
expect(out).to.eql(["𓀀"]);
});
});
});
});
}
Expand Down
41 changes: 41 additions & 0 deletions src/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,47 @@ export function withLineBuffer(fn) {
return r;
}

/**
* Creates a function that accepts character codes in UTF-8 encoding, and calls
* the callback whenever a complete codepoint is received.
*
* @param {(line: string) => void} fn - The callback to call when a complete
* codepoint was received
* @returns {(c: number) => void} A function that accepts character codes in
* UTF-8 encoding.
*/
export function withBuffer(fn) {
/** @type {number[]} */
let buffer = [];
let n = 0;
const decoder = new TextDecoder();
return (/** @type {number} */ c) => {
if (n > 0) {
buffer.push(c);
n--;
if (n === 0) {
fn(decoder.decode(Uint8Array.from(buffer)));
buffer = [];
}
} else if ((c & 0x80) === 0x00) {
fn(String.fromCharCode(c));
} else {
buffer.push(c);
if ((c & 0xe0) === 0xc0) {
n = 1;
} else if ((c & 0xf0) === 0xe0) {
n = 2;
} else if ((c & 0xf8) === 0xf0) {
n = 3;
} else if ((c & 0xfc) === 0xf8) {
n = 4;
} else if ((c & 0xfe) === 0xfc) {
n = 5;
}
}
};
}

/** @returns {Device & {flush: () => void}} */
export function LogConsole() {
const out = withLineBuffer(console.log);
Expand Down

0 comments on commit 30de653

Please sign in to comment.