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 RBTreeAbility = requireNapi('util.struct'); 30 const ErrorUtil = RBTreeAbility.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: any, value: any): 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 RBTreeAbility.RBTreeClass(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() { 88 ErrorUtil.checkBindError("clear", TreeSet, this); 89 this.constitute.clearTree(); 90 } 91 getFirstValue(): T { 92 ErrorUtil.checkBindError("getFirstValue", TreeSet, this); 93 let tempNode: any = undefined; 94 tempNode = this.constitute.firstNode(); 95 if (tempNode === undefined) { 96 return tempNode; 97 } 98 return tempNode.key; 99 } 100 getLastValue(): T { 101 ErrorUtil.checkBindError("getLastValue", TreeSet, this); 102 let tempNode: any = undefined; 103 tempNode = this.constitute.lastNode(); 104 if (tempNode === undefined) { 105 return tempNode; 106 } 107 return tempNode.key; 108 } 109 getLowerValue(key: T): T { 110 ErrorUtil.checkBindError("getLowerValue", TreeSet, this); 111 let tempNode: any = undefined; 112 tempNode = this.constitute.getNode(key); 113 if (tempNode === undefined) { 114 return tempNode; 115 } 116 if (tempNode.left !== undefined) { 117 return tempNode.left.key; 118 } 119 let node: any = tempNode; 120 while (node.parent !== undefined) { 121 if (node.parent.right === node) { 122 return node.parent.key; 123 } 124 node = node.parent; // node.parent.left === node is true; 125 } 126 return undefined; 127 } 128 getHigherValue(key: T): T { 129 ErrorUtil.checkBindError("getHigherValue", TreeSet, this); 130 let tempNode: any = undefined; 131 tempNode = this.constitute.getNode(key); 132 if (tempNode === undefined) { 133 return tempNode; 134 } 135 if (tempNode.right !== undefined) { 136 return tempNode.right.key; 137 } 138 let node: any = tempNode; 139 while (node.parent !== undefined) { 140 if (node.parent.left === node) { 141 return node.parent.key; 142 } 143 node = node.parent; // node.parent.right === node is true; 144 } 145 undefined; 146 } 147 popFirst(): T { 148 ErrorUtil.checkBindError("popFirst", TreeSet, this); 149 let firstNode: any = undefined; 150 firstNode = this.constitute.firstNode(); 151 if (firstNode === undefined) { 152 return firstNode; 153 } 154 let value: T = firstNode.value; 155 this.constitute.removeNodeProcess(firstNode); 156 return value; 157 } 158 popLast(): T { 159 ErrorUtil.checkBindError("popLast", TreeSet, this); 160 let lastNode: any = undefined; 161 lastNode = this.constitute.lastNode(); 162 if (lastNode === undefined) { 163 return lastNode; 164 } 165 let value: T = lastNode.value; 166 this.constitute.removeNodeProcess(lastNode); 167 return value; 168 } 169 values(): IterableIterator<T> { 170 ErrorUtil.checkBindError("values", TreeSet, this); 171 let data: any = this.constitute; 172 let count: number = 0; 173 return { 174 next: function () { 175 let done: boolean = false; 176 let value: T = undefined; 177 done = count >= data.memberNumber; 178 value = done ? undefined : data.keyValueArray[count].value as T; 179 count++; 180 return { 181 done: done, 182 value: value, 183 }; 184 }, 185 }; 186 } 187 forEach(callbackfn: (value?: T, key?: T, set?: TreeSet<T>) => void, 188 thisArg?: Object): void { 189 ErrorUtil.checkBindError("forEach", TreeSet, this); 190 ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn); 191 let data: any = this.constitute; 192 let tagetArray: Array<any> = data.keyValueArray; 193 for (let i: number = 0; i < data.memberNumber; i++) { 194 callbackfn.call(thisArg, tagetArray[i].value as T, tagetArray[i].key); 195 } 196 } 197 entries(): IterableIterator<[T, T]> { 198 ErrorUtil.checkBindError("entries", TreeSet, this); 199 let data: any = this.constitute; 200 let count: number = 0; 201 return { 202 next: function () { 203 let done: boolean = false; 204 let value: [T, T] = undefined; 205 done = count >= data.memberNumber; 206 value = done ? undefined : data.keyValueArray[count].entry(); 207 count++; 208 return { 209 done: done, 210 value: value, 211 }; 212 }, 213 }; 214 } 215 [Symbol.iterator](): IterableIterator<T> { 216 ErrorUtil.checkBindError("Symbol.iterator", TreeSet, this); 217 return this.values(); 218 } 219 } 220 Object.freeze(TreeSet); 221 fastTreeSet = TreeSet; 222} 223export default fastTreeSet; 224