rockstar-playground/node_modules/n-readlines/readlines.js
2020-12-06 15:26:29 -05:00

159 lines
3.9 KiB
JavaScript

'use strict';
const fs = require('fs');
/**
* @class
*/
class LineByLine {
constructor(file, options) {
options = options || {};
if (!options.readChunk) options.readChunk = 1024;
if (!options.newLineCharacter) {
options.newLineCharacter = 0x0a; //linux line ending
} else {
options.newLineCharacter = options.newLineCharacter.charCodeAt(0);
}
if (typeof file === 'number') {
this.fd = file;
} else {
this.fd = fs.openSync(file, 'r');
}
this.options = options;
this.newLineCharacter = options.newLineCharacter;
this.reset();
}
_searchInBuffer(buffer, hexNeedle) {
let found = -1;
for (let i = 0; i <= buffer.length; i++) {
let b_byte = buffer[i];
if (b_byte === hexNeedle) {
found = i;
break;
}
}
return found;
}
reset() {
this.eofReached = false;
this.linesCache = [];
this.fdPosition = 0;
}
close() {
fs.closeSync(this.fd);
this.fd = null;
}
_extractLines(buffer) {
let line;
const lines = [];
let bufferPosition = 0;
let lastNewLineBufferPosition = 0;
while (true) {
let bufferPositionValue = buffer[bufferPosition++];
if (bufferPositionValue === this.newLineCharacter) {
line = buffer.slice(lastNewLineBufferPosition, bufferPosition);
lines.push(line);
lastNewLineBufferPosition = bufferPosition;
} else if (bufferPositionValue === undefined) {
break;
}
}
let leftovers = buffer.slice(lastNewLineBufferPosition, bufferPosition);
if (leftovers.length) {
lines.push(leftovers);
}
return lines;
};
_readChunk(lineLeftovers) {
let totalBytesRead = 0;
let bytesRead;
const buffers = [];
do {
const readBuffer = new Buffer(this.options.readChunk);
bytesRead = fs.readSync(this.fd, readBuffer, 0, this.options.readChunk, this.fdPosition);
totalBytesRead = totalBytesRead + bytesRead;
this.fdPosition = this.fdPosition + bytesRead;
buffers.push(readBuffer);
} while (bytesRead && this._searchInBuffer(buffers[buffers.length-1], this.options.newLineCharacter) === -1);
let bufferData = Buffer.concat(buffers);
if (bytesRead < this.options.readChunk) {
this.eofReached = true;
bufferData = bufferData.slice(0, totalBytesRead);
}
if (totalBytesRead) {
this.linesCache = this._extractLines(bufferData);
if (lineLeftovers) {
this.linesCache[0] = Buffer.concat([lineLeftovers, this.linesCache[0]]);
}
}
return totalBytesRead;
}
next() {
if (!this.fd) return false;
let line = false;
if (this.eofReached && this.linesCache.length === 0) {
return line;
}
let bytesRead;
if (!this.linesCache.length) {
bytesRead = this._readChunk();
}
if (this.linesCache.length) {
line = this.linesCache.shift();
const lastLineCharacter = line[line.length-1];
if (lastLineCharacter !== this.newLineCharacter) {
bytesRead = this._readChunk(line);
if (bytesRead) {
line = this.linesCache.shift();
}
}
}
if (this.eofReached && this.linesCache.length === 0) {
this.close();
}
if (line && line[line.length-1] === this.newLineCharacter) {
line = line.slice(0, line.length-1);
}
return line;
}
}
module.exports = LineByLine;