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