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 */ 15type CompFun<T> = (firstValue: T, secondValue: T) => boolean; 16 17function hashCode(element: any): number { 18 let str: string = ''; 19 str = String(element); 20 let hash: number = 0; 21 if (hash === 0 && str.length > 0) { 22 for (let i: number = 0; i < str.length; i++) { 23 let char: number = 0; 24 char = str.charCodeAt(i); 25 hash = ((hash << 5) - hash) + char; 26 hash = hash & hash; 27 } 28 } 29 return hash; 30} 31function insert<T>(a: Array<T>, index: number, value: T): void { 32 for (let i: number = a.length; i > index; i--) { 33 a[i] = a[i - 1]; 34 } 35 a[index] = value; 36} 37enum ComparResult { 38 LESS_THAN = -1, 39 BIGGER_THAN = 1, 40 EQUALS = 0 41} 42function compareToString(string1: String, string2: String): number { 43 let len1: number = string1.length; 44 let len2: number = string2.length; 45 let lim: number = 0; 46 lim = (len1 > len2 ? len2 : len1); 47 let k: number = 0; 48 while (k < lim) { 49 if (string1.charCodeAt(k) === string2.charCodeAt(k)) { 50 k++; 51 if (k === lim) { 52 return len1 > len2 ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN; 53 } 54 continue; 55 } 56 return string1.charCodeAt(k) > string2.charCodeAt(k) ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN; 57 } 58 throw new Error('this compare function run error'); 59} 60function currencyCompare(a: any, b: any, compareFn?: CompFun<any>): number { 61 if (a === b) { 62 return ComparResult.EQUALS; 63 } 64 if (a instanceof Pair && b instanceof Pair) { 65 return currencyCompare(a.key, b.key, compareFn); 66 } 67 if (compareFn != undefined) { 68 return compareFn(a, b) ? ComparResult.BIGGER_THAN : ComparResult.LESS_THAN; 69 } 70 if (typeof a === 'number' && typeof b === 'number') { 71 if (a > b) { 72 return ComparResult.BIGGER_THAN; 73 } else { 74 return ComparResult.LESS_THAN; 75 } 76 } else if (typeof a === 'string' && typeof b === 'string') { 77 return compareToString(a, b); 78 } else if (typeof a === 'string' && typeof b === 'number') { 79 return ComparResult.BIGGER_THAN; 80 } else if (typeof a === 'number' && typeof b === 'string') { 81 return ComparResult.LESS_THAN; 82 } 83 throw new Error('This form of comparison is not supported'); 84} 85function isIncludeToArray(array1: Array<any>, array2: Array<any>): boolean { 86 let newList: number[] = []; 87 newList = array1.filter((val) => { 88 return array2.indexOf(val) > -1; 89 }) 90 if (newList.length === array2.length) { 91 return true; 92 } 93 return false; 94} 95class Pair<K, V>{ 96 key: K; 97 value: V; 98 constructor(key: K, value: V = key as unknown as V) { 99 this.key = key; 100 this.value = value; 101 } 102 entry(): [K, V] { 103 return [this.key, this.value]; 104 } 105 toString(): string { 106 return `[#${this.key}: ${this.value}]`; 107 } 108} 109class PlainArrayMembers<T> { 110 keys: Array<number>; 111 values: Array<T>; 112 constructor() { 113 this.keys = []; 114 this.values = []; 115 } 116} 117class PlainArrayClass<T> { 118 protected memberNumber: number; 119 protected members: PlainArrayMembers<T>; 120 constructor() { 121 this.memberNumber = 0; 122 this.members = new PlainArrayMembers<T>(); 123 } 124 protected addmember(key: number, value: T): void { 125 let index: number = 0; 126 index = this.binarySearchAtPlain(key); 127 if (index >= 0) { 128 this.members.keys[index] = key; 129 this.members.values[index] = value; 130 } else { 131 index = ~index; 132 insert(this.members.keys, index, key); 133 insert(this.members.values, index, value); 134 this.memberNumber++; 135 } 136 } 137 protected deletemember(index: number, safeSize: number = 1): T { 138 this.memberNumber -= safeSize; 139 this.members.keys.splice(index, safeSize); 140 let removeValue = this.members.values.splice(index, safeSize)[0]; 141 return removeValue; 142 } 143 protected binarySearchAtPlain(key: number, startIndex: number = 0, endIndex: number = this.memberNumber): number { 144 let low: number = startIndex; 145 let high: number = endIndex - 1; 146 while (low <= high) { 147 let mid: number = (low + high) >>> 1; 148 let midVal: number = this.members.keys[mid]; 149 if (midVal < key) { 150 low = mid + 1; 151 } else { 152 if (midVal <= key) { 153 return mid; 154 } 155 high = mid - 1; 156 } 157 } 158 return -(low + 1); 159 } 160} 161class LightWeightMembers<K, V> { 162 hashs: Array<number>; 163 keys: Array<K>; 164 values: Array<V>; 165 constructor() { 166 this.hashs = []; 167 this.keys = []; 168 this.values = []; 169 } 170} 171class LightWeightClass<K, V> { 172 protected memberNumber: number; 173 protected members: LightWeightMembers<K, V>; 174 protected capacity: number = 8; 175 constructor() { 176 this.memberNumber = 0; 177 this.members = new LightWeightMembers<K, V>(); 178 } 179 protected addmember(key: K, value: V = key as unknown as V): void { 180 let hash: number = 0; 181 hash = hashCode(key); 182 let index: number = 0; 183 index = this.binarySearchAtLightWeight(hash); 184 if (index >= 0) { 185 this.members.keys[index] = key; 186 this.members.values[index] = value; 187 } else { 188 index = ~index; 189 insert(this.members.hashs, index, hash); 190 insert(this.members.keys, index, key); 191 insert(this.members.values, index, value); 192 this.memberNumber++; 193 } 194 if (this.capacity < this.memberNumber) this.ensureCapacity(1); 195 } 196 protected getIndexByKey(key: K): number { 197 let hash: number = 0; 198 hash = hashCode(key); 199 let index: number = 0; 200 index = this.binarySearchAtLightWeight(hash); 201 // js ( A negative number indicates an inverted number in the array ) 202 if (index < 0 || index >= this.memberNumber) return -1; 203 return index; 204 } 205 protected deletemember(key: K): V { 206 let result: any = undefined; 207 let index: number = 0; 208 index = this.getIndexByKey(key); 209 if (index < 0) { 210 return result; 211 } 212 this.memberNumber--; 213 this.members.hashs.splice(index, 1); 214 this.members.keys.splice(index, 1); 215 return this.members.values.splice(index, 1)[0]; 216 } 217 protected ensureCapacity(addCapacity: number = 1): void { 218 let tempCapacity: number = 0; 219 tempCapacity = this.capacity + addCapacity; 220 while (this.capacity < tempCapacity) { 221 this.capacity = 2 * this.capacity; 222 } 223 } 224 protected getIndex(key: K): number { 225 let hash: number = 0; 226 hash = hashCode(key); 227 let index: number = 0; 228 index = this.binarySearchAtLightWeight(hash); 229 if (index < 0) { 230 index = ~index; 231 } 232 return index; 233 } 234 protected keyValueStringArray(): Array<string> { 235 let resultArray: Array<string> = []; 236 for (let i: number = 0; i < this.memberNumber; i++) { 237 resultArray.push(JSON.stringify(this.members.keys[i]) + ':' + JSON.stringify(this.members.values[i])); 238 } 239 return resultArray; 240 } 241 protected binarySearchAtLightWeight(hash: number, startIndex: number = 0, endIndex: number = this.memberNumber): number { 242 let low: number = startIndex; 243 let high: number = endIndex - 1; 244 while (low <= high) { 245 let mid: number = 0; 246 mid = (low + high) >>> 1; 247 let midVal: number = 0; 248 midVal = this.members.hashs[mid]; 249 if (midVal < hash) { 250 low = mid + 1; 251 } else { 252 if (midVal <= hash) { 253 return mid; 254 } 255 high = mid - 1; 256 } 257 } 258 return -(low + 1); 259 } 260} 261type RBTreeNodeColor = 0 | 1; 262const BLACK = 0; 263const RED = 1; 264class RBTreeNode<K, V> extends Pair<K, V>{ 265 color: RBTreeNodeColor; 266 left: RBTreeNode<K, V> | undefined; 267 right: RBTreeNode<K, V> | undefined; 268 parent: RBTreeNode<K, V> | undefined; 269 constructor(key: K, 270 value?: V, 271 color: RBTreeNodeColor = RED, 272 parent?: RBTreeNode<K, V>, 273 left?: RBTreeNode<K, V>, 274 right?: RBTreeNode<K, V>) { 275 super(key, value); 276 this.color = color; 277 this.left = left; 278 this.right = right; 279 this.parent = parent; 280 } 281} 282class RBTreeClass<K, V> { 283 private root: RBTreeNode<K, V> | undefined; 284 public memberNumber: number; 285 private isChange: boolean; 286 private treeNodeArray: Array<RBTreeNode<K, V>>; 287 private compFun: CompFun<K> | undefined; 288 constructor(comparator?: CompFun<K>, root?: RBTreeNode<K, V>) { 289 this.root = root; 290 this.compFun = comparator; 291 this.memberNumber = 0; 292 this.isChange = true; 293 this.treeNodeArray = []; 294 } 295 get keyValueArray(): Array<RBTreeNode<K, V>> { 296 let result: Array<RBTreeNode<K, V>> = []; 297 result = this.recordByMinToMax(); 298 return result; 299 } 300 addNode(key: K, value: V = key as unknown as V): RBTreeClass<K, V> { 301 if (this.root === undefined) { 302 this.root = new RBTreeNode<K, V>(key, value); 303 this.setColor(BLACK, this.root); 304 this.memberNumber++; 305 this.isChange = true; 306 } else { 307 this.addProcess(key, value) 308 } 309 return this; 310 } 311 addProcess(key: K, value: V): RBTreeClass<K, V> { 312 let leafNode: RBTreeNode<K, V> | undefined = this.root; 313 let parentNode: RBTreeNode<K, V> = this.root as RBTreeNode<K, V>; 314 let comp: number = 0; 315 while (leafNode !== undefined) { 316 parentNode = leafNode; 317 comp = currencyCompare(leafNode.key, key, this.compFun); 318 if (comp === 0) { 319 leafNode.value = value; 320 return this; 321 } else if (comp < 0) { 322 leafNode = leafNode.right; 323 } else { 324 leafNode = leafNode.left; 325 } 326 } 327 leafNode = new RBTreeNode<K, V>(key, value) 328 leafNode.parent = parentNode; 329 if (comp < 0) { 330 parentNode.right = leafNode; 331 } else { 332 parentNode.left = leafNode; 333 } 334 this.insertRebalance(leafNode); 335 this.memberNumber++; 336 this.isChange = true; 337 return this; 338 } 339 removeNode(key: K): V | undefined { 340 let removeNode: RBTreeNode<K, V> | undefined = undefined; 341 removeNode = this.getNode(key); 342 if (removeNode === undefined) { 343 return undefined; 344 } else { 345 let result: V = removeNode.value; 346 this.removeNodeProcess(removeNode); 347 return result; 348 } 349 } 350 removeNodeProcess(removeNode: RBTreeNode<K, V>): void { 351 if (removeNode.left !== undefined && removeNode.right !== undefined) { 352 let successor: RBTreeNode<K, V> | undefined = removeNode.right; 353 while (successor.left !== undefined) { 354 successor = successor.left; 355 } 356 removeNode.key = successor.key; 357 removeNode.value = successor.value; 358 this.removeNodeProcess(successor); // only once 359 return; 360 } else { // one or zero child 361 let child: RBTreeNode<K, V> | undefined = undefined; 362 child = (removeNode.left === undefined ? removeNode.right : removeNode.left); 363 if (removeNode.parent === undefined) { // remove is root 364 if (child === undefined) { 365 this.root = undefined; 366 } else { 367 child.parent = undefined; 368 child.color = BLACK; 369 this.root = child; 370 } 371 } else { 372 if (child != undefined) { 373 // delete removeNode 374 if (removeNode.parent.left === removeNode) { 375 removeNode.parent.left = child; 376 } else { 377 removeNode.parent.right = child; 378 } 379 if (this.getColor(removeNode) === BLACK) { 380 this.deleteRebalance(child) 381 } 382 } else { 383 if (this.getColor(removeNode) === BLACK) { 384 this.deleteRebalance(removeNode) 385 } 386 if (removeNode.parent.left === removeNode) { 387 removeNode.parent.left = child; 388 } else { 389 removeNode.parent.right = child; 390 } 391 } 392 } 393 this.memberNumber--; 394 this.isChange = true; 395 } 396 } 397 getNode(key: K): RBTreeNode<K, V> | undefined { 398 if (this.root === undefined) { 399 return undefined; 400 } 401 let findNode: RBTreeNode<K, V> | undefined = this.root; 402 while (findNode !== undefined && findNode.key !== key) { 403 findNode = currencyCompare(findNode.key, key, this.compFun) === ComparResult.BIGGER_THAN ? 404 findNode.left : findNode.right; 405 } 406 return findNode; 407 } 408 findNode(value: V): RBTreeNode<K, V> | undefined { 409 let tempNode: RBTreeNode<K, V> | undefined = undefined; 410 this.recordByMinToMax(); 411 for (let i: number = 0; i < this.memberNumber; i++) { 412 if (this.treeNodeArray[i].value === value) { 413 tempNode = this.treeNodeArray[i]; 414 break; 415 } 416 } 417 return tempNode; 418 } 419 firstNode(): RBTreeNode<K, V> | undefined { 420 let tempNode: RBTreeNode<K, V> | undefined = this.root; 421 while (tempNode !== undefined && tempNode.left !== undefined) { 422 tempNode = tempNode.left; 423 } 424 return tempNode; 425 } 426 lastNode(): RBTreeNode<K, V> | undefined { 427 let tempNode: RBTreeNode<K, V> | undefined = this.root; 428 while (tempNode !== undefined && tempNode.right !== undefined) { 429 tempNode = tempNode.right; 430 } 431 return tempNode; 432 } 433 isEmpty(): boolean { 434 return this.root === undefined; 435 } 436 setAll(map: RBTreeClass<K, V>): void { 437 let tempArray: RBTreeNode<K, V>[] = []; 438 tempArray = map.recordByMinToMax(); 439 for (let i: number = 0; i < map.memberNumber; i++) { 440 this.addNode(tempArray[i].key, tempArray[i].value); 441 } 442 } 443 clearTree(): void { 444 this.root = undefined; 445 this.memberNumber = 0; 446 } 447 private recordByMinToMax(): Array<RBTreeNode<K, V>> { 448 if (!this.isChange) { 449 return this.treeNodeArray; 450 } 451 let stack: Array<any> = []; 452 this.treeNodeArray = []; 453 let node: RBTreeNode<K, V> | undefined = this.root; 454 while (node != undefined || stack.length) { 455 while (node != undefined) { 456 stack.push(node); 457 node = node.left; 458 } 459 let tempNode = stack.pop(); 460 if (tempNode === undefined) { 461 throw new Error('this function run error'); 462 } 463 node = tempNode; 464 this.treeNodeArray.push(node); 465 node = node.right; 466 } 467 this.isChange = false; 468 this.memberNumber = this.treeNodeArray.length; 469 return this.treeNodeArray; 470 } 471 private lRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> { 472 let newTopNode: RBTreeNode<K, V> | undefined = datumPointNode.right; 473 if (newTopNode === undefined) { 474 throw new Error('[rotate right error]: the right child node of the base node === undefined') 475 } 476 datumPointNode.right = newTopNode.left; 477 datumPointNode.right !== undefined ? datumPointNode.right.parent = datumPointNode : ''; 478 newTopNode.parent = datumPointNode.parent; 479 if (datumPointNode.parent === undefined) { 480 this.root = newTopNode; 481 } else if (datumPointNode.parent.left === datumPointNode) { 482 datumPointNode.parent.left = newTopNode; 483 } else if (datumPointNode.parent.right === datumPointNode) { 484 datumPointNode.parent.right = newTopNode; 485 } 486 datumPointNode.parent = newTopNode; 487 newTopNode.left = datumPointNode; 488 return this; 489 } 490 private rRotate(datumPointNode: RBTreeNode<K, V>): RBTreeClass<K, V> { 491 let newTopNode: RBTreeNode<K, V> | undefined = datumPointNode.left; 492 if (newTopNode === undefined) { 493 throw new Error('[rotate right error]: the left child node of the base node === undefined') 494 } 495 datumPointNode.left = newTopNode.right; 496 datumPointNode.left !== undefined ? datumPointNode.left.parent = datumPointNode : ''; 497 newTopNode.parent = datumPointNode.parent 498 if (datumPointNode.parent === undefined) { 499 this.root = newTopNode; 500 } else if (datumPointNode === datumPointNode.parent.left) { 501 datumPointNode.parent.left = newTopNode; 502 } else if (datumPointNode === datumPointNode.parent.right) { 503 datumPointNode.parent.right = newTopNode; 504 } 505 datumPointNode.parent = newTopNode; 506 newTopNode.right = datumPointNode; 507 return this; 508 } 509 private insertRebalance(fixNode: RBTreeNode<K, V>): RBTreeClass<K, V> { 510 let parentNode: RBTreeNode<K, V> | undefined = fixNode.parent; 511 while (this.getColor(parentNode) === RED && 512 parentNode !== undefined && 513 parentNode.parent !== undefined) { 514 let grandpaNode = parentNode && parentNode.parent; 515 if (parentNode === grandpaNode.left && 516 this.getColor(grandpaNode.right) === BLACK && 517 fixNode === parentNode.left) { 518 this 519 .setColor(BLACK, parentNode) 520 .setColor(RED, grandpaNode) 521 .rRotate(grandpaNode) 522 break; 523 } else if (parentNode === grandpaNode.left && 524 this.getColor(grandpaNode.right) === BLACK && 525 fixNode === parentNode.right) { 526 this 527 .setColor(BLACK, fixNode) 528 .setColor(RED, grandpaNode) 529 .lRotate(parentNode) 530 .rRotate(grandpaNode) 531 break; 532 } else if (parentNode === grandpaNode.right && 533 this.getColor(grandpaNode.left) === BLACK && 534 fixNode === parentNode.left) { 535 this 536 .setColor(BLACK, fixNode) 537 .setColor(RED, grandpaNode) 538 .rRotate(parentNode) 539 .lRotate(grandpaNode) 540 break; 541 } else if (parentNode === grandpaNode.right && 542 this.getColor(grandpaNode.left) === BLACK && 543 fixNode === parentNode.right) { 544 this 545 .setColor(BLACK, parentNode) 546 .setColor(RED, grandpaNode) 547 .lRotate(grandpaNode) 548 break; 549 } else if ((parentNode === grandpaNode.right && this.getColor(grandpaNode.left) === RED) || 550 (parentNode === grandpaNode.left && this.getColor(grandpaNode.right) === RED)) { 551 this 552 .setColor(BLACK, parentNode) 553 .setColor(BLACK, parentNode === grandpaNode.left ? grandpaNode.right : grandpaNode.left) 554 .setColor(RED, grandpaNode) 555 fixNode = grandpaNode; 556 parentNode = fixNode.parent; 557 } else { 558 throw new Error('Exceptions after adding') 559 } 560 } 561 this.root ? this.root.color = BLACK : ''; 562 return this; 563 } 564 private deleteRebalance(fixNode: RBTreeNode<K, V>): void { 565 while (this.getColor(fixNode) === BLACK && fixNode !== this.root && fixNode.parent) { 566 let sibling: RBTreeNode<K, V> | undefined = undefined; 567 if (fixNode === fixNode.parent.left) { 568 sibling = fixNode.parent.right; 569 if (this.getColor(sibling) === RED) { 570 this 571 .setColor(RED, fixNode.parent) 572 .setColor(BLACK, sibling) 573 .lRotate(fixNode.parent) 574 sibling = fixNode.parent.right; 575 } 576 if (sibling === undefined) { 577 throw new Error('Error sibling node is undefined') 578 } 579 if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) { 580 this.setColor(RED, sibling) 581 fixNode = fixNode.parent 582 } else if (this.getColor(sibling.left) === RED && this.getColor(sibling.right) === BLACK) { 583 this 584 .setColor(RED, sibling) 585 .setColor(BLACK, sibling.left) 586 .rRotate(sibling); 587 sibling = fixNode.parent.right 588 if (sibling === undefined) { 589 throw new Error('Error sibling node is empty') 590 } 591 this 592 .setColor(fixNode.parent.color, sibling) 593 .setColor(BLACK, fixNode.parent) 594 .setColor(BLACK, sibling.right) 595 .lRotate(fixNode.parent); 596 break; 597 } else if (this.getColor(sibling.right) === RED) { 598 this 599 .setColor(fixNode.parent.color, sibling) 600 .setColor(BLACK, fixNode.parent) 601 .setColor(BLACK, sibling.right) 602 .lRotate(fixNode.parent); 603 break; 604 } else { 605 throw new Error('Adjust the error after the error is deleted') 606 } 607 } else { 608 sibling = fixNode.parent.left; 609 if (this.getColor(sibling) === RED) { 610 this 611 .setColor(BLACK, sibling) 612 .setColor(RED, fixNode.parent) 613 .rRotate(fixNode.parent); 614 sibling = fixNode.parent.left; 615 } 616 if (sibling === undefined) { 617 throw new Error('Error sibling node is undefined') 618 } 619 if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === BLACK) { 620 this 621 .setColor(RED, sibling) 622 fixNode = fixNode.parent; 623 } else if (this.getColor(sibling.left) === BLACK && this.getColor(sibling.right) === RED) { 624 this 625 .setColor(RED, sibling) 626 .setColor(BLACK, sibling.right) 627 .lRotate(sibling); 628 sibling = fixNode.parent.left; 629 if (sibling === undefined) { 630 throw new Error('Adjust the error after the error is deleted') 631 } 632 this 633 .setColor(fixNode.parent.color, sibling) 634 .setColor(BLACK, fixNode.parent) 635 .setColor(BLACK, sibling.left) 636 .rRotate(fixNode.parent); 637 break; 638 } else if (this.getColor(sibling.left) === RED) { 639 this 640 .setColor(fixNode.parent.color, sibling) 641 .setColor(BLACK, fixNode.parent,) 642 .setColor(BLACK, sibling.left) 643 .rRotate(fixNode.parent); 644 break; 645 } else { 646 throw new Error('Adjust the error after the error is deleted') 647 } 648 } 649 } 650 this.setColor(BLACK, fixNode) 651 } 652 private getColor(node: RBTreeNode<K, V> | undefined): RBTreeNodeColor { 653 return node === undefined ? BLACK : node.color; 654 } 655 private setColor(color: RBTreeNodeColor, node: RBTreeNode<K, V> | undefined): RBTreeClass<K, V> { 656 if (node === undefined) { 657 throw new Error('Wrong color setting') 658 } else { 659 node.color = color 660 } 661 return this; 662 } 663} 664const MAXcapacity = 1 << 30; 665const LOADER_FACTOR = 0.75; 666class DictionaryClass<K, V> { 667 private tableLink: { [hashIndex: number]: LinkedList<Pair<K, V>> | RBTreeClass<K, V> }; 668 protected memberNumber: number; 669 private isChange: boolean; 670 private memberArray: Array<Pair<K, V>>; 671 private capacity: number; 672 constructor() { 673 this.tableLink = {}; 674 this.memberNumber = 0; 675 this.isChange = true; 676 this.memberArray = []; 677 this.capacity = 16; 678 } 679 get keyValueArray(): Pair<K, V>[] { 680 let result: Pair<K, V>[] = []; 681 result = this.keyValues(); 682 return result; 683 } 684 protected getHashIndex(key: K): number { 685 let h: number = 0; 686 let hash: number = 0; 687 hash = ((key === null) ? 0 : ((h = hashCode(key)) ^ (h >>> 16))); 688 if (this.expandCapacity()) { 689 this.keyValues(); 690 this.memberNumber = 0; 691 this.tableLink = {}; 692 this.isChange = true; 693 for (let item of this.memberArray) { 694 this.put(item.key, item.value); 695 } 696 this.memberNumber++; 697 } 698 let n: number = 0; 699 n = this.power(this.capacity); 700 return (n - 1) & hash; 701 } 702 private power(size: number): number { 703 let n: number = 1; 704 let temp: number = size; 705 while (temp >>> 1 != 1) { 706 n++; 707 temp = temp >>> 1; 708 } 709 return n; 710 } 711 private keyValues(): Pair<K, V>[] { 712 if (!this.isChange) { 713 return this.memberArray; 714 } 715 this.memberArray = []; 716 let keys: number[] = []; 717 keys = Object.keys(this.tableLink).map((item) => parseInt(item)); 718 for (let i: number = 0; i < keys.length; i++) { 719 let members: RBTreeClass<K, V> | LinkedList<Pair<K, V>> = undefined; 720 members = this.tableLink[keys[i]]; 721 if (members instanceof RBTreeClass) { 722 let tempArray: RBTreeNode<K, V>[] = members.keyValueArray; 723 for (let i: number = 0; i < members.memberNumber; i++) { 724 this.memberArray.push(new Pair(tempArray[i].key, tempArray[i].value)); 725 } 726 } else { 727 if (members != undefined && !members.isEmpty()) { 728 let current: Node<Pair<K, V>> = members.getHead(); 729 while (current != undefined) { 730 this.memberArray.push(current.element); 731 current = current.next; 732 } 733 } 734 } 735 } 736 this.memberNumber = this.memberArray.length; 737 let valuePairs: Pair<K, V>[] = this.memberArray; 738 return valuePairs; 739 } 740 protected expandCapacity(): boolean { 741 let capacityChange: boolean = false; 742 while (this.capacity < this.memberNumber / LOADER_FACTOR && this.capacity < MAXcapacity) { 743 this.capacity = 2 * this.capacity; 744 capacityChange = true; 745 } 746 return capacityChange; 747 } 748 protected put(key: K, value: V = key as unknown as V): boolean { 749 this.isChange = true; 750 if (!this.hasKey(key)) { 751 this.memberNumber++; 752 } 753 let position: number = 0; 754 position = this.getHashIndex(key); 755 let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined; 756 members = this.tableLink[position]; 757 if (members instanceof LinkedList && members.count >= 8) { 758 let newElement: RBTreeClass<K, V> = new RBTreeClass<K, V>(); 759 let current: Node<Pair<K, V>> = undefined; 760 current = members.getHead(); 761 while (current != null || current != undefined) { 762 if (!(current.element instanceof Pair)) return false; 763 newElement.addNode(current.element.key, current.element.value); 764 current = current.next; 765 } 766 newElement.addNode(key, value); 767 this.tableLink[position] = newElement; 768 return true; 769 } else if (members instanceof RBTreeClass) { 770 members.addNode(key, value); 771 this.tableLink[position] = members; 772 return true; 773 } else { 774 if (this.tableLink[position] === undefined) { 775 members = new LinkedList<Pair<K, V>>(); 776 } 777 if (!this.replaceMember(key, value)) { 778 members.push(new Pair(key, value)); 779 this.tableLink[position] = members; 780 } 781 return true; 782 } 783 } 784 protected replaceMember(key: K, value: V = key as unknown as V): boolean { 785 let position: number = 0; 786 position = this.getHashIndex(key); 787 let members: LinkedList<Pair<K, V>> = undefined; 788 members = this.tableLink[position] as LinkedList<Pair<K, V>>; 789 if (members === null || members === undefined) { 790 return false; 791 } 792 let current: Node<Pair<K, V>> = undefined; 793 current = members.getHead(); 794 while (current != undefined) { 795 if (current.element.key === key) { 796 current.element.value = value; 797 return true; 798 } 799 current = current.next; 800 } 801 return false; 802 } 803 protected getValueByKey(key: K): V | undefined { 804 let position: number = 0; 805 position = this.getHashIndex(key); 806 let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined; 807 members = this.tableLink[position]; 808 if (members instanceof RBTreeClass) { 809 let resultNode: RBTreeNode<K, V> | undefined = undefined; 810 resultNode = members.getNode(key); 811 if (resultNode === undefined) return undefined; 812 return resultNode.value; 813 } else { 814 if (members != undefined && !members.isEmpty()) { 815 members as LinkedList<Pair<K, V>>; 816 let current: Node<Pair<K, V>> = undefined; 817 current = members.getHead(); 818 while (current != undefined) { 819 if (current.element.key === key) { 820 return current.element.value; 821 } 822 current = current.next; 823 } 824 } 825 } 826 return undefined; 827 } 828 protected removeMember(key: K): V | undefined { 829 let position: number = 0; 830 position = this.getHashIndex(key); 831 let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined; 832 members = this.tableLink[position]; 833 if (members instanceof RBTreeClass) { 834 let result: V | undefined = members.removeNode(key); 835 if (result != undefined) { 836 this.isChange = true; 837 this.memberNumber--; 838 return result; 839 } 840 } else { 841 if (members != undefined && !members.isEmpty()) { 842 let current: Node<Pair<K, V>> = undefined; 843 current = members.getHead(); 844 while (current != undefined) { 845 if (current.element.key === key) { 846 let result: V | undefined = current.element.value; 847 members.remove(current.element); 848 if (members.isEmpty()) { 849 delete this.tableLink[position]; 850 } 851 this.isChange = true; 852 this.memberNumber--; 853 return result; 854 } 855 current = current.next; 856 } 857 } 858 } 859 return undefined; 860 } 861 protected clear() { 862 this.tableLink = {}; 863 this.memberNumber = 0; 864 this.isChange = true; 865 this.capacity = 16; 866 } 867 protected hasKey(key: K): boolean { 868 let position: number = 0; 869 position = this.getHashIndex(key); 870 let members: LinkedList<Pair<K, V>> | RBTreeClass<K, V> = undefined; 871 members = this.tableLink[position]; 872 if (members === undefined || members === undefined) { 873 return false; 874 } 875 if (members instanceof RBTreeClass) { 876 return members.getNode(key) !== undefined; 877 } 878 let current: Node<Pair<K, V>> = undefined; 879 current = members.getHead(); 880 while (current != undefined && current != undefined) { 881 if (current.element.key === key) { 882 return true; 883 } 884 current = current.next; 885 } 886 return false; 887 } 888 protected setAll(map: DictionaryClass<K, V>): void { 889 let memebers: Pair<K, V>[] = []; 890 memebers = map.keyValues(); 891 for (let i: number = 0; i < memebers.length; i++) { 892 this.put(memebers[i].key, memebers[i].value); 893 } 894 } 895 protected Values(): V[] { 896 let values: Array<V> = []; 897 let valuePairs: Pair<K, V>[] = []; 898 valuePairs = this.keyValues(); 899 for (let i: number = 0; i < valuePairs.length; i++) { 900 values.push(valuePairs[i].value); 901 } 902 return values; 903 } 904} 905class Node<T> { 906 element: T; 907 next: Node<T> | undefined; 908 constructor(element: T, next?: Node<T>) { 909 this.element = element; 910 this.next = next; 911 } 912} 913class LinkedList<T> { 914 public count: number; 915 protected next: Node<T> | undefined; 916 protected head: Node<T> | undefined; 917 constructor() { 918 this.count = 0; 919 this.next = undefined; 920 this.head = undefined; 921 } 922 push(element: T): void { 923 let node: Node<T> = undefined; 924 node = new Node(element); 925 let current: undefined | Node<T>; 926 if (this.head === undefined) { 927 this.head = node; 928 } else { 929 current = this.head; 930 while (current.next != undefined) { 931 current = current.next; 932 } 933 current.next = node; 934 } 935 this.count++; 936 } 937 removeAt(index: number): T { 938 if (index >= 0 && index < this.count) { 939 let current: Node<T> = this.head; 940 if (index === 0 && current != undefined) { 941 this.head = current.next; 942 } else { 943 let previous: Node<T> = this.getElementAt(index--); 944 if (previous !== undefined) { 945 current = previous.next; 946 previous.next = (current === undefined ? undefined : current.next); 947 } 948 } 949 if (current !== undefined) { 950 this.count--; 951 return current.element; 952 } 953 } 954 return undefined; 955 } 956 getElementAt(index: number): Node<T> { 957 if (index > 0 && index < this.count) { 958 let current: Node<T> = this.head; 959 for (let i: number = 0; i < index && current != undefined; i++) { 960 current = current.next; 961 } 962 return current; 963 } 964 return undefined; 965 } 966 insert(element: T, index: number): boolean { 967 if (index >= 0 && index <= this.count) { 968 let node: Node<T> = undefined; 969 node = new Node(element); 970 if (index === 0) { 971 node.next = this.head; 972 this.head = node; 973 } else { 974 let previous: Node<T> = this.getElementAt(index--); 975 if (previous === undefined) 976 throw new Error('data storage error'); 977 node.next = previous.next; 978 previous.next = node; 979 } 980 this.count++; 981 return true; 982 } 983 return false; 984 } 985 indexOf(element: T, compareFn?: CompFun<T>): number { 986 let current: Node<T> = this.head; 987 for (let i: number = 0; i < this.count && current != undefined; i++) { 988 if (currencyCompare(element, current.element, compareFn) === ComparResult.EQUALS) { 989 return i; 990 } 991 current = current.next; 992 } 993 return -1; 994 } 995 remove(element: T, compareFn?: CompFun<T>): void { 996 this.removeAt(this.indexOf(element, compareFn)); 997 } 998 clear(): void { 999 this.head = undefined; 1000 this.count = 0; 1001 } 1002 isEmpty(): boolean { 1003 return this.count === 0; 1004 } 1005 getHead(): Node<T> { 1006 return this.head; 1007 } 1008 toString(): string { 1009 if (this.head === undefined) { 1010 return ''; 1011 } 1012 let objString: string = ''; 1013 objString = `${this.head.element}`; 1014 let current: Node<T> = undefined; 1015 current = this.head.next; 1016 for (let i: number = 1; i < this.count && current != undefined; i++) { 1017 objString = `${objString}, ${current.element}`; 1018 current = current.next; 1019 } 1020 return objString; 1021 } 1022} 1023 1024const NEWTARGET_IS_NULL_ERROR_CODE = 10200012; 1025const BIND_ERROR_CODE = 10200011; 1026const RANGE_ERROR_CODE = 10200001; 1027const TYPE_ERROR_CODE = 401; 1028const EMPTY_ERROR_CODE = 10200010; 1029 1030class BusinessError extends Error { 1031 code: number; 1032 constructor(message, code) { 1033 super(); 1034 this.name = "BusinessError"; 1035 this.message = message; 1036 this.code = code; 1037 } 1038} 1039 1040function checkBindError(methodName: string, className: Function, self: unknown) { 1041 if (!(self instanceof className)) { 1042 throw new BusinessError(`The ${methodName} method cannot be bound`, BIND_ERROR_CODE); 1043 } 1044} 1045 1046function checkTypeError(paramName:string, type:string, receivedValue:unknown) { 1047 let tmpType = ""; 1048 if (typeof receivedValue === "object") { 1049 tmpType = (receivedValue === null) ? "Null" : receivedValue.constructor.name; 1050 } else { 1051 tmpType = typeof receivedValue; 1052 } 1053 if (tmpType === "number" && type === "Integer") { 1054 tmpType = Number.isInteger(receivedValue) ? "Integer" : "number"; 1055 } 1056 if (tmpType === "function" && type === "callable") { 1057 tmpType = "callable"; 1058 } 1059 if (tmpType.toLocaleLowerCase() !== type.toLocaleLowerCase()) { 1060 type = (type === "Integer") ? "number" : type; 1061 throw new BusinessError(`The type of "${paramName}" must be ${type}. Received value is: ${receivedValue}`, TYPE_ERROR_CODE); 1062 } 1063} 1064 1065function checkRangeError(paramName: string, receivedValue:unknown, min?: number, max?: number, options?:string) { 1066 let range = []; 1067 let minFlag = true; 1068 let maxFlag = true; 1069 if (min !== undefined) { 1070 if (options === "!=min") { 1071 minFlag = (receivedValue > min); 1072 range.push(`> ${min}`); 1073 } else { 1074 minFlag = (receivedValue >= min); 1075 range.push(`>= ${min}`); 1076 } 1077 } 1078 if (max !== undefined) { 1079 max = (max < 0) ? 0 : max; 1080 maxFlag = (receivedValue <= max); 1081 range.push(`<= ${max}`); 1082 } 1083 if (!(minFlag && maxFlag)) { 1084 throw new BusinessError( 1085 `The value of "${paramName}" is out of range. It must be ${range.join(' && ')}. Received value is: ${receivedValue}`, RANGE_ERROR_CODE); 1086 } 1087} 1088 1089function checkIsEmptyError(isEmpty: boolean) { 1090 if (isEmpty) { 1091 throw new BusinessError(`Container is empty`, EMPTY_ERROR_CODE); 1092 } 1093} 1094 1095function checkNewTargetIsNullError(className: string, isNull: boolean) { 1096 if (isNull) { 1097 throw new BusinessError(`The ${className}'s constructor cannot be directly invoked`, NEWTARGET_IS_NULL_ERROR_CODE); 1098 } 1099} 1100 1101let ErrorUtil = { 1102 checkBindError, 1103 checkTypeError, 1104 checkRangeError, 1105 checkIsEmptyError, 1106 checkNewTargetIsNullError 1107} 1108export default { 1109 isIncludeToArray, 1110 LightWeightClass, 1111 PlainArrayClass, 1112 RBTreeClass, 1113 DictionaryClass, 1114 ErrorUtil 1115} 1116 1117