summaryrefslogtreecommitdiff
path: root/lib/internal/fs/read_file_context.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/internal/fs/read_file_context.js')
-rw-r--r--lib/internal/fs/read_file_context.js108
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/internal/fs/read_file_context.js b/lib/internal/fs/read_file_context.js
new file mode 100644
index 0000000000..b3e81a5db1
--- /dev/null
+++ b/lib/internal/fs/read_file_context.js
@@ -0,0 +1,108 @@
+'use strict';
+
+const { Buffer } = require('buffer');
+const { FSReqWrap, close, read } = process.binding('fs');
+
+const kReadFileBufferLength = 8 * 1024;
+
+function readFileAfterRead(err, bytesRead) {
+ const context = this.context;
+
+ if (err)
+ return context.close(err);
+
+ if (bytesRead === 0)
+ return context.close();
+
+ context.pos += bytesRead;
+
+ if (context.size !== 0) {
+ if (context.pos === context.size)
+ context.close();
+ else
+ context.read();
+ } else {
+ // unknown size, just read until we don't get bytes.
+ context.buffers.push(context.buffer.slice(0, bytesRead));
+ context.read();
+ }
+}
+
+function readFileAfterClose(err) {
+ const context = this.context;
+ const callback = context.callback;
+ let buffer = null;
+
+ if (context.err || err)
+ return callback(context.err || err);
+
+ try {
+ if (context.size === 0)
+ buffer = Buffer.concat(context.buffers, context.pos);
+ else if (context.pos < context.size)
+ buffer = context.buffer.slice(0, context.pos);
+ else
+ buffer = context.buffer;
+
+ if (context.encoding)
+ buffer = buffer.toString(context.encoding);
+ } catch (err) {
+ return callback(err);
+ }
+
+ callback(null, buffer);
+}
+
+class ReadFileContext {
+ constructor(callback, encoding) {
+ this.fd = undefined;
+ this.isUserFd = undefined;
+ this.size = undefined;
+ this.callback = callback;
+ this.buffers = null;
+ this.buffer = null;
+ this.pos = 0;
+ this.encoding = encoding;
+ this.err = null;
+ }
+
+ read() {
+ let buffer;
+ let offset;
+ let length;
+
+ if (this.size === 0) {
+ buffer = this.buffer = Buffer.allocUnsafeSlow(kReadFileBufferLength);
+ offset = 0;
+ length = kReadFileBufferLength;
+ } else {
+ buffer = this.buffer;
+ offset = this.pos;
+ length = Math.min(kReadFileBufferLength, this.size - this.pos);
+ }
+
+ const req = new FSReqWrap();
+ req.oncomplete = readFileAfterRead;
+ req.context = this;
+
+ read(this.fd, buffer, offset, length, -1, req);
+ }
+
+ close(err) {
+ const req = new FSReqWrap();
+ req.oncomplete = readFileAfterClose;
+ req.context = this;
+ this.err = err;
+
+ if (this.isUserFd) {
+ process.nextTick(function tick() {
+ req.oncomplete(null);
+ });
+ return;
+ }
+
+ close(this.fd, req);
+ }
+}
+
+module.exports = ReadFileContext;