Skip to content

Commit 445df3f

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 bf1aebc commit 445df3f

File tree

5 files changed

+195
-58
lines changed

5 files changed

+195
-58
lines changed

doc/api/buffer.md

Lines changed: 21 additions & 6 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[, start[, end]][, encoding])`
20732073

20742074
<!-- YAML
20752075
added: v5.3.0
20762076
changes:
2077+
- version: REPLACEME
2078+
pr-url: https://github.com/nodejs/node/pull/62390
2079+
description: Added the `end` parameter.
20772080
- version:
20782081
- v25.5.0
20792082
- v24.13.1
@@ -2082,8 +2085,10 @@ changes:
20822085
-->
20832086

20842087
* `value` {string|Buffer|Uint8Array|integer} What to search for.
2085-
* `byteOffset` {integer} Where to begin searching in `buf`. If negative, then
2088+
* `start` {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/62390
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: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -700,83 +700,91 @@ const encodingOps = {
700700
byteLength: byteLengthUtf8,
701701
write: utf8Write,
702702
slice: utf8Slice,
703-
indexOf: (buf, val, byteOffset, dir) =>
704-
indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir),
703+
indexOf: (buf, val, byteOffset, dir, end) =>
704+
indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir, end),
705705
},
706706
ucs2: {
707707
encoding: 'ucs2',
708708
encodingVal: encodingsMap.utf16le,
709709
byteLength: (string) => string.length * 2,
710710
write: ucs2Write,
711711
slice: ucs2Slice,
712-
indexOf: (buf, val, byteOffset, dir) =>
713-
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir),
712+
indexOf: (buf, val, byteOffset, dir, end) =>
713+
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir, end),
714714
},
715715
utf16le: {
716716
encoding: 'utf16le',
717717
encodingVal: encodingsMap.utf16le,
718718
byteLength: (string) => string.length * 2,
719719
write: ucs2Write,
720720
slice: ucs2Slice,
721-
indexOf: (buf, val, byteOffset, dir) =>
722-
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir),
721+
indexOf: (buf, val, byteOffset, dir, end) =>
722+
indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir, end),
723723
},
724724
latin1: {
725725
encoding: 'latin1',
726726
encodingVal: encodingsMap.latin1,
727727
byteLength: (string) => string.length,
728728
write: latin1Write,
729729
slice: latin1Slice,
730-
indexOf: (buf, val, byteOffset, dir) =>
731-
indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir),
730+
indexOf: (buf, val, byteOffset, dir, end) =>
731+
indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir, end),
732732
},
733733
ascii: {
734734
encoding: 'ascii',
735735
encodingVal: encodingsMap.ascii,
736736
byteLength: (string) => string.length,
737737
write: asciiWrite,
738738
slice: asciiSlice,
739-
indexOf: (buf, val, byteOffset, dir) =>
740-
indexOfString(buf, val, byteOffset, encodingsMap.ascii, dir),
739+
indexOf: (buf, val, byteOffset, dir, end) =>
740+
indexOfBuffer(buf,
741+
fromStringFast(val, encodingOps.ascii),
742+
byteOffset,
743+
encodingsMap.ascii,
744+
dir,
745+
end),
741746
},
742747
base64: {
743748
encoding: 'base64',
744749
encodingVal: encodingsMap.base64,
745750
byteLength: (string) => base64ByteLength(string, string.length),
746751
write: base64Write,
747752
slice: base64Slice,
748-
indexOf: (buf, val, byteOffset, dir) =>
753+
indexOf: (buf, val, byteOffset, dir, end) =>
749754
indexOfBuffer(buf,
750755
fromStringFast(val, encodingOps.base64),
751756
byteOffset,
752757
encodingsMap.base64,
753-
dir),
758+
dir,
759+
end),
754760
},
755761
base64url: {
756762
encoding: 'base64url',
757763
encodingVal: encodingsMap.base64url,
758764
byteLength: (string) => base64ByteLength(string, string.length),
759765
write: base64urlWrite,
760766
slice: base64urlSlice,
761-
indexOf: (buf, val, byteOffset, dir) =>
767+
indexOf: (buf, val, byteOffset, dir, end) =>
762768
indexOfBuffer(buf,
763769
fromStringFast(val, encodingOps.base64url),
764770
byteOffset,
765771
encodingsMap.base64url,
766-
dir),
772+
dir,
773+
end),
767774
},
768775
hex: {
769776
encoding: 'hex',
770777
encodingVal: encodingsMap.hex,
771778
byteLength: (string) => string.length >>> 1,
772779
write: hexWrite,
773780
slice: hexSlice,
774-
indexOf: (buf, val, byteOffset, dir) =>
781+
indexOf: (buf, val, byteOffset, dir, end) =>
775782
indexOfBuffer(buf,
776783
fromStringFast(val, encodingOps.hex),
777784
byteOffset,
778785
encodingsMap.hex,
779-
dir),
786+
dir,
787+
end),
780788
},
781789
};
782790
function getEncodingOps(encoding) {
@@ -1030,9 +1038,10 @@ Buffer.prototype.compare = function compare(target,
10301038
// - buffer - a Buffer to search
10311039
// - val - a string, Buffer, or number
10321040
// - byteOffset - an index into `buffer`; will be clamped to an int32
1041+
// - end - absolute exclusive end of the search range
10331042
// - encoding - an optional encoding, relevant if val is a string
10341043
// - dir - true for indexOf, false for lastIndexOf
1035-
function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
1044+
function bidirectionalIndexOf(buffer, val, byteOffset, end, encoding, dir) {
10361045
validateBuffer(buffer);
10371046

10381047
if (typeof byteOffset === 'string') {
@@ -1052,7 +1061,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
10521061
dir = !!dir; // Cast to bool.
10531062

10541063
if (typeof val === 'number')
1055-
return indexOfNumber(buffer, val >>> 0, byteOffset, dir);
1064+
return indexOfNumber(buffer, val >>> 0, byteOffset, dir, end);
10561065

10571066
let ops;
10581067
if (encoding === undefined)
@@ -1063,30 +1072,48 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
10631072
if (typeof val === 'string') {
10641073
if (ops === undefined)
10651074
throw new ERR_UNKNOWN_ENCODING(encoding);
1066-
return ops.indexOf(buffer, val, byteOffset, dir);
1075+
return ops.indexOf(buffer, val, byteOffset, dir, end);
10671076
}
10681077

10691078
if (isUint8Array(val)) {
10701079
const encodingVal =
10711080
(ops === undefined ? encodingsMap.utf8 : ops.encodingVal);
1072-
return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir);
1081+
return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir, end);
10731082
}
10741083

10751084
throw new ERR_INVALID_ARG_TYPE(
10761085
'value', ['number', 'string', 'Buffer', 'Uint8Array'], val,
10771086
);
10781087
}
10791088

1080-
Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
1081-
return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
1089+
Buffer.prototype.indexOf = function indexOf(val, offset, end, encoding) {
1090+
if (typeof end === 'string') {
1091+
encoding = end;
1092+
end = this.length;
1093+
} else if (end === undefined) {
1094+
end = this.length;
1095+
}
1096+
return bidirectionalIndexOf(this, val, offset, end, encoding, true);
10821097
};
10831098

1084-
Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
1085-
return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
1099+
Buffer.prototype.lastIndexOf = function lastIndexOf(val, offset, end, encoding) {
1100+
if (typeof end === 'string') {
1101+
encoding = end;
1102+
end = this.length;
1103+
} else if (end === undefined) {
1104+
end = this.length;
1105+
}
1106+
return bidirectionalIndexOf(this, val, offset, end, encoding, false);
10861107
};
10871108

1088-
Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
1089-
return bidirectionalIndexOf(this, val, byteOffset, encoding, true) !== -1;
1109+
Buffer.prototype.includes = function includes(val, offset, end, encoding) {
1110+
if (typeof end === 'string') {
1111+
encoding = end;
1112+
end = this.length;
1113+
} else if (end === undefined) {
1114+
end = this.length;
1115+
}
1116+
return bidirectionalIndexOf(this, val, offset, end, encoding, true) !== -1;
10901117
};
10911118

10921119
// Usage:

0 commit comments

Comments
 (0)