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