• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  List: number;
17  Load(key: number): Object;
18}
19let flag: boolean = false;
20let fastList: Object = undefined;
21let arkPritvate: ArkPrivate = globalThis['ArkPrivate'] || undefined;
22if (arkPritvate !== undefined) {
23  fastList = arkPritvate.Load(arkPritvate.List);
24} else {
25  flag = true;
26}
27declare function requireNapi(s: string): any;
28if (flag || fastList === undefined) {
29  const {ErrorUtil} = requireNapi('util.struct');
30  class HandlerList<T> {
31    get(obj: List<T>, prop: any): T {
32      if (typeof prop === 'symbol') {
33        return obj[prop];
34      }
35      let index: number = Number.parseInt(prop);
36      if (Number.isInteger(index)) {
37        ErrorUtil.checkRangeError("index", index, 0, obj.length - 1);
38        return obj.get(index);
39      }
40      return obj[prop];
41    }
42    set(obj: List<T>, prop: any, value: T): boolean {
43      if (prop === 'elementNum' ||
44        prop === 'capacity' ||
45        prop === 'head' ||
46        prop === 'next') {
47        obj[prop] = value;
48        return true;
49      }
50      let index: number = Number.parseInt(prop);
51      if (Number.isInteger(index)) {
52        ErrorUtil.checkRangeError("index", index, 0, obj.length);
53        obj.set(index, value);
54        return true;
55      }
56      return false;
57    }
58    deleteProperty(obj: List<T>, prop: any): boolean {
59      let index: number = Number.parseInt(prop);
60      if (Number.isInteger(index)) {
61        ErrorUtil.checkRangeError("index", index, 0, obj.length - 1);
62        obj.removeByIndex(index);
63        return true;
64      }
65      return false;
66    }
67    has(obj: List<T>, prop: any): boolean {
68      return obj.has(prop);
69    }
70    ownKeys(obj: List<T>): Array<string> {
71      let keys: Array<string> = [];
72      for (let i: number = 0; i < obj.length; i++) {
73        keys.push(i.toString());
74      }
75      return keys;
76    }
77    defineProperty(): boolean {
78      return true;
79    }
80    getOwnPropertyDescriptor(obj: List<T>, prop: any): Object {
81      let index: number = Number.parseInt(prop);
82      if (Number.isInteger(index)) {
83        ErrorUtil.checkRangeError("index", index, 0, obj.length - 1);
84        return Object.getOwnPropertyDescriptor(obj, prop);
85      }
86      return;
87    }
88    setPrototypeOf(): T {
89      throw new Error(`Can't setPrototype on List Object`);
90    }
91  }
92  interface IterableIterator<T> {
93    next: () => {
94      value: T;
95      done: boolean;
96    };
97  }
98  class NodeObj<T> {
99    element: T;
100    next?: NodeObj<T>;
101    constructor(element: T, next?: NodeObj<T>) {
102      this.element = element;
103      this.next = next;
104    }
105  }
106  class List<T> {
107    private head: NodeObj<T>;
108    private elementNum: number;
109    private capacity: number;
110    constructor() {
111      ErrorUtil.checkNewTargetIsNullError("List", !new.target);
112      this.head = undefined;
113      this.elementNum = 0;
114      this.capacity = 10;
115      return new Proxy(this, new HandlerList());
116    }
117    get length(): number {
118      return this.elementNum;
119    }
120    private getNode(index: number): NodeObj<T> | undefined {
121      if (index >= 0 && index < this.elementNum) {
122        let current: NodeObj<T> = this.head;
123        for (let i: number = 0; i < index; i++) {
124          if (current !== undefined) {
125            current = current.next;
126          }
127        }
128        return current;
129      }
130      return undefined;
131    }
132    get(index: number): T {
133      ErrorUtil.checkBindError("get", List, this);
134      ErrorUtil.checkTypeError("index", "Integer", index);
135      if (index >= 0 && index < this.elementNum) {
136        let current: NodeObj<T> = this.head;
137        for (let i: number = 0; i < index && current != undefined; i++) {
138          current = current.next;
139        }
140        return current.element;
141      }
142      return undefined;
143    }
144    add(element: T): boolean {
145      ErrorUtil.checkBindError("add", List, this);
146      let node: NodeObj<T> = new NodeObj(element);
147      if (this.head === undefined) {
148        this.head = node;
149      } else {
150        let current: NodeObj<T> = this.head;
151        while (current.next !== undefined) {
152          current = current.next;
153        }
154        current.next = node;
155      }
156      this.elementNum++;
157      return true;
158    }
159    clear(): void {
160      ErrorUtil.checkBindError("clear", List, this);
161      this.head = undefined;
162      this.elementNum = 0;
163    }
164    has(element: T): boolean {
165      ErrorUtil.checkBindError("has", List, this);
166      if (this.head !== undefined) {
167        if (this.head.element === element) {
168          return true;
169        }
170        let current: NodeObj<T> = this.head;
171        while (current.next !== undefined) {
172          current = current.next;
173          if (current.element === element) {
174            return true;
175          }
176        }
177      }
178      return false;
179    }
180    equal(obj: Object): boolean {
181      ErrorUtil.checkBindError("equal", List, this);
182      if (obj === this) {
183        return true;
184      }
185      if (!(obj instanceof List)) {
186        return false;
187      } else {
188        let e1: NodeObj<T> = this.head;
189        let e2: NodeObj<T> = obj.head;
190        if (e1 !== undefined && e2 !== undefined) {
191          while (e1.next !== undefined && e2.next !== undefined) {
192            e1 = e1.next;
193            e2 = e2.next;
194            if (e1.element !== e2.element) {
195              return false;
196            }
197          }
198          return !(e1.next !== undefined || e2.next !== undefined);
199        } else if (e1 !== undefined && e2 === undefined) {
200          return false;
201        } else if (e1 === undefined && e2 !== undefined) {
202          return false;
203        } else {
204          return true;
205        }
206      }
207    }
208    getIndexOf(element: T): number {
209      ErrorUtil.checkBindError("getIndexOf", List, this);
210      for (let i: number = 0; i < this.elementNum; i++) {
211        let curNode: NodeObj<T> = undefined;
212        curNode = this.getNode(i);
213        if (curNode !== undefined && curNode.element === element) {
214          return i;
215        }
216      }
217      return -1;
218    }
219    getLastIndexOf(element: T): number {
220      ErrorUtil.checkBindError("getLastIndexOf", List, this);
221      for (let i: number = this.elementNum - 1; i >= 0; i--) {
222        let curNode: NodeObj<T> = undefined;
223        curNode = this.getNode(i);
224        if (curNode !== undefined && curNode.element === element) {
225          return i;
226        }
227      }
228      return -1;
229    }
230    removeByIndex(index: number): T {
231      ErrorUtil.checkBindError("removeByIndex", List, this);
232      ErrorUtil.checkTypeError("index", "Integer", index);
233      ErrorUtil.checkRangeError("index", index, 0, this.elementNum - 1);
234      let oldNode: NodeObj<T> = this.head;
235      if (index === 0) {
236        oldNode = this.head;
237        this.head = oldNode && oldNode.next;
238      } else {
239        let prevNode: NodeObj<T> = undefined;
240        prevNode = this.getNode(index - 1);
241        oldNode = prevNode.next;
242        prevNode.next = oldNode.next;
243      }
244      this.elementNum--;
245      return oldNode && oldNode.element;
246    }
247    remove(element: T): boolean {
248      ErrorUtil.checkBindError("remove", List, this);
249      if (this.has(element)) {
250        let index: number = 0;
251        index = this.getIndexOf(element);
252        this.removeByIndex(index);
253        return true;
254      }
255      return false;
256    }
257    replaceAllElements(callbackfn: (value: T, index?: number, list?: List<T>) => T,
258      thisArg?: Object): void {
259      ErrorUtil.checkBindError("replaceAllElements", List, this);
260      ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn);
261      let index: number = 0;
262      if (this.head !== undefined) {
263        let current: NodeObj<T> = this.head;
264        if (this.elementNum > 0) {
265          this.getNode(index).element = callbackfn.call(thisArg, this.head.element, index, this);
266        }
267        while (current.next !== undefined) {
268          current = current.next;
269          this.getNode(++index).element = callbackfn.call(thisArg, current.element, index, this);
270        }
271      }
272    }
273    getFirst(): T {
274      ErrorUtil.checkBindError("getFirst", List, this);
275      if (this.isEmpty()) {
276        return undefined;
277      }
278      let element: T = this.head.element;
279      return element;
280    }
281    getLast(): T {
282      ErrorUtil.checkBindError("getLast", List, this);
283      if (this.isEmpty()) {
284        return undefined;
285      }
286      let newNode: NodeObj<T> = undefined;
287      newNode = this.getNode(this.elementNum - 1);
288      let element: T = newNode.element;
289      return element;
290    }
291    insert(element: T, index: number): void {
292      ErrorUtil.checkBindError("insert", List, this);
293      ErrorUtil.checkTypeError("index", "Integer", index);
294      ErrorUtil.checkRangeError("index", index, 0, this.elementNum);
295      let newNode: NodeObj<T> = undefined;
296      newNode = new NodeObj(element);
297      if (index === 0) {
298        let current: NodeObj<T> = this.head;
299        newNode.next = current;
300        this.head = newNode;
301      } else {
302        let prevNode: NodeObj<T> = undefined;
303        prevNode = this.getNode(index - 1);
304        newNode.next = prevNode.next;
305        prevNode.next = newNode;
306      }
307      this.elementNum++;
308    }
309    set(index: number, element: T): T {
310      ErrorUtil.checkBindError("set", List, this);
311      ErrorUtil.checkTypeError("index", "Integer", index);
312      ErrorUtil.checkRangeError("index", index, 0, this.length - 1);
313      let current: NodeObj<T> = undefined;
314      current = this.getNode(index);
315      current.element = element;
316      return current.element;
317    }
318    sort(comparator: (firstValue: T, secondValue: T) => number): void {
319      ErrorUtil.checkBindError("sort", List, this);
320      ErrorUtil.checkTypeError("comparator", "callable", comparator);
321      let isSort: boolean = true;
322      for (let i: number = 0; i < this.elementNum; i++) {
323        for (let j: number = 0; j < this.elementNum - 1 - i; j++) {
324          if (
325            comparator(this.getNode(j).element, this.getNode(j + 1).element) > 0
326          ) {
327            isSort = false;
328            let temp: T = undefined;
329            temp = this.getNode(j).element;
330            this.getNode(j).element = this.getNode(j + 1).element;
331            this.getNode(j + 1).element = temp;
332          }
333        }
334        if (isSort) {
335          break;
336        }
337      }
338    }
339    getSubList(fromIndex: number, toIndex: number): List<T> {
340      ErrorUtil.checkBindError("getSubList", List, this);
341      ErrorUtil.checkTypeError("fromIndex", "Integer", fromIndex);
342      ErrorUtil.checkTypeError("toIndex", "Integer", toIndex);
343      ErrorUtil.checkRangeError("fromIndex", fromIndex, 0,
344                                (toIndex > this.elementNum) ? this.elementNum - 1 : toIndex - 1);
345      ErrorUtil.checkRangeError("toIndex", toIndex, 0, this.elementNum);
346      let list: List<T> = new List<T>();
347      for (let i: number = fromIndex; i < toIndex; i++) {
348        let element: T = undefined;
349        element = this.getNode(i).element;
350        list.add(element);
351        if (element === undefined) {
352          break;
353        }
354      }
355      return list;
356    }
357    convertToArray(): Array<T> {
358      ErrorUtil.checkBindError("convertToArray", List, this);
359      let arr: Array<T> = [];
360      let index: number = 0;
361      if (this.elementNum <= 0) {
362        return arr;
363      }
364      if (this.head !== undefined) {
365        let current: NodeObj<T> = this.head;
366        arr[index] = this.head.element;
367        while (current.next !== undefined) {
368          current = current.next;
369          arr[++index] = current.element;
370        }
371      }
372      return arr;
373    }
374    isEmpty(): boolean {
375      ErrorUtil.checkBindError("isEmpty", List, this);
376      return this.elementNum === 0;
377    }
378    forEach(callbackfn: (value: T, index?: number, list?: List<T>) => void,
379      thisArg?: Object): void {
380      ErrorUtil.checkBindError("forEach", List, this);
381      ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn);
382      let index: number = 0;
383      if (this.head !== undefined) {
384        let current: NodeObj<T> = this.head;
385        if (this.elementNum > 0) {
386          callbackfn.call(thisArg, this.head.element, index, this);
387        }
388        while (current.next !== undefined) {
389          current = current.next;
390          callbackfn.call(thisArg, current.element, ++index, this);
391        }
392      }
393    }
394    [Symbol.iterator](): IterableIterator<T> {
395      ErrorUtil.checkBindError("Symbol.iterator", List, this);
396      let count: number = 0;
397      let list: List<T> = this;
398      return {
399        next: function () {
400          let done: boolean = false;
401          let value: T = undefined;
402          done = count >= list.elementNum;
403          value = done ? undefined : list.getNode(count++).element;
404          return {
405            done: done,
406            value: value,
407          };
408        },
409      };
410    }
411  }
412  Object.freeze(List);
413  fastList = List;
414}
415export default fastList;
416