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