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 LightWeightSet: number; 18 Load(key: number): Object; 19} 20let flag: boolean = false; 21let fastLightWeightSet: Object = undefined; 22let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 23if (arkPritvate !== undefined) { 24 fastLightWeightSet = arkPritvate.Load(arkPritvate.LightWeightSet); 25} else { 26 flag = true; 27} 28if (flag || fastLightWeightSet === 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 HandlerLightWeightSet<T> { 38 set(target: LightWeightSet<T>, 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 LightWeightSet Object`); 47 } 48 deleteProperty(): boolean { 49 throw new Error(`Can't delete Property on LightWeightSet Object`); 50 } 51 setPrototypeOf(): boolean { 52 throw new Error(`Can't set Prototype on LightWeightSet Object`); 53 } 54 } 55 class LightWeightSet<T> extends lightWeightAbility.LightWeightClass<T, T> { 56 constructor() { 57 errorUtil.checkNewTargetIsNullError('LightWeightSet', !new.target); 58 super(); 59 return new Proxy(this, new HandlerLightWeightSet()); 60 } 61 get length(): number { 62 return this.memberNumber; 63 } 64 add(obj: T): boolean { 65 errorUtil.checkBindError('add', LightWeightSet, this); 66 if (this.members.keys.indexOf(obj) > 0) { 67 return false; 68 } 69 this.addmember(obj); 70 return true; 71 } 72 addAll(set: LightWeightSet<T>): boolean { 73 errorUtil.checkBindError('addAll', LightWeightSet, this); 74 errorUtil.checkTypeError('set', 'LightWeightSet', set); 75 if (!(set instanceof LightWeightSet)) { 76 throw new TypeError('Incoming object is not JSAPILightWeightSet'); 77 } 78 let change: boolean = false; 79 if (set.memberNumber === 0) { 80 change = false; 81 } else { 82 for (let i: number = 0; i < set.memberNumber; i++) { 83 change = this.add(set.members.keys[i]) || change; 84 } 85 } 86 return change; 87 } 88 hasAll(set: LightWeightSet<T>): boolean { 89 errorUtil.checkBindError('hasAll', LightWeightSet, this); 90 errorUtil.checkTypeError('set', 'LightWeightSet', set); 91 if (set.memberNumber > this.memberNumber) { 92 return false; 93 } 94 if (lightWeightAbility.isIncludeToArray(this.members.keys, set.members.keys)) { 95 return true; 96 } 97 return false; 98 } 99 has(key: T): boolean { 100 errorUtil.checkBindError('has', LightWeightSet, this); 101 return this.members.keys.indexOf(key) > -1; 102 } 103 equal(obj: Object): boolean { 104 errorUtil.checkBindError('equal', LightWeightSet, this); 105 if (this.memberNumber === 0) { 106 return false; 107 } 108 if (obj instanceof LightWeightSet) { 109 return JSON.stringify(obj.members.keys) === JSON.stringify(this.members.keys); 110 } 111 if (JSON.stringify(obj) === JSON.stringify(this.members.keys)) { 112 return true; 113 } 114 return false; 115 } 116 increaseCapacityTo(minimumCapacity: number): void { 117 errorUtil.checkBindError('increaseCapacityTo', LightWeightSet, this); 118 errorUtil.checkTypeError('minimumCapacity', 'Integer', minimumCapacity); 119 errorUtil.checkRangeError('minimumCapacity', minimumCapacity, this.capacity, 120 undefined, '!=min'); 121 super.ensureCapacity(minimumCapacity); 122 } 123 getIndexOf(key: T): number { 124 errorUtil.checkBindError('getIndexOf', LightWeightSet, this); 125 return super.getIndexByKey(key); 126 } 127 isEmpty(): boolean { 128 errorUtil.checkBindError('isEmpty', LightWeightSet, this); 129 return this.memberNumber === 0; 130 } 131 remove(key: T): T { 132 errorUtil.checkBindError('remove', LightWeightSet, this); 133 return super.deletemember(key); 134 } 135 removeAt(index: number): boolean { 136 errorUtil.checkBindError('removeAt', LightWeightSet, this); 137 errorUtil.checkTypeError('index', 'Integer', index); 138 if (index > this.memberNumber--) { 139 return false; 140 } 141 this.members.hashs.splice(index, 1); 142 this.members.values.splice(index, 1); 143 this.members.keys.splice(index, 1); 144 this.memberNumber--; 145 return true; 146 } 147 clear(): void { 148 errorUtil.checkBindError('clear', LightWeightSet, this); 149 if (this.memberNumber !== 0 || this.capacity > 8) { // 8 : means number 150 this.members.hashs = []; 151 this.members.keys = []; 152 this.members.values = []; 153 this.memberNumber = 0; 154 this.capacity = 8; // 8 : means number 155 } 156 } 157 forEach(callbackfn: (value?: T, key?: T, set?: LightWeightSet<T>) => void, 158 thisArg?: Object): void { 159 errorUtil.checkBindError('forEach', LightWeightSet, this); 160 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 161 for (let i: number = 0; i < this.memberNumber; i++) { 162 callbackfn.call(thisArg, this.members.keys[i], this.members.keys[i], this); 163 } 164 } 165 [Symbol.iterator](): IterableIterator<T> { 166 errorUtil.checkBindError('Symbol.iterator', LightWeightSet, this); 167 let count: number = 0; 168 return { 169 next: function (): { done: boolean, value: T } { 170 let done: boolean = false; 171 let value: T = undefined; 172 done = count >= this.memberNumber; 173 value = done ? undefined : this.members.keys[count]; 174 count++; 175 return { 176 done: done, 177 value: value, 178 }; 179 }, 180 }; 181 } 182 toString(): string { 183 errorUtil.checkBindError('toString', LightWeightSet, this); 184 return this.members.keys.join(','); 185 } 186 toArray(): Array<T> { 187 errorUtil.checkBindError('toArray', LightWeightSet, this); 188 return this.members.keys.slice(); 189 } 190 getValueAt(index: number): T { 191 errorUtil.checkBindError('getValueAt', LightWeightSet, this); 192 errorUtil.checkTypeError('index', 'Integer', index); 193 return this.members.keys[index]; 194 } 195 values(): IterableIterator<T> { 196 errorUtil.checkBindError('values', LightWeightSet, this); 197 return this.members.keys.values() as IterableIterator<T>; 198 } 199 entries(): IterableIterator<[T, T]> { 200 errorUtil.checkBindError('entries', LightWeightSet, this); 201 let count: number = 0; 202 return { 203 next: function (): { done: boolean, value: [T, T] } { 204 let done: boolean = false; 205 let value: [T, T] = undefined; 206 let tempValue: T = undefined; 207 done = count >= this.memberNumber; 208 tempValue = this.members.keys[count]; 209 value = done ? undefined : ([tempValue, tempValue] as [T, T]); 210 count++; 211 return { 212 done: done, 213 value: value, 214 }; 215 }, 216 }; 217 } 218 } 219 Object.freeze(LightWeightSet); 220 fastLightWeightSet = LightWeightSet; 221} 222export default fastLightWeightSet; 223