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