Skip to content

Commit 23a8bca

Browse files
committed
buffer: simplify Buffer.concat
Signed-off-by: Richard Gibson <richard.gibson@gmail.com>
1 parent 29d183d commit 23a8bca

1 file changed

Lines changed: 35 additions & 50 deletions

File tree

lib/buffer.js

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -616,66 +616,51 @@ Buffer.concat = function concat(list, length) {
616616
if (list.length === 0)
617617
return new FastBuffer();
618618

619-
if (length === undefined) {
619+
const autoLength = length === undefined;
620+
if (autoLength) {
620621
length = 0;
621-
for (let i = 0; i < list.length; i++) {
622-
const buf = list[i];
623-
if (!isUint8Array(buf)) {
624-
// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
625-
// Instead, find the proper error code for this.
626-
throw new ERR_INVALID_ARG_TYPE(
627-
`list[${i}]`, ['Buffer', 'Uint8Array'], buf);
628-
}
629-
length += TypedArrayPrototypeGetByteLength(buf);
630-
}
631-
632-
const buffer = allocate(length);
633-
let pos = 0;
634-
for (let i = 0; i < list.length; i++) {
635-
const buf = list[i];
636-
const bufLength = TypedArrayPrototypeGetByteLength(buf);
637-
TypedArrayPrototypeSet(buffer, buf, pos);
638-
pos += bufLength;
639-
}
640-
641-
if (pos < length) {
642-
TypedArrayPrototypeFill(buffer, 0, pos, length);
643-
}
644-
return buffer;
622+
} else {
623+
validateOffset(length, 'length');
645624
}
646625

647-
validateOffset(length, 'length');
648-
for (let i = 0; i < list.length; i++) {
649-
if (!isUint8Array(list[i])) {
650-
// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
651-
// Instead, find the proper error code for this.
652-
throw new ERR_INVALID_ARG_TYPE(
653-
`list[${i}]`, ['Buffer', 'Uint8Array'], list[i]);
626+
let i = 0;
627+
let j = 0;
628+
let pos = 0;
629+
const postPositions = new Array(list.length);
630+
try {
631+
for (; i < list.length; i++) {
632+
pos += TypedArrayPrototypeGetByteLength(list[i]);
633+
postPositions[i] = pos;
634+
j += pos <= length;
654635
}
636+
} catch {
637+
// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
638+
// Instead, find the proper error code for this.
639+
throw new ERR_INVALID_ARG_TYPE(
640+
`list[${i}]`, ['Buffer', 'Uint8Array'], list[i]);
641+
}
642+
if (autoLength) {
643+
length = pos;
644+
j = list.length;
655645
}
656646

657647
const buffer = allocate(length);
658-
let pos = 0;
659-
for (let i = 0; i < list.length; i++) {
660-
const buf = list[i];
661-
const bufLength = TypedArrayPrototypeGetByteLength(buf);
662-
if (pos + bufLength > length) {
663-
TypedArrayPrototypeSet(buffer,
664-
TypedArrayPrototypeSubarray(buf, 0, length - pos),
665-
pos);
666-
pos = length;
667-
break;
668-
}
669-
TypedArrayPrototypeSet(buffer, buf, pos);
670-
pos += bufLength;
648+
// Copy from every input that fits completely.
649+
for (pos = i = 0; i < j; i++) {
650+
TypedArrayPrototypeSet(buffer, list[i], pos);
651+
pos = postPositions[i];
671652
}
672653

673-
// Note: `length` is always equal to `buffer.length` at this point
674654
if (pos < length) {
675-
// Zero-fill the remaining bytes if the specified `length` was more than
676-
// the actual total length, i.e. if we have some remaining allocated bytes
677-
// there were not initialized.
678-
TypedArrayPrototypeFill(buffer, 0, pos, length);
655+
// Populate the remaining bytes, either by partially consuming the next
656+
// input or by zero-filling.
657+
if (j < list.length) {
658+
TypedArrayPrototypeSet(buffer,
659+
TypedArrayPrototypeSubarray(list[j], 0, length - pos),
660+
pos);
661+
} else {
662+
TypedArrayPrototypeFill(buffer, 0, pos, length);
663+
}
679664
}
680665

681666
return buffer;

0 commit comments

Comments
 (0)