Skip to content

Commit

Permalink
stream: augment BufferList.prototype
Browse files Browse the repository at this point in the history
Move functions that deal with `BufferList` to `BufferList.prototype`.

PR-URL: #18353
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
lpinca authored and BridgeAR committed Feb 1, 2018
1 parent 5898dc3 commit ccf64e5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 90 deletions.
92 changes: 2 additions & 90 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -987,106 +987,18 @@ function fromList(n, state) {
if (state.decoder)
ret = state.buffer.join('');
else if (state.buffer.length === 1)
ret = state.buffer.head.data;
ret = state.buffer.first();
else
ret = state.buffer.concat(state.length);
state.buffer.clear();
} else {
// read part of list
ret = fromListPartial(n, state.buffer, state.decoder);
ret = state.buffer.consume(n, state.decoder);
}

return ret;
}

// Extracts only enough buffered data to satisfy the amount requested.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function fromListPartial(n, list, hasStrings) {
var ret;
if (n < list.head.data.length) {
// slice is the same for buffers and strings
ret = list.head.data.slice(0, n);
list.head.data = list.head.data.slice(n);
} else if (n === list.head.data.length) {
// first chunk is a perfect match
ret = list.shift();
} else {
// result spans more than one buffer
ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
}
return ret;
}

// Copies a specified amount of characters from the list of buffered data
// chunks.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function copyFromBufferString(n, list) {
var p = list.head;
var c = 1;
var ret = p.data;
n -= ret.length;
while (p = p.next) {
const str = p.data;
const nb = (n > str.length ? str.length : n);
if (nb === str.length)
ret += str;
else
ret += str.slice(0, n);
n -= nb;
if (n === 0) {
if (nb === str.length) {
++c;
if (p.next)
list.head = p.next;
else
list.head = list.tail = null;
} else {
list.head = p;
p.data = str.slice(nb);
}
break;
}
++c;
}
list.length -= c;
return ret;
}

// Copies a specified amount of bytes from the list of buffered data chunks.
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function copyFromBuffer(n, list) {
const ret = Buffer.allocUnsafe(n);
var p = list.head;
var c = 1;
p.data.copy(ret);
n -= p.data.length;
while (p = p.next) {
const buf = p.data;
const nb = (n > buf.length ? buf.length : n);
buf.copy(ret, ret.length - n, 0, nb);
n -= nb;
if (n === 0) {
if (nb === buf.length) {
++c;
if (p.next)
list.head = p.next;
else
list.head = list.tail = null;
} else {
list.head = p;
p.data = buf.slice(nb);
}
break;
}
++c;
}
list.length -= c;
return ret;
}

function endReadable(stream) {
var state = stream._readableState;

Expand Down
85 changes: 85 additions & 0 deletions lib/internal/streams/BufferList.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,91 @@ module.exports = class BufferList {
return ret;
}

// Consumes a specified amount of bytes or characters from the buffered data.
consume(n, hasStrings) {
var ret;
if (n < this.head.data.length) {
// `slice` is the same for buffers and strings.
ret = this.head.data.slice(0, n);
this.head.data = this.head.data.slice(n);
} else if (n === this.head.data.length) {
// First chunk is a perfect match.
ret = this.shift();
} else {
// Result spans more than one buffer.
ret = hasStrings ? this._getString(n) : this._getBuffer(n);
}
return ret;
}

first() {
return this.head.data;
}

// Consumes a specified amount of characters from the buffered data.
_getString(n) {
var p = this.head;
var c = 1;
var ret = p.data;
n -= ret.length;
while (p = p.next) {
const str = p.data;
const nb = (n > str.length ? str.length : n);
if (nb === str.length)
ret += str;
else
ret += str.slice(0, n);
n -= nb;
if (n === 0) {
if (nb === str.length) {
++c;
if (p.next)
this.head = p.next;
else
this.head = this.tail = null;
} else {
this.head = p;
p.data = str.slice(nb);
}
break;
}
++c;
}
this.length -= c;
return ret;
}

// Consumes a specified amount of bytes from the buffered data.
_getBuffer(n) {
const ret = Buffer.allocUnsafe(n);
var p = this.head;
var c = 1;
p.data.copy(ret);
n -= p.data.length;
while (p = p.next) {
const buf = p.data;
const nb = (n > buf.length ? buf.length : n);
buf.copy(ret, ret.length - n, 0, nb);
n -= nb;
if (n === 0) {
if (nb === buf.length) {
++c;
if (p.next)
this.head = p.next;
else
this.head = this.tail = null;
} else {
this.head = p;
p.data = buf.slice(nb);
}
break;
}
++c;
}
this.length -= c;
return ret;
}

[inspect.custom]() {
const obj = inspect({ length: this.length });
return `${this.constructor.name} ${obj}`;
Expand Down

0 comments on commit ccf64e5

Please sign in to comment.