Created
April 6, 2020 08:17
-
-
Save osdrv/e000165edeb14981f783ce4758fa6541 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require("fs") | |
const DefaultBlockSize = 4096 | |
function tail(fileName, nLines) { | |
return new Promise((resolve, reject) => { | |
fs.stat(fileName, (err, stat) => { | |
if (err != null) { | |
return reject(err) | |
} | |
if (nLines <= 0) { | |
return resolve([]) | |
} | |
let blksize = stat.blksize || DefaultBlockSize, | |
size = stat.size | |
fs.open(fileName, "r", (err, fd) => { | |
if (err != null) { | |
return reject(err) | |
} | |
let thumbstones = [size], | |
buf = Buffer.alloc(blksize) | |
let readNextBlock = (until) => { | |
if (until < 0) { | |
thumbstones.push(0) | |
return readNormal(fd, thumbstones, resolve, reject) | |
} | |
let toRead = Math.min(until, blksize), | |
from = until - toRead | |
fs.read(fd, buf, 0, toRead, from, (err, nBytes, buf) => { | |
if (err != null) { | |
return reject(err) | |
} | |
let i = nBytes - 1 | |
while (i >= 0) { | |
if (buf[i] == 10) { // \n | |
if (i > 0 && buf[i - 1] == 13) { // \r | |
i-- | |
} | |
if (thumbstones.length == 1 && | |
thumbstones[0] - (from + i) <= 1) { | |
thumbstones[0] = from + i | |
} else { | |
thumbstones.push(from + i) | |
} | |
if (thumbstones.length > nLines) { | |
return readNormal(fd, thumbstones, resolve, reject) | |
} | |
} | |
i-- | |
} | |
readNextBlock(from > 0 ? from : -1) | |
}) | |
} | |
readNextBlock(size) | |
}) | |
}) | |
}) | |
} | |
// eslint-disable-next-line | |
function readNormal(fd, thumbstones, resolve, reject) { | |
thumbstones = thumbstones.reverse() | |
let maxLen = 0 | |
for (let i = 0; i < thumbstones.length - 1; i++) { | |
let len = thumbstones[i + 1] - thumbstones[i] | |
if (len > maxLen) { | |
maxLen = len | |
} | |
} | |
let buf = Buffer.alloc(maxLen), | |
lines = [] | |
let readNextBlock = (ix) => { | |
if (ix >= thumbstones.length-1) { | |
return resolve(lines) | |
} | |
fs.read( | |
fd, | |
buf, | |
0, | |
thumbstones[ix + 1] - thumbstones[ix], | |
thumbstones[ix], | |
(err, nBytes, buf) => { | |
if (err != null) { | |
return reject(err) | |
} | |
let off = 0, | |
until = nBytes | |
while (off < nBytes - 1 && (buf[off] == 10 || buf[off] == 13)) { | |
off++ | |
} | |
while (until > off && (buf[off] == 10 || buf[off] == 13)) { | |
until-- | |
} | |
let line = buf.slice(off, until).toString("utf8") | |
lines.push(line) | |
readNextBlock(ix + 1) | |
} | |
) | |
} | |
readNextBlock(0) | |
} | |
module.exports.tail = tail |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment