1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15interface ArkPrivate { 16 Deque: number; 17 Load(key: number): Object; 18} 19let flag: boolean = false; 20let fastDeque: Object = undefined; 21let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 22if (arkPritvate !== undefined) { 23 fastDeque = arkPritvate.Load(arkPritvate.Deque); 24} else { 25 flag = true; 26} 27declare function requireNapi(s: string): any; 28if (flag || fastDeque === undefined) { 29 const { errorUtil } = requireNapi('util.struct'); 30 class HandlerDeque<T> { 31 private isOutBounds(prop: string): void { 32 let index: number = Number.parseInt(prop); 33 if (Number.isInteger(index)) { 34 errorUtil.checkRangeError('index', index, 0); 35 } 36 } 37 get(obj: Deque<T>, prop: string): T { 38 if (typeof prop === 'symbol') { 39 return obj[prop]; 40 } 41 this.isOutBounds(prop); 42 return obj[prop]; 43 } 44 set(obj: Deque<T>, prop: any, value: T): boolean { 45 if (prop === 'front' || prop === 'capacity' || prop === 'rear') { 46 obj[prop] = value; 47 return true; 48 } 49 let index: number = Number(prop); 50 if (Number.isInteger(index)) { 51 errorUtil.checkRangeError('index', index, 0); 52 obj[index] = value; 53 return true; 54 } 55 return false; 56 } 57 has(obj: Deque<T>, prop: T): boolean { 58 return obj.has(prop); 59 } 60 ownKeys(obj: Deque<T>): Array<string> { 61 let keys: Array<string> = []; 62 for (let i: number = 0; i < obj.length; i++) { 63 keys.push(i.toString()); 64 } 65 return keys; 66 } 67 defineProperty(): boolean { 68 return true; 69 } 70 getOwnPropertyDescriptor(obj: Deque<T>, prop: string): Object { 71 this.isOutBounds(prop); 72 let index: number = Number.parseInt(prop); 73 if (index >= 0 && Number.isInteger(index)) { 74 return Object.getOwnPropertyDescriptor(obj, prop); 75 } 76 return Object; 77 } 78 setPrototypeOf(): T { 79 throw new Error(`Can't setPrototype on Deque Object`); 80 } 81 } 82 interface IterableIterator<T> { 83 next: () => { 84 value: T; 85 done: boolean; 86 }; 87 } 88 class Deque<T> { 89 private front: number; 90 private capacity: number; 91 private rear: number; 92 constructor() { 93 errorUtil.checkNewTargetIsNullError('Deque', !new.target); 94 this.front = 0; 95 this.capacity = 8; 96 this.rear = 0; 97 return new Proxy(this, new HandlerDeque()); 98 } 99 get length(): number { 100 let result: number = 0; 101 result = (this.rear - this.front + this.capacity) % this.capacity; 102 return result; 103 } 104 insertFront(element: T): void { 105 errorUtil.checkBindError('insertFront', Deque, this); 106 if (this.isFull()) { 107 this.increaseCapacity(); 108 } 109 this.front = (this.front - 1 + this.capacity) % this.capacity; 110 this[this.front] = element; 111 } 112 insertEnd(element: T): void { 113 errorUtil.checkBindError('insertEnd', Deque, this); 114 if (this.isFull()) { 115 this.increaseCapacity(); 116 } 117 this[this.rear] = element; 118 this.rear = (this.rear + 1) % (this.capacity + 1); 119 } 120 getFirst(): T { 121 errorUtil.checkBindError('getFirst', Deque, this); 122 if (this.isEmpty()) { 123 return undefined; 124 } 125 return this[this.front]; 126 } 127 getLast(): T { 128 errorUtil.checkBindError('getLast', Deque, this); 129 if (this.isEmpty()) { 130 return undefined; 131 } 132 return this[this.rear - 1]; 133 } 134 has(element: T): boolean { 135 errorUtil.checkBindError('has', Deque, this); 136 let result: boolean = false; 137 this.forEach(function (value) { 138 if (value === element) { 139 result = true; 140 } 141 }); 142 return result; 143 } 144 popFirst(): T { 145 errorUtil.checkBindError('popFirst', Deque, this); 146 if (this.isEmpty()) { 147 return undefined; 148 } 149 let result: T = undefined; 150 result = this[this.front]; 151 this.front = (this.front + 1) % (this.capacity + 1); 152 return result; 153 } 154 popLast(): T { 155 errorUtil.checkBindError('popLast', Deque, this); 156 if (this.isEmpty()) { 157 return undefined; 158 } 159 let result: T = undefined; 160 result = this[this.rear - 1]; 161 this.rear = (this.rear + this.capacity) % (this.capacity + 1); 162 return result; 163 } 164 forEach(callbackfn: (value: T, index?: number, deque?: Deque<T>) => void, 165 thisArg?: Object): void { 166 errorUtil.checkBindError('forEach', Deque, this); 167 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 168 let k: number = 0; 169 let i: number = this.front; 170 while (true) { 171 callbackfn.call(thisArg, this[i], k, this); 172 i = (i + 1) % this.capacity; 173 k++; 174 if (i === this.rear) { 175 break; 176 } 177 } 178 } 179 private increaseCapacity(): void { 180 let count: number = 0; 181 let arr: Array<T> = []; 182 let length: number = this.length; 183 while (true) { 184 arr[count++] = this[this.front]; 185 this.front = (this.front + 1) % this.capacity; 186 if (this.front === this.rear) { 187 break; 188 } 189 } 190 for (let i: number = 0; i < length; i++) { 191 this[i] = arr[i]; 192 } 193 this.capacity = 2 * this.capacity; // 2 : means number 194 this.front = 0; 195 this.rear = length; 196 } 197 private isFull(): boolean { 198 return (this.rear + 1) % this.capacity === this.front; 199 } 200 private isEmpty(): boolean { 201 return this.length === 0; 202 } 203 [Symbol.iterator](): IterableIterator<T> { 204 errorUtil.checkBindError('Symbol.iterator', Deque, this); 205 let deque: Deque<T> = this; 206 let count: number = deque.front; 207 return { 208 next: function (): { done: boolean, value: T } { 209 let done: boolean = false; 210 let value: T = undefined; 211 done = count === deque.rear; 212 value = done ? undefined : deque[count]; 213 count = (count + 1) % deque.capacity; 214 return { 215 done: done, 216 value: value, 217 }; 218 }, 219 }; 220 } 221 } 222 Object.freeze(Deque); 223 fastDeque = Deque; 224} 225export default fastDeque; 226