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