stream: augment BufferList.prototype
Move functions that deal with `BufferList` to `BufferList.prototype`. PR-URL: https://github.com/nodejs/node/pull/18353 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
parent
5898dc3d0c
commit
ccf64e5f22
@ -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;
|
||||
|
||||
|
@ -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}`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user