• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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  ArrayList: number;
17  Load(key: number): Object;
18}
19let flag: boolean = false;
20let fastArrayList: Object = undefined;
21let arkPritvate: ArkPrivate = globalThis['ArkPrivate'] || undefined;
22if (arkPritvate !== undefined) {
23  fastArrayList = arkPritvate.Load(arkPritvate.ArrayList);
24} else {
25  flag = true;
26}
27declare function requireNapi(s: string): any;
28if (flag || fastArrayList === undefined) {
29  const { errorUtil } = requireNapi('util.struct');
30  class HandlerArrayList<T> {
31    private isOutBounds(obj: ArrayList<T>, prop: string): void {
32      let index: number = Number.parseInt(prop);
33      if (Number.isInteger(index)) {
34        errorUtil.checkRangeError('index', index, 0, obj.length - 1);
35      }
36    }
37    get(obj: ArrayList<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: ArrayList<T>, prop: any, value: T): boolean {
45      if (prop === 'elementNum' || prop === 'capacity') {
46        obj[prop] = value;
47        return true;
48      }
49      let index: number = Number.parseInt(prop);
50      if (Number.isInteger(index)) {
51        errorUtil.checkRangeError('index', index, 0, obj.length);
52        obj[index] = value;
53        return true;
54      }
55      return false;
56    }
57    deleteProperty(obj: ArrayList<T>, prop: string): boolean {
58      this.isOutBounds(obj, prop);
59      let index: number = Number.parseInt(prop);
60      if (index >= 0 && index < obj.length && Number.isInteger(index)) {
61        obj.removeByIndex(index);
62        return true;
63      }
64      return false;
65    }
66    has(obj: ArrayList<T>, prop: T): boolean {
67      return obj.has(prop);
68    }
69    ownKeys(obj: ArrayList<T>): Array<string> {
70      let keys: Array<string> = [];
71      for (let i: number = 0; i < obj.length; i++) {
72        keys.push(i.toString());
73      }
74      return keys;
75    }
76    defineProperty(): boolean {
77      return true;
78    }
79    getOwnPropertyDescriptor(obj: ArrayList<T>, prop: string): Object {
80      this.isOutBounds(obj, prop);
81      let index: number = Number.parseInt(prop);
82      if (index >= 0 && index < obj.length && Number.isInteger(index)) {
83        return Object.getOwnPropertyDescriptor(obj, prop);
84      }
85      return Object;
86    }
87    setPrototypeOf(): T {
88      throw new Error(`Can't setPrototype on ArrayList Object`);
89    }
90  }
91  interface IterableIterator<T> {
92    next: () => {
93      value: T;
94      done: boolean;
95    };
96  }
97  class ArrayList<T> {
98    private elementNum: number = 0;
99    private capacity: number = 10; // 10 : means number
100    constructor() {
101      errorUtil.checkNewTargetIsNullError('ArrayList', !new.target);
102      return new Proxy(this, new HandlerArrayList());
103    }
104    get length(): number {
105      return this.elementNum;
106    }
107    add(element: T): boolean {
108      errorUtil.checkBindError('add', ArrayList, this);
109      if (this.isFull()) {
110        this.resize();
111      }
112      this[this.elementNum++] = element;
113      return true;
114    }
115    insert(element: T, index: number): void {
116      errorUtil.checkBindError('insert', ArrayList, this);
117      errorUtil.checkTypeError('index', 'Integer', index);
118      errorUtil.checkRangeError('index', index, 0, this.elementNum);
119      if (this.isFull()) {
120        this.resize();
121      }
122      for (let i: number = this.elementNum; i > index; i--) {
123        this[i] = this[i - 1];
124      }
125      this[index] = element;
126      this.elementNum++;
127    }
128    has(element: T): boolean {
129      errorUtil.checkBindError('has', ArrayList, this);
130      for (let i: number = 0; i < this.elementNum; i++) {
131        if (this[i] === element) {
132          return true;
133        }
134      }
135      return false;
136    }
137    getIndexOf(element: T): number {
138      errorUtil.checkBindError('getIndexOf', ArrayList, this);
139      for (let i: number = 0; i < this.elementNum; i++) {
140        if (element === this[i]) {
141          return i;
142        }
143      }
144      return -1;
145    }
146    removeByIndex(index: number): T {
147      errorUtil.checkBindError('removeByIndex', ArrayList, this);
148      errorUtil.checkTypeError('index', 'Integer', index);
149      errorUtil.checkRangeError('index', index, 0, this.elementNum - 1);
150      let result: T = this[index];
151      for (let i: number = index; i < this.elementNum - 1; i++) {
152        this[i] = this[i + 1];
153      }
154      this.elementNum--;
155      return result;
156    }
157    remove(element: T): boolean {
158      errorUtil.checkBindError('remove', ArrayList, this);
159      if (this.has(element)) {
160        let index: number = this.getIndexOf(element);
161        for (let i: number = index; i < this.elementNum - 1; i++) {
162          this[i] = this[i + 1];
163        }
164        this.elementNum--;
165        return true;
166      }
167      return false;
168    }
169    getLastIndexOf(element: T): number {
170      errorUtil.checkBindError('getLastIndexOf', ArrayList, this);
171      for (let i: number = this.elementNum - 1; i >= 0; i--) {
172        if (element === this[i]) {
173          return i;
174        }
175      }
176      return -1;
177    }
178    removeByRange(fromIndex: number, toIndex: number): void {
179      errorUtil.checkBindError('removeByRange', ArrayList, this);
180      errorUtil.checkTypeError('fromIndex', 'Integer', fromIndex);
181      errorUtil.checkTypeError('toIndex', 'Integer', toIndex);
182      errorUtil.checkRangeError('fromIndex', fromIndex, 0,
183        (toIndex > this.elementNum) ? this.elementNum - 1 : toIndex - 1);
184      errorUtil.checkRangeError('toIndex', toIndex, 0, this.elementNum);
185      let i: number = fromIndex;
186      for (let j: number = toIndex; j < this.elementNum; j++) {
187        this[i] = this[j];
188        i++;
189      }
190      this.elementNum -= toIndex - fromIndex;
191    }
192    replaceAllElements(callbackfn: (value: T, index?: number, arrList?: ArrayList<T>) => T,
193      thisArg?: Object): void {
194      errorUtil.checkBindError('replaceAllElements', ArrayList, this);
195      errorUtil.checkTypeError('callbackfn', 'callable', callbackfn);
196      for (let i: number = 0; i < this.elementNum; i++) {
197        this[i] = callbackfn.call(thisArg, this[i], i, this);
198      }
199    }
200    forEach(callbackfn: (value: T, index?: number, arrList?: ArrayList<T>) => void,
201      thisArg?: Object): void {
202      errorUtil.checkBindError('forEach', ArrayList, this);
203      errorUtil.checkTypeError('callbackfn', 'callable', callbackfn);
204      for (let i: number = 0; i < this.elementNum; i++) {
205        callbackfn.call(thisArg, this[i], i, this);
206      }
207    }
208    sort(comparator?: (firstValue: T, secondValue: T) => number): void {
209      errorUtil.checkBindError('sort', ArrayList, this);
210      let isSort: boolean = true;
211      if (comparator) {
212        errorUtil.checkTypeError('comparator', 'callable', comparator);
213        for (let i: number = 0; i < this.elementNum; i++) {
214          for (let j: number = 0; j < this.elementNum - 1 - i; j++) {
215            if (comparator(this[j], this[j + 1]) > 0) {
216              isSort = false;
217              let temp: T = this[j];
218              this[j] = this[j + 1];
219              this[j + 1] = temp;
220            }
221          }
222        }
223      } else {
224        for (let i: number = 0; i < this.length - 1; i++) {
225          for (let j: number = 0; j < this.elementNum - 1 - i; j++) {
226            if (this.asciSort(this[j], this[j + 1])) {
227              isSort = false;
228              let temp: T = this[j];
229              this[j] = this[j + 1];
230              this[j + 1] = temp;
231            }
232          }
233          if (isSort) {
234            break;
235          }
236        }
237      }
238    }
239    private asciSort(curElement: string, nextElement: string): boolean {
240      if ((Object.prototype.toString.call(curElement) === '[object String]' ||
241        Object.prototype.toString.call(curElement) === '[object Number]') &&
242        (Object.prototype.toString.call(nextElement) === '[object String]' ||
243          Object.prototype.toString.call(nextElement) === '[object Number]')) {
244        curElement = curElement.toString();
245        nextElement = nextElement.toString();
246        if (curElement > nextElement) {
247          return true;
248        }
249        return false;
250      }
251      return false;
252    }
253    subArrayList(fromIndex: number, toIndex: number): ArrayList<T> {
254      errorUtil.checkBindError('subArrayList', ArrayList, this);
255      errorUtil.checkTypeError('fromIndex', 'Integer', fromIndex);
256      errorUtil.checkTypeError('toIndex', 'Integer', toIndex);
257      errorUtil.checkRangeError('fromIndex', fromIndex, 0,
258        (toIndex > this.elementNum) ? this.elementNum - 1 : toIndex - 1);
259      errorUtil.checkRangeError('toIndex', toIndex, 0, this.elementNum);
260      let arraylist: ArrayList<T> = new ArrayList<T>();
261      for (let i: number = fromIndex; i < toIndex; i++) {
262        arraylist.add(this[i]);
263      }
264      return arraylist;
265    }
266    clear(): void {
267      errorUtil.checkBindError('clear', ArrayList, this);
268      this.elementNum = 0;
269    }
270    clone(): ArrayList<T> {
271      errorUtil.checkBindError('clone', ArrayList, this);
272      let clone: ArrayList<T> = new ArrayList<T>();
273      for (let i: number = 0; i < this.elementNum; i++) {
274        clone.add(this[i]);
275      }
276      return clone;
277    }
278    getCapacity(): number {
279      errorUtil.checkBindError('getCapacity', ArrayList, this);
280      return this.capacity;
281    }
282    convertToArray(): Array<T> {
283      errorUtil.checkBindError('convertToArray', ArrayList, this);
284      let arr: Array<T> = [];
285      for (let i: number = 0; i < this.elementNum; i++) {
286        arr[i] = this[i];
287      }
288      return arr;
289    }
290    private isFull(): boolean {
291      return this.elementNum === this.capacity;
292    }
293    private resize(): void {
294      this.capacity = 1.5 * this.capacity; // 1.5 : means number
295    }
296    isEmpty(): boolean {
297      errorUtil.checkBindError('isEmpty', ArrayList, this);
298      return this.elementNum === 0;
299    }
300    increaseCapacityTo(newCapacity: number): void {
301      errorUtil.checkBindError('increaseCapacityTo', ArrayList, this);
302      errorUtil.checkTypeError('newCapacity', 'Integer', newCapacity);
303      if (newCapacity >= this.elementNum) {
304        this.capacity = newCapacity;
305      }
306    }
307    trimToCurrentLength(): void {
308      errorUtil.checkBindError('trimToCurrentLength', ArrayList, this);
309      this.capacity = this.elementNum;
310    }
311    [Symbol.iterator](): IterableIterator<T> {
312      errorUtil.checkBindError('Symbol.iterator', ArrayList, this);
313      let count: number = 0;
314      let arraylist: ArrayList<T> = this;
315      return {
316        next: function (): { done: boolean, value: T } {
317          let done: boolean = false;
318          let value: T = undefined;
319          done = count >= arraylist.elementNum;
320          value = done ? undefined : arraylist[count++];
321          return {
322            done: done,
323            value: value,
324          };
325        },
326      };
327    }
328  }
329  Object.freeze(ArrayList);
330  fastArrayList = ArrayList;
331}
332export default fastArrayList;
333