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