@wocker/core
Version:
Core of the Wocker
141 lines (140 loc) • 4.91 kB
JavaScript
"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;