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