Skip to content

Commit 16f7e07

Browse files
committed
stream: add Readable.readv
A faster alternative to Readable.read for certain use cases. e.g. fs.writevSync(fd, readable.readv())
1 parent 6176222 commit 16f7e07

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

lib/internal/streams/readable.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,73 @@ function howMuchToRead(n, state) {
641641
return (state[kState] & kEnded) !== 0 ? state.length : 0;
642642
}
643643

644+
Readable.prototype.readv = function () {
645+
const state = this._readableState;
646+
647+
state[kState] &= ~kEmittedReadable;
648+
649+
// if we need a readable event, then we need to do some reading.
650+
let doRead = (state[kState] & kNeedReadable) !== 0;
651+
652+
// If we currently have less than the highWaterMark, then also read some.
653+
if (state.length === 0 || state.length - n < state.highWaterMark) {
654+
doRead = true;
655+
}
656+
657+
// However, if we've ended, then there's no point, if we're already
658+
// reading, then it's unnecessary, if we're constructing we have to wait,
659+
// and if we're destroyed or errored, then it's not allowed,
660+
if ((state[kState] & (kReading | kEnded | kDestroyed | kErrored | kConstructed)) !== kConstructed) {
661+
doRead = false;
662+
} else if (doRead) {
663+
state[kState] |= kReading | kSync;
664+
// If the length is currently zero, then we *need* a readable event.
665+
if (state.length === 0)
666+
state[kState] |= kNeedReadable;
667+
668+
// Call internal read method
669+
try {
670+
this._read(state.highWaterMark);
671+
} catch (err) {
672+
errorOrDestroy(this, err);
673+
}
674+
state[kState] &= ~kSync;
675+
}
676+
677+
let ret = state.buffer;
678+
const ret = state.buffer.splice(state.bufferIndex);
679+
state.bufferIndex = 0;
680+
state.length = 0;
681+
682+
if (ret.length === 0) {
683+
state[kState] |= state.length <= state.highWaterMark ? kNeedReadable : 0;
684+
} else if ((state[kState] & kMultiAwaitDrain) !== 0) {
685+
state.awaitDrainWriters.clear();
686+
} else {
687+
state.awaitDrainWriters = null;
688+
}
689+
690+
if (state.length === 0) {
691+
// If we have nothing in the buffer, then we want to know
692+
// as soon as we *do* get something into the buffer.
693+
if ((state[kState] & kEnded) === 0)
694+
state[kState] |= kNeedReadable;
695+
696+
// If we tried to read() past the EOF, then emit end on the next tick.
697+
if ((state[kState] & kEnded) !== 0)
698+
endReadable(this);
699+
}
700+
701+
if (ret !== null && (state[kState] & (kErrorEmitted | kCloseEmitted)) === 0) {
702+
state[kState] |= kDataEmitted;
703+
for (let n = 0; n < ret.length; n++) {
704+
this.emit('data', ret[n]);
705+
}
706+
}
707+
708+
return ret;
709+
};
710+
644711
// You can override either this method, or the async _read(n) below.
645712
Readable.prototype.read = function(n) {
646713
debug('read', n);

0 commit comments

Comments
 (0)