UNPKG

@wocker/core

Version:
141 lines (140 loc) 4.91 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.File = void 0; const fs_1 = __importDefault(require("fs")); const stream_1 = require("stream"); const readline_1 = require("readline"); class File { constructor(path, flags = "r", mode, driver = fs_1.default) { this.path = path; this.flags = flags; this.mode = mode; this.driver = driver; this._closed = true; this.open(); } get fd() { return this._fd; } get closed() { return this._closed; } open() { if (!this.closed) { return; } this._fd = this.driver.openSync(this.path, this.flags, this.mode); this._closed = false; } stat() { return this.driver.fstatSync(this.fd); } close() { if (this.closed) { return; } this.driver.closeSync(this.fd); this._closed = true; } createReadStream(options) { const stream = this.driver.createReadStream(this.path, Object.assign(Object.assign({}, options || {}), { fd: this.fd, autoClose: false, emitClose: false })); stream.on("close", () => { this._closed = true; }); return stream; } createReadlineStream(options) { let { start, end, encoding } = options || {}; const startLine = typeof start !== "undefined" ? this.getLinePosition(start) : undefined; const endLine = typeof end !== "undefined" ? this.getLinePosition(end) : undefined; const stream = this.createReadStream({ encoding: encoding, start: startLine, end: endLine }); const outputStream = new stream_1.Readable({ objectMode: true, read() { } }); const readline = (0, readline_1.createInterface)({ input: stream, crlfDelay: Infinity }); readline.on("line", (line) => { outputStream.push(line); }); readline.on("close", () => { outputStream.push(null); }); readline.on("error", (err) => { outputStream.emit("error", err); }); stream.on("error", (err) => { outputStream.emit("error", err); }); return outputStream; } readBytes(position = 0, size) { const stats = this.stat(); if (position < 0 && typeof size === "undefined") { size = position * -1; position = stats.size - size; } else if (typeof size === "undefined") { size = stats.size - position; } if (size <= 0) { return Buffer.alloc(0); } const buffer = Buffer.alloc(size); this.driver.readSync(this.fd, buffer, 0, size, position); return buffer; } getLinePosition(line) { var _a, _b; if (line === 0) { throw new Error("Line number must be a non-zero"); } const bufferSize = 1024, isForward = line > 0, targetLine = Math.abs(line), stats = this.stat(); let position = isForward ? 0 : stats.size, currentLine = 0, currentOffset = isForward ? 0 : stats.size + 1, stump = ""; while (isForward ? position < stats.size : position > 0) { const readSize = isForward ? Math.min(bufferSize, stats.size - position) : Math.min(bufferSize, position); if (!isForward) { position -= readSize; } const chunk = this.readBytes(position, readSize).toString(), lines = (isForward ? stump + chunk : chunk + stump).split("\n"); if (isForward) { position += readSize; } if (isForward ? position === stats.size : position === 0) { stump = ""; } else { stump = isForward ? (_a = lines.pop()) !== null && _a !== void 0 ? _a : "" : (_b = lines.shift()) !== null && _b !== void 0 ? _b : ""; } for (let i = isForward ? 0 : lines.length - 1; isForward ? i < lines.length : i >= 0; isForward ? i++ : i--) { const lineLength = Buffer.byteLength(`${lines[i]}\n`); currentLine++; if (currentLine === targetLine) { return isForward ? currentOffset : currentOffset - lineLength; } currentOffset += isForward ? lineLength : -lineLength; } } return isForward ? Math.min(currentOffset, stats.size) : Math.max(currentOffset, 0); } } exports.File = File;