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 count: number = 0; 94 return { 95 next: function (): { done: boolean, value: [K, V] } { 96 let done: boolean = false; 97 let value: [K, V] = undefined; 98 done = count >= this.memberNumber; 99 value = done ? undefined : [this.members.keys[count], this.members.values[count]] as [K, V]; 100 count++; 101 return { 102 done: done, 103 value: value, 104 }; 105 }, 106 }; 107 } 108 get(key: K): V { 109 errorUtil.checkBindError('get', LightWeightMap, this); 110 let index: number = 0; 111 index = this.getIndexByKey(key); 112 return this.members.values[index]; 113 } 114 getIndexOfKey(key: K): number { 115 errorUtil.checkBindError('getIndexOfKey', LightWeightMap, this); 116 return this.getIndexByKey(key); 117 } 118 getIndexOfValue(value: V): number { 119 errorUtil.checkBindError('getIndexOfValue', LightWeightMap, this); 120 return this.members.values.indexOf(value); 121 } 122 isEmpty(): boolean { 123 errorUtil.checkBindError('isEmpty', LightWeightMap, this); 124 return this.memberNumber === 0; 125 } 126 getKeyAt(index: number): K { 127 errorUtil.checkBindError('getKeyAt', LightWeightMap, this); 128 errorUtil.checkTypeError('index', 'Integer', index); 129 errorUtil.checkRangeError('index', index, 0, this.length - 1); 130 return this.members.keys[index]; 131 } 132 keys(): IterableIterator<K> { 133 errorUtil.checkBindError('keys', LightWeightMap, this); 134 let count: number = 0; 135 return { 136 next: function (): { done: boolean, value: K } { 137 let done: boolean = false; 138 let value: K = undefined; 139 done = count >= this.memberNumber; 140 value = done ? undefined : this.members.keys[count]; 141 count++; 142 return { 143 done: done, 144 value: value, 145 }; 146 }, 147 }; 148 } 149 setAll(map: LightWeightMap<K, V>): void { 150 errorUtil.checkBindError('setAll', LightWeightMap, this); 151 errorUtil.checkTypeError('map', 'LightWeightMap', map); 152 if (this.memberNumber === 0) { 153 this.members.hashs = map.members.hashs.slice(); 154 this.members.keys = map.members.keys.slice(); 155 this.members.values = map.members.values.slice(); 156 this.memberNumber = map.memberNumber; 157 } else { 158 for (let i: number = 0; i < map.memberNumber; i++) { 159 this.addmember(map.members.keys[i], map.members.values[i]); 160 } 161 } 162 } 163 set(key: K, value: V): Object { 164 errorUtil.checkBindError('set', LightWeightMap, this); 165 this.addmember(key, value); 166 return this; 167 } 168 remove(key: K): V { 169 errorUtil.checkBindError('remove', LightWeightMap, this); 170 return this.deletemember(key); 171 } 172 removeAt(index: number): boolean { 173 errorUtil.checkBindError('removeAt', LightWeightMap, this); 174 errorUtil.checkTypeError('index', 'Integer', index); 175 if (index > this.memberNumber--) { 176 return false; 177 } 178 this.members.hashs.splice(index, 1); 179 this.members.values.splice(index, 1); 180 this.members.keys.splice(index, 1); 181 this.memberNumber--; 182 return true; 183 } 184 clear(): void { 185 errorUtil.checkBindError('clear', LightWeightMap, this); 186 if (this.memberNumber !== 0 || this.capacity > 8) { // 8 : means number 187 this.members.hashs = []; 188 this.members.keys = []; 189 this.members.values = []; 190 this.memberNumber = 0; 191 this.capacity = 8; 192 } 193 } 194 setValueAt(index: number, newValue: V): boolean { 195 errorUtil.checkBindError('setValueAt', LightWeightMap, this); 196 errorUtil.checkTypeError('index', 'Integer', index); 197 errorUtil.checkRangeError('index', index, 0, this.length - 1); 198 if (index > this.memberNumber || this.members.values[index] === undefined) { 199 return false; 200 } 201 this.members.values[index] = newValue; 202 return true; 203 } 204 forEach(callbackfn: (value?: V, key?: K, map?: LightWeightMap<K, V>) => void, 205 thisArg?: Object): void { 206 errorUtil.checkBindError('forEach', LightWeightMap, this); 207 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 208 for (let i: number = 0; i < this.memberNumber; i++) { 209 callbackfn.call(thisArg, this.members.values[i], this.members.keys[i], this); 210 } 211 } 212 [Symbol.iterator](): IterableIterator<[K, V]> { 213 errorUtil.checkBindError('Symbol.iterator', LightWeightMap, this); 214 return this.entries(); 215 } 216 toString(): string { 217 errorUtil.checkBindError('toString', LightWeightMap, this); 218 let result: string[] = []; 219 for (let i: number = 0; i < this.memberNumber; i++) { 220 result.push(this.members.keys[i] + ':' + this.members.values[i]); 221 } 222 return result.join(','); 223 } 224 getValueAt(index: number): V { 225 errorUtil.checkBindError('getValueAt', LightWeightMap, this); 226 errorUtil.checkTypeError('index', 'Integer', index); 227 errorUtil.checkRangeError('index', index, 0, this.length - 1); 228 return this.members.values[index]; 229 } 230 values(): IterableIterator<V> { 231 errorUtil.checkBindError('values', LightWeightMap, this); 232 let count: number = 0; 233 return { 234 next: function (): { done: boolean, value: V } { 235 let done: boolean = false; 236 let value: V = undefined; 237 done = count >= this.memberNumber; 238 value = done ? undefined : this.members.values[count]; 239 count++; 240 return { 241 done: done, 242 value: value, 243 }; 244 }, 245 }; 246 } 247 } 248 Object.freeze(LightWeightMap); 249 fastLightWeightMap = LightWeightMap; 250} 251export default fastLightWeightMap; 252