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 TreeMap: number; 18 Load(key: number): Object; 19} 20let flag: boolean = false; 21let fastTreeMap: Object = undefined; 22let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 23if (arkPritvate !== undefined) { 24 fastTreeMap = arkPritvate.Load(arkPritvate.TreeMap); 25} else { 26 flag = true; 27} 28if (flag || fastTreeMap === undefined) { 29 let treeAbility = requireNapi('util.struct'); 30 const errorUtil = treeAbility.errorUtil; 31 interface IterableIterator<T> { 32 next: () => { 33 value: T | undefined; 34 done: boolean; 35 }; 36 } 37 class HandlerTreeMap<K, V> { 38 set(target: TreeMap<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 TreeMap Object`); 47 } 48 deleteProperty(): boolean { 49 throw new Error(`Can't delete Property on TreeMap Object`); 50 } 51 setPrototypeOf(): boolean { 52 throw new Error(`Can't set Prototype on TreeMap Object`); 53 } 54 } 55 class TreeMap<K, V> { 56 private constitute: any; 57 constructor(comparator?: (firstValue: K, secondValue: K) => boolean) { 58 errorUtil.checkNewTargetIsNullError('TreeMap', !new.target); 59 if (comparator) { 60 errorUtil.checkTypeError('comparator', 'callable', comparator); 61 } 62 this.constitute = new treeAbility.TreeClass(comparator); 63 return new Proxy(this, new HandlerTreeMap()); 64 } 65 get length(): number { 66 return this.constitute.memberNumber; 67 } 68 isEmpty(): boolean { 69 errorUtil.checkBindError('isEmpty', TreeMap, this); 70 return this.constitute.memberNumber === 0; 71 } 72 hasKey(key: K): boolean { 73 errorUtil.checkBindError('hasKey', TreeMap, this); 74 return this.constitute.getNode(key) !== undefined; 75 } 76 hasValue(value: V): boolean { 77 errorUtil.checkBindError('hasValue', TreeMap, this); 78 return this.constitute.findNode(value) !== undefined; 79 } 80 get(key: K): V { 81 errorUtil.checkBindError('get', TreeMap, this); 82 if (this.constitute.getNode(key) === undefined) { 83 return undefined; 84 } 85 return this.constitute.getNode(key).value; 86 } 87 getFirstKey(): K { 88 errorUtil.checkBindError('getFirstKey', TreeMap, this); 89 if (this.constitute.firstNode() === undefined) { 90 return undefined; 91 } 92 return this.constitute.firstNode().key; 93 } 94 getLastKey(): K { 95 errorUtil.checkBindError('getLastKey', TreeMap, this); 96 if (this.constitute.lastNode() === undefined) { 97 return undefined; 98 } 99 return this.constitute.lastNode().key; 100 } 101 setAll(map: TreeMap<K, V>): void { 102 errorUtil.checkBindError('setAll', TreeMap, this); 103 errorUtil.checkTypeError('map', 'TreeMap', map); 104 this.constitute.setAll(map.constitute); 105 } 106 set(key: K, value: V): Object { 107 errorUtil.checkBindError('set', TreeMap, this); 108 return this.constitute.addNode(key, value); 109 } 110 remove(key: K): V { 111 errorUtil.checkBindError('remove', TreeMap, this); 112 return this.constitute.removeNode(key); 113 } 114 clear(): void { 115 errorUtil.checkBindError('clear', TreeMap, this); 116 this.constitute.clearTree(); 117 } 118 getLowerKey(key: K): K { 119 errorUtil.checkBindError('getLowerKey', TreeMap, this); 120 let result: K | undefined = undefined; 121 if (this.constitute.getNode(key) === undefined) { 122 return undefined; 123 } 124 if (this.constitute.getNode(key).left !== undefined) { 125 return this.constitute.getNode(key).left.key; 126 } 127 let node = this.constitute.getNode(key); 128 while (node.parent !== undefined) { 129 if (node.parent.right === node) { 130 return node.parent.key; 131 } 132 node = node.parent; 133 } 134 return result; 135 } 136 getHigherKey(key: K): K { 137 errorUtil.checkBindError('getHigherKey', TreeMap, this); 138 let result: K | undefined = undefined; 139 if (this.constitute.getNode(key) === undefined) { 140 return undefined; 141 } 142 if (this.constitute.getNode(key).right !== undefined) { 143 return this.constitute.getNode(key).right.key; 144 } 145 let node = this.constitute.getNode(key); 146 while (node.parent !== undefined) { 147 if (node.parent.left === node) { 148 return node.parent.key; 149 } 150 node = node.parent; 151 } 152 return result; 153 } 154 keys(): IterableIterator<K> { 155 errorUtil.checkBindError('keys', TreeMap, this); 156 let count: number = 0; 157 return { 158 next: function (): { done: boolean, value: K } { 159 let done: boolean = false; 160 let value: K = undefined; 161 done = count >= this.constitute.memberNumber; 162 value = done ? undefined : this.constitute.keyValueArray[count].key; 163 count++; 164 return { 165 done: done, 166 value: value, 167 }; 168 }, 169 }; 170 } 171 values(): IterableIterator<V> { 172 errorUtil.checkBindError('values', TreeMap, this); 173 let count: number = 0; 174 return { 175 next: function (): { done: boolean, value: V } { 176 let done: boolean = false; 177 let value: V = undefined; 178 done = count >= this.constitute.memberNumber; 179 value = done ? undefined : this.constitute.keyValueArray[count].value; 180 count++; 181 return { 182 done: done, 183 value: value, 184 }; 185 }, 186 }; 187 } 188 replace(key: K, newValue: V): boolean { 189 errorUtil.checkBindError('replace', TreeMap, this); 190 if (this.constitute.getNode(key) === undefined) { 191 return false; 192 } 193 this.constitute.getNode(key).value = newValue; 194 return true; 195 } 196 forEach(callbackfn: (value?: V, key?: K, map?: TreeMap<K, V>) => void, 197 thisArg?: Object): void { 198 errorUtil.checkBindError('forEach', TreeMap, this); 199 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 200 for (let i: number = 0; i < this.constitute.memberNumber; i++) { 201 callbackfn.call(thisArg, this.constitute.keyValueArray[i].value as V, this.constitute.keyValueArray[i].key); 202 } 203 } 204 entries(): IterableIterator<[K, V]> { 205 errorUtil.checkBindError('entries', TreeMap, this); 206 let count: number = 0; 207 return { 208 next: function (): { done: boolean, value: [K, V] } { 209 let done: boolean = false; 210 let value: [K, V] = undefined; 211 done = count >= this.constitute.memberNumber; 212 value = done ? undefined : this.constitute.keyValueArray[count].entry(); 213 count++; 214 return { 215 done: done, 216 value: value, 217 }; 218 }, 219 }; 220 } 221 [Symbol.iterator](): IterableIterator<[K, V]> { 222 errorUtil.checkBindError('Symbol.iterator', TreeMap, this); 223 return this.entries(); 224 } 225 } 226 Object.freeze(TreeMap); 227 fastTreeMap = TreeMap; 228} 229export default fastTreeMap; 230