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>( 97 values: T[] | TypedArray, 98 target: T, 99 ): number | undefined { 100 if (values.length === 0) { 101 return undefined; 102 } 103 104 let low = 0; 105 let high = values.length - 1; 106 107 let result: number | undefined = undefined; 108 109 while (low <= high) { 110 const mid = (low + high) >> 1; 111 112 if (values[mid] < target) { 113 low = mid + 1; 114 } else if (values[mid] > target) { 115 if (result === undefined || result > mid) { 116 result = mid; 117 } 118 high = mid - 1; 119 } else { 120 low = mid + 1; 121 } 122 } 123 124 return result; 125 } 126 127 static toUintLittleEndian( 128 buffer: Uint8Array, 129 start: number, 130 end: number, 131 ): bigint { 132 let result = 0n; 133 for (let i = end - 1; i >= start; --i) { 134 result *= 256n; 135 result += BigInt(buffer[i]); 136 } 137 return result; 138 } 139 140 static toIntLittleEndian( 141 buffer: Uint8Array, 142 start: number, 143 end: number, 144 ): bigint { 145 const numOfBits = BigInt(Math.max(0, 8 * (end - start))); 146 if (numOfBits <= 0n) { 147 return 0n; 148 } 149 150 let result = ArrayUtils.toUintLittleEndian(buffer, start, end); 151 const maxSignedValue = 2n ** (numOfBits - 1n) - 1n; 152 if (result > maxSignedValue) { 153 const valuesRange = 2n ** numOfBits; 154 result -= valuesRange; 155 } 156 157 return result; 158 } 159} 160 161export {ArrayUtils}; 162