Skip to content

Commit b739413

Browse files
committed
buffer: add end parameter
To limit how far into the buffer we search without allocating an unnecessary subarray. PR-URL: #62390
1 parent 35fed19 commit b739413

File tree

5 files changed

+188
-55
lines changed

5 files changed

+188
-55
lines changed

doc/api/buffer.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,11 +2069,14 @@ console.log(buf.fill('zz', 'hex'));
20692069
// Throws an exception.
20702070
```
20712071

2072-
### `buf.includes(value[, byteOffset][, encoding])`
2072+
### `buf.includes(value[, byteOffset[, end]][, encoding])`
20732073

20742074
<!-- YAML
20752075
added: v5.3.0
20762076
changes:
2077+
- version: REPLACEME
2078+
pr-url: https://github.com/nodejs/node/pull/REPLACEME
2079+
description: Added the `end` parameter.
20772080
- version:
20782081
- v25.5.0
20792082
- v24.13.1
@@ -2084,6 +2087,8 @@ changes:
20842087
* `value` {string|Buffer|Uint8Array|integer} What to search for.
20852088
* `byteOffset` {integer} Where to begin searching in `buf`. If negative, then
20862089
offset is calculated from the end of `buf`. **Default:** `0`.
2090+
* `end` {integer} Where to stop searching in `buf` (exclusive). **Default:**
2091+
`buf.length`.
20872092
* `encoding` {string} If `value` is a string, this is its encoding.
20882093
**Default:** `'utf8'`.
20892094
* Returns: {boolean} `true` if `value` was found in `buf`, `false` otherwise.
@@ -2132,11 +2137,14 @@ console.log(buf.includes('this', 4));
21322137
// Prints: false
21332138
```
21342139

2135-
### `buf.indexOf(value[, byteOffset][, encoding])`
2140+
### `buf.indexOf(value[, start[, end]][, encoding])`
21362141

21372142
<!-- YAML
21382143
added: v1.5.0
21392144
changes:
2145+
- version: REPLACEME
2146+
pr-url: https://github.com/nodejs/node/pull/REPLACEME
2147+
description: Added the `end` parameter.
21402148
- version: v8.0.0
21412149
pr-url: https://github.com/nodejs/node/pull/10236
21422150
description: The `value` can now be a `Uint8Array`.
@@ -2149,8 +2157,10 @@ changes:
21492157
-->
21502158

