Skip to content

Commit 8d75e12

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 8d75e12

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

lib/internal/streams/readable.js

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

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

0 commit comments

Comments
 (0)