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