| const bufLength = 1024 * 16; |
|
|
| |
| const td = |
| typeof TextDecoder !== 'undefined' |
| ? new TextDecoder() |
| : typeof Buffer !== 'undefined' |
| ? { |
| decode(buf: Uint8Array): string { |
| const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength); |
| return out.toString(); |
| }, |
| } |
| : { |
| decode(buf: Uint8Array): string { |
| let out = ''; |
| for (let i = 0; i < buf.length; i++) { |
| out += String.fromCharCode(buf[i]); |
| } |
| return out; |
| }, |
| }; |
|
|
| export class StringWriter { |
| pos = 0; |
| private out = ''; |
| private buffer = new Uint8Array(bufLength); |
|
|
| write(v: number): void { |
| const { buffer } = this; |
| buffer[this.pos++] = v; |
| if (this.pos === bufLength) { |
| this.out += td.decode(buffer); |
| this.pos = 0; |
| } |
| } |
|
|
| flush(): string { |
| const { buffer, out, pos } = this; |
| return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out; |
| } |
| } |
|
|
| export class StringReader { |
| pos = 0; |
| declare private buffer: string; |
|
|
| constructor(buffer: string) { |
| this.buffer = buffer; |
| } |
|
|
| next(): number { |
| return this.buffer.charCodeAt(this.pos++); |
| } |
|
|
| peek(): number { |
| return this.buffer.charCodeAt(this.pos); |
| } |
|
|
| indexOf(char: string): number { |
| const { buffer, pos } = this; |
| const idx = buffer.indexOf(char, pos); |
| return idx === -1 ? buffer.length : idx; |
| } |
| } |
|
|