14d6c458bSopenharmony_ci/* 24d6c458bSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License. 54d6c458bSopenharmony_ci * You may obtain a copy of the License at 64d6c458bSopenharmony_ci * 74d6c458bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84d6c458bSopenharmony_ci * 94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and 134d6c458bSopenharmony_ci * limitations under the License. 144d6c458bSopenharmony_ci */ 154d6c458bSopenharmony_ciinterface ArkPrivate { 164d6c458bSopenharmony_ci Deque: number; 174d6c458bSopenharmony_ci Load(key: number): Object; 184d6c458bSopenharmony_ci} 194d6c458bSopenharmony_ciinterface errorUtil{ 204d6c458bSopenharmony_ci checkRangeError(paramName: string, receivedValue: unknown, min?: number, max?: number, options?: string): void; 214d6c458bSopenharmony_ci checkNewTargetIsNullError(className: string, isNull: boolean): void; 224d6c458bSopenharmony_ci checkBindError(methodName: string, className: Function, self: unknown): void; 234d6c458bSopenharmony_ci checkTypeError(paramName: string, type: string, receivedValue: unknown): void; 244d6c458bSopenharmony_ci} 254d6c458bSopenharmony_cilet flag: boolean = false; 264d6c458bSopenharmony_cilet fastDeque: Object = undefined; 274d6c458bSopenharmony_cilet arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 284d6c458bSopenharmony_ciif (arkPritvate !== undefined) { 294d6c458bSopenharmony_ci fastDeque = arkPritvate.Load(arkPritvate.Deque); 304d6c458bSopenharmony_ci} else { 314d6c458bSopenharmony_ci flag = true; 324d6c458bSopenharmony_ci} 334d6c458bSopenharmony_cideclare function requireNapi(s: string): errorUtil; 344d6c458bSopenharmony_ciif (flag || fastDeque === undefined) { 354d6c458bSopenharmony_ci const errorUtil = requireNapi('util.struct'); 364d6c458bSopenharmony_ci class HandlerDeque<T> { 374d6c458bSopenharmony_ci private isOutBounds(prop: string): void { 384d6c458bSopenharmony_ci let index: number = Number.parseInt(prop); 394d6c458bSopenharmony_ci if (Number.isInteger(index)) { 404d6c458bSopenharmony_ci errorUtil.checkRangeError('index', index, 0); 414d6c458bSopenharmony_ci } 424d6c458bSopenharmony_ci } 434d6c458bSopenharmony_ci get(obj: Deque<T>, prop: string): T { 444d6c458bSopenharmony_ci if (typeof prop === 'symbol') { 454d6c458bSopenharmony_ci return obj[prop]; 464d6c458bSopenharmony_ci } 474d6c458bSopenharmony_ci this.isOutBounds(prop); 484d6c458bSopenharmony_ci return obj[prop]; 494d6c458bSopenharmony_ci } 504d6c458bSopenharmony_ci set(obj: Deque<T>, prop: any, value: T): boolean { 514d6c458bSopenharmony_ci if (prop === 'front' || prop === 'capacity' || prop === 'rear') { 524d6c458bSopenharmony_ci obj[prop] = value; 534d6c458bSopenharmony_ci return true; 544d6c458bSopenharmony_ci } 554d6c458bSopenharmony_ci let index: number = Number(prop); 564d6c458bSopenharmony_ci if (Number.isInteger(index)) { 574d6c458bSopenharmony_ci errorUtil.checkRangeError('index', index, 0); 584d6c458bSopenharmony_ci obj[index] = value; 594d6c458bSopenharmony_ci return true; 604d6c458bSopenharmony_ci } 614d6c458bSopenharmony_ci return false; 624d6c458bSopenharmony_ci } 634d6c458bSopenharmony_ci has(obj: Deque<T>, prop: T): boolean { 644d6c458bSopenharmony_ci return obj.has(prop); 654d6c458bSopenharmony_ci } 664d6c458bSopenharmony_ci ownKeys(obj: Deque<T>): Array<string> { 674d6c458bSopenharmony_ci let keys: Array<string> = []; 684d6c458bSopenharmony_ci for (let i: number = 0; i < obj.length; i++) { 694d6c458bSopenharmony_ci keys.push(i.toString()); 704d6c458bSopenharmony_ci } 714d6c458bSopenharmony_ci return keys; 724d6c458bSopenharmony_ci } 734d6c458bSopenharmony_ci defineProperty(): boolean { 744d6c458bSopenharmony_ci return true; 754d6c458bSopenharmony_ci } 764d6c458bSopenharmony_ci getOwnPropertyDescriptor(obj: Deque<T>, prop: string): Object { 774d6c458bSopenharmony_ci this.isOutBounds(prop); 784d6c458bSopenharmony_ci let index: number = Number.parseInt(prop); 794d6c458bSopenharmony_ci if (index >= 0 && Number.isInteger(index)) { 804d6c458bSopenharmony_ci return Object.getOwnPropertyDescriptor(obj, prop); 814d6c458bSopenharmony_ci } 824d6c458bSopenharmony_ci return Object; 834d6c458bSopenharmony_ci } 844d6c458bSopenharmony_ci setPrototypeOf(): T { 854d6c458bSopenharmony_ci throw new Error(`Can't setPrototype on Deque Object`); 864d6c458bSopenharmony_ci } 874d6c458bSopenharmony_ci } 884d6c458bSopenharmony_ci interface IterableIterator<T> { 894d6c458bSopenharmony_ci next: () => { 904d6c458bSopenharmony_ci value: T; 914d6c458bSopenharmony_ci done: boolean; 924d6c458bSopenharmony_ci }; 934d6c458bSopenharmony_ci } 944d6c458bSopenharmony_ci class Deque<T> { 954d6c458bSopenharmony_ci private front: number; 964d6c458bSopenharmony_ci private capacity: number; 974d6c458bSopenharmony_ci private rear: number; 984d6c458bSopenharmony_ci constructor() { 994d6c458bSopenharmony_ci errorUtil.checkNewTargetIsNullError('Deque', !new.target); 1004d6c458bSopenharmony_ci this.front = 0; 1014d6c458bSopenharmony_ci this.capacity = 8; 1024d6c458bSopenharmony_ci this.rear = 0; 1034d6c458bSopenharmony_ci return new Proxy(this, new HandlerDeque()); 1044d6c458bSopenharmony_ci } 1054d6c458bSopenharmony_ci get length(): number { 1064d6c458bSopenharmony_ci let result: number = 0; 1074d6c458bSopenharmony_ci result = (this.rear - this.front + this.capacity) % this.capacity; 1084d6c458bSopenharmony_ci return result; 1094d6c458bSopenharmony_ci } 1104d6c458bSopenharmony_ci insertFront(element: T): void { 1114d6c458bSopenharmony_ci errorUtil.checkBindError('insertFront', Deque, this); 1124d6c458bSopenharmony_ci if (this.isFull()) { 1134d6c458bSopenharmony_ci this.increaseCapacity(); 1144d6c458bSopenharmony_ci } 1154d6c458bSopenharmony_ci this.front = (this.front - 1 + this.capacity) % this.capacity; 1164d6c458bSopenharmony_ci this[this.front] = element; 1174d6c458bSopenharmony_ci } 1184d6c458bSopenharmony_ci insertEnd(element: T): void { 1194d6c458bSopenharmony_ci errorUtil.checkBindError('insertEnd', Deque, this); 1204d6c458bSopenharmony_ci if (this.isFull()) { 1214d6c458bSopenharmony_ci this.increaseCapacity(); 1224d6c458bSopenharmony_ci } 1234d6c458bSopenharmony_ci this[this.rear] = element; 1244d6c458bSopenharmony_ci this.rear = (this.rear + 1) % (this.capacity + 1); 1254d6c458bSopenharmony_ci } 1264d6c458bSopenharmony_ci getFirst(): T { 1274d6c458bSopenharmony_ci errorUtil.checkBindError('getFirst', Deque, this); 1284d6c458bSopenharmony_ci if (this.isEmpty()) { 1294d6c458bSopenharmony_ci return undefined; 1304d6c458bSopenharmony_ci } 1314d6c458bSopenharmony_ci return this[this.front]; 1324d6c458bSopenharmony_ci } 1334d6c458bSopenharmony_ci getLast(): T { 1344d6c458bSopenharmony_ci errorUtil.checkBindError('getLast', Deque, this); 1354d6c458bSopenharmony_ci if (this.isEmpty()) { 1364d6c458bSopenharmony_ci return undefined; 1374d6c458bSopenharmony_ci } 1384d6c458bSopenharmony_ci return this[this.rear - 1]; 1394d6c458bSopenharmony_ci } 1404d6c458bSopenharmony_ci has(element: T): boolean { 1414d6c458bSopenharmony_ci errorUtil.checkBindError('has', Deque, this); 1424d6c458bSopenharmony_ci let result: boolean = false; 1434d6c458bSopenharmony_ci this.forEach(function (value) { 1444d6c458bSopenharmony_ci if (value === element) { 1454d6c458bSopenharmony_ci result = true; 1464d6c458bSopenharmony_ci } 1474d6c458bSopenharmony_ci }); 1484d6c458bSopenharmony_ci return result; 1494d6c458bSopenharmony_ci } 1504d6c458bSopenharmony_ci popFirst(): T { 1514d6c458bSopenharmony_ci errorUtil.checkBindError('popFirst', Deque, this); 1524d6c458bSopenharmony_ci if (this.isEmpty()) { 1534d6c458bSopenharmony_ci return undefined; 1544d6c458bSopenharmony_ci } 1554d6c458bSopenharmony_ci let result: T = undefined; 1564d6c458bSopenharmony_ci result = this[this.front]; 1574d6c458bSopenharmony_ci this.front = (this.front + 1) % (this.capacity + 1); 1584d6c458bSopenharmony_ci return result; 1594d6c458bSopenharmony_ci } 1604d6c458bSopenharmony_ci popLast(): T { 1614d6c458bSopenharmony_ci errorUtil.checkBindError('popLast', Deque, this); 1624d6c458bSopenharmony_ci if (this.isEmpty()) { 1634d6c458bSopenharmony_ci return undefined; 1644d6c458bSopenharmony_ci } 1654d6c458bSopenharmony_ci let result: T = undefined; 1664d6c458bSopenharmony_ci result = this[this.rear - 1]; 1674d6c458bSopenharmony_ci this.rear = (this.rear + this.capacity) % (this.capacity + 1); 1684d6c458bSopenharmony_ci return result; 1694d6c458bSopenharmony_ci } 1704d6c458bSopenharmony_ci forEach(callbackfn: (value: T, index?: number, deque?: Deque<T>) => void, 1714d6c458bSopenharmony_ci thisArg?: Object): void { 1724d6c458bSopenharmony_ci errorUtil.checkBindError('forEach', Deque, this); 1734d6c458bSopenharmony_ci errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 1744d6c458bSopenharmony_ci let k: number = 0; 1754d6c458bSopenharmony_ci let i: number = this.front; 1764d6c458bSopenharmony_ci while (true) { 1774d6c458bSopenharmony_ci callbackfn.call(thisArg, this[i], k, this); 1784d6c458bSopenharmony_ci i = (i + 1) % this.capacity; 1794d6c458bSopenharmony_ci k++; 1804d6c458bSopenharmony_ci if (i === this.rear) { 1814d6c458bSopenharmony_ci break; 1824d6c458bSopenharmony_ci } 1834d6c458bSopenharmony_ci } 1844d6c458bSopenharmony_ci } 1854d6c458bSopenharmony_ci private increaseCapacity(): void { 1864d6c458bSopenharmony_ci let count: number = 0; 1874d6c458bSopenharmony_ci let arr: Array<T> = []; 1884d6c458bSopenharmony_ci let length: number = this.length; 1894d6c458bSopenharmony_ci while (true) { 1904d6c458bSopenharmony_ci arr[count++] = this[this.front]; 1914d6c458bSopenharmony_ci this.front = (this.front + 1) % this.capacity; 1924d6c458bSopenharmony_ci if (this.front === this.rear) { 1934d6c458bSopenharmony_ci break; 1944d6c458bSopenharmony_ci } 1954d6c458bSopenharmony_ci } 1964d6c458bSopenharmony_ci for (let i: number = 0; i < length; i++) { 1974d6c458bSopenharmony_ci this[i] = arr[i]; 1984d6c458bSopenharmony_ci } 1994d6c458bSopenharmony_ci this.capacity = 2 * this.capacity; // 2 : means number 2004d6c458bSopenharmony_ci this.front = 0; 2014d6c458bSopenharmony_ci this.rear = length; 2024d6c458bSopenharmony_ci } 2034d6c458bSopenharmony_ci private isFull(): boolean { 2044d6c458bSopenharmony_ci return (this.rear + 1) % this.capacity === this.front; 2054d6c458bSopenharmony_ci } 2064d6c458bSopenharmony_ci private isEmpty(): boolean { 2074d6c458bSopenharmony_ci return this.length === 0; 2084d6c458bSopenharmony_ci } 2094d6c458bSopenharmony_ci [Symbol.iterator](): IterableIterator<T> { 2104d6c458bSopenharmony_ci errorUtil.checkBindError('Symbol.iterator', Deque, this); 2114d6c458bSopenharmony_ci let count: number = this.front; 2124d6c458bSopenharmony_ci return { 2134d6c458bSopenharmony_ci next: function (): { done: boolean, value: T } { 2144d6c458bSopenharmony_ci let done: boolean = false; 2154d6c458bSopenharmony_ci let value: T = undefined; 2164d6c458bSopenharmony_ci done = count === this.rear; 2174d6c458bSopenharmony_ci value = done ? undefined : this[count]; 2184d6c458bSopenharmony_ci count = (count + 1) % this.capacity; 2194d6c458bSopenharmony_ci return { 2204d6c458bSopenharmony_ci done: done, 2214d6c458bSopenharmony_ci value: value, 2224d6c458bSopenharmony_ci }; 2234d6c458bSopenharmony_ci }, 2244d6c458bSopenharmony_ci }; 2254d6c458bSopenharmony_ci } 2264d6c458bSopenharmony_ci } 2274d6c458bSopenharmony_ci Object.freeze(Deque); 2284d6c458bSopenharmony_ci fastDeque = Deque; 2294d6c458bSopenharmony_ci} 2304d6c458bSopenharmony_ciexport default fastDeque; 231