2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2022-11-29 06:01:21 +00:00
|
|
|
// This module is browser compatible.
|
|
|
|
|
2024-04-16 06:59:52 +00:00
|
|
|
/**
|
|
|
|
* Returns the index of the first occurrence of the needle array in the source
|
2022-11-29 06:01:21 +00:00
|
|
|
* array, or -1 if it is not present.
|
|
|
|
*
|
|
|
|
* A start index can be specified as the third argument that begins the search
|
|
|
|
* at that given index. The start index defaults to the start of the array.
|
|
|
|
*
|
2024-04-16 06:59:52 +00:00
|
|
|
* The complexity of this function is `O(source.length * needle.length)`.
|
2022-11-29 06:01:21 +00:00
|
|
|
*
|
2024-04-16 06:59:52 +00:00
|
|
|
* @param source Source array to check.
|
|
|
|
* @param needle Needle array to check for.
|
|
|
|
* @param start Start index in the source array to begin the search. Defaults to
|
|
|
|
* 0.
|
2024-04-22 07:07:34 +00:00
|
|
|
* @returns Index of the first occurrence of the needle array in the source
|
|
|
|
* array, or -1 if it is not present.
|
2024-04-16 06:59:52 +00:00
|
|
|
*
|
|
|
|
* @example Basic usage
|
2022-11-29 06:01:21 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { indexOfNeedle } from "@std/bytes/index-of-needle";
|
2024-05-08 06:18:26 +00:00
|
|
|
* import { assertEquals } from "@std/assert/assert-equals";
|
2024-04-16 06:59:52 +00:00
|
|
|
*
|
2022-11-29 06:01:21 +00:00
|
|
|
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
|
|
|
* const needle = new Uint8Array([1, 2]);
|
2024-04-16 06:59:52 +00:00
|
|
|
* const notNeedle = new Uint8Array([5, 0]);
|
|
|
|
*
|
2024-05-08 06:18:26 +00:00
|
|
|
* assertEquals(indexOfNeedle(source, needle), 1);
|
|
|
|
* assertEquals(indexOfNeedle(source, notNeedle), -1);
|
2024-04-16 06:59:52 +00:00
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @example Start index
|
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { indexOfNeedle } from "@std/bytes/index-of-needle";
|
2024-05-08 06:18:26 +00:00
|
|
|
* import { assertEquals } from "@std/assert/assert-equals";
|
2024-04-16 06:59:52 +00:00
|
|
|
*
|
|
|
|
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
|
|
|
* const needle = new Uint8Array([1, 2]);
|
|
|
|
*
|
2024-05-08 06:18:26 +00:00
|
|
|
* assertEquals(indexOfNeedle(source, needle, 2), 3);
|
|
|
|
* assertEquals(indexOfNeedle(source, needle, 6), -1);
|
2022-11-29 06:01:21 +00:00
|
|
|
* ```
|
2024-04-16 06:59:52 +00:00
|
|
|
* Defining a start index will begin the search at the specified index in the
|
|
|
|
* source array.
|
2022-11-29 06:01:21 +00:00
|
|
|
*/
|
|
|
|
export function indexOfNeedle(
|
|
|
|
source: Uint8Array,
|
|
|
|
needle: Uint8Array,
|
|
|
|
start = 0,
|
|
|
|
): number {
|
|
|
|
if (start < 0) {
|
|
|
|
start = Math.max(0, source.length + start);
|
|
|
|
}
|
2024-05-19 02:10:00 +00:00
|
|
|
if (needle.length > source.length - start) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-11-29 06:01:21 +00:00
|
|
|
const s = needle[0];
|
|
|
|
for (let i = start; i < source.length; i++) {
|
|
|
|
if (source[i] !== s) continue;
|
|
|
|
let matched = 1;
|
2024-04-17 05:01:37 +00:00
|
|
|
let j = i + 1;
|
|
|
|
while (matched < needle.length && source[j] === needle[j - i]) {
|
2022-11-29 06:01:21 +00:00
|
|
|
matched++;
|
2024-04-17 05:01:37 +00:00
|
|
|
j++;
|
2022-11-29 06:01:21 +00:00
|
|
|
}
|
|
|
|
if (matched === needle.length) {
|
2024-04-17 05:01:37 +00:00
|
|
|
return i;
|
2022-11-29 06:01:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|