• 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 */
15declare function requireNapi(s: string): any;
16interface ArkPrivate {
17  LightWeightMap: number;
18  Load(key: number): Object;
19}
20let flag: boolean = false;
21let fastLightWeightMap: Object = undefined;
22let arkPritvate: ArkPrivate = globalThis['ArkPrivate'] || undefined;
23if (arkPritvate !== undefined) {
24  fastLightWeightMap = arkPritvate.Load(arkPritvate.LightWeightMap);
25} else {
26  flag = true;
27}
28if (flag || fastLightWeightMap === undefined) {
29  const lightWeightAbility = requireNapi('util.struct');
30  const errorUtil = lightWeightAbility.errorUtil;
31  interface IterableIterator<T> {
32    next: () => {
33      value: T | undefined;
34      done: boolean;
35    };
36  }
37  class HandlerLightWeightMap<K, V> {
38    set(target: LightWeightMap<K, V>, p: string, value: string): boolean {
39      if (p in target) {
40        target[p] = value;
41        return true;
42      }
43      return false;
44    }
45    defineProperty(): boolean {
46      throw new Error(`Can't define Property on LightWeightMap Object`);
47    }
48    deleteProperty(): boolean {
49      throw new Error(`Can't delete Property on LightWeightMap Object`);
50    }
51    setPrototypeOf(): boolean {
52      throw new Error(`Can't set Prototype on LightWeightMap Object`);
53    }
54  }
55  class LightWeightMap<K, V> extends lightWeightAbility.LightWeightClass<K, V> {
56    constructor() {
57      errorUtil.checkNewTargetIsNullError('LightWeightMap', !new.target);
58      super();
59      return new Proxy(this, new HandlerLightWeightMap());
60    }
61    get length(): number {
62      return this.memberNumber;
63    }
64    hasAll(map: LightWeightMap<K, V>): boolean {
65      errorUtil.checkBindError('hasAll', LightWeightMap, this);
66      errorUtil.checkTypeError('map', 'LightWeightMap', map);
67      if (!(map instanceof LightWeightMap)) {
68        throw new TypeError('map is not JSAPILightWeightMap');
69      }
70      if (map.memberNumber > this.memberNumber) {
71        return false;
72      }
73      if (lightWeightAbility.isIncludeToArray(this.keyValueStringArray(), map.keyValueStringArray())) {
74        return true;
75      }
76      return false;
77    }
78    hasKey(key: K): boolean {
79      errorUtil.checkBindError('hasKey', LightWeightMap, this);
80      return this.members.keys.indexOf(key) > -1;
81    }
82    hasValue(value: V): boolean {
83      errorUtil.checkBindError('hasValue', LightWeightMap, this);
84      return this.members.values.indexOf(value) > -1;
85    }
86    increaseCapacityTo(minimumCapacity: number): void {
87      errorUtil.checkBindError('increaseCapacityTo', LightWeightMap, this);
88      errorUtil.checkTypeError('minimumCapacity', 'Integer', minimumCapacity);
89      super.ensureCapacity(minimumCapacity);
90    }
91    entries(): IterableIterator<[K, V]> {
92      errorUtil.checkBindError('entries', LightWeightMap, this);
93      let data: LightWeightMap<K, V> = this;
94      let count: number = 0;
95      return {
96        next: function (): { done: boolean, value: [K, V] } {
97          let done: boolean = false;
98          let value: [K, V] = undefined;
99          done = count >= data.memberNumber;
100          value = done ? undefined : [data.members.keys[count], data.members.values[count]] as [K, V];
101          count++;
102          return {
103            done: done,
104            value: value,
105          };
106        },
107      };
108    }
109    get(key: K): V {
110      errorUtil.checkBindError('get', LightWeightMap, this);
111      let index: number = 0;
112      index = this.getIndexByKey(key);
113      return this.members.values[index];
114    }
115    getIndexOfKey(key: K): number {
116      errorUtil.checkBindError('getIndexOfKey', LightWeightMap, this);
117      return this.getIndexByKey(key);
118    }
119    getIndexOfValue(value: V): number {
120      errorUtil.checkBindError('getIndexOfValue', LightWeightMap, this);
121      return this.members.values.indexOf(value);
122    }
123    isEmpty(): boolean {
124      errorUtil.checkBindError('isEmpty', LightWeightMap, this);
125      return this.memberNumber === 0;
126    }
127    getKeyAt(index: number): K {
128      errorUtil.checkBindError('getKeyAt', LightWeightMap, this);
129      errorUtil.checkTypeError('index', 'Integer', index);
130      errorUtil.checkRangeError('index', index, 0, this.length - 1);
131      return this.members.keys[index];
132    }
133    keys(): IterableIterator<K> {
134      errorUtil.checkBindError('keys', LightWeightMap, this);
135      let data: LightWeightMap<K, V> = this;
136      let count: number = 0;
137      return {
138        next: function (): { done: boolean, value: K } {
139          let done: boolean = false;
140          let value: K = undefined;
141          done = count >= data.memberNumber;
142          value = done ? undefined : data.members.keys[count];
143          count++;
144          return {
145            done: done,
146            value: value,
147          };
148        },
149      };
150    }
151    setAll(map: LightWeightMap<K, V>): void {
152      errorUtil.checkBindError('setAll', LightWeightMap, this);
153      errorUtil.checkTypeError('map', 'LightWeightMap', map);
154      if (this.memberNumber === 0) {
155        this.members.hashs = map.members.hashs.slice();
156        this.members.keys = map.members.keys.slice();
157        this.members.values = map.members.values.slice();
158        this.memberNumber = map.memberNumber;
159      } else {
160        for (let i: number = 0; i < map.memberNumber; i++) {
161          this.addmember(map.members.keys[i], map.members.values[i]);
162        }
163      }
164    }
165    set(key: K, value: V): Object {
166      errorUtil.checkBindError('set', LightWeightMap, this);
167      this.addmember(key, value);
168      return this;
169    }
170    remove(key: K): V {
171      errorUtil.checkBindError('remove', LightWeightMap, this);
172      return this.deletemember(key);
173    }
174    removeAt(index: number): boolean {
175      errorUtil.checkBindError('removeAt', LightWeightMap, this);
176      errorUtil.checkTypeError('index', 'Integer', index);
177      if (index > this.memberNumber--) {
178        return false;
179      }
180      this.members.hashs.splice(index, 1);
181      this.members.values.splice(index, 1);
182      this.members.keys.splice(index, 1);
183      this.memberNumber--;
184      return true;
185    }
186    clear(): void {
187      errorUtil.checkBindError('clear', LightWeightMap, this);
188      if (this.memberNumber !== 0 || this.capacity > 8) { // 8 : means number
189        this.members.hashs = [];
190        this.members.keys = [];
191        this.members.values = [];
192        this.memberNumber = 0;
193        this.capacity = 8;
194      }
195    }
196    setValueAt(index: number, newValue: V): boolean {
197      errorUtil.checkBindError('setValueAt', LightWeightMap, this);
198      errorUtil.checkTypeError('index', 'Integer', index);
199      errorUtil.checkRangeError('index', index, 0, this.length - 1);
200      if (index > this.memberNumber || this.members.values[index] === undefined) {
201        return false;
202      }
203      this.members.values[index] = newValue;
204      return true;
205    }
206    forEach(callbackfn: (value?: V, key?: K, map?: LightWeightMap<K, V>) => void,
207      thisArg?: Object): void {
208      errorUtil.checkBindError('forEach', LightWeightMap, this);
209      errorUtil.checkTypeError('callbackfn', 'callable', callbackfn);
210      let data: LightWeightMap<K, V> = this;
211      for (let i: number = 0; i < data.memberNumber; i++) {
212        callbackfn.call(thisArg, data.members.values[i], data.members.keys[i], data);
213      }
214    }
215    [Symbol.iterator](): IterableIterator<[K, V]> {
216      errorUtil.checkBindError('Symbol.iterator', LightWeightMap, this);
217      return this.entries();
218    }
219    toString(): string {
220      errorUtil.checkBindError('toString', LightWeightMap, this);
221      let result: string[] = [];
222      for (let i: number = 0; i < this.memberNumber; i++) {
223        result.push(this.members.keys[i] + ':' + this.members.values[i]);
224      }
225      return result.join(',');
226    }
227    getValueAt(index: number): V {
228      errorUtil.checkBindError('getValueAt', LightWeightMap, this);
229      errorUtil.checkTypeError('index', 'Integer', index);
230      errorUtil.checkRangeError('index', index, 0, this.length - 1);
231      return this.members.values[index];
232    }
233    values(): IterableIterator<V> {
234      errorUtil.checkBindError('values', LightWeightMap, this);
235      let data: LightWeightMap<K, V> = this;
236      let count: number = 0;
237      return {
238        next: function (): { done: boolean, value: V } {
239          let done: boolean = false;
240          let value: V = undefined;
241          done = count >= data.memberNumber;
242          value = done ? undefined : data.members.values[count];
243          count++;
244          return {
245            done: done,
246            value: value,
247          };
248        },
249      };
250    }
251  }
252  Object.freeze(LightWeightMap);
253  fastLightWeightMap = LightWeightMap;
254}
255export default fastLightWeightMap;
256