21512159
* `value` {string|Buffer|Uint8Array|integer} What to search for.
2152-
* `byteOffset` {integer} Where to begin searching in `buf`. If negative, then
2160+
* `start` {integer} Where to begin searching in `buf`. If negative, then
21532161
offset is calculated from the end of `buf`. **Default:** `0`.
2162+
* `end` {integer} Where to stop searching in `buf` (exclusive). **Default:**
2163+
`buf.length`.
21542164
* `encoding` {string} If `value` is a string, this is the encoding used to
21552165
determine the binary representation of the string that will be searched for in
21562166
`buf`. **Default:** `'utf8'`.
@@ -2310,20 +2320,25 @@ for (const key of buf.keys()) {
23102320
// 5
23112321
```
23122322

2313-
### `buf.lastIndexOf(value[, byteOffset][, encoding])`
2323+
### `buf.lastIndexOf(value[, start[, end]][, encoding])`
23142324

23152325
<!-- YAML
23162326
added: v6.0.0
23172327
changes:
2328+
- version: REPLACEME
2329+
pr-url: https://github.com/nodejs/node/pull/62390
2330+
description: Added the `end` parameter.
23182331
- version: v8.0.0
23192332
pr-url: https://github.com/nodejs/node/pull/10236
23202333
description: The `value` can now be a `Uint8Array`.
23212334
-->
23222335

23232336
* `value` {string|Buffer|Uint8Array|integer} What to search for.
2324-
* `byteOffset` {integer} Where to begin searching in `buf`. If negative, then
2337+
* `start` {integer} Where to begin searching in `buf`. If negative, then
23252338
offset is calculated from the end of `buf`. **Default:**
23262339
`buf.length - 1`.
2340+
* `end` {integer} Where to stop searching in `buf` (exclusive). **Default:**
2341+
`buf.length`.
23272342
* `encoding` {string} If `value` is a string, this is the encoding used to
23282343
determine the binary representation of the string that will be searched for in
23292344
`buf`. **Default:** `'utf8'`.

lib/buffer.js

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -695,87 +695,91 @@ const encodingOps = {
695695
byteLength: byteLengthUtf8,
696696
write: utf8Write,
697697
slice: utf8Slice,
698-
indexOf: (buf, val, byteOffset, dir) =>
699-
indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir),
698+
indexOf: (buf, val, byteOffset, dir, end) =>
699+
indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir, end),
700700
},
701701
ucs2: {
702702
encoding: 'ucs2',
703703
encodingVal: encodingsMap.utf16le,
704704
byteLength: (string) => string.length * 2,
705705
write: ucs2Write,
706706
slice: ucs2Slice,
707-
indexOf: (buf, val, byteOffset, dir) =>
708-
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir),
707+
indexOf: (buf, val, byteOffset, dir, end) =>
708+
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir, end),
709709
},
710710
utf16le: {
711711
encoding: 'utf16le',
712712
encodingVal: encodingsMap.utf16le,
713713
byteLength: (string) => string.length * 2,
714714
write: ucs2Write,
715715
slice: ucs2Slice,
716-
indexOf: (buf, val, byteOffset, dir) =>
717-
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir),
716+
indexOf: (buf, val, byteOffset, dir, end) =>
717+
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir, end),
718718
},
719719
latin1: {
720720
encoding: 'latin1',
721721
encodingVal: encodingsMap.latin1,
722722
byteLength: (string) => string.length,
723723
write: latin1Write,
724724
slice: latin1Slice,
725-
indexOf: (buf, val, byteOffset, dir) =>
726-
indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir),
725+
indexOf: (buf, val, byteOffset, dir, end) =>
726+
indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir, end),
727727
},
728728
ascii: {
729729
encoding: 'ascii',
730730
encodingVal: encodingsMap.ascii,
731731
byteLength: (string) => string.length,
732732
write: asciiWrite,
733733
slice: asciiSlice,
734-
indexOf: (buf, val, byteOffset, dir) =>
734+
indexOf: (buf, val, byteOffset, dir, end) =>
735735
indexOfBuffer(buf,
736736
fromStringFast(val, encodingOps.ascii),
737737
byteOffset,
738738
encodingsMap.ascii,
739-
dir),
739+
dir,
740+
end),
740741
},
741742
base64: {
742743
encoding: 'base64',
743744
encodingVal: encodingsMap.base64,
744745
byteLength: (string) => base64ByteLength(string, string.length),
745746
write: base64Write,
746747
slice: base64Slice,
747-
indexOf: (buf, val, byteOffset, dir) =>
748+
indexOf: (buf, val, byteOffset, dir, end) =>
748749
indexOfBuffer(buf,
749750
fromStringFast(val, encodingOps.base64),
750751
byteOffset,
751752
encodingsMap.base64,
752-
dir),
753+
dir,
754+
end),
753755
},
754756
base64url: {
755757
encoding: 'base64url',
756758
encodingVal: encodingsMap.base64url,
757759
byteLength: (string) => base64ByteLength(string, string.length),
758760
write: base64urlWrite,
759761
slice: base64urlSlice,
760-
indexOf: (buf, val, byteOffset, dir) =>
762+
indexOf: (buf, val, byteOffset, dir, end) =>
761763
indexOfBuffer(buf,
762764
fromStringFast(val, encodingOps.base64url),
763765
byteOffset,
764766
encodingsMap.base64url,
765-
dir),
767+
dir,
768+
end),
766769
},
767770
hex: {
768771
encoding: 'hex',
769772
encodingVal: encodingsMap.hex,
770773
byteLength: (string) => string.length >>> 1,
771774
write: hexWrite,
772775
slice: hexSlice,
773-
indexOf: (buf, val, byteOffset, dir) =>
776+
indexOf: (buf, val, byteOffset, dir, end) =>
774777
indexOfBuffer(buf,
775778
fromStringFast(val, encodingOps.hex),
776779
byteOffset,
777780
encodingsMap.hex,
778-
dir),
781+
dir,
782+
end),
779783
},
780784
};
781785
function getEncodingOps(encoding) {
@@ -1029,9 +1033,10 @@ Buffer.prototype.compare = function compare(target,
10291033
// - buffer - a Buffer to search
10301034
// - val - a string, Buffer, or number
10311035
// - byteOffset - an index into `buffer`; will be clamped to an int32
1036+
// - end - absolute exclusive end of the search range
10321037
// - encoding - an optional encoding, relevant if val is a string
10331038
// - dir - true for indexOf, false for lastIndexOf
1034-
function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
1039+
function bidirectionalIndexOf(buffer, val, byteOffset, end, encoding, dir) {
10351040
validateBuffer(buffer);
10361041

10371042
if (typeof byteOffset === 'string') {
@@ -1051,7 +1056,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
10511056
dir = !!dir; // Cast to bool.
10521057

10531058
if (typeof val === 'number')
1054-
return indexOfNumber(buffer, val >>> 0, byteOffset, dir);
1059+
return indexOfNumber(buffer, val >>> 0, byteOffset, dir, end);
10551060

10561061
let ops;
10571062
if (encoding === undefined)
@@ -1062,30 +1067,48 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
10621067
if (typeof val === 'string') {
10631068
if (ops === undefined)
10641069
throw new ERR_UNKNOWN_ENCODING(encoding);
1065-
return ops.indexOf(buffer, val, byteOffset, dir);
1070+
return ops.indexOf(buffer, val, byteOffset, dir, end);
10661071
}
10671072

10681073
if (isUint8Array(val)) {
10691074
const encodingVal =
10701075
(ops === undefined ? encodingsMap.utf8 : ops.encodingVal);
1071-
return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir);
1076+
return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir, end);
10721077
}
10731078

10741079
throw new ERR_INVALID_ARG_TYPE(
10751080
'value', ['number', 'string', 'Buffer', 'Uint8Array'], val,
10761081
);
10771082
}
10781083

1079-
Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
1080-
return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
1084+
Buffer.prototype.indexOf = function indexOf(val, offset, end, encoding) {
1085+
if (typeof end === 'string') {
1086+
encoding = end;
1087+
end = this.length;
1088+
} else if (end === undefined) {
1089+
end = this.length;
1090+
}
1091+
return bidirectionalIndexOf(this, val, offset, end, encoding, true);
10811092
};
10821093

1083-
Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
1084-
return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
1094+
Buffer.prototype.lastIndexOf = function lastIndexOf(val, offset, end, encoding) {
1095+
if (typeof end === 'string') {
1096+
encoding = end;
1097+
end = this.length;
1098+
} else if (end === undefined) {
1099+
end = this.length;
1100+
}
1101+
return bidirectionalIndexOf(this, val, offset, end, encoding, false);
10851102
};
10861103

1087-
Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
1088-
return bidirectionalIndexOf(this, val, byteOffset, encoding, true) !== -1;
1104+
Buffer.prototype.includes = function includes(val, offset, end, encoding) {
1105+
if (typeof end === 'string') {
1106+
encoding = end;
1107+
end = this.length;
1108+
} else if (end === undefined) {
1109+
end = this.length;
1110+
}
1111+
return bidirectionalIndexOf(this, val, offset, end, encoding, true) !== -1;
10891112
};
10901113

10911114
// Usage:

0 commit comments

Comments
 (0)