1/* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16type TypedArray = 17 | Int8Array 18 | Uint8Array 19 | Uint8ClampedArray 20 | Int16Array 21 | Uint16Array 22 | Int32Array 23 | Uint32Array 24 | Float32Array 25 | Float64Array; 26 27class ArrayUtils { 28 static equal<T>(a: T[] | TypedArray, b: T[] | TypedArray): boolean { 29 if (a.length !== b.length) { 30 return false; 31 } 32 33 for (let i = 0; i < a.length; i++) { 34 if (a[i] !== b[i]) { 35 return false; 36 } 37 } 38 39 return true; 40 } 41 42 static searchSubarray<T>( 43 array: T[] | TypedArray, 44 subarray: T[] | TypedArray 45 ): number | undefined { 46 for (let i = 0; i + subarray.length <= array.length; ++i) { 47 let match = true; 48 49 for (let j = 0; j < subarray.length; ++j) { 50 if (array[i + j] !== subarray[j]) { 51 match = false; 52 break; 53 } 54 } 55 56 if (match) { 57 return i; 58 } 59 } 60 61 return undefined; 62 } 63 64 static binarySearchFirstGreaterOrEqual<T>( 65 values: T[] | TypedArray, 66 target: T 67 ): number | undefined { 68 if (values.length === 0) { 69 return undefined; 70 } 71 72 let low = 0; 73 let high = values.length - 1; 74 75 let result: number | undefined = undefined; 76 77 while (low <= high) { 78 const mid = (low + high) >> 1; 79 80 if (values[mid] < target) { 81 low = mid + 1; 82 } else if (values[mid] > target) { 83 if (result === undefined || result > mid) { 84 result = mid; 85 } 86 high = mid - 1; 87 } else { 88 result = mid; 89 high = mid - 1; 90 } 91 } 92 93 return result; 94 } 95 96 static binarySearchFirstGreater<T>(values: T[] | TypedArray, target: T): number | undefined { 97 if (values.length === 0) { 98 return undefined; 99 } 100 101 let low = 0; 102 let high = values.length - 1; 103 104 let result: number | undefined = undefined; 105 106 while (low <= high) { 107 const mid = (low + high) >> 1; 108 109 if (values[mid] < target) { 110 low = mid + 1; 111 } else if (values[mid] > target) { 112 if (result === undefined || result > mid) { 113 result = mid; 114 } 115 high = mid - 1; 116 } else { 117 low = mid + 1; 118 } 119 } 120 121 return result; 122 } 123 124 static toUintLittleEndian(buffer: Uint8Array, start: number, end: number): bigint { 125 let result = 0n; 126 for (let i = end - 1; i >= start; --i) { 127 result *= 256n; 128 result += BigInt(buffer[i]); 129 } 130 return result; 131 } 132 133 static toIntLittleEndian(buffer: Uint8Array, start: number, end: number): bigint { 134 const numOfBits = BigInt(Math.max(0, 8 * (end - start))); 135 if (numOfBits <= 0n) { 136 return 0n; 137 } 138 139 let result = ArrayUtils.toUintLittleEndian(buffer, start, end); 140 const maxSignedValue = 2n ** (numOfBits - 1n) - 1n; 141 if (result > maxSignedValue) { 142 const valuesRange = 2n ** numOfBits; 143 result -= valuesRange; 144 } 145 146 return result; 147 } 148} 149 150export {ArrayUtils}; 151