1/* 2 * Copyright (c) 2021 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 */ 15 16interface HelpUtil{ 17 TextEncoder : Object; 18 TextDecoder : Object; 19 Base64 : Object; 20 Types : Object; 21 dealwithformatstring(formatString : string | Array<string | number | Fn>) : string; 22 printf(formatString : string | Array<string | number | Fn>, 23 ...valueString : Array<Object>) : string; 24 getErrorString(errnum : number) : string; 25 createExternalType() : Object; 26} 27 28interface Fn{ 29 () : void; 30} 31declare function requireInternal(s : string) : HelpUtil; 32const helpUtil = requireInternal('util'); 33var TextEncoder = helpUtil.TextEncoder; 34var TextDecoder = helpUtil.TextDecoder; 35var Base64 = helpUtil.Base64; 36var Types = helpUtil.Types; 37function switchLittleObject(enter : string, obj : Object, count : number) : string | Object 38{ 39 let str : string = ''; 40 if (obj === null) { 41 str += obj; 42 } else if (obj instanceof Array) { 43 str += '[ ' + arrayToString(enter, obj, count) + '[length]: ' + obj.length + ' ]'; 44 } else if (typeof obj === 'function') { 45 str += '{ [Function: ' + obj.name + ']' + enter 46 + '[length]: ' + obj.length + ',' + enter 47 + '[name] :\'' + obj.name + '\',' + enter 48 + '[prototype]: ' + obj.name + ' { [constructor]: [Circular] } }'; 49 } else if (typeof obj === 'object') { 50 str += '{ '; 51 let i : string; 52 let flag : boolean = false; 53 for (i in obj) { 54 flag = true; 55 str += switchLittleValue(enter, i, obj, count); 56 } 57 if (!flag) { 58 return obj; 59 } 60 str = str.substr(0, str.length - enter.length - 1); 61 str += ' }'; 62 } else if (typeof obj === 'string') { 63 str += '\'' + obj + '\''; 64 } else { 65 str += obj; 66 } 67 return str; 68} 69 70function switchLittleValue(enter : string, protoName : string, obj : Object, count : number) : string 71{ 72 let str : string = ''; 73 if (obj[protoName] === null) { 74 str += protoName + ': null,' + enter; 75 } else if (obj[protoName] instanceof Array) { 76 str += protoName + ':' + enter 77 + '[ ' + arrayToString(enter + ' ', obj[protoName], count) + '[length]: ' 78 + obj[protoName].length + ' ],' + enter; 79 } else if (typeof obj[protoName] === 'object') { 80 if (obj[protoName] === obj) { 81 str += protoName + ': [Circular]' + enter; 82 } else { 83 str += protoName + ':' + enter; 84 str += switchLittleObject(enter + ' ', obj[protoName], count + 1) + ',' + enter; 85 } 86 } else if (typeof obj[protoName] === 'function') { 87 let space : string= enter; 88 if (obj[protoName].name !== '') { 89 str += obj[protoName].name + ':' + space; 90 } 91 space += ' '; 92 str += '{ [Function: ' + obj[protoName].name + ']' + space 93 + '[length]: ' + obj[protoName].length + ',' + space 94 + '[name] :\'' + obj[protoName].name + '\',' + space 95 + '[prototype]: ' + obj[protoName].name 96 + ' { [constructor]: [Circular] } },' + enter; 97 } else { 98 if (typeof obj[protoName] === 'string') { 99 str += protoName + ': \'' + obj[protoName] + '\',' + enter; 100 } else { 101 str += protoName + ': ' + obj[protoName] + ',' + enter; 102 } 103 } 104 return str; 105} 106 107function arrayToString(enter : string, arr : Array<string | number | Fn>, count : number) : string 108{ 109 let str : string = ''; 110 if (!arr.length) { 111 return ''; 112 } 113 let arrayEnter : string = ', '; 114 for (let k in arr) { 115 if (arr[k] !== null && (typeof arr[k] === 'function' || typeof arr[k] === 'object') && count <= 2) { 116 arrayEnter += enter; 117 break; 118 } 119 } 120 for (let i of arr) { 121 if (typeof i === 'string') { 122 str += '\'' + i.toString() + '\'' + arrayEnter; 123 } else if (typeof i === 'object') { 124 str += switchLittleObject(enter + ' ', i, count + 1); 125 str += arrayEnter; 126 } else if (typeof i === 'function') { 127 let space : string = enter; 128 space += ' '; 129 let end : string = ''; 130 if (i.name !== '') { 131 str += '{ [Function: ' + i.name + ']' + space; 132 end = i.name + ' { [constructor]: [Circular] } }' + arrayEnter; 133 } else { 134 str += '{ [Function]' + space; 135 end = '{ [constructor]: [Circular] } }' + arrayEnter; 136 } 137 str += '[length]: ' 138 + i.length + ',' + space 139 + '[name] :\'' + i.name + '\',' + space 140 + '[prototype]: ' + end; 141 } else { 142 str += i + arrayEnter; 143 } 144 } 145 return str; 146} 147 148function switchBigObject(enter : string, obj : Object, count : number) : string | Object 149{ 150 let str : string = ''; 151 if (obj === null) { 152 str += obj; 153 } else if (obj instanceof Array) { 154 str += '[ ' + arrayToBigString(enter, obj, count) + ' ]'; 155 } else if (typeof obj === 'function') { 156 str += '{ [Function: ' + obj.name + '] }'; 157 } else if (typeof obj === 'object') { 158 str += '{ '; 159 let i : string; 160 let flag : boolean = false; 161 for (i in obj) { 162 flag = true; 163 str += switchBigValue(enter, i, obj, count); 164 } 165 if (!flag) { 166 return obj; 167 } 168 str = str.substr(0, str.length - enter.length - 1); 169 str += ' }'; 170 } else if (typeof obj === 'string') { 171 str += '\'' + obj + '\''; 172 } else { 173 str += obj; 174 } 175 return str; 176} 177 178function switchBigValue(enter : string, protoName : string, obj : Object, count : number) : string 179{ 180 let str : string = ''; 181 if (obj[protoName] === null) { 182 str += protoName + ': null,' + enter; 183 } else if (obj[protoName] instanceof Array) { 184 str += protoName + ':' + enter 185 + '[ ' + arrayToBigString(enter + ' ', obj[protoName], count) + ' ],' + enter; 186 } else if (typeof obj[protoName] === 'object') { 187 if (obj[protoName] === obj) { 188 str += protoName + ': [Circular]' + enter; 189 } else { 190 str += protoName + ':' + enter; 191 str += switchBigObject(enter + ' ', obj[protoName], count + 1) + ',' + enter; 192 } 193 } else if (typeof obj[protoName] === 'function') { 194 if (obj[protoName].name !== '') { 195 str += obj[protoName].name + ': '; 196 } 197 str += '[Function: ' + obj[protoName].name + '],' + enter; 198 } else { 199 if (typeof obj[protoName] === 'string') { 200 str += protoName + ': \'' + obj[protoName] + '\',' + enter; 201 } else { 202 str += protoName + ': ' + obj[protoName] + ',' + enter; 203 } 204 } 205 return str; 206} 207function arrayToBigString(enter : string, arr : Array<string | number | Fn>, count : number) : string 208{ 209 let str : string = ''; 210 if (!arr.length) { 211 return ''; 212 } 213 214 let arrayEnter = ', '; 215 for (let i of arr) { 216 if (i !== null && (typeof i === 'object') && count <= 2) { 217 arrayEnter += enter; 218 break; 219 } 220 } 221 for (let j of arr) { 222 if (typeof j === 'string') { 223 str += '\'' + j + '\'' + arrayEnter; 224 } else if (typeof j === 'object') { 225 str += switchBigObject(enter + ' ', j, count + 1); 226 str += arrayEnter; 227 } else if (typeof j === 'function') { 228 if (j.name !== '') { 229 str += '[Function: ' + j.name + ']' + arrayEnter; 230 } else { 231 str += '[Function]' + arrayEnter; 232 } 233 } else { 234 str += j + arrayEnter; 235 } 236 } 237 str = str.substr(0, str.length - arrayEnter.length); 238 return str; 239} 240function switchIntValue(value : Object | symbol) : string 241{ 242 let str : string = ''; 243 if (value === '') { 244 str += 'NaN'; 245 } else if (typeof value === 'bigint') { 246 str += value + 'n'; 247 } else if (typeof value === 'symbol') { 248 str += 'NaN'; 249 } else if (typeof value === 'number') { 250 str += parseInt(value.toString(), 10); // 10:The function uses decimal. 251 } else if (value instanceof Array) { 252 if (typeof value[0] === 'number') { 253 str += parseInt(value[0].toString(), 10); // 10:The function uses decimal. 254 } else if (typeof value[0] === 'string') { 255 if (isNaN(Number(value[0]))) { 256 str += 'NaN'; 257 } else { 258 str += parseInt(value[0], 10); // 10:The function uses decimal. 259 } 260 } 261 } else if (typeof value === 'string') { 262 if (isNaN(Number(value))) { 263 str += 'NaN'; 264 } else { 265 str += parseInt(value, 10); // 10:The function uses decimal. 266 } 267 } else { 268 str += 'NaN'; 269 } 270 return str; 271} 272function switchFloatValue(value : Object | symbol) : string 273{ 274 let str : string = ''; 275 if (value === '') { 276 str += 'NaN'; 277 } else if (typeof value === 'symbol') { 278 str += 'NaN'; 279 } else if (typeof value === 'number') { 280 str += value; 281 } else if (value instanceof Array) { 282 if (typeof value[0] === 'number') { 283 str += parseFloat(value.toString()); 284 } else if (typeof value[0] === 'string') { 285 if (isNaN(Number(value[0]))) { 286 str += 'NaN'; 287 } else { 288 str += parseFloat(value[0]); 289 } 290 } 291 } else if (typeof value === 'string') { 292 if (isNaN(Number(value))) { 293 str += 'NaN'; 294 } else { 295 str += parseFloat(value); 296 } 297 } else if (typeof value === 'bigint') { 298 str += value; 299 } else { 300 str += 'NaN'; 301 } 302 return str; 303} 304 305function switchNumberValue(value : Object | symbol) : string 306{ 307 let str : string = ''; 308 if (value === '') { 309 str += '0'; 310 } else if (typeof value === 'symbol') { 311 str += 'NaN'; 312 } else if (typeof value === 'number') { 313 str += value; 314 } else if (value instanceof Array) { 315 str += 'NaN'; 316 } else if (typeof value === 'string') { 317 if (isNaN(Number(value))) { 318 str += 'NaN'; 319 } else { 320 str += Number(value); 321 } 322 } else if (typeof value === 'bigint') { 323 str += value.toString() + 'n'; 324 } else { 325 str += 'NaN'; 326 } 327 return str; 328} 329 330function switchStringValue(value : Object | symbol) : string 331{ 332 let str : string = ''; 333 if (typeof value === 'undefined') { 334 str += 'undefined'; 335 } else if (typeof value === 'object') { 336 if (value === null) { 337 str += 'null'; 338 } else { 339 str += value; 340 } 341 } else if (typeof value === 'symbol') { 342 str += value.toString(); 343 } else { 344 str += value; 345 } 346 return str; 347} 348// printf(formatString : string | Array<string | number | Fn>, 349// ...valueString : Array<string | number | Fn | object>) : string; 350function printf(formatString : Array<string | number | Fn>, ...valueString : Array<Object>) : string 351{ 352 let formats : string = helpUtil.dealwithformatstring(formatString); 353 let arr : Array<Object>= []; 354 arr = formats.split(' '); 355 let switchString : Array<Object>= []; 356 let valueLength : number = valueString.length; 357 let arrLength : number = arr.length; 358 let i : number= 0; 359 for (let sub of valueString) { 360 if (i >= arrLength) { 361 break; 362 } 363 if (arr[i] === 'o') { 364 switchString.push(switchLittleObject('\n ', sub, 1)); 365 } else if (arr[i] === 'O') { 366 switchString.push(switchBigObject('\n ', sub, 1)); 367 } else if (arr[i] === 'i') { 368 switchString.push(switchIntValue(sub)); 369 } else if (arr[i] === 'j') { 370 switchString.push(JSON.stringify(sub)); 371 } else if (arr[i] === 'd') { 372 switchString.push(switchNumberValue(sub)); 373 } else if (arr[i] === 's') { 374 switchString.push(switchStringValue(sub)); 375 } else if (arr[i] === 'f') { 376 switchString.push(switchFloatValue(sub)); 377 } else if (arr[i] === 'c') { 378 switchString.push(sub.toString()); 379 } 380 ++i; 381 } 382 while (i < valueLength) { 383 switchString.push(valueString[i].toString()); 384 i++; 385 } 386 let helpUtilString : string = helpUtil.printf(formatString, ...switchString); 387 return helpUtilString; 388} 389 390function getErrorString(errnum : number) : string 391{ 392 let errorString : string = helpUtil.getErrorString(errnum); 393 return errorString; 394} 395 396function createExternalType() : Object 397{ 398 let externalType : Object = helpUtil.createExternalType(); 399 return externalType; 400} 401 402function callbackified(original : Fn, ...args : Array<string | number | Fn>) : void 403{ 404 const maybeCb = args.pop(); 405 if (typeof maybeCb !== 'function') { 406 throw new Error('maybe is not function'); 407 } 408 const cb = (...args : Array<null>) => { 409 Reflect.apply(maybeCb, this, args); 410 }; 411 Reflect.apply(original, this, args).then((ret : null) => cb(null, ret), (rej : null) => cb(rej)); 412} 413 414function getOwnPropertyDescriptors(obj : Fn) : PropertyDescriptorMap 415{ 416 const result : PropertyDescriptorMap = {}; 417 for (let key of Reflect.ownKeys(obj)) { 418 if (typeof key === 'string') { 419 result[key] = Object.getOwnPropertyDescriptor(obj, key); 420 } 421 } 422 return result; 423} 424 425function callbackWrapper(original : Fn) : void 426{ 427 if (typeof original !== 'function') { 428 throw new Error('original is not function'); 429 } 430 const descriptors = getOwnPropertyDescriptors(original); 431 if (typeof descriptors.length.value === 'number') { 432 descriptors.length.value++; 433 } 434 if (typeof descriptors.name.value === 'string') { 435 descriptors.name.value += 'callbackified'; 436 } 437 438 function cb(...args : Array<string | number | Fn>) { 439 callbackified(original, ...args); 440 } 441 Object.defineProperties(cb, descriptors); 442} 443 444function promiseWrapper(func : Function) : Object 445{ 446 return function (...args : Array<Object>) { 447 return new Promise((resolve, reject) => { 448 let callback : Function = function (err : Object | string, ...values : Array<Object>) { 449 if (err) { 450 reject(err); 451 } else { 452 resolve(values); 453 } 454 }; 455 func.apply(null, [...args, callback]); 456 }); 457 }; 458} 459 460class LruBuffer 461{ 462 private cache: Map<Object | undefined, Object | undefined>; 463 private maxSize : number = 64; 464 private maxNumber : number = 2147483647; 465 private putCount : number = 0; 466 private createCount : number = 0; 467 private evictionCount : number = 0; 468 private hitCount : number = 0; 469 private missCount : number = 0; 470 public length : number = 0; 471 472 public constructor(capacity?: number) 473 { 474 if (capacity !== undefined) { 475 if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) { 476 throw new Error('data error'); 477 } 478 this.maxSize = capacity; 479 } 480 this.cache = new Map(); 481 } 482 483 public updateCapacity(newCapacity : number) : void 484 { 485 if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) { 486 throw new Error('data error'); 487 } else if (this.cache.size >newCapacity) { 488 this.changeCapacity(newCapacity); 489 } 490 this.length = this.cache.size; 491 this.maxSize = newCapacity; 492 } 493 494 public get(key : Object) : Object 495 { 496 if (key === null) { 497 throw new Error('key not be null'); 498 } 499 let value : Object; 500 if (this.cache.has(key)) { 501 value = this.cache.get(key); 502 this.hitCount++; 503 this.cache.delete(key); 504 this.cache.set(key, value); 505 return value; 506 } 507 508 this.missCount++; 509 let createValue : Object = this.createDefault(key); 510 if (createValue === undefined) { 511 return undefined; 512 } else { 513 value = this.put(key, createValue); 514 this.createCount++; 515 if (value !== undefined) { 516 this.put(key, value); 517 this.afterRemoval(false, key, createValue, value); 518 return value; 519 } 520 return createValue; 521 } 522 } 523 524 public put(key : Object, value : Object) : Object 525 { 526 if (key === null || value === null) { 527 throw new Error('key or value not be null'); 528 } 529 let former : Object; 530 this.putCount++; 531 if (this.cache.has(key)) { 532 former = this.cache.get(key); 533 this.cache.delete(key); 534 this.afterRemoval(false, key, former, value); 535 } else if (this.cache.size >= this.maxSize) { 536 this.cache.delete(this.cache.keys().next().value); 537 this.evictionCount++; 538 } 539 this.cache.set(key, value); 540 this.length = this.cache.size; 541 return former; 542 } 543 544 public getCreateCount() : number 545 { 546 return this.createCount; 547 } 548 549 public getMissCount() : number 550 { 551 return this.missCount; 552 } 553 554 public getRemovalCount() : number 555 { 556 return this.evictionCount; 557 } 558 559 public getMatchCount() : number 560 { 561 return this.hitCount; 562 } 563 564 public getPutCount() : number 565 { 566 return this.putCount; 567 } 568 569 public getCapacity() : number 570 { 571 return this.maxSize; 572 } 573 574 public clear() : void 575 { 576 this.cache.clear(); 577 this.afterRemoval(false, this.cache.keys(), this.cache.values(), null); 578 this.length = this.cache.size; 579 } 580 581 public isEmpty() :boolean 582 { 583 let temp : boolean = false; 584 if (this.cache.size === 0) { 585 temp = true; 586 } 587 return temp; 588 } 589 590 public contains(key : Object) : boolean 591 { 592 let flag : boolean = false; 593 if (this.cache.has(key)) { 594 flag = true; 595 let value : Object; 596 this.hitCount++; 597 value = this.cache.get(key); 598 this.cache.delete(key); 599 this.cache.set(key, value); 600 this.length = this.cache.size; 601 return flag; 602 } 603 this.missCount++; 604 return flag; 605 } 606 607 public remove(key : Object) : Object 608 { 609 if (key === null) { 610 throw new Error('key not be null'); 611 } else if (this.cache.has(key)) { 612 let former : Object; 613 former = this.cache.get(key); 614 this.cache.delete(key); 615 if (former !== null) { 616 this.afterRemoval(false, key, former, null); 617 this.length = this.cache.size; 618 return former; 619 } 620 } 621 this.length = this.cache.size; 622 return undefined; 623 } 624 625 public toString() : string 626 { 627 let peek : number = 0; 628 let hitRate : number = 0; 629 peek = this.hitCount + this.missCount; 630 if (peek !== 0) { 631 hitRate = 100 * this.hitCount / peek; 632 } else { 633 hitRate = 0; 634 } 635 let str : string = ''; 636 str = 'Lrubuffer[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + ', misses = ' + this.missCount 637 + ', hitRate = ' + hitRate + '% ]'; 638 return str; 639 } 640 641 public values() : Object[] 642 { 643 let arr : Array<Object> = []; 644 for(let value of this.cache.values()) { 645 arr.push(value); 646 } 647 return arr; 648 } 649 650 public keys() : Object[] 651 { 652 let arr : Array<Object> = []; 653 for(let key of this.cache.keys()) { 654 arr.push(key); 655 } 656 return arr; 657 } 658 659 protected afterRemoval(isEvict : boolean, key : Object | undefined | null, value : Object | undefined | null, 660 newValue : Object | undefined | null) : void 661 { 662 663 } 664 665 protected createDefault(key : Object) : Object 666 { 667 return undefined; 668 } 669 670 public entries() : IterableIterator<[Object, Object]> 671 { 672 return this.cache.entries(); 673 } 674 675 public [Symbol.iterator] () : IterableIterator<[Object, Object]> 676 { 677 return this.cache.entries(); 678 } 679 680 private changeCapacity(newCapacity : number) : void 681 { 682 while(this.cache.size >newCapacity) { 683 this.cache.delete(this.cache.keys().next().value); 684 this.evictionCount++; 685 this.afterRemoval(true, this.cache.keys(), this.cache.values(), null); 686 } 687 } 688} 689 690class RationalNumber 691{ 692 private mnum : number = 0; 693 private mden : number = 0; 694 public constructor(num : number, den : number) 695 { 696 num = den < 0 ? num * (-1) : num; 697 den = den < 0 ? den * (-1) : den; 698 if (den === 0) { 699 if (num > 0) { 700 this.mnum = 1; 701 this.mden = 0; 702 } else if (num < 0) { 703 this.mnum = -1; 704 this.mden = 0; 705 } else { 706 this.mnum = 0; 707 this.mden = 0; 708 } 709 } else if (num === 0) { 710 this.mnum = 0; 711 this.mden = 1; 712 } else { 713 let gnum : number = 0; 714 gnum = this.getCommonDivisor(num, den); 715 if (gnum !== 0) { 716 this.mnum = num / gnum; 717 this.mden = den / gnum; 718 } 719 } 720 } 721 722 public createRationalFromString(str : string): RationalNumber 723 { 724 if (str === null) { 725 throw new Error('string invalid!'); 726 } 727 if (str === 'NaN') { 728 return new RationalNumber(0, 0); 729 } 730 let colon : number = str.indexOf(':'); 731 let semicolon : number = str.indexOf('/'); 732 if ((colon < 0 && semicolon < 0) || (colon > 0 && semicolon > 0)) { 733 throw new Error('string invalid!'); 734 } 735 let index : number = (colon > 0) ? colon : semicolon; 736 let s1 : string = str.substr(0, index); 737 let s2 : string = str.substr(index + 1, str.length); 738 let num1 : number = Number(s1); 739 let num2 : number = Number(s2); 740 return new RationalNumber(num1, num2); 741 } 742 743 public compareTo(other : RationalNumber) : number 744 { 745 if (this.mnum === other.mnum && this.mden === other.mden) { 746 return 0; 747 } else if (this.mnum === 0 && this.mden === 0) { 748 return 1; 749 } else if ((other.mnum === 0) && (other.mden === 0)) { 750 return -1; 751 } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) { 752 return 1; 753 } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) { 754 return -1; 755 } 756 let thisnum : number = this.mnum * other.mden; 757 let othernum : number = other.mnum * this.mden; 758 if (thisnum < othernum) { 759 return -1; 760 } else if (thisnum > othernum) { 761 return 1; 762 } else { 763 return 0; 764 } 765 } 766 767 public equals(obj : object) :boolean 768 { 769 if (!(obj instanceof RationalNumber)) { 770 return false; 771 } 772 let thisnum : number = this.mnum * obj.mden; 773 let objnum : number = obj.mnum * this.mden; 774 if (this.mnum === obj.mnum && this.mden === obj.mden) { 775 return true; 776 } else if ((thisnum === objnum) && (this.mnum !== 0 && this.mden !== 0) && (obj.mnum !== 0 && obj.mden !== 0)) { 777 return true; 778 } else if ((this.mnum === 0 && this.mden !== 0) && (obj.mnum === 0 && obj.mden !== 0)) { 779 return true; 780 } else if ((this.mnum > 0 && this.mden === 0) && (obj.mnum > 0 && obj.mden === 0)) { 781 return true; 782 } else if ((this.mnum < 0 && this.mden === 0) && (obj.mnum < 0 && obj.mden === 0)) { 783 return true; 784 } else { 785 return false; 786 } 787 } 788 789 public valueOf() : number 790 { 791 if (this.mnum > 0 && this.mden === 0) { 792 return Number.POSITIVE_INFINITY; 793 } else if (this.mnum < 0 && this.mden === 0) { 794 return Number.NEGATIVE_INFINITY; 795 } else if ((this.mnum === 0) && (this.mden === 0)) { 796 return Number.NaN; 797 } else { 798 return this.mnum / this.mden; 799 } 800 } 801 802 public getCommonDivisor(number1 : number, number2 : number) : number 803 { 804 if (number1 === 0 || number2 === 0) { 805 throw new Error('Parameter cannot be zero!'); 806 } 807 let temp : number = 0; 808 if (number1 < number2) { 809 temp = number1; 810 number1 = number2; 811 number2 = temp; 812 } 813 while (number1 % number2 !== 0) { 814 temp = number1 % number2; 815 number1 = number2; 816 number2 = temp; 817 } 818 return number2; 819 } 820 821 public getDenominator() :number 822 { 823 return this.mden; 824 } 825 826 public getNumerator() : number 827 { 828 return this.mnum; 829 } 830 831 public isFinite() : boolean 832 { 833 return this.mden !== 0; 834 } 835 836 public isNaN() : boolean 837 { 838 return this.mnum === 0 && this.mden === 0; 839 } 840 841 public isZero() : boolean 842 { 843 return this.mnum === 0 && this.mden !== 0; 844 } 845 846 public toString() : string 847 { 848 let buf : string; 849 if (this.mnum === 0 && this.mden === 0) { 850 buf = 'NaN'; 851 } else if (this.mnum > 0 && this.mden === 0) { 852 buf = 'Infinity'; 853 } else if (this.mnum < 0 && this.mden === 0) { 854 buf = '-Infinity'; 855 } else { 856 buf = String(this.mnum) + '/' + String(this.mden); 857 } 858 return buf; 859 } 860} 861 862interface ScopeComparable { 863 compareTo(other: ScopeComparable): boolean; 864} 865 866type ScopeType = ScopeComparable; 867 868class Scope { 869 private readonly _lowerLimit: ScopeType; 870 private readonly _upperLimit: ScopeType; 871 872 public constructor(readonly lowerObj: ScopeType, readonly upperObj: ScopeType) { 873 this.checkNull(lowerObj, 'lower limit not be null'); 874 this.checkNull(upperObj, 'upper limit not be null'); 875 876 if(lowerObj.compareTo(upperObj)) { 877 throw new Error('lower limit must be less than or equal to upper limit'); 878 } 879 this._lowerLimit = lowerObj; 880 this._upperLimit = upperObj; 881 } 882 883 public getLower(): ScopeType { 884 return this._lowerLimit; 885 } 886 887 public getUpper(): ScopeType { 888 return this._upperLimit; 889 } 890 891 public compareTo(): boolean { 892 return false; 893 } 894 895 public contains(value: ScopeType): boolean; 896 public contains(scope: Scope): boolean; 897 public contains(x: Scope|ScopeType): boolean { 898 let resLower: boolean; 899 let resUpper: boolean; 900 this.checkNull(x, 'value must not be null'); 901 if (x instanceof Scope) { 902 resLower= x._lowerLimit.compareTo(this._lowerLimit); 903 resUpper= this._upperLimit.compareTo(x._upperLimit); 904 } else { 905 resLower= x.compareTo(this._lowerLimit); 906 resUpper= this._upperLimit.compareTo(x); 907 } 908 return resLower && resUpper; 909 } 910 911 public clamp(value: ScopeType): ScopeType { 912 this.checkNull(value, 'value must not be null'); 913 914 if (!value.compareTo(this._lowerLimit)) { 915 return this._lowerLimit; 916 } else if (value.compareTo(this._upperLimit)) { 917 return this._upperLimit; 918 } else { 919 return value; 920 } 921 } 922 923 public intersect(scope: Scope): Scope; 924 public intersect(lowerObj: ScopeType, upperObj: ScopeType): Scope; 925 public intersect(x: Scope, y?: Scope|ScopeType): Scope { 926 let reLower: boolean; 927 let reUpper: boolean; 928 let mLower: ScopeType; 929 let mUpper: ScopeType; 930 if (y) { 931 this.checkNull(x, 'lower limit must not be null'); 932 this.checkNull(y, 'upper limit must not be null'); 933 reLower = this._lowerLimit.compareTo(x); 934 reUpper = y.compareTo(this._upperLimit); 935 if (reLower && reUpper) { 936 return this; 937 } else { 938 mLower = reLower ? this._lowerLimit : x; 939 mUpper = reUpper ? this._upperLimit : y; 940 return new Scope(mLower, mUpper); 941 } 942 } else { 943 this.checkNull(x, 'scope must not be null'); 944 reLower = this._lowerLimit.compareTo(x._lowerLimit); 945 reUpper = x._upperLimit.compareTo(this._upperLimit); 946 if (!reLower && !reUpper) { 947 return x; 948 } else if (reLower && reUpper) { 949 return this; 950 } else { 951 mLower = reLower ? this._lowerLimit : x._lowerLimit; 952 mUpper = reUpper ? this._upperLimit : x._upperLimit; 953 return new Scope(mLower, mUpper); 954 } 955 } 956 } 957 958 public expand(obj: ScopeType): Scope; 959 public expand(scope: Scope): Scope; 960 public expand(lowerObj: ScopeType, upperObj: ScopeType): Scope; 961 public expand(x: ScopeType, y?: ScopeType): Scope { 962 let reLower: boolean; 963 let reUpper: boolean; 964 let mLower: ScopeType; 965 let mUpper: ScopeType; 966 if (!y) { 967 this.checkNull(x, 'value must not be null'); 968 if (!(x instanceof Scope)) { 969 this.checkNull(x, 'value must not be null'); 970 return this.expand(x, x); 971 } 972 reLower = x._lowerLimit.compareTo(this._lowerLimit); 973 reUpper = this._upperLimit.compareTo(x._upperLimit); 974 if (reLower && reUpper) { 975 return this; 976 } else if (!reLower && !reUpper) { 977 return x; 978 } else { 979 mLower = reLower ? this._lowerLimit : x._lowerLimit; 980 mUpper = reUpper ? this._upperLimit : x._upperLimit; 981 return new Scope(mLower, mUpper); 982 } 983 984 } else { 985 this.checkNull(x, 'lower limit must not be null'); 986 this.checkNull(y, 'upper limit must not be null'); 987 reLower = x.compareTo(this._lowerLimit); 988 reUpper = this._upperLimit.compareTo(y); 989 if (reLower && reUpper) { 990 return this; 991 } 992 mLower = reLower ? this._lowerLimit : x; 993 mUpper = reUpper ? this._upperLimit : y; 994 return new Scope(mLower, mUpper); 995 } 996 } 997 998 public toString(): string { 999 let strLower : string = this._lowerLimit.toString(); 1000 let strUpper : string = this._upperLimit.toString(); 1001 return `[${strLower}, ${strUpper}]`; 1002 } 1003 1004 public checkNull(o: ScopeType, str: string): void { 1005 if (o === null) { 1006 throw new Error(str); 1007 } 1008 } 1009} 1010 1011export default { 1012 printf: printf, 1013 getErrorString: getErrorString, 1014 callbackWrapper: callbackWrapper, 1015 promiseWrapper: promiseWrapper, 1016 createExternalType: createExternalType, 1017 TextEncoder: TextEncoder, 1018 TextDecoder: TextDecoder, 1019 Base64: Base64, 1020 types: Types, 1021 LruBuffer: LruBuffer, 1022 RationalNumber : RationalNumber, 1023 Scope : Scope, 1024}; 1025