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 Base64Helper: NativeBase64; 21 Types: Object; 22 dealwithformatstring(formatString: string | Array<string | number | Fn>): string; 23 printf(formatString: string | Array<string | number | Fn>, 24 ...valueString: Array<Object>): string; 25 format(formatString: Array<string | number | Fn>, ...valueString: Array<Object>): string 26 geterrorstring(errnum: number): string; 27 errnoToString(errnum: number): string; 28 randomUUID(entropyCache?: boolean): string; 29 randomBinaryUUID(entropyCache?: boolean): Uint8Array; 30 parseUUID(uuid: string): Uint8Array; 31} 32 33interface Fn { 34 (): void; 35} 36declare function requireInternal(s: string): HelpUtil; 37const helpUtil = requireInternal('util'); 38let textEncoder = helpUtil.TextEncoder; 39let textDecoder = helpUtil.TextDecoder; 40let base64 = helpUtil.Base64; 41let types = helpUtil.Types; 42 43 44interface NativeBase64 { 45 new(): NativeBase64; 46 encodeSync(src: Uint8Array): Uint8Array; 47 encodeToStringSync(src: Uint8Array, options?: Type): string; 48 decodeSync(src: Uint8Array | string, options?: Type): Uint8Array; 49 encode(src: Uint8Array): Promise<Uint8Array>; 50 encodeToString(src: Uint8Array, options?: Type): Promise<string>; 51 decode(src: Uint8Array | string, options?: Type): Promise<Uint8Array>; 52} 53 54interface Base64Helper { 55 Base64Helper: NativeBase64; 56} 57 58enum Type { 59 BASIC, 60 MIME 61} 62 63class Base64Helper { 64 base64: NativeBase64; 65 constructor() { 66 this.base64 = new helpUtil.Base64Helper(); 67 } 68 69 encodeSync(src: Uint8Array): Uint8Array { 70 let result: Uint8Array = this.base64.encodeSync(src); 71 return result; 72 } 73 74 private addBreaks(resultString: string): string { 75 const chunkSize = 76; 76 let i = 0; 77 let newString: string = ''; 78 let stringLength = resultString.length; 79 while (i < stringLength && stringLength > chunkSize) { 80 let index = i + chunkSize; 81 if (i + chunkSize > stringLength) { 82 index = stringLength; 83 } 84 let temp: string = resultString.substring(i, index); 85 newString = newString + temp + '\r\n'; 86 i += chunkSize; 87 } 88 return newString; 89 } 90 91 encodeToStringSync(src: Uint8Array, options?: Type): string { 92 let resultString: string = this.base64.encodeToStringSync(src); 93 if (options === Type.MIME) { 94 let breakString: string = this.addBreaks(resultString); 95 return breakString; 96 } 97 return resultString; 98 } 99 100 decodeSync(src: Uint8Array | string, options?: Type): Uint8Array { 101 if (typeof src === 'string' && src.indexOf('\r\n') !== -1 && options === Type.MIME) { 102 src = src.replace(/\r\n/g, ''); 103 } 104 let result: Uint8Array = this.base64.decodeSync(src); 105 return result; 106 } 107 108 encode(src: Uint8Array): Promise<Uint8Array> { 109 let result: Promise<Uint8Array> = this.base64.encode(src); 110 return result; 111 } 112 113 async processData(src: Uint8Array): Promise<string> { 114 return this.base64.encodeToString(src).then((result: string) => { 115 let breakString: string = this.addBreaks(result); 116 return breakString; 117 }); 118 } 119 120 encodeToString(src: Uint8Array, options?: Type): Promise<string> { 121 if (options === Type.MIME) { 122 let result: Promise<string> = this.processData(src); 123 return result; 124 } 125 let base64Result: Promise<string> = this.base64.encodeToString(src); 126 return base64Result; 127 } 128 129 decode(src: Uint8Array | string, options?: Type): Promise<Uint8Array> { 130 if (typeof src === 'string' && src.indexOf('\r\n') !== -1 && options === Type.MIME) { 131 src = src.replace(/\r\n/g, ''); 132 } 133 let result: Promise<Uint8Array> = this.base64.decode(src); 134 return result; 135 } 136} 137 138const typeErrorCode = 401; 139const syntaxErrorCode = 10200002; 140class BusinessError extends Error { 141 code: number; 142 constructor(msg: string) { 143 super(msg); 144 this.name = 'BusinessError'; 145 this.code = typeErrorCode; 146 } 147} 148 149function switchLittleObject(enter: string, obj: Object, count: number): string | Object { 150 let str: string = ''; 151 if (obj === null) { 152 str += obj; 153 } else if (obj instanceof Array) { 154 str += '[ ' + arrayToString(enter, obj, count) + '[length]: ' + obj.length + ' ]'; 155 } else if (typeof obj === 'function') { 156 str += '{ [Function: ' + obj.name + ']' + enter + 157 '[length]: ' + obj.length + ',' + enter + 158 '[name] :\'' + obj.name + '\',' + enter + 159 '[prototype]: ' + obj.name + ' { [constructor]: [Circular] } }'; 160 } else if (typeof obj === 'object') { 161 str += '{ '; 162 let i: string; 163 let flag: boolean = false; 164 for (i in obj) { 165 flag = true; 166 str += switchLittleValue(enter, i, obj, count); 167 } 168 if (!flag) { 169 return obj; 170 } 171 str = str.substr(0, str.length - enter.length - 1); 172 str += ' }'; 173 } else if (typeof obj === 'string') { 174 str += '\'' + obj + '\''; 175 } else { 176 str += obj; 177 } 178 return str; 179} 180 181function switchLittleValue(enter: string, protoName: string, obj: Object, count: number): string { 182 let str: string = ''; 183 if (obj[protoName] === null) { 184 str += protoName + ': null,' + enter; 185 } else if (obj[protoName] instanceof Array) { 186 str += protoName + ':' + enter + 187 '[ ' + arrayToString(enter + ' ', obj[protoName], count) + '[length]: ' + 188 obj[protoName].length + ' ],' + enter; 189 } else if (typeof obj[protoName] === 'object') { 190 if (obj[protoName] === obj) { 191 str += protoName + ': [Circular]' + enter; 192 } else { 193 str += protoName + ':' + enter; 194 str += switchLittleObject(enter + ' ', obj[protoName], count + 1) + ',' + enter; 195 } 196 } else if (typeof obj[protoName] === 'function') { 197 let space: string = enter; 198 if (obj[protoName].name !== '') { 199 str += obj[protoName].name + ':' + space; 200 } 201 space += ' '; 202 str += '{ [Function: ' + obj[protoName].name + ']' + space + 203 '[length]: ' + obj[protoName].length + ',' + space + 204 '[name] :\'' + obj[protoName].name + '\',' + space + 205 '[prototype]: ' + obj[protoName].name + 206 ' { [constructor]: [Circular] } },' + enter; 207 } else { 208 if (typeof obj[protoName] === 'string') { 209 str += protoName + ': \'' + obj[protoName] + '\',' + enter; 210 } else { 211 str += protoName + ': ' + obj[protoName] + ',' + enter; 212 } 213 } 214 return str; 215} 216 217function arrayToString(enter: string, arr: Array<string | number | Fn>, count: number): string { 218 let str: string = ''; 219 if (!arr.length) { 220 return ''; 221 } 222 let arrayEnter: string = ', '; 223 for (let k in arr) { 224 if (arr[k] !== null && (typeof arr[k] === 'function' || typeof arr[k] === 'object') && count <= 2) { 225 arrayEnter += enter; 226 break; 227 } 228 } 229 for (let i of arr) { 230 if (typeof i === 'string') { 231 str += '\'' + i.toString() + '\'' + arrayEnter; 232 } else if (typeof i === 'object') { 233 str += switchLittleObject(enter + ' ', i, count + 1); 234 str += arrayEnter; 235 } else if (typeof i === 'function') { 236 let space: string = enter; 237 space += ' '; 238 let end: string = ''; 239 if (i.name !== '') { 240 str += '{ [Function: ' + i.name + ']' + space; 241 end = i.name + ' { [constructor]: [Circular] } }' + arrayEnter; 242 } else { 243 str += '{ [Function]' + space; 244 end = '{ [constructor]: [Circular] } }' + arrayEnter; 245 } 246 str += '[length]: ' + 247 i.length + ',' + space + 248 '[name] :\'' + i.name + '\',' + space + 249 '[prototype]: ' + end; 250 } else { 251 str += i + arrayEnter; 252 } 253 } 254 return str; 255} 256 257function switchBigObject(enter: string, obj: Object, count: number): string | Object { 258 let str: string = ''; 259 if (obj === null) { 260 str += obj; 261 } else if (obj instanceof Array) { 262 str += '[ ' + arrayToBigString(enter, obj, count) + ' ]'; 263 } else if (typeof obj === 'function') { 264 str += '{ [Function: ' + obj.name + '] }'; 265 } else if (typeof obj === 'object') { 266 str += '{ '; 267 let i: string; 268 let flag: boolean = false; 269 for (i in obj) { 270 flag = true; 271 str += switchBigValue(enter, i, obj, count); 272 } 273 if (!flag) { 274 return obj; 275 } 276 str = str.substr(0, str.length - enter.length - 1); 277 str += ' }'; 278 } else if (typeof obj === 'string') { 279 str += '\'' + obj + '\''; 280 } else { 281 str += obj; 282 } 283 return str; 284} 285 286function switchBigValue(enter: string, protoName: string, obj: Object, count: number): string { 287 let str: string = ''; 288 if (obj[protoName] === null) { 289 str += protoName + ': null,' + enter; 290 } else if (obj[protoName] instanceof Array) { 291 str += protoName + ':' + enter + 292 '[ ' + arrayToBigString(enter + ' ', obj[protoName], count) + ' ],' + enter; 293 } else if (typeof obj[protoName] === 'object') { 294 if (obj[protoName] === obj) { 295 str += protoName + ': [Circular]' + enter; 296 } else { 297 str += protoName + ':' + enter; 298 str += switchBigObject(enter + ' ', obj[protoName], count + 1) + ',' + enter; 299 } 300 } else if (typeof obj[protoName] === 'function') { 301 if (obj[protoName].name !== '') { 302 str += obj[protoName].name + ': '; 303 } 304 str += '[Function: ' + obj[protoName].name + '],' + enter; 305 } else { 306 if (typeof obj[protoName] === 'string') { 307 str += protoName + ': \'' + obj[protoName] + '\',' + enter; 308 } else { 309 str += protoName + ': ' + obj[protoName] + ',' + enter; 310 } 311 } 312 return str; 313} 314 315function arrayToBigString(enter: string, arr: Array<string | number | Fn>, count: number): string { 316 let str: string = ''; 317 if (!arr.length) { 318 return ''; 319 } 320 321 let arrayEnter = ', '; 322 for (let i of arr) { 323 if (i !== null && (typeof i === 'object') && count <= 2) { 324 arrayEnter += enter; 325 break; 326 } 327 } 328 for (let j of arr) { 329 if (typeof j === 'string') { 330 str += '\'' + j + '\'' + arrayEnter; 331 } else if (typeof j === 'object') { 332 str += switchBigObject(enter + ' ', j, count + 1); 333 str += arrayEnter; 334 } else if (typeof j === 'function') { 335 if (j.name !== '') { 336 str += '[Function: ' + j.name + ']' + arrayEnter; 337 } else { 338 str += '[Function]' + arrayEnter; 339 } 340 } else { 341 str += j + arrayEnter; 342 } 343 } 344 str = str.substr(0, str.length - arrayEnter.length); 345 return str; 346} 347 348function switchIntValue(value: Object | symbol): string { 349 let str: string = ''; 350 if (value === '') { 351 str += 'NaN'; 352 } else if (typeof value === 'bigint') { 353 str += value + 'n'; 354 } else if (typeof value === 'symbol') { 355 str += 'NaN'; 356 } else if (typeof value === 'number') { 357 str += parseInt(value.toString(), 10); // 10:The function uses decimal. 358 } else if (value instanceof Array) { 359 if (typeof value[0] === 'number') { 360 str += parseInt(value[0].toString(), 10); // 10:The function uses decimal. 361 } else if (typeof value[0] === 'string') { 362 if (isNaN(Number(value[0]))) { 363 str += 'NaN'; 364 } else { 365 str += parseInt(value[0], 10); // 10:The function uses decimal. 366 } 367 } 368 } else if (typeof value === 'string') { 369 if (isNaN(Number(value))) { 370 str += 'NaN'; 371 } else { 372 str += parseInt(value, 10); // 10:The function uses decimal. 373 } 374 } else { 375 str += 'NaN'; 376 } 377 return str; 378} 379 380function switchFloatValue(value: Object | symbol): string { 381 let str: string = ''; 382 if (value === '') { 383 str += 'NaN'; 384 } else if (typeof value === 'symbol') { 385 str += 'NaN'; 386 } else if (typeof value === 'number') { 387 str += value; 388 } else if (value instanceof Array) { 389 if (typeof value[0] === 'number') { 390 str += parseFloat(value.toString()); 391 } else if (typeof value[0] === 'string') { 392 if (isNaN(Number(value[0]))) { 393 str += 'NaN'; 394 } else { 395 str += parseFloat(value[0]); 396 } 397 } 398 } else if (typeof value === 'string') { 399 if (isNaN(Number(value))) { 400 str += 'NaN'; 401 } else { 402 str += parseFloat(value); 403 } 404 } else if (typeof value === 'bigint') { 405 str += value; 406 } else { 407 str += 'NaN'; 408 } 409 return str; 410} 411 412function switchNumberValue(value: Object | symbol): string { 413 let str: string = ''; 414 if (value === '') { 415 str += '0'; 416 } else if (typeof value === 'symbol') { 417 str += 'NaN'; 418 } else if (typeof value === 'number') { 419 str += value; 420 } else if (value instanceof Array) { 421 str += 'NaN'; 422 } else if (typeof value === 'string') { 423 if (isNaN(Number(value))) { 424 str += 'NaN'; 425 } else { 426 str += Number(value); 427 } 428 } else if (typeof value === 'bigint') { 429 str += value.toString() + 'n'; 430 } else { 431 str += 'NaN'; 432 } 433 return str; 434} 435 436function switchStringValue(value: Object | symbol): string { 437 let str: string = ''; 438 if (typeof value === 'undefined') { 439 str += 'undefined'; 440 } else if (typeof value === 'object') { 441 if (value === null) { 442 str += 'null'; 443 } else { 444 str += value; 445 } 446 } else if (typeof value === 'symbol') { 447 str += value.toString(); 448 } else { 449 str += value; 450 } 451 return str; 452} 453 454// printf(formatString : string | Array<string | number | Fn>, 455// ...valueString : Array<string | number | Fn | object>) : string; 456function printf(formatString: Array<string | number | Fn>, ...valueString: Array<Object>): string { 457 let formats: string = helpUtil.dealwithformatstring(formatString); 458 let arr: Array<Object> = []; 459 arr = formats.split(' '); 460 let switchString: Array<Object> = []; 461 let valueLength: number = valueString.length; 462 let arrLength: number = arr.length; 463 let i: number = 0; 464 for (let sub of valueString) { 465 if (i >= arrLength) { 466 break; 467 } 468 if (arr[i] === 'o') { 469 switchString.push(switchLittleObject('\n ', sub, 1)); 470 } else if (arr[i] === 'O') { 471 switchString.push(switchBigObject('\n ', sub, 1)); 472 } else if (arr[i] === 'i') { 473 switchString.push(switchIntValue(sub)); 474 } else if (arr[i] === 'j') { 475 switchString.push(JSON.stringify(sub)); 476 } else if (arr[i] === 'd') { 477 switchString.push(switchNumberValue(sub)); 478 } else if (arr[i] === 's') { 479 switchString.push(switchStringValue(sub)); 480 } else if (arr[i] === 'f') { 481 switchString.push(switchFloatValue(sub)); 482 } else if (arr[i] === 'c') { 483 switchString.push(sub.toString()); 484 } 485 ++i; 486 } 487 while (i < valueLength) { 488 switchString.push(valueString[i].toString()); 489 i++; 490 } 491 let helpUtilString: string = helpUtil.printf(formatString, ...switchString); 492 return helpUtilString; 493} 494 495function format(formatString: Array<string | number | Fn>, ...valueString: Array<Object>): string { 496 if (!(formatString instanceof Array) && (typeof formatString !== 'string')) { 497 let error = new BusinessError(`Parameter error.The type of ${formatString} must be string or array`); 498 throw error; 499 } 500 let valueLength: number = valueString.length; 501 if (valueLength !== 0) { 502 for (let val of valueString) { 503 if (typeof val !== 'object' && typeof val !== 'number' && 504 typeof val !== 'function' && typeof val !== 'string') { 505 let error = new BusinessError('Parameter error.The type of last parameters must be object'); 506 throw error; 507 } 508 } 509 } 510 let formats: string = helpUtil.dealwithformatstring(formatString); 511 let arr: Array<Object> = []; 512 arr = formats.split(' '); 513 let switchString: Array<Object> = []; 514 let arrLength: number = arr.length; 515 let i: number = 0; 516 for (let sub of valueString) { 517 if (i >= arrLength) { 518 break; 519 } 520 if (arr[i] === 'o') { 521 switchString.push(switchLittleObject('\n ', sub, 1)); 522 } else if (arr[i] === 'O') { 523 switchString.push(switchBigObject('\n ', sub, 1)); 524 } else if (arr[i] === 'i') { 525 switchString.push(switchIntValue(sub)); 526 } else if (arr[i] === 'j') { 527 switchString.push(JSON.stringify(sub)); 528 } else if (arr[i] === 'd') { 529 switchString.push(switchNumberValue(sub)); 530 } else if (arr[i] === 's') { 531 switchString.push(switchStringValue(sub)); 532 } else if (arr[i] === 'f') { 533 switchString.push(switchFloatValue(sub)); 534 } else if (arr[i] === 'c') { 535 switchString.push(sub.toString()); 536 } 537 ++i; 538 } 539 while (i < valueLength) { 540 switchString.push(valueString[i].toString()); 541 i++; 542 } 543 let helpUtilString: string = helpUtil.printf(formatString, ...switchString); 544 return helpUtilString; 545} 546 547function getErrorString(errnum: number): string { 548 let errorString: string = helpUtil.geterrorstring(errnum); 549 return errorString; 550} 551 552function errnoToString(errnum: number): string { 553 if (typeof errnum !== 'number') { 554 let error = new BusinessError(`Parameter error.The type of ${errnum} must be number`); 555 throw error; 556 } 557 let errorString: string = helpUtil.geterrorstring(errnum); 558 return errorString; 559} 560 561function randomUUID(entropyCache?: boolean): string { 562 if (entropyCache === undefined || entropyCache === null) { 563 entropyCache = true; 564 } 565 if (typeof entropyCache !== 'boolean') { 566 let error = new BusinessError(`Parameter error.The type of ${entropyCache} must be boolean`); 567 throw error; 568 } 569 let uuidString: string = helpUtil.randomUUID(entropyCache); 570 return uuidString; 571} 572 573function randomBinaryUUID(entropyCache?: boolean): Uint8Array { 574 if (entropyCache === undefined || entropyCache === null) { 575 entropyCache = true; 576 } 577 if (typeof entropyCache !== 'boolean') { 578 let error = new BusinessError(`Parameter error.The type of ${entropyCache} must be boolean`); 579 throw error; 580 } 581 let uuidArray: Uint8Array = helpUtil.randomBinaryUUID(entropyCache); 582 return uuidArray; 583} 584 585function parseUUID(uuid: string): Uint8Array { 586 let format = /[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}/; 587 if (!format.test(uuid)) { 588 let error = new BusinessError(`Syntax Error.Invalid ${uuid} string`); 589 error.code = syntaxErrorCode; 590 throw error; 591 } 592 let uuidArray: Uint8Array = helpUtil.parseUUID(uuid); 593 return uuidArray; 594} 595 596function callbackified(original: Fn, ...args: Array<string | number | Fn>): void { 597 const maybeCb = args.pop(); 598 if (typeof maybeCb !== 'function') { 599 throw new Error('maybe is not function'); 600 } 601 const cb = (...args: Array<null>) => { 602 Reflect.apply(maybeCb, this, args); 603 }; 604 Reflect.apply(original, this, args).then((ret: null) => cb(null, ret), (rej: null) => cb(rej)); 605} 606 607function getOwnPropertyDescriptors(obj: Fn): PropertyDescriptorMap { 608 const result: PropertyDescriptorMap = {}; 609 for (let key of Reflect.ownKeys(obj)) { 610 if (typeof key === 'string') { 611 result[key] = Object.getOwnPropertyDescriptor(obj, key); 612 } 613 } 614 return result; 615} 616 617function callbackWrapper(original: Fn): Function { 618 if (typeof original !== 'function') { 619 let error = new BusinessError(`Parameter error.The type of ${original} must be function`); 620 throw error; 621 } 622 const descriptors = getOwnPropertyDescriptors(original); 623 if (typeof descriptors.length.value === 'number') { 624 descriptors.length.value++; 625 } 626 if (typeof descriptors.name.value === 'string') { 627 descriptors.name.value += 'callbackified'; 628 } 629 function cb(...args: Array<string | number | Fn>) { 630 callbackified(original, ...args); 631 } 632 Object.defineProperties(cb, descriptors); 633 return cb; 634} 635 636function promiseWrapper(func: Function): Object { 637 return function (...args: Array<Object>) { 638 return new Promise((resolve, reject) => { 639 let callback: Function = function (err: Object | string, ...values: Array<Object>) { 640 if (err) { 641 reject(err); 642 } else { 643 resolve(values); 644 } 645 }; 646 func.apply(null, [...args, callback]); 647 }); 648 }; 649} 650 651function promisify(func: Function): Function { 652 if (typeof func !== 'function') { 653 let error = new BusinessError(`Parameter error.The type of ${func} must be function`); 654 throw error; 655 } 656 return function (...args: Array<Object>) { 657 return new Promise((resolve, reject) => { 658 let callback: Function = function (err: Object | string, ...values: Array<Object>) { 659 if (err) { 660 reject(err); 661 } else { 662 resolve(values); 663 } 664 }; 665 func.apply(null, [...args, callback]); 666 }); 667 }; 668} 669 670class LruBuffer { 671 private cache: Map<Object | undefined, Object | undefined>; 672 // Default current size 673 private maxSize: number = 64; 674 // Default maximum size 675 private maxNumber: number = 2147483647; 676 private putCount: number = 0; 677 private createCount: number = 0; 678 private evictionCount: number = 0; 679 private hitCount: number = 0; 680 private missCount: number = 0; 681 public length: number = 0; 682 683 public constructor(capacity?: number) { 684 if (capacity !== undefined && capacity !== null) { 685 if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) { 686 throw new Error('data error'); 687 } 688 this.maxSize = capacity; 689 } 690 this.cache = new Map(); 691 } 692 693 public updateCapacity(newCapacity: number): void { 694 if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) { 695 throw new Error('data error'); 696 } else if (this.cache.size > newCapacity) { 697 this.changeCapacity(newCapacity); 698 } 699 this.length = this.cache.size; 700 this.maxSize = newCapacity; 701 } 702 703 public get(key: Object): Object { 704 if (key === null) { 705 throw new Error('key not be null'); 706 } 707 let value: Object; 708 if (this.cache.has(key)) { 709 value = this.cache.get(key); 710 this.hitCount++; 711 this.cache.delete(key); 712 this.cache.set(key, value); 713 return value; 714 } 715 716 this.missCount++; 717 let createValue: Object = this.createDefault(key); 718 if (createValue === undefined) { 719 return undefined; 720 } else { 721 value = this.put(key, createValue); 722 this.createCount++; 723 if (value !== undefined) { 724 this.put(key, value); 725 this.afterRemoval(false, key, createValue, value); 726 return value; 727 } 728 return createValue; 729 } 730 } 731 732 public put(key: Object, value: Object): Object { 733 if (key === null || value === null) { 734 throw new Error('key or value not be null'); 735 } 736 let former: Object = undefined; 737 this.putCount++; 738 if (this.cache.has(key)) { 739 former = this.cache.get(key); 740 this.cache.delete(key); 741 this.afterRemoval(false, key, former, value); 742 } else if (this.cache.size >= this.maxSize) { 743 this.cache.delete(this.cache.keys().next().value); 744 this.evictionCount++; 745 this.afterRemoval(true, key, value, null); 746 } 747 this.cache.set(key, value); 748 this.length = this.cache.size; 749 return former; 750 } 751 752 public getCreateCount(): number { 753 return this.createCount; 754 } 755 756 public getMissCount(): number { 757 return this.missCount; 758 } 759 760 public getRemovalCount(): number { 761 return this.evictionCount; 762 } 763 764 public getMatchCount(): number { 765 return this.hitCount; 766 } 767 768 public getPutCount(): number { 769 return this.putCount; 770 } 771 772 public getCapacity(): number { 773 return this.maxSize; 774 } 775 776 public clear(): void { 777 this.afterRemoval(false, this.cache.keys(), this.cache.values(), null); 778 this.cache.clear(); 779 this.length = this.cache.size; 780 } 781 782 public isEmpty(): boolean { 783 let temp: boolean = false; 784 if (this.cache.size === 0) { 785 temp = true; 786 } 787 return temp; 788 } 789 790 public contains(key: Object): boolean { 791 let flag: boolean = false; 792 if (this.cache.has(key)) { 793 flag = true; 794 let value: Object; 795 this.hitCount++; 796 value = this.cache.get(key); 797 this.cache.delete(key); 798 this.cache.set(key, value); 799 this.length = this.cache.size; 800 return flag; 801 } 802 this.missCount++; 803 return flag; 804 } 805 806 public remove(key: Object): Object { 807 if (key === null) { 808 throw new Error('key not be null'); 809 } else if (this.cache.has(key)) { 810 let former: Object; 811 former = this.cache.get(key); 812 this.cache.delete(key); 813 if (former !== null) { 814 this.afterRemoval(false, key, former, null); 815 this.length = this.cache.size; 816 return former; 817 } 818 } 819 this.length = this.cache.size; 820 return undefined; 821 } 822 823 public toString(): string { 824 let peek: number = 0; 825 let hitRate: number = 0; 826 peek = this.hitCount + this.missCount; 827 if (peek !== 0) { 828 // The value is 100 times larger 829 hitRate = 100 * this.hitCount / peek; 830 } else { 831 hitRate = 0; 832 } 833 let str: string = ''; 834 str = 'Lrubuffer[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + 835 ', misses = ' + this.missCount + ', hitRate = ' + hitRate + '% ]'; 836 return str; 837 } 838 839 public values(): Object[] { 840 let arr: Array<Object> = []; 841 for (let value of this.cache.values()) { 842 arr.push(value); 843 } 844 return arr; 845 } 846 847 public keys(): Object[] { 848 let arr: Array<Object> = []; 849 for (let key of this.cache.keys()) { 850 arr.push(key); 851 } 852 return arr; 853 } 854 855 protected afterRemoval(isEvict: boolean, key: Object | undefined | null, value: Object | undefined | null, 856 newValue: Object | undefined | null): void { 857 } 858 859 protected createDefault(key: Object): Object { 860 return undefined; 861 } 862 863 public entries(): IterableIterator<[Object, Object]> { 864 return this.cache.entries(); 865 } 866 867 public [Symbol.iterator](): IterableIterator<[Object, Object]> { 868 return this.cache.entries(); 869 } 870 871 private changeCapacity(newCapacity: number): void { 872 while (this.cache.size > newCapacity) { 873 this.cache.delete(this.cache.keys().next().value); 874 this.evictionCount++; 875 this.afterRemoval(true, this.cache.keys(), this.cache.values(), null); 876 } 877 } 878} 879 880class LRUCache { 881 private cache: Map<Object | undefined, Object | undefined>; 882 // Default current size 883 private maxSize: number = 64; 884 // Default maximum size 885 private maxNumber: number = 2147483647; 886 private putCount: number = 0; 887 private createCount: number = 0; 888 private evictionCount: number = 0; 889 private hitCount: number = 0; 890 private missCount: number = 0; 891 public length: number = 0; 892 893 public constructor(capacity?: number) { 894 if (capacity !== undefined && capacity !== null) { 895 if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) { 896 throw new Error('data error'); 897 } 898 this.maxSize = capacity; 899 } 900 this.cache = new Map(); 901 } 902 903 private changeCapacity(newCapacity: number): void { 904 while (this.cache.size > newCapacity) { 905 this.cache.delete(this.cache.keys().next().value); 906 this.evictionCount++; 907 this.afterRemoval(true, this.cache.keys(), this.cache.values(), null); 908 } 909 } 910 911 protected afterRemoval(isEvict: boolean, key: Object | undefined | null, value: Object | undefined | null, 912 newValue: Object | undefined | null): void { 913 } 914 915 protected createDefault(key: Object): Object { 916 if (typeof (key as Object) === 'undefined') { 917 let error = new BusinessError(`Parameter error.The type of ${key} must be Object`); 918 throw error; 919 } 920 return undefined; 921 } 922 923 public updateCapacity(newCapacity: number): void { 924 if (typeof newCapacity !== 'number') { 925 let error = new BusinessError(`Parameter error.The type of ${newCapacity} must be number`); 926 throw error; 927 } 928 if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) { 929 throw new Error('data error'); 930 } else if (this.cache.size > newCapacity) { 931 this.changeCapacity(newCapacity); 932 } 933 this.length = this.cache.size; 934 this.maxSize = newCapacity; 935 } 936 937 public get(key: Object): Object { 938 if (typeof (key as Object) === 'undefined') { 939 let error = new BusinessError(`Parameter error.The type of ${key} must be Object`); 940 throw error; 941 } 942 if (key === null) { 943 throw new Error('key not be null'); 944 } 945 let value: Object; 946 if (this.cache.has(key)) { 947 value = this.cache.get(key); 948 this.hitCount++; 949 this.cache.delete(key); 950 this.cache.set(key, value); 951 return value; 952 } 953 954 this.missCount++; 955 let createValue: Object = this.createDefault(key); 956 if (createValue === undefined) { 957 return undefined; 958 } else { 959 value = this.put(key, createValue); 960 this.createCount++; 961 if (value !== undefined) { 962 this.put(key, value); 963 this.afterRemoval(false, key, createValue, value); 964 return value; 965 } 966 return createValue; 967 } 968 } 969 970 public put(key: Object, value: Object): Object { 971 if (typeof (key as Object) === 'undefined') { 972 let error = new BusinessError(`Parameter error.The type of ${key} must be Object`); 973 throw error; 974 } 975 if (typeof (value as Object) === 'undefined') { 976 let error = new BusinessError(`Parameter error.The type of ${value} must be Object`); 977 throw error; 978 } 979 if (key === null || value === null) { 980 throw new Error('key or value not be null'); 981 } 982 let former: Object = undefined; 983 this.putCount++; 984 if (this.cache.has(key)) { 985 former = this.cache.get(key); 986 this.cache.delete(key); 987 this.afterRemoval(false, key, former, value); 988 } else if (this.cache.size >= this.maxSize) { 989 this.cache.delete(this.cache.keys().next().value); 990 this.evictionCount++; 991 this.afterRemoval(true, key, value, null); 992 } 993 this.cache.set(key, value); 994 this.length = this.cache.size; 995 return former; 996 } 997 998 public remove(key: Object): Object { 999 if (typeof (key as Object) === 'undefined') { 1000 let error = new BusinessError(`Parameter error.The type of ${key} must be Object`); 1001 throw error; 1002 } 1003 if (key === null) { 1004 throw new Error('key not be null'); 1005 } else if (this.cache.has(key)) { 1006 let former: Object = this.cache.get(key); 1007 this.cache.delete(key); 1008 if (former !== null) { 1009 this.afterRemoval(false, key, former, null); 1010 this.length = this.cache.size; 1011 return former; 1012 } 1013 } 1014 this.length = this.cache.size; 1015 return undefined; 1016 } 1017 1018 public contains(key: Object): boolean { 1019 if (typeof (key as Object) === 'undefined') { 1020 let error = new BusinessError(`Parameter error.The type of ${key} must be Object`); 1021 throw error; 1022 } 1023 let flag: boolean = false; 1024 if (this.cache.has(key)) { 1025 flag = true; 1026 this.hitCount++; 1027 let value: Object = this.cache.get(key); 1028 this.cache.delete(key); 1029 this.cache.set(key, value); 1030 this.length = this.cache.size; 1031 return flag; 1032 } 1033 this.missCount++; 1034 return flag; 1035 } 1036 1037 public getCreateCount(): number { 1038 return this.createCount; 1039 } 1040 1041 public getMissCount(): number { 1042 return this.missCount; 1043 } 1044 1045 public getRemovalCount(): number { 1046 return this.evictionCount; 1047 } 1048 1049 public getMatchCount(): number { 1050 return this.hitCount; 1051 } 1052 1053 public getPutCount(): number { 1054 return this.putCount; 1055 } 1056 1057 public getCapacity(): number { 1058 return this.maxSize; 1059 } 1060 1061 public clear(): void { 1062 this.afterRemoval(false, this.cache.keys(), this.cache.values(), null); 1063 this.cache.clear(); 1064 this.length = this.cache.size; 1065 } 1066 1067 public isEmpty(): boolean { 1068 return this.cache.size === 0; 1069 } 1070 1071 public toString(): string { 1072 let peek: number = 0; 1073 let hitRate: number = 0; 1074 peek = this.hitCount + this.missCount; 1075 if (peek !== 0) { 1076 // The value is 100 times larger 1077 hitRate = 100 * this.hitCount / peek; 1078 } 1079 let str: string = ''; 1080 str = 'LRUCache[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + 1081 ', misses = ' + this.missCount + ', hitRate = ' + hitRate + '% ]'; 1082 return str; 1083 } 1084 1085 public values(): Object[] { 1086 let arr: Array<Object> = []; 1087 for (let value of this.cache.values()) { 1088 arr.push(value); 1089 } 1090 return arr; 1091 } 1092 1093 public keys(): Object[] { 1094 let arr: Array<Object> = []; 1095 for (let key of this.cache.keys()) { 1096 arr.push(key); 1097 } 1098 return arr; 1099 } 1100 1101 public entries(): IterableIterator<[Object, Object]> { 1102 return this.cache.entries(); 1103 } 1104 1105 public [Symbol.iterator](): IterableIterator<[Object, Object]> { 1106 return this.cache.entries(); 1107 } 1108} 1109 1110class RationalNumber { 1111 private mnum: number = 0; 1112 private mden: number = 0; 1113 1114 public constructor() 1115 public constructor(num: number, den: number) 1116 public constructor(num?: number, den?: number) { 1117 if (!num && !den) { 1118 1119 } 1120 else { 1121 num = den < 0 ? num * (-1) : num; 1122 den = den < 0 ? den * (-1) : den; 1123 if (den === 0) { 1124 if (num > 0) { 1125 this.mnum = 1; 1126 this.mden = 0; 1127 } else if (num < 0) { 1128 this.mnum = -1; 1129 this.mden = 0; 1130 } else { 1131 this.mnum = 0; 1132 this.mden = 0; 1133 } 1134 } else if (num === 0) { 1135 this.mnum = 0; 1136 this.mden = 1; 1137 } else { 1138 let gnum: number = 0; 1139 gnum = this.getCommonDivisor(num, den); 1140 if (gnum !== 0) { 1141 this.mnum = num / gnum; 1142 this.mden = den / gnum; 1143 } 1144 } 1145 } 1146 } 1147 1148 static parseRationalNumber(num: number, den: number): RationalNumber { 1149 if (typeof num !== 'number') { 1150 let error = new BusinessError(`Parameter error.The type of ${num} must be number`); 1151 throw error; 1152 } 1153 if (typeof den !== 'number') { 1154 let error = new BusinessError(`Parameter error.The type of ${den} must be number`); 1155 throw error; 1156 } 1157 1158 num = den < 0 ? num * (-1) : num; 1159 den = den < 0 ? den * (-1) : den; 1160 let ratNum = new RationalNumber(); 1161 if (den === 0) { 1162 if (num > 0) { 1163 ratNum.mnum = 1; 1164 ratNum.mden = 0; 1165 } else if (num < 0) { 1166 ratNum.mnum = -1; 1167 ratNum.mden = 0; 1168 } else { 1169 ratNum.mnum = 0; 1170 ratNum.mden = 0; 1171 } 1172 } else if (num === 0) { 1173 ratNum.mnum = 0; 1174 ratNum.mden = 1; 1175 } else { 1176 let gnum: number = 0; 1177 gnum = this.getCommonFactor(num, den); 1178 if (gnum !== 0) { 1179 ratNum.mnum = num / gnum; 1180 ratNum.mden = den / gnum; 1181 } 1182 } 1183 return ratNum; 1184 } 1185 1186 static createRationalFromString(str: string): RationalNumber { 1187 if (typeof str !== 'string') { 1188 let error = new BusinessError(`Parameter error.The type of ${str} must be string`); 1189 throw error; 1190 } 1191 if (str === null) { 1192 throw new Error('string invalid!'); 1193 } 1194 let colon: number = str.indexOf(':'); 1195 let semicolon: number = str.indexOf('/'); 1196 if ((colon < 0 && semicolon < 0) || (colon > 0 && semicolon > 0)) { 1197 throw new Error('string invalid!'); 1198 } 1199 let index: number = (colon > 0) ? colon : semicolon; 1200 let s1: string = str.substr(0, index); 1201 let s2: string = str.substr(index + 1, str.length); 1202 let num1: number = Number(s1); 1203 let num2: number = Number(s2); 1204 return RationalNumber.parseRationalNumber(num1, num2); 1205 } 1206 1207 public compareTo(other: RationalNumber): number { 1208 if (this.mnum === other.mnum && this.mden === other.mden) { 1209 return 0; 1210 } else if (this.mnum === 0 && this.mden === 0) { 1211 return 1; 1212 } else if ((other.mnum === 0) && (other.mden === 0)) { 1213 return -1; 1214 } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) { 1215 return 1; 1216 } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) { 1217 return -1; 1218 } 1219 let thisnum: number = this.mnum * other.mden; 1220 let othernum: number = other.mnum * this.mden; 1221 if (thisnum < othernum) { 1222 return -1; 1223 } else if (thisnum > othernum) { 1224 return 1; 1225 } else { 1226 return 0; 1227 } 1228 } 1229 1230 public compare(other: RationalNumber): number { 1231 if (!(other instanceof RationalNumber)) { 1232 let error = new BusinessError(`Parameter error.The type of ${other} must be RationalNumber`); 1233 throw error; 1234 } 1235 if (this.mnum === other.mnum && this.mden === other.mden) { 1236 return 0; 1237 } else if (this.mnum === 0 && this.mden === 0) { 1238 return 1; 1239 } else if ((other.mnum === 0) && (other.mden === 0)) { 1240 return -1; 1241 } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) { 1242 return 1; 1243 } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) { 1244 return -1; 1245 } 1246 let thisnum: number = this.mnum * other.mden; 1247 let othernum: number = other.mnum * this.mden; 1248 if (thisnum < othernum) { 1249 return -1; 1250 } else if (thisnum > othernum) { 1251 return 1; 1252 } else { 1253 return 0; 1254 } 1255 } 1256 1257 public equals(obj: object): boolean { 1258 if (!(obj instanceof RationalNumber)) { 1259 return false; 1260 } 1261 let thisnum: number = this.mnum * obj.mden; 1262 let objnum: number = obj.mnum * this.mden; 1263 if (this.mnum === obj.mnum && this.mden === obj.mden) { 1264 return true; 1265 } else if ((thisnum === objnum) && (this.mnum !== 0 && this.mden !== 0) && (obj.mnum !== 0 && obj.mden !== 0)) { 1266 return true; 1267 } else if ((this.mnum === 0 && this.mden !== 0) && (obj.mnum === 0 && obj.mden !== 0)) { 1268 return true; 1269 } else if ((this.mnum > 0 && this.mden === 0) && (obj.mnum > 0 && obj.mden === 0)) { 1270 return true; 1271 } else if ((this.mnum < 0 && this.mden === 0) && (obj.mnum < 0 && obj.mden === 0)) { 1272 return true; 1273 } else { 1274 return false; 1275 } 1276 } 1277 1278 public valueOf(): number { 1279 if (this.mnum > 0 && this.mden === 0) { 1280 return Number.POSITIVE_INFINITY; 1281 } else if (this.mnum < 0 && this.mden === 0) { 1282 return Number.NEGATIVE_INFINITY; 1283 } else if ((this.mnum === 0) && (this.mden === 0)) { 1284 return Number.NaN; 1285 } else { 1286 return this.mnum / this.mden; 1287 } 1288 } 1289 1290 public getCommonDivisor(number1: number, number2: number): number { 1291 if (number1 === 0 || number2 === 0) { 1292 throw new Error('Parameter cannot be zero!'); 1293 } 1294 let temp: number = 0; 1295 if (number1 < number2) { 1296 temp = number1; 1297 number1 = number2; 1298 number2 = temp; 1299 } 1300 while (number1 % number2 !== 0) { 1301 temp = number1 % number2; 1302 number1 = number2; 1303 number2 = temp; 1304 } 1305 return number2; 1306 } 1307 1308 static getCommonFactor(firNum: number, SecNum: number): number { 1309 if (typeof firNum !== 'number') { 1310 let error = new BusinessError(`Parameter error.The type of ${firNum} must be number`); 1311 throw error; 1312 } 1313 if (typeof SecNum !== 'number') { 1314 let error = new BusinessError(`Parameter error.The type of ${SecNum} must be number`); 1315 throw error; 1316 } 1317 if (firNum === 0 || SecNum === 0) { 1318 throw new Error('Parameter cannot be zero!'); 1319 } 1320 let temp: number = 0; 1321 if (firNum < SecNum) { 1322 temp = firNum; 1323 firNum = SecNum; 1324 SecNum = temp; 1325 } 1326 while (firNum % SecNum !== 0) { 1327 temp = firNum % SecNum; 1328 firNum = SecNum; 1329 SecNum = temp; 1330 } 1331 return SecNum; 1332 } 1333 1334 public getDenominator(): number { 1335 return this.mden; 1336 } 1337 1338 public getNumerator(): number { 1339 return this.mnum; 1340 } 1341 1342 public isFinite(): boolean { 1343 return this.mden !== 0; 1344 } 1345 1346 public isNaN(): boolean { 1347 return this.mnum === 0 && this.mden === 0; 1348 } 1349 1350 public isZero(): boolean { 1351 return this.mnum === 0 && this.mden !== 0; 1352 } 1353 1354 public toString(): string { 1355 let buf: string; 1356 if (this.mnum === 0 && this.mden === 0) { 1357 buf = 'NaN'; 1358 } else if (this.mnum > 0 && this.mden === 0) { 1359 buf = 'Infinity'; 1360 } else if (this.mnum < 0 && this.mden === 0) { 1361 buf = '-Infinity'; 1362 } else { 1363 buf = String(this.mnum) + '/' + String(this.mden); 1364 } 1365 return buf; 1366 } 1367} 1368 1369interface ScopeComparable { 1370 compareTo(other: ScopeComparable): boolean; 1371} 1372 1373type ScopeType = ScopeComparable; 1374 1375class Scope { 1376 private readonly _lowerLimit: ScopeType; 1377 private readonly _upperLimit: ScopeType; 1378 1379 public constructor(readonly lowerObj: ScopeType, readonly upperObj: ScopeType) { 1380 this.checkNull(lowerObj, 'lower limit not be null'); 1381 this.checkNull(upperObj, 'upper limit not be null'); 1382 1383 if (lowerObj.compareTo(upperObj)) { 1384 throw new Error('lower limit must be less than or equal to upper limit'); 1385 } 1386 this._lowerLimit = lowerObj; 1387 this._upperLimit = upperObj; 1388 } 1389 1390 public getLower(): ScopeType { 1391 return this._lowerLimit; 1392 } 1393 1394 public getUpper(): ScopeType { 1395 return this._upperLimit; 1396 } 1397 1398 public compareTo(): boolean { 1399 return false; 1400 } 1401 1402 public contains(value: ScopeType): boolean; 1403 public contains(scope: Scope): boolean; 1404 public contains(x: Scope | ScopeType): boolean { 1405 let resLower: boolean; 1406 let resUpper: boolean; 1407 this.checkNull(x, 'value must not be null'); 1408 if (x instanceof Scope) { 1409 resLower = x._lowerLimit.compareTo(this._lowerLimit); 1410 resUpper = this._upperLimit.compareTo(x._upperLimit); 1411 } else { 1412 resLower = x.compareTo(this._lowerLimit); 1413 resUpper = this._upperLimit.compareTo(x); 1414 } 1415 return resLower && resUpper; 1416 } 1417 1418 public clamp(value: ScopeType): ScopeType { 1419 this.checkNull(value, 'value must not be null'); 1420 if (!value.compareTo(this._lowerLimit)) { 1421 return this._lowerLimit; 1422 } else if (value.compareTo(this._upperLimit)) { 1423 return this._upperLimit; 1424 } else { 1425 return value; 1426 } 1427 } 1428 1429 public intersect(scope: Scope): Scope; 1430 public intersect(lowerObj: ScopeType, upperObj: ScopeType): Scope; 1431 public intersect(x: Scope, y?: Scope | ScopeType): Scope { 1432 let reLower: boolean; 1433 let reUpper: boolean; 1434 let mLower: ScopeType; 1435 let mUpper: ScopeType; 1436 if (y) { 1437 this.checkNull(x, 'lower limit must not be null'); 1438 this.checkNull(y, 'upper limit must not be null'); 1439 reLower = this._lowerLimit.compareTo(x); 1440 reUpper = y.compareTo(this._upperLimit); 1441 if (reLower && reUpper) { 1442 return this; 1443 } else { 1444 mLower = reLower ? this._lowerLimit : x; 1445 mUpper = reUpper ? this._upperLimit : y; 1446 return new Scope(mLower, mUpper); 1447 } 1448 } else { 1449 this.checkNull(x, 'scope must not be null'); 1450 reLower = this._lowerLimit.compareTo(x._lowerLimit); 1451 reUpper = x._upperLimit.compareTo(this._upperLimit); 1452 if (!reLower && !reUpper) { 1453 return x; 1454 } else if (reLower && reUpper) { 1455 return this; 1456 } else { 1457 mLower = reLower ? this._lowerLimit : x._lowerLimit; 1458 mUpper = reUpper ? this._upperLimit : x._upperLimit; 1459 return new Scope(mLower, mUpper); 1460 } 1461 } 1462 } 1463 1464 public expand(obj: ScopeType): Scope; 1465 public expand(scope: Scope): Scope; 1466 public expand(lowerObj: ScopeType, upperObj: ScopeType): Scope; 1467 public expand(x: ScopeType, y?: ScopeType): Scope { 1468 let reLower: boolean; 1469 let reUpper: boolean; 1470 let mLower: ScopeType; 1471 let mUpper: ScopeType; 1472 if (!y) { 1473 this.checkNull(x, 'value must not be null'); 1474 if (!(x instanceof Scope)) { 1475 this.checkNull(x, 'value must not be null'); 1476 return this.expand(x, x); 1477 } 1478 reLower = x._lowerLimit.compareTo(this._lowerLimit); 1479 reUpper = this._upperLimit.compareTo(x._upperLimit); 1480 if (reLower && reUpper) { 1481 return this; 1482 } else if (!reLower && !reUpper) { 1483 return x; 1484 } else { 1485 mLower = reLower ? this._lowerLimit : x._lowerLimit; 1486 mUpper = reUpper ? this._upperLimit : x._upperLimit; 1487 return new Scope(mLower, mUpper); 1488 } 1489 1490 } else { 1491 this.checkNull(x, 'lower limit must not be null'); 1492 this.checkNull(y, 'upper limit must not be null'); 1493 reLower = x.compareTo(this._lowerLimit); 1494 reUpper = this._upperLimit.compareTo(y); 1495 if (reLower && reUpper) { 1496 return this; 1497 } 1498 mLower = reLower ? this._lowerLimit : x; 1499 mUpper = reUpper ? this._upperLimit : y; 1500 return new Scope(mLower, mUpper); 1501 } 1502 } 1503 1504 public toString(): string { 1505 let strLower: string = this._lowerLimit.toString(); 1506 let strUpper: string = this._upperLimit.toString(); 1507 return `[${strLower}, ${strUpper}]`; 1508 } 1509 1510 public checkNull(o: ScopeType, str: string): void { 1511 if (o === null) { 1512 throw new Error(str); 1513 } 1514 } 1515} 1516 1517class ScopeHelper { 1518 private readonly _lowerLimit: ScopeType; 1519 private readonly _upperLimit: ScopeType; 1520 public constructor(readonly lowerObj: ScopeType, readonly upperObj: ScopeType) { 1521 if (typeof lowerObj !== 'object') { 1522 let error = new BusinessError(`Parameter error.The type of ${lowerObj} must be object`); 1523 throw error; 1524 } 1525 if (typeof upperObj !== 'object') { 1526 let error = new BusinessError(`Parameter error.The type of ${upperObj} must be object`); 1527 throw error; 1528 } 1529 1530 this.checkNull(lowerObj, 'lower limit not be null'); 1531 this.checkNull(upperObj, 'upper limit not be null'); 1532 1533 if (lowerObj.compareTo(upperObj)) { 1534 throw new Error('lower limit must be less than or equal to upper limit'); 1535 } 1536 this._lowerLimit = lowerObj; 1537 this._upperLimit = upperObj; 1538 } 1539 1540 public getLower(): ScopeType { 1541 return this._lowerLimit; 1542 } 1543 1544 public getUpper(): ScopeType { 1545 return this._upperLimit; 1546 } 1547 1548 public compareTo(): boolean { 1549 return false; 1550 } 1551 1552 public contains(value: ScopeType): boolean; 1553 public contains(scope: ScopeHelper): boolean; 1554 public contains(x: ScopeHelper | ScopeType): boolean { 1555 this.checkNull(x, 'value must not be null'); 1556 if (typeof x !== 'object') { 1557 let error = new BusinessError(`Parameter error.The type of ${x} must be object or ScopeHelper`); 1558 throw error; 1559 } 1560 let resLower: boolean; 1561 let resUpper: boolean; 1562 if (x instanceof ScopeHelper) { 1563 resLower = x._lowerLimit.compareTo(this._lowerLimit); 1564 resUpper = this._upperLimit.compareTo(x._upperLimit); 1565 } else { 1566 resLower = x.compareTo(this._lowerLimit); 1567 resUpper = this._upperLimit.compareTo(x); 1568 } 1569 return resLower && resUpper; 1570 } 1571 1572 public clamp(value: ScopeType): ScopeType { 1573 this.checkNull(value, 'value must not be null'); 1574 if (typeof value !== 'object') { 1575 let error = new BusinessError(`Parameter error.The type of ${value} must be object`); 1576 throw error; 1577 } 1578 1579 if (!value.compareTo(this._lowerLimit)) { 1580 return this._lowerLimit; 1581 } else if (value.compareTo(this._upperLimit)) { 1582 return this._upperLimit; 1583 } else { 1584 return value; 1585 } 1586 } 1587 1588 public intersect(scope: ScopeHelper): ScopeHelper; 1589 public intersect(lowerObj: ScopeType, upperObj: ScopeType): ScopeHelper; 1590 public intersect(x: ScopeHelper, y?: ScopeType): ScopeHelper { 1591 if (typeof x !== 'object') { 1592 let error = new BusinessError(`Parameter error.The type of ${x} must be ScopeHelper or ScopeType`); 1593 throw error; 1594 } 1595 let reLower: boolean; 1596 let reUpper: boolean; 1597 let mLower: ScopeType; 1598 let mUpper: ScopeType; 1599 if (y) { 1600 this.checkNull(x, 'lower limit must not be null'); 1601 this.checkNull(y, 'upper limit must not be null'); 1602 if (typeof y !== 'object') { 1603 let error = new BusinessError(`Parameter error.The type of ${y} must be ScopeType`); 1604 throw error; 1605 } 1606 reLower = this._lowerLimit.compareTo(x); 1607 reUpper = y.compareTo(this._upperLimit); 1608 if (reLower && reUpper) { 1609 return this; 1610 } else { 1611 mLower = reLower ? this._lowerLimit : x; 1612 mUpper = reUpper ? this._upperLimit : y; 1613 return new ScopeHelper(mLower, mUpper); 1614 } 1615 } else { 1616 this.checkNull(x, 'scope must not be null'); 1617 reLower = this._lowerLimit.compareTo(x._lowerLimit); 1618 reUpper = x._upperLimit.compareTo(this._upperLimit); 1619 if (!reLower && !reUpper) { 1620 return x; 1621 } else if (reLower && reUpper) { 1622 return this; 1623 } else { 1624 mLower = reLower ? this._lowerLimit : x._lowerLimit; 1625 mUpper = reUpper ? this._upperLimit : x._upperLimit; 1626 return new ScopeHelper(mLower, mUpper); 1627 } 1628 } 1629 } 1630 1631 public expand(obj: ScopeType): ScopeHelper; 1632 public expand(scope: ScopeHelper): ScopeHelper; 1633 public expand(lowerObj: ScopeType, upperObj: ScopeType): ScopeHelper; 1634 public expand(x: ScopeType, y?: ScopeType): ScopeHelper { 1635 if (typeof x !== 'object') { 1636 let error = new BusinessError(`Parameter error.The type of ${x} must be ScopeHelper or ScopeType`); 1637 throw error; 1638 } 1639 let reLower: boolean; 1640 let reUpper: boolean; 1641 let mLower: ScopeType; 1642 let mUpper: ScopeType; 1643 if (!y) { 1644 this.checkNull(x, 'value must not be null'); 1645 if (!(x instanceof ScopeHelper)) { 1646 this.checkNull(x, 'value must not be null'); 1647 return this.expand(x, x); 1648 } 1649 reLower = x._lowerLimit.compareTo(this._lowerLimit); 1650 reUpper = this._upperLimit.compareTo(x._upperLimit); 1651 if (reLower && reUpper) { 1652 return this; 1653 } else if (!reLower && !reUpper) { 1654 return x; 1655 } else { 1656 mLower = reLower ? this._lowerLimit : x._lowerLimit; 1657 mUpper = reUpper ? this._upperLimit : x._upperLimit; 1658 return new ScopeHelper(mLower, mUpper); 1659 } 1660 1661 } else { 1662 if (typeof y !== 'object') { 1663 let error = new BusinessError(`Parameter error.The type of ${y} must be ScopeType`); 1664 throw error; 1665 } 1666 1667 this.checkNull(x, 'lower limit must not be null'); 1668 this.checkNull(y, 'upper limit must not be null'); 1669 reLower = x.compareTo(this._lowerLimit); 1670 reUpper = this._upperLimit.compareTo(y); 1671 if (reLower && reUpper) { 1672 return this; 1673 } 1674 mLower = reLower ? this._lowerLimit : x; 1675 mUpper = reUpper ? this._upperLimit : y; 1676 return new ScopeHelper(mLower, mUpper); 1677 } 1678 } 1679 1680 public toString(): string { 1681 let strLower: string = this._lowerLimit.toString(); 1682 let strUpper: string = this._upperLimit.toString(); 1683 return `[${strLower}, ${strUpper}]`; 1684 } 1685 1686 public checkNull(o: ScopeType, str: string): void { 1687 if (o === null) { 1688 throw new Error(str); 1689 } 1690 } 1691} 1692 1693export default { 1694 printf: printf, 1695 format: format, 1696 getErrorString: getErrorString, 1697 errnoToString: errnoToString, 1698 callbackWrapper: callbackWrapper, 1699 promiseWrapper: promiseWrapper, 1700 promisify: promisify, 1701 randomUUID: randomUUID, 1702 randomBinaryUUID: randomBinaryUUID, 1703 generateRandomUUID: randomUUID, 1704 generateRandomBinaryUUID: randomBinaryUUID, 1705 parseUUID: parseUUID, 1706 TextEncoder: textEncoder, 1707 TextDecoder: textDecoder, 1708 Base64: base64, 1709 Base64Helper: Base64Helper, 1710 types: types, 1711 LruBuffer: LruBuffer, 1712 LRUCache: LRUCache, 1713 RationalNumber: RationalNumber, 1714 Scope: Scope, 1715 ScopeHelper: ScopeHelper, 1716 Type: Type, 1717}; 1718