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