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 Queue: number; 17 Load(key: number): Object; 18} 19let flag: boolean = false; 20let fastQueue: Object = undefined; 21let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 22if (arkPritvate !== undefined) { 23 fastQueue = arkPritvate.Load(arkPritvate.Queue); 24} else { 25 flag = true; 26} 27declare function requireNapi(s: string): any; 28if (flag || fastQueue === undefined) { 29 const { errorUtil } = requireNapi('util.struct'); 30 class HandlerQueue<T> { 31 private isOutBounds(obj: Queue<T>, prop: string): void { 32 let index: number = Number.parseInt(prop); 33 if (Number.isInteger(index)) { 34 errorUtil.checkRangeError('index', index, 0, obj.length); 35 } 36 } 37 get(obj: Queue<T>, prop: string): T { 38 if (typeof prop === 'symbol') { 39 return obj[prop]; 40 } 41 this.isOutBounds(obj, prop); 42 return obj[prop]; 43 } 44 set(obj: Queue<T>, prop: any, value: T): boolean { 45 if (prop === 'front' || prop === 'capacity' || prop === 'rear') { 46 obj[prop] = value; 47 return true; 48 } 49 this.isOutBounds(obj, prop); 50 let index: number = Number(prop); 51 if (index >= 0 && index <= obj.length && Number.isInteger(index)) { 52 obj[index] = value; 53 return true; 54 } 55 return false; 56 } 57 ownKeys(obj: Queue<T>): Array<string> { 58 let keys: string[] = []; 59 for (let i: number = 0; i < obj.length; i++) { 60 keys.push(i.toString()); 61 } 62 return keys; 63 } 64 defineProperty(): boolean { 65 return true; 66 } 67 getOwnPropertyDescriptor(obj: Queue<T>, prop: string): Object { 68 this.isOutBounds(obj, prop); 69 let index: number = Number.parseInt(prop); 70 if (index >= 0 && index < obj.length && Number.isInteger(index)) { 71 return Object.getOwnPropertyDescriptor(obj, prop); 72 } 73 return Object; 74 } 75 setPrototypeOf(): T { 76 throw new Error(`Can't setPrototype on Queue Object`); 77 } 78 } 79 interface IterableIterator<T> { 80 next: () => { 81 value: T; 82 done: boolean; 83 }; 84 } 85 class Queue<T> { 86 private front: number; 87 private capacity: number; 88 private rear: number; 89 constructor() { 90 errorUtil.checkNewTargetIsNullError('Queue', !new.target); 91 this.front = 0; 92 this.capacity = 8; 93 this.rear = 0; 94 return new Proxy(this, new HandlerQueue()); 95 } 96 get length(): number { 97 return this.rear - this.front; 98 } 99 add(element: T): boolean { 100 errorUtil.checkBindError('add', Queue, this); 101 if (this.isFull()) { 102 this.increaseCapacity(); 103 } 104 this[this.rear] = element; 105 this.rear = (this.rear + 1) % (this.capacity + 1); 106 return true; 107 } 108 getFirst(): T { 109 errorUtil.checkBindError('getFirst', Queue, this); 110 if (this.isEmpty()) { 111 return undefined; 112 } 113 return this[this.front]; 114 } 115 pop(): T { 116 errorUtil.checkBindError('pop', Queue, this); 117 if (this.isEmpty()) { 118 return undefined; 119 } 120 let result: T = undefined; 121 result = this[this.front]; 122 this.front = (this.front + 1) % (this.capacity + 1); 123 return result; 124 } 125 forEach(callbackfn: (value: T, index?: number, queue?: Queue<T>) => void, 126 thisArg?: Object): void { 127 errorUtil.checkBindError('forEach', Queue, this); 128 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 129 let k: number = 0; 130 let i: number = this.front; 131 if (this.isEmpty()) { 132 return; 133 } else { 134 while (true) { 135 callbackfn.call(thisArg, this[i], k, this); 136 i = (i + 1) % this.capacity; 137 k++; 138 if (i === this.rear) { 139 break; 140 } 141 } 142 } 143 } 144 private isFull(): boolean { 145 return this.length === this.capacity; 146 } 147 private isEmpty(): boolean { 148 return this.length === 0; 149 } 150 [Symbol.iterator](): IterableIterator<T> { 151 errorUtil.checkBindError('Symbol.iterator', Queue, this); 152 let count: number = this.front; 153 let queue: Queue<T> = this; 154 return { 155 next: function (): { done: boolean, value: T } { 156 let done: boolean = false; 157 let value: T = undefined; 158 done = count === queue.rear; 159 value = done ? undefined : queue[count]; 160 count = (count + 1) % queue.capacity; 161 return { 162 done: done, 163 value: value, 164 }; 165 }, 166 }; 167 } 168 private increaseCapacity(): void { 169 this.capacity = 2 * this.capacity; // 2 : means number 170 } 171 } 172 Object.freeze(Queue); 173 fastQueue = Queue; 174} 175export default fastQueue; 176