From ef14d62462d7f5bc2f091c3521409b4a16c5f87c Mon Sep 17 00:00:00 2001 From: Ali Hasani Date: Wed, 20 May 2020 19:02:28 +0430 Subject: [PATCH] feat(std/bytes): add hasSuffix and contains functions, update docs (#4801) --- std/bytes/mod.ts | 95 ++++++++++++++++++++++++++++++++--------------- std/bytes/test.ts | 20 ++++++++++ 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/std/bytes/mod.ts b/std/bytes/mod.ts index 7d51e995ce..e52e2365b5 100644 --- a/std/bytes/mod.ts +++ b/std/bytes/mod.ts @@ -1,17 +1,20 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { copyBytes } from "../io/util.ts"; -/** Find first index of binary pattern from a. If not found, then return -1 **/ -export function findIndex(a: Uint8Array, pat: Uint8Array): number { +/** Find first index of binary pattern from a. If not found, then return -1 + * @param source soruce array + * @param pat pattern to find in source array + */ +export function findIndex(source: Uint8Array, pat: Uint8Array): number { const s = pat[0]; - for (let i = 0; i < a.length; i++) { - if (a[i] !== s) continue; + for (let i = 0; i < source.length; i++) { + if (source[i] !== s) continue; const pin = i; let matched = 1; let j = i; while (matched < pat.length) { j++; - if (a[j] !== pat[j - pin]) { + if (source[j] !== pat[j - pin]) { break; } matched++; @@ -23,17 +26,20 @@ export function findIndex(a: Uint8Array, pat: Uint8Array): number { return -1; } -/** Find last index of binary pattern from a. If not found, then return -1 **/ -export function findLastIndex(a: Uint8Array, pat: Uint8Array): number { +/** Find last index of binary pattern from a. If not found, then return -1. + * @param source soruce array + * @param pat pattern to find in source array + */ +export function findLastIndex(source: Uint8Array, pat: Uint8Array): number { const e = pat[pat.length - 1]; - for (let i = a.length - 1; i >= 0; i--) { - if (a[i] !== e) continue; + for (let i = source.length - 1; i >= 0; i--) { + if (source[i] !== e) continue; const pin = i; let matched = 1; let j = i; while (matched < pat.length) { j--; - if (a[j] !== pat[pat.length - 1 - (pin - j)]) { + if (source[j] !== pat[pat.length - 1 - (pin - j)]) { break; } matched++; @@ -45,36 +51,56 @@ export function findLastIndex(a: Uint8Array, pat: Uint8Array): number { return -1; } -/** Check whether binary arrays are equal to each other **/ -export function equal(a: Uint8Array, match: Uint8Array): boolean { - if (a.length !== match.length) return false; +/** Check whether binary arrays are equal to each other. + * @param source first array to check equality + * @param match second array to check equality + */ +export function equal(source: Uint8Array, match: Uint8Array): boolean { + if (source.length !== match.length) return false; for (let i = 0; i < match.length; i++) { - if (a[i] !== match[i]) return false; + if (source[i] !== match[i]) return false; } return true; } -/** Check whether binary array has binary prefix **/ -export function hasPrefix(a: Uint8Array, prefix: Uint8Array): boolean { +/** Check whether binary array starts with prefix. + * @param source srouce array + * @param prefix prefix array to check in source + */ +export function hasPrefix(source: Uint8Array, prefix: Uint8Array): boolean { for (let i = 0, max = prefix.length; i < max; i++) { - if (a[i] !== prefix[i]) return false; + if (source[i] !== prefix[i]) return false; } return true; } -/** - * Repeat bytes. returns a new byte slice consisting of `count` copies of `b`. - * @param b The origin bytes +/** Check whether binary array ends with suffix. + * @param source srouce array + * @param suffix suffix array to check in source + */ +export function hasSuffix(source: Uint8Array, suffix: Uint8Array): boolean { + for ( + let srci = source.length - 1, sfxi = suffix.length - 1; + sfxi >= 0; + srci--, sfxi-- + ) { + if (source[srci] !== suffix[sfxi]) return false; + } + return true; +} + +/** Repeat bytes. returns a new byte slice consisting of `count` copies of `b`. + * @param origin The origin bytes * @param count The count you want to repeat. */ -export function repeat(b: Uint8Array, count: number): Uint8Array { +export function repeat(origin: Uint8Array, count: number): Uint8Array { if (count === 0) { return new Uint8Array(); } if (count < 0) { throw new Error("bytes: negative repeat count"); - } else if ((b.length * count) / count !== b.length) { + } else if ((origin.length * count) / count !== origin.length) { throw new Error("bytes: repeat count causes overflow"); } @@ -84,9 +110,9 @@ export function repeat(b: Uint8Array, count: number): Uint8Array { throw new Error("bytes: repeat count must be an integer"); } - const nb = new Uint8Array(b.length * count); + const nb = new Uint8Array(origin.length * count); - let bp = copyBytes(b, nb); + let bp = copyBytes(origin, nb); for (; bp < nb.length; bp *= 2) { copyBytes(nb.slice(0, bp), nb, bp); @@ -95,10 +121,21 @@ export function repeat(b: Uint8Array, count: number): Uint8Array { return nb; } -/** Concatenate two binary arrays and return new one */ -export function concat(a: Uint8Array, b: Uint8Array): Uint8Array { - const output = new Uint8Array(a.length + b.length); - output.set(a, 0); - output.set(b, a.length); +/** Concatenate two binary arrays and return new one. + * @param origin origin array to concatenate + * @param b array to concatenate with origin + */ +export function concat(origin: Uint8Array, b: Uint8Array): Uint8Array { + const output = new Uint8Array(origin.length + b.length); + output.set(origin, 0); + output.set(b, origin.length); return output; } + +/** Check srouce array contains pattern array. + * @param source srouce array + * @param pat patter array + */ +export function contains(source: Uint8Array, pat: Uint8Array): boolean { + return findIndex(source, pat) != -1; +} diff --git a/std/bytes/test.ts b/std/bytes/test.ts index 13ac7a1fd4..8b03de9262 100644 --- a/std/bytes/test.ts +++ b/std/bytes/test.ts @@ -5,8 +5,10 @@ import { findLastIndex, equal, hasPrefix, + hasSuffix, repeat, concat, + contains, } from "./mod.ts"; import { assertEquals, assertThrows, assert } from "../testing/asserts.ts"; import { encode, decode } from "../encoding/utf8.ts"; @@ -24,6 +26,11 @@ Deno.test("[bytes] findIndex2", () => { assertEquals(i, 1); }); +Deno.test("[bytes] findIndex3", () => { + const i = findIndex(encode("Deno"), encode("D")); + assertEquals(i, 0); +}); + Deno.test("[bytes] findLastIndex1", () => { const i = findLastIndex( new Uint8Array([0, 1, 2, 0, 1, 2, 0, 1, 3]), @@ -47,6 +54,11 @@ Deno.test("[bytes] hasPrefix", () => { assertEquals(v, true); }); +Deno.test("[bytes] hasSuffix", () => { + const v = hasSuffix(new Uint8Array([0, 1, 2]), new Uint8Array([1, 2])); + assertEquals(v, true); +}); + Deno.test("[bytes] repeat", () => { // input / output / count / error message const repeatTestCase = [ @@ -97,3 +109,11 @@ Deno.test("[bytes] concat empty arrays", () => { assert(u1 !== joined); assert(u2 !== joined); }); + +Deno.test("[bytes] contain", () => { + const source = encode("deno.land"); + const pattern = encode("deno"); + assert(contains(source, pattern)); + + assert(contains(new Uint8Array([0, 1, 2, 3]), new Uint8Array([2, 3]))); +});