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