• 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');
38var TextEncoder = helpUtil.TextEncoder;
39var TextDecoder = helpUtil.TextDecoder;
40var Base64 = helpUtil.Base64;
41var Base64Helper = helpUtil.Base64Helper;
42var 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
536    function cb(...args : Array<string | number | Fn>) {
537        callbackified(original, ...args);
538    }
539    Object.defineProperties(cb, descriptors);
540    return cb;
541}
542
543function promiseWrapper(func : Function) : Object {
544    return function (...args : Array<Object>) {
545        return new Promise((resolve, reject) => {
546            let callback : Function = function (err : Object | string, ...values : Array<Object>) {
547                if (err) {
548                    reject(err);
549                } else {
550                    resolve(values);
551                }
552            };
553            func.apply(null, [...args, callback]);
554        });
555    };
556}
557
558function promisify(func : Function) : Function {
559    if (typeof func !== 'function') {
560        let error = new BusinessError(`Parameter error.The type of ${func} must be function`);
561        throw error;
562    }
563    return function (...args : Array<Object>) {
564        return new Promise((resolve, reject) => {
565            let callback : Function = function (err : Object | string, ...values : Array<Object>) {
566                if (err) {
567                    reject(err);
568                } else {
569                    resolve(values);
570                }
571            };
572            func.apply(null, [...args, callback]);
573        });
574    };
575}
576
577class LruBuffer {
578    private cache: Map<Object | undefined, Object | undefined>;
579    private maxSize : number = 64;
580    private maxNumber : number = 2147483647;
581    private putCount : number = 0;
582    private createCount : number = 0;
583    private evictionCount : number = 0;
584    private hitCount : number = 0;
585    private missCount : number = 0;
586    public length : number = 0;
587
588    public constructor(capacity?: number) {
589        if (capacity !== undefined) {
590            if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) {
591                throw new Error('data error');
592            }
593            this.maxSize = capacity;
594        }
595        this.cache = new Map();
596    }
597
598    public updateCapacity(newCapacity : number) : void {
599        if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) {
600            throw new Error('data error');
601        } else if (this.cache.size > newCapacity) {
602            this.changeCapacity(newCapacity);
603        }
604        this.length = this.cache.size;
605        this.maxSize = newCapacity;
606    }
607
608    public get(key : Object) : Object {
609        if (key === null) {
610            throw new Error('key not be null');
611        }
612        let value : Object;
613        if (this.cache.has(key)) {
614            value = this.cache.get(key);
615            this.hitCount++;
616            this.cache.delete(key);
617            this.cache.set(key, value);
618            return value;
619        }
620
621        this.missCount++;
622        let createValue : Object = this.createDefault(key);
623        if (createValue === undefined) {
624            return undefined;
625        } else {
626            value = this.put(key, createValue);
627            this.createCount++;
628            if (value !== undefined) {
629                this.put(key, value);
630                this.afterRemoval(false, key, createValue, value);
631                return value;
632            }
633            return createValue;
634        }
635    }
636
637    public put(key : Object, value : Object) : Object {
638        if (key === null || value === null) {
639            throw new Error('key or value not be null');
640        }
641        let former : Object = undefined;
642        this.putCount++;
643        if (this.cache.has(key)) {
644            former = this.cache.get(key);
645            this.cache.delete(key);
646            this.afterRemoval(false, key, former, value);
647        } else if (this.cache.size >= this.maxSize) {
648            this.cache.delete(this.cache.keys().next().value);
649            this.evictionCount++;
650            this.afterRemoval(true, key, value, null);
651        }
652        this.cache.set(key, value);
653        this.length = this.cache.size;
654        return former;
655    }
656
657    public getCreateCount() : number {
658        return this.createCount;
659    }
660
661    public getMissCount() : number {
662        return this.missCount;
663    }
664
665    public getRemovalCount() : number {
666        return this.evictionCount;
667    }
668
669    public getMatchCount() : number {
670        return this.hitCount;
671    }
672
673    public getPutCount() : number {
674        return this.putCount;
675    }
676
677    public getCapacity() : number {
678         return this.maxSize;
679    }
680
681    public clear() : void {
682        this.afterRemoval(false, this.cache.keys(), this.cache.values(), null);
683        this.cache.clear();
684        this.length = this.cache.size;
685    }
686
687    public isEmpty() :boolean {
688        let temp : boolean = false;
689        if (this.cache.size === 0) {
690            temp = true;
691        }
692        return temp;
693    }
694
695    public contains(key : Object) : boolean {
696        let flag : boolean = false;
697        if (this.cache.has(key)) {
698            flag = true;
699            let value : Object;
700            this.hitCount++;
701            value = this.cache.get(key);
702            this.cache.delete(key);
703            this.cache.set(key, value);
704            this.length = this.cache.size;
705            return flag;
706        }
707        this.missCount++;
708        return flag;
709    }
710
711    public remove(key : Object) : Object {
712        if (key === null) {
713            throw new Error('key not be null');
714        } else if (this.cache.has(key)) {
715            let former : Object;
716            former = this.cache.get(key);
717            this.cache.delete(key);
718            if (former !== null) {
719                this.afterRemoval(false, key, former, null);
720                this.length = this.cache.size;
721                return former;
722            }
723        }
724        this.length = this.cache.size;
725        return undefined;
726    }
727
728    public toString() : string {
729        let peek : number = 0;
730        let hitRate : number = 0;
731        peek = this.hitCount + this.missCount;
732        if (peek !== 0) {
733            hitRate = 100 * this.hitCount / peek;
734        } else {
735            hitRate = 0;
736        }
737        let str : string = '';
738        str = 'Lrubuffer[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + ', misses = ' + this.missCount
739            + ', hitRate = ' + hitRate + '% ]';
740        return str;
741    }
742
743    public values() : Object[] {
744        let arr : Array<Object> = [];
745        for(let value of this.cache.values()) {
746            arr.push(value);
747        }
748        return arr;
749    }
750
751    public keys() : Object[] {
752        let arr : Array<Object> = [];
753        for(let key of this.cache.keys()) {
754            arr.push(key);
755        }
756        return arr;
757    }
758
759    protected afterRemoval(isEvict : boolean, key : Object | undefined | null, value : Object | undefined | null,
760                           newValue : Object | undefined | null) : void {
761    }
762
763    protected createDefault(key : Object) : Object {
764        return undefined;
765    }
766
767    public entries() : IterableIterator<[Object, Object]> {
768        return this.cache.entries();
769    }
770
771    public [Symbol.iterator] () : IterableIterator<[Object, Object]> {
772        return this.cache.entries();
773    }
774
775    private changeCapacity(newCapacity : number) : void {
776        while (this.cache.size > newCapacity) {
777            this.cache.delete(this.cache.keys().next().value);
778            this.evictionCount++;
779            this.afterRemoval(true, this.cache.keys(), this.cache.values(), null);
780        }
781    }
782}
783
784class LRUCache {
785    private cache : Map<Object | undefined, Object | undefined>;
786    private maxSize : number = 64;
787    private maxNumber : number = 2147483647;
788    private putCount : number = 0;
789    private createCount : number = 0;
790    private evictionCount : number = 0;
791    private hitCount : number = 0;
792    private missCount : number = 0;
793    public length : number = 0;
794
795    public constructor(capacity ?: number) {
796        if (capacity !== undefined) {
797            if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) {
798                throw new Error('data error');
799            }
800            this.maxSize = capacity;
801        }
802        this.cache = new Map();
803    }
804
805    private changeCapacity(newCapacity : number) : void {
806        while (this.cache.size > newCapacity) {
807            this.cache.delete(this.cache.keys().next().value);
808            this.evictionCount++;
809            this.afterRemoval(true, this.cache.keys(), this.cache.values(), null);
810        }
811    }
812
813    protected afterRemoval(isEvict : boolean, key : Object | undefined | null, value : Object | undefined | null,
814        newValue : Object | undefined | null) : void {
815    }
816
817    protected createDefault(key : Object) : Object {
818        if (typeof (key as Object) === 'undefined') {
819            let error = new BusinessError(`Parameter error.The type of ${key} must be Object`);
820            throw error;
821        }
822        return undefined;
823    }
824
825    public updateCapacity(newCapacity : number) : void {
826        if (typeof newCapacity !== 'number') {
827            let error = new BusinessError(`Parameter error.The type of ${newCapacity} must be number`);
828            throw error;
829        }
830        if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) {
831            throw new Error('data error');
832        } else if (this.cache.size > newCapacity) {
833            this.changeCapacity(newCapacity);
834        }
835        this.length = this.cache.size;
836        this.maxSize = newCapacity;
837    }
838
839    public get(key : Object) : Object {
840        if (typeof (key as Object) === 'undefined') {
841            let error = new BusinessError(`Parameter error.The type of ${key} must be Object`);
842            throw error;
843        }
844        if (key === null) {
845            throw new Error('key not be null');
846        }
847        let value : Object;
848        if (this.cache.has(key)) {
849            value = this.cache.get(key);
850            this.hitCount++;
851            this.cache.delete(key);
852            this.cache.set(key, value);
853            return value;
854        }
855
856        this.missCount++;
857        let createValue : Object = this.createDefault(key);
858        if (createValue === undefined) {
859            return undefined;
860        } else {
861            value = this.put(key, createValue);
862            this.createCount++;
863            if (value !== undefined) {
864                this.put(key, value);
865                this.afterRemoval(false, key, createValue, value);
866                return value;
867            }
868            return createValue;
869        }
870    }
871
872    public put(key : Object, value : Object) : Object {
873        if (typeof (key as Object) === 'undefined') {
874            let error = new BusinessError(`Parameter error.The type of ${key} must be Object`);
875            throw error;
876        }
877        if (typeof (value as Object) === 'undefined') {
878            let error = new BusinessError(`Parameter error.The type of ${value} must be Object`);
879            throw error;
880        }
881        if (key === null || value === null) {
882            throw new Error('key or value not be null');
883        }
884        let former : Object = undefined;
885        this.putCount++;
886        if (this.cache.has(key)) {
887            former = this.cache.get(key);
888            this.cache.delete(key);
889            this.afterRemoval(false, key, former, value);
890        } else if (this.cache.size >= this.maxSize) {
891            this.cache.delete(this.cache.keys().next().value);
892            this.evictionCount++;
893            this.afterRemoval(true, key, value, null);
894        }
895        this.cache.set(key, value);
896        this.length = this.cache.size;
897        return former;
898    }
899
900    public remove(key : Object) : Object {
901        if (typeof (key as Object) === 'undefined') {
902            let error = new BusinessError(`Parameter error.The type of ${key} must be Object`);
903            throw error;
904        }
905        if (key === null) {
906            throw new Error('key not be null');
907        } else if (this.cache.has(key)) {
908            let former : Object = this.cache.get(key);
909            this.cache.delete(key);
910            if (former !== null) {
911                this.afterRemoval(false, key, former, null);
912                this.length = this.cache.size;
913                return former;
914            }
915        }
916        this.length = this.cache.size;
917        return undefined;
918    }
919
920    public contains(key : Object) : boolean {
921        if (typeof (key as Object) === 'undefined') {
922            let error = new BusinessError(`Parameter error.The type of ${key} must be Object`);
923            throw error;
924        }
925        let flag : boolean = false;
926        if (this.cache.has(key)) {
927            flag = true;
928            this.hitCount++;
929            let value : Object = this.cache.get(key);
930            this.cache.delete(key);
931            this.cache.set(key, value);
932            this.length = this.cache.size;
933            return flag;
934        }
935        this.missCount++;
936        return flag;
937    }
938
939    public getCreateCount() : number {
940        return this.createCount;
941    }
942
943    public getMissCount() : number {
944        return this.missCount;
945    }
946
947    public getRemovalCount() : number {
948        return this.evictionCount;
949    }
950
951    public getMatchCount() : number {
952        return this.hitCount;
953    }
954
955    public getPutCount() : number {
956        return this.putCount;
957    }
958
959    public getCapacity() : number {
960        return this.maxSize;
961    }
962
963    public clear() : void {
964        this.afterRemoval(false, this.cache.keys(), this.cache.values(), null);
965        this.cache.clear();
966        this.length = this.cache.size;
967    }
968
969    public isEmpty() : boolean {
970        return this.cache.size === 0;
971    }
972
973    public toString() : string {
974        let peek : number = 0;
975        let hitRate : number = 0;
976        peek = this.hitCount + this.missCount;
977        if (peek !== 0) {
978            hitRate = 100 * this.hitCount / peek;
979        }
980        let str : string = '';
981        str = 'LRUCache[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + ', misses = ' + this.missCount
982            + ', hitRate = ' + hitRate + '% ]';
983        return str;
984    }
985
986    public values() : Object[] {
987        let arr : Array<Object> = [];
988        for(let value of this.cache.values()) {
989            arr.push(value);
990        }
991        return arr;
992    }
993
994    public keys() : Object[] {
995        let arr : Array<Object> = [];
996        for(let key of this.cache.keys()) {
997            arr.push(key);
998        }
999        return arr;
1000    }
1001
1002    public entries() : IterableIterator<[Object, Object]> {
1003        return this.cache.entries();
1004    }
1005
1006    public [Symbol.iterator] () : IterableIterator<[Object, Object]> {
1007        return this.cache.entries();
1008    }
1009}
1010
1011class RationalNumber {
1012    private mnum : number = 0;
1013    private mden : number = 0;
1014
1015    public constructor()
1016    public constructor(num : number, den : number)
1017    public constructor(num ?: number, den ?: number) {
1018        if(!num && !den) {
1019
1020        }
1021        else {
1022            num = den < 0 ?  num * (-1) : num;
1023            den = den < 0 ?  den * (-1) : den;
1024            if (den === 0) {
1025                if (num > 0) {
1026                    this.mnum = 1;
1027                    this.mden = 0;
1028                } else if (num < 0) {
1029                    this.mnum = -1;
1030                    this.mden = 0;
1031                } else {
1032                    this.mnum = 0;
1033                    this.mden = 0;
1034                }
1035            } else if (num === 0) {
1036                this.mnum = 0;
1037                this.mden = 1;
1038            } else {
1039                let gnum : number = 0;
1040                gnum = this.getCommonDivisor(num, den);
1041                if (gnum !== 0) {
1042                    this.mnum = num / gnum;
1043                    this.mden = den / gnum;
1044                }
1045            }
1046        }
1047    }
1048
1049    static parseRationalNumber(num : number, den : number): RationalNumber {
1050        if (typeof num !== 'number') {
1051            let error = new BusinessError(`Parameter error.The type of ${num} must be number`);
1052            throw error;
1053        }
1054        if (typeof den !== 'number') {
1055            let error = new BusinessError(`Parameter error.The type of ${den} must be number`);
1056            throw error;
1057        }
1058
1059        num = den < 0 ?  num * (-1) : num;
1060        den = den < 0 ?  den * (-1) : den;
1061        let ratNum = new RationalNumber();
1062        if (den === 0) {
1063            if (num > 0) {
1064                ratNum.mnum = 1;
1065                ratNum.mden = 0;
1066            } else if (num < 0) {
1067                ratNum.mnum = -1;
1068                ratNum.mden = 0;
1069            } else {
1070                ratNum.mnum = 0;
1071                ratNum.mden = 0;
1072            }
1073        } else if (num === 0) {
1074            ratNum.mnum = 0;
1075            ratNum.mden = 1;
1076        } else {
1077            let gnum : number = 0;
1078            gnum = this.getCommonFactor(num, den);
1079            if (gnum !== 0) {
1080                ratNum.mnum = num / gnum;
1081                ratNum.mden = den / gnum;
1082            }
1083        }
1084        return ratNum;
1085    }
1086
1087    static createRationalFromString(str : string) : RationalNumber {
1088        if (typeof str !== 'string') {
1089            let error = new BusinessError(`Parameter error.The type of ${str} must be string`);
1090            throw error;
1091        }
1092        if (str === null) {
1093            throw new Error('string invalid!');
1094        }
1095        let colon : number = str.indexOf(':');
1096        let semicolon : number = str.indexOf('/');
1097        if ((colon < 0 && semicolon < 0) || (colon > 0 && semicolon > 0)) {
1098            throw new Error('string invalid!');
1099        }
1100        let index : number = (colon > 0) ? colon : semicolon;
1101        let s1 : string = str.substr(0, index);
1102        let s2 : string = str.substr(index + 1, str.length);
1103        let num1 : number = Number(s1);
1104        let num2 : number = Number(s2);
1105        return RationalNumber.parseRationalNumber(num1, num2);
1106    }
1107
1108    public compareTo(other : RationalNumber) : number {
1109        if (this.mnum === other.mnum && this.mden === other.mden) {
1110            return 0;
1111        } else if (this.mnum === 0 && this.mden === 0) {
1112            return 1;
1113        } else if ((other.mnum === 0) && (other.mden === 0)) {
1114            return -1;
1115        } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) {
1116            return 1;
1117        } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) {
1118            return -1;
1119        }
1120        let thisnum : number = this.mnum * other.mden;
1121        let othernum : number = other.mnum * this.mden;
1122        if (thisnum < othernum) {
1123            return -1;
1124        } else if (thisnum > othernum) {
1125            return 1;
1126        } else {
1127            return 0;
1128        }
1129    }
1130
1131    public compare(other : RationalNumber) : number {
1132        if (!(other instanceof RationalNumber)) {
1133            let error = new BusinessError(`Parameter error.The type of ${other} must be RationalNumber`);
1134            throw error;
1135        }
1136        if (this.mnum === other.mnum && this.mden === other.mden) {
1137            return 0;
1138        } else if (this.mnum === 0 && this.mden === 0) {
1139            return 1;
1140        } else if ((other.mnum === 0) && (other.mden === 0)) {
1141            return -1;
1142        } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) {
1143            return 1;
1144        } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) {
1145            return -1;
1146        }
1147        let thisnum : number = this.mnum * other.mden;
1148        let othernum : number = other.mnum * this.mden;
1149        if (thisnum < othernum) {
1150            return -1;
1151        } else if (thisnum > othernum) {
1152            return 1;
1153        } else {
1154            return 0;
1155        }
1156    }
1157
1158    public equals(obj : object) :boolean {
1159        if (!(obj instanceof RationalNumber)) {
1160            return false;
1161        }
1162        let thisnum : number = this.mnum * obj.mden;
1163        let objnum : number = obj.mnum * this.mden;
1164        if (this.mnum === obj.mnum && this.mden === obj.mden) {
1165            return true;
1166        } else if ((thisnum === objnum) && (this.mnum !== 0 && this.mden !== 0) && (obj.mnum !== 0 && obj.mden !== 0)) {
1167            return true;
1168        } else if ((this.mnum === 0 && this.mden !== 0) && (obj.mnum === 0 && obj.mden !== 0)) {
1169            return true;
1170        } else if ((this.mnum > 0 && this.mden === 0) && (obj.mnum > 0 && obj.mden === 0)) {
1171            return true;
1172        } else if ((this.mnum < 0 && this.mden === 0) && (obj.mnum < 0 && obj.mden === 0)) {
1173            return true;
1174        } else {
1175            return false;
1176        }
1177    }
1178
1179    public valueOf() : number {
1180        if (this.mnum > 0 && this.mden === 0) {
1181            return Number.POSITIVE_INFINITY;
1182        } else if (this.mnum < 0 && this.mden === 0) {
1183            return Number.NEGATIVE_INFINITY;
1184        } else if ((this.mnum === 0) && (this.mden === 0)) {
1185            return Number.NaN;
1186        } else {
1187            return this.mnum / this.mden;
1188        }
1189    }
1190
1191    public getCommonDivisor(number1: number, number2: number) : number {
1192        if (number1 === 0 || number2 === 0) {
1193            throw new Error('Parameter cannot be zero!');
1194        }
1195        let temp : number = 0;
1196        if (number1 < number2) {
1197            temp = number1;
1198            number1 = number2;
1199            number2 = temp;
1200        }
1201        while (number1 % number2 !== 0) {
1202            temp = number1 % number2;
1203            number1 = number2;
1204            number2 = temp;
1205        }
1206        return number2;
1207    }
1208
1209    static getCommonFactor(firNum : number, SecNum : number) : number {
1210        if (typeof firNum !== 'number') {
1211            let error = new BusinessError(`Parameter error.The type of ${firNum} must be number`);
1212            throw error;
1213        }
1214        if (typeof SecNum !== 'number') {
1215            let error = new BusinessError(`Parameter error.The type of ${SecNum} must be number`);
1216            throw error;
1217        }
1218        if (firNum === 0 || SecNum === 0) {
1219            throw new Error('Parameter cannot be zero!');
1220        }
1221        let temp : number = 0;
1222        if (firNum < SecNum) {
1223            temp = firNum;
1224            firNum = SecNum;
1225            SecNum = temp;
1226        }
1227        while (firNum % SecNum !== 0) {
1228            temp = firNum % SecNum;
1229            firNum = SecNum;
1230            SecNum = temp;
1231        }
1232        return SecNum;
1233    }
1234
1235    public getDenominator() :number {
1236        return this.mden;
1237    }
1238
1239    public getNumerator() : number {
1240        return this.mnum;
1241    }
1242
1243    public isFinite() : boolean {
1244        return this.mden !== 0;
1245    }
1246
1247    public isNaN() : boolean {
1248        return this.mnum === 0 && this.mden === 0;
1249    }
1250
1251    public isZero() : boolean {
1252        return this.mnum === 0 && this.mden !== 0;
1253    }
1254
1255    public toString() : string {
1256        let buf : string;
1257        if (this.mnum === 0 && this.mden === 0) {
1258            buf = 'NaN';
1259        } else if (this.mnum > 0 && this.mden === 0) {
1260            buf = 'Infinity';
1261        } else if (this.mnum < 0 && this.mden === 0) {
1262            buf = '-Infinity';
1263        } else {
1264            buf = String(this.mnum) + '/' + String(this.mden);
1265        }
1266        return buf;
1267    }
1268}
1269
1270interface ScopeComparable {
1271    compareTo(other: ScopeComparable): boolean;
1272}
1273
1274type ScopeType = ScopeComparable;
1275
1276class Scope {
1277    private readonly _lowerLimit: ScopeType;
1278    private readonly _upperLimit: ScopeType;
1279
1280    public constructor(readonly lowerObj: ScopeType, readonly upperObj: ScopeType) {
1281        this.checkNull(lowerObj, 'lower limit not be null');
1282        this.checkNull(upperObj, 'upper limit not be null');
1283
1284        if(lowerObj.compareTo(upperObj)) {
1285            throw new Error('lower limit must be less than or equal to upper limit');
1286        }
1287        this._lowerLimit = lowerObj;
1288        this._upperLimit = upperObj;
1289    }
1290
1291    public getLower(): ScopeType {
1292        return this._lowerLimit;
1293    }
1294
1295    public getUpper(): ScopeType {
1296        return this._upperLimit;
1297    }
1298
1299    public compareTo(): boolean {
1300        return false;
1301    }
1302
1303    public contains(value: ScopeType): boolean;
1304    public contains(scope: Scope): boolean;
1305    public contains(x: Scope|ScopeType): boolean {
1306        let resLower: boolean;
1307        let resUpper: boolean;
1308        this.checkNull(x, 'value must not be null');
1309        if (x instanceof Scope) {
1310            resLower= x._lowerLimit.compareTo(this._lowerLimit);
1311            resUpper= this._upperLimit.compareTo(x._upperLimit);
1312        } else {
1313            resLower= x.compareTo(this._lowerLimit);
1314            resUpper= this._upperLimit.compareTo(x);
1315        }
1316        return resLower && resUpper;
1317    }
1318
1319    public clamp(value: ScopeType): ScopeType {
1320        this.checkNull(value, 'value must not be null');
1321        if (!value.compareTo(this._lowerLimit)) {
1322            return this._lowerLimit;
1323        } else if (value.compareTo(this._upperLimit)) {
1324            return this._upperLimit;
1325        } else {
1326            return value;
1327        }
1328    }
1329
1330    public intersect(scope: Scope): Scope;
1331    public intersect(lowerObj: ScopeType, upperObj: ScopeType): Scope;
1332    public intersect(x: Scope, y?: Scope|ScopeType): Scope {
1333        let reLower: boolean;
1334        let reUpper: boolean;
1335        let mLower: ScopeType;
1336        let mUpper: ScopeType;
1337        if (y) {
1338            this.checkNull(x, 'lower limit must not be null');
1339            this.checkNull(y, 'upper limit must not be null');
1340            reLower = this._lowerLimit.compareTo(x);
1341            reUpper = y.compareTo(this._upperLimit);
1342            if (reLower && reUpper) {
1343                return this;
1344            } else {
1345            mLower = reLower ? this._lowerLimit : x;
1346            mUpper = reUpper ? this._upperLimit : y;
1347            return new Scope(mLower, mUpper);
1348            }
1349        } else {
1350            this.checkNull(x, 'scope must not be null');
1351            reLower = this._lowerLimit.compareTo(x._lowerLimit);
1352            reUpper = x._upperLimit.compareTo(this._upperLimit);
1353            if (!reLower && !reUpper) {
1354                return x;
1355            } else if (reLower && reUpper) {
1356                return this;
1357            } else {
1358                mLower = reLower ? this._lowerLimit : x._lowerLimit;
1359                mUpper = reUpper ? this._upperLimit : x._upperLimit;
1360                return new Scope(mLower, mUpper);
1361           }
1362        }
1363    }
1364
1365    public expand(obj: ScopeType): Scope;
1366    public expand(scope: Scope): Scope;
1367    public expand(lowerObj: ScopeType, upperObj: ScopeType): Scope;
1368    public expand(x: ScopeType, y?: ScopeType): Scope {
1369        let reLower: boolean;
1370        let reUpper: boolean;
1371        let mLower: ScopeType;
1372        let mUpper: ScopeType;
1373        if (!y) {
1374            this.checkNull(x, 'value must not be null');
1375            if (!(x instanceof Scope)) {
1376                this.checkNull(x, 'value must not be null');
1377                return this.expand(x, x);
1378            }
1379            reLower = x._lowerLimit.compareTo(this._lowerLimit);
1380            reUpper = this._upperLimit.compareTo(x._upperLimit);
1381            if (reLower && reUpper) {
1382                 return this;
1383            } else if (!reLower && !reUpper) {
1384                 return x;
1385            } else {
1386                mLower = reLower ? this._lowerLimit : x._lowerLimit;
1387                mUpper = reUpper ? this._upperLimit : x._upperLimit;
1388                return new Scope(mLower, mUpper);
1389            }
1390
1391        } else {
1392            this.checkNull(x, 'lower limit must not be null');
1393            this.checkNull(y, 'upper limit must not be null');
1394            reLower = x.compareTo(this._lowerLimit);
1395            reUpper = this._upperLimit.compareTo(y);
1396            if (reLower && reUpper) {
1397                return this;
1398            }
1399            mLower = reLower ? this._lowerLimit : x;
1400            mUpper = reUpper ? this._upperLimit : y;
1401            return new Scope(mLower, mUpper);
1402        }
1403    }
1404
1405    public toString(): string {
1406        let strLower : string = this._lowerLimit.toString();
1407        let strUpper : string = this._upperLimit.toString();
1408        return `[${strLower}, ${strUpper}]`;
1409    }
1410
1411    public checkNull(o: ScopeType, str: string): void {
1412        if (o === null) {
1413            throw new Error(str);
1414        }
1415    }
1416}
1417
1418class ScopeHelper {
1419    private readonly _lowerLimit : ScopeType;
1420    private readonly _upperLimit : ScopeType;
1421    public constructor(readonly lowerObj : ScopeType, readonly upperObj : ScopeType) {
1422        if (typeof lowerObj !== 'object') {
1423            let error = new BusinessError(`Parameter error.The type of ${lowerObj} must be object`);
1424            throw error;
1425        }
1426        if (typeof upperObj !== 'object') {
1427            let error = new BusinessError(`Parameter error.The type of ${upperObj} must be object`);
1428            throw error;
1429        }
1430
1431        this.checkNull(lowerObj, 'lower limit not be null');
1432        this.checkNull(upperObj, 'upper limit not be null');
1433
1434        if(lowerObj.compareTo(upperObj)) {
1435            throw new Error('lower limit must be less than or equal to upper limit');
1436        }
1437        this._lowerLimit = lowerObj;
1438        this._upperLimit = upperObj;
1439    }
1440
1441    public getLower() : ScopeType {
1442        return this._lowerLimit;
1443    }
1444
1445    public getUpper() : ScopeType {
1446        return this._upperLimit;
1447    }
1448
1449    public compareTo() : boolean {
1450        return false;
1451    }
1452
1453    public contains(value : ScopeType) : boolean;
1454    public contains(scope : ScopeHelper) : boolean;
1455    public contains(x : ScopeHelper | ScopeType) : boolean {
1456        this.checkNull(x, 'value must not be null');
1457        if (typeof x !== 'object') {
1458            let error = new BusinessError(`Parameter error.The type of ${x} must be object or ScopeHelper`);
1459            throw error;
1460        }
1461        let resLower : boolean;
1462        let resUpper : boolean;
1463        if (x instanceof ScopeHelper) {
1464            resLower= x._lowerLimit.compareTo(this._lowerLimit);
1465            resUpper= this._upperLimit.compareTo(x._upperLimit);
1466        } else {
1467            resLower= x.compareTo(this._lowerLimit);
1468            resUpper= this._upperLimit.compareTo(x);
1469        }
1470        return resLower && resUpper;
1471    }
1472
1473    public clamp(value : ScopeType) : ScopeType {
1474        this.checkNull(value, 'value must not be null');
1475        if (typeof value !== 'object') {
1476            let error = new BusinessError(`Parameter error.The type of ${value} must be object`);
1477            throw error;
1478        }
1479
1480        if (!value.compareTo(this._lowerLimit)) {
1481            return this._lowerLimit;
1482        } else if (value.compareTo(this._upperLimit)) {
1483            return this._upperLimit;
1484        } else {
1485            return value;
1486        }
1487    }
1488
1489    public intersect(scope : ScopeHelper) : ScopeHelper;
1490    public intersect(lowerObj : ScopeType, upperObj : ScopeType) : ScopeHelper;
1491    public intersect(x : ScopeHelper, y? : ScopeType) : ScopeHelper {
1492        if (typeof x !== 'object') {
1493            let error = new BusinessError(`Parameter error.The type of ${x} must be ScopeHelper or ScopeType`);
1494            throw error;
1495        }
1496        let reLower : boolean;
1497        let reUpper : boolean;
1498        let mLower : ScopeType;
1499        let mUpper : ScopeType;
1500        if (y) {
1501            this.checkNull(x, 'lower limit must not be null');
1502            this.checkNull(y, 'upper limit must not be null');
1503            if (typeof y !== 'object') {
1504                let error = new BusinessError(`Parameter error.The type of ${y} must be ScopeType`);
1505                throw error;
1506            }
1507            reLower = this._lowerLimit.compareTo(x);
1508            reUpper = y.compareTo(this._upperLimit);
1509            if (reLower && reUpper) {
1510                return this;
1511            } else {
1512            mLower = reLower ? this._lowerLimit : x;
1513            mUpper = reUpper ? this._upperLimit : y;
1514            return new ScopeHelper(mLower, mUpper);
1515            }
1516        } else {
1517            this.checkNull(x, 'scope must not be null');
1518            reLower = this._lowerLimit.compareTo(x._lowerLimit);
1519            reUpper = x._upperLimit.compareTo(this._upperLimit);
1520            if (!reLower && !reUpper) {
1521                return x;
1522            } else if (reLower && reUpper) {
1523                return this;
1524            } else {
1525                mLower = reLower ? this._lowerLimit : x._lowerLimit;
1526                mUpper = reUpper ? this._upperLimit : x._upperLimit;
1527                return new ScopeHelper(mLower, mUpper);
1528           }
1529        }
1530    }
1531
1532    public expand(obj : ScopeType) : ScopeHelper;
1533    public expand(scope : ScopeHelper) : ScopeHelper;
1534    public expand(lowerObj : ScopeType, upperObj : ScopeType) : ScopeHelper;
1535    public expand(x : ScopeType, y? : ScopeType) : ScopeHelper {
1536        if (typeof x !== 'object') {
1537            let error = new BusinessError(`Parameter error.The type of ${x} must be ScopeHelper or ScopeType`);
1538            throw error;
1539        }
1540        let reLower : boolean;
1541        let reUpper : boolean;
1542        let mLower : ScopeType;
1543        let mUpper : ScopeType;
1544        if (!y) {
1545            this.checkNull(x, 'value must not be null');
1546            if (!(x instanceof ScopeHelper)) {
1547                this.checkNull(x, 'value must not be null');
1548                return this.expand(x, x);
1549            }
1550            reLower = x._lowerLimit.compareTo(this._lowerLimit);
1551            reUpper = this._upperLimit.compareTo(x._upperLimit);
1552            if (reLower && reUpper) {
1553                 return this;
1554            } else if (!reLower && !reUpper) {
1555                 return x;
1556            } else {
1557                mLower = reLower ? this._lowerLimit : x._lowerLimit;
1558                mUpper = reUpper ? this._upperLimit : x._upperLimit;
1559                return new ScopeHelper(mLower, mUpper);
1560            }
1561
1562        } else {
1563            if (typeof y !== 'object') {
1564                let error = new BusinessError(`Parameter error.The type of ${y} must be ScopeType`);
1565                throw error;
1566            }
1567
1568            this.checkNull(x, 'lower limit must not be null');
1569            this.checkNull(y, 'upper limit must not be null');
1570            reLower = x.compareTo(this._lowerLimit);
1571            reUpper = this._upperLimit.compareTo(y);
1572            if (reLower && reUpper) {
1573                return this;
1574            }
1575            mLower = reLower ? this._lowerLimit : x;
1576            mUpper = reUpper ? this._upperLimit : y;
1577            return new ScopeHelper(mLower, mUpper);
1578        }
1579    }
1580
1581    public toString() : string {
1582        let strLower : string = this._lowerLimit.toString();
1583        let strUpper : string = this._upperLimit.toString();
1584        return `[${strLower}, ${strUpper}]`;
1585    }
1586
1587    public checkNull(o : ScopeType, str : string) : void {
1588        if (o === null) {
1589            throw new Error(str);
1590        }
1591    }
1592}
1593
1594export default {
1595    printf: printf,
1596    format: format,
1597    getErrorString: getErrorString,
1598    errnoToString: errnoToString,
1599    callbackWrapper: callbackWrapper,
1600    promiseWrapper: promiseWrapper,
1601    promisify: promisify,
1602    randomUUID: randomUUID,
1603    randomBinaryUUID: randomBinaryUUID,
1604    generateRandomUUID: randomUUID,
1605    generateRandomBinaryUUID: randomBinaryUUID,
1606    parseUUID: parseUUID,
1607    TextEncoder: TextEncoder,
1608    TextDecoder: TextDecoder,
1609    Base64: Base64,
1610    Base64Helper: Base64Helper,
1611    types: Types,
1612    LruBuffer: LruBuffer,
1613    LRUCache: LRUCache,
1614    RationalNumber: RationalNumber,
1615    Scope: Scope,
1616    ScopeHelper: ScopeHelper,
1617};
1618