199da06d0Sopenharmony_ci/**
299da06d0Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
399da06d0Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
499da06d0Sopenharmony_ci * you may not use this file except in compliance with the License.
599da06d0Sopenharmony_ci * You may obtain a copy of the License at
699da06d0Sopenharmony_ci *
799da06d0Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
899da06d0Sopenharmony_ci *
999da06d0Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1099da06d0Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1199da06d0Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1299da06d0Sopenharmony_ci * See the License for the specific language governing permissions and
1399da06d0Sopenharmony_ci * limitations under the License.
1499da06d0Sopenharmony_ci */
1599da06d0Sopenharmony_ci
1699da06d0Sopenharmony_ci/**
1799da06d0Sopenharmony_ci * @file: Deep copy
1899da06d0Sopenharmony_ci */
1999da06d0Sopenharmony_ciimport Method from './Method';
2099da06d0Sopenharmony_ci
2199da06d0Sopenharmony_ciconst mapType = '[object Map]';
2299da06d0Sopenharmony_ciconst setType = '[object Set]';
2399da06d0Sopenharmony_ciconst arrayType = '[object Array]';
2499da06d0Sopenharmony_ciconst objectType = '[object Object]';
2599da06d0Sopenharmony_ciconst argsType = '[object Arguments]';
2699da06d0Sopenharmony_ciconst boolType = '[object Boolean]';
2799da06d0Sopenharmony_ciconst dateType = '[object Date]';
2899da06d0Sopenharmony_ciconst numberType = '[object Number]';
2999da06d0Sopenharmony_ciconst stringType = '[object String]';
3099da06d0Sopenharmony_ciconst symbolType = '[object Symbol]';
3199da06d0Sopenharmony_ciconst errorType = '[object Error]';
3299da06d0Sopenharmony_ciconst regexpType = '[object RegExp]';
3399da06d0Sopenharmony_ciconst funcType = '[object Function]';
3499da06d0Sopenharmony_ciconst deepType = [mapType, setType, arrayType, objectType, argsType];
3599da06d0Sopenharmony_ci
3699da06d0Sopenharmony_ciexport default class Getclone {
3799da06d0Sopenharmony_ci  private static getclone: Getclone = new Getclone();
3899da06d0Sopenharmony_ci
3999da06d0Sopenharmony_ci  public static getInstance(): Getclone {
4099da06d0Sopenharmony_ci    return this.getclone;
4199da06d0Sopenharmony_ci  }
4299da06d0Sopenharmony_ci
4399da06d0Sopenharmony_ci  /**
4499da06d0Sopenharmony_ci   * forEach
4599da06d0Sopenharmony_ci   *
4699da06d0Sopenharmony_ci   * @param { array } array
4799da06d0Sopenharmony_ci   *
4899da06d0Sopenharmony_ci   * @param { function } iteratee
4999da06d0Sopenharmony_ci   */
5099da06d0Sopenharmony_ci  private forEach(array, iteratee) {
5199da06d0Sopenharmony_ci    let index = -1;
5299da06d0Sopenharmony_ci    const length = array.length;
5399da06d0Sopenharmony_ci
5499da06d0Sopenharmony_ci    while (++index < length) {
5599da06d0Sopenharmony_ci      iteratee(array[index], index);
5699da06d0Sopenharmony_ci    }
5799da06d0Sopenharmony_ci    return array;
5899da06d0Sopenharmony_ci  }
5999da06d0Sopenharmony_ci
6099da06d0Sopenharmony_ci  /**
6199da06d0Sopenharmony_ci   * is object
6299da06d0Sopenharmony_ci   *
6399da06d0Sopenharmony_ci   * @param { any } target
6499da06d0Sopenharmony_ci   */
6599da06d0Sopenharmony_ci  private isObject(target) {
6699da06d0Sopenharmony_ci    const type = typeof target;
6799da06d0Sopenharmony_ci    return target !== null && (type === 'object' || type === 'function');
6899da06d0Sopenharmony_ci  }
6999da06d0Sopenharmony_ci
7099da06d0Sopenharmony_ci  /**
7199da06d0Sopenharmony_ci   * get type
7299da06d0Sopenharmony_ci   *
7399da06d0Sopenharmony_ci   * @param { any } target
7499da06d0Sopenharmony_ci   */
7599da06d0Sopenharmony_ci  private getType(target) {
7699da06d0Sopenharmony_ci    return Object.prototype.toString.call(target);
7799da06d0Sopenharmony_ci  }
7899da06d0Sopenharmony_ci
7999da06d0Sopenharmony_ci  /**
8099da06d0Sopenharmony_ci   * get init
8199da06d0Sopenharmony_ci   *
8299da06d0Sopenharmony_ci   * @param { any } target
8399da06d0Sopenharmony_ci   */
8499da06d0Sopenharmony_ci  private getInit(target) {
8599da06d0Sopenharmony_ci    const ctor = target.constructor;
8699da06d0Sopenharmony_ci    return new ctor();
8799da06d0Sopenharmony_ci  }
8899da06d0Sopenharmony_ci
8999da06d0Sopenharmony_ci  /**
9099da06d0Sopenharmony_ci   * clone symbol
9199da06d0Sopenharmony_ci   *
9299da06d0Sopenharmony_ci   * @param { any } target
9399da06d0Sopenharmony_ci   */
9499da06d0Sopenharmony_ci  private cloneSymbo(target) {
9599da06d0Sopenharmony_ci    return Object(Symbol.prototype.valueOf.call(target));
9699da06d0Sopenharmony_ci  }
9799da06d0Sopenharmony_ci
9899da06d0Sopenharmony_ci  /**
9999da06d0Sopenharmony_ci   * clone reg
10099da06d0Sopenharmony_ci   *
10199da06d0Sopenharmony_ci   * @param { any } target
10299da06d0Sopenharmony_ci   */
10399da06d0Sopenharmony_ci  private cloneRegister(target) {
10499da06d0Sopenharmony_ci    const reFlags = /\w*$/;
10599da06d0Sopenharmony_ci    const result = new target.constructor(target.source, reFlags.exec(target));
10699da06d0Sopenharmony_ci    result.lastIndex = target.lastIndex;
10799da06d0Sopenharmony_ci    return result;
10899da06d0Sopenharmony_ci  }
10999da06d0Sopenharmony_ci
11099da06d0Sopenharmony_ci  /**
11199da06d0Sopenharmony_ci   * clone function
11299da06d0Sopenharmony_ci   *
11399da06d0Sopenharmony_ci   * @param { function } func
11499da06d0Sopenharmony_ci   */
11599da06d0Sopenharmony_ci  private cloneFunc(func) {
11699da06d0Sopenharmony_ci    const bodyRegister = /(?<={)(.|\n)+(?=})/m;
11799da06d0Sopenharmony_ci    const paramRegister = /(?<=\().+(?=\)\s+{)/;
11899da06d0Sopenharmony_ci    const funcStr = func.toString();
11999da06d0Sopenharmony_ci    if (func.prototype) {
12099da06d0Sopenharmony_ci      const param = paramRegister.exec(funcStr);
12199da06d0Sopenharmony_ci      const bodys = bodyRegister.exec(funcStr);
12299da06d0Sopenharmony_ci      if (bodys) {
12399da06d0Sopenharmony_ci        if (param) {
12499da06d0Sopenharmony_ci          const paramArray = param[0].split(',');
12599da06d0Sopenharmony_ci          return new Function(...paramArray, bodys[0]);
12699da06d0Sopenharmony_ci        } else {
12799da06d0Sopenharmony_ci          return new Function(bodys[0]);
12899da06d0Sopenharmony_ci        }
12999da06d0Sopenharmony_ci      } else {
13099da06d0Sopenharmony_ci        return null;
13199da06d0Sopenharmony_ci      }
13299da06d0Sopenharmony_ci    } else {
13399da06d0Sopenharmony_ci      return eval(funcStr);
13499da06d0Sopenharmony_ci    }
13599da06d0Sopenharmony_ci  }
13699da06d0Sopenharmony_ci
13799da06d0Sopenharmony_ci  /**
13899da06d0Sopenharmony_ci   * clone other type
13999da06d0Sopenharmony_ci   *
14099da06d0Sopenharmony_ci   * @param { any } target
14199da06d0Sopenharmony_ci   *
14299da06d0Sopenharmony_ci   * @param { any } type - data type
14399da06d0Sopenharmony_ci   */
14499da06d0Sopenharmony_ci  private cloneOtherType(target, type) {
14599da06d0Sopenharmony_ci    const ctor = target.constructor;
14699da06d0Sopenharmony_ci    switch (type) {
14799da06d0Sopenharmony_ci      case boolType:
14899da06d0Sopenharmony_ci      case numberType:
14999da06d0Sopenharmony_ci      case stringType:
15099da06d0Sopenharmony_ci      case errorType:
15199da06d0Sopenharmony_ci      case dateType:
15299da06d0Sopenharmony_ci        return new ctor(target);
15399da06d0Sopenharmony_ci      case regexpType:
15499da06d0Sopenharmony_ci        return this.cloneRegister(target);
15599da06d0Sopenharmony_ci      case symbolType:
15699da06d0Sopenharmony_ci        return this.cloneSymbo(target);
15799da06d0Sopenharmony_ci      case funcType:
15899da06d0Sopenharmony_ci        return this.cloneFunc(target);
15999da06d0Sopenharmony_ci      default:
16099da06d0Sopenharmony_ci        return null;
16199da06d0Sopenharmony_ci    }
16299da06d0Sopenharmony_ci  }
16399da06d0Sopenharmony_ci
16499da06d0Sopenharmony_ci  /**
16599da06d0Sopenharmony_ci   * clone
16699da06d0Sopenharmony_ci   *
16799da06d0Sopenharmony_ci   * @param { any } target
16899da06d0Sopenharmony_ci   *
16999da06d0Sopenharmony_ci   * @param { map } map
17099da06d0Sopenharmony_ci   */
17199da06d0Sopenharmony_ci  public clone(target, map = new WeakMap()) {
17299da06d0Sopenharmony_ci    if (!this.isObject(target)) {
17399da06d0Sopenharmony_ci      return target;
17499da06d0Sopenharmony_ci    }
17599da06d0Sopenharmony_ci
17699da06d0Sopenharmony_ci    const type = this.getType(target);
17799da06d0Sopenharmony_ci    let cloneTargets;
17899da06d0Sopenharmony_ci
17999da06d0Sopenharmony_ci    if (Method.includes(deepType, type)) {
18099da06d0Sopenharmony_ci      cloneTargets = this.getInit(target);
18199da06d0Sopenharmony_ci    } else {
18299da06d0Sopenharmony_ci      return this.cloneOtherType(target, type);
18399da06d0Sopenharmony_ci    }
18499da06d0Sopenharmony_ci
18599da06d0Sopenharmony_ci    if (map.get(target)) {
18699da06d0Sopenharmony_ci      return map.get(target);
18799da06d0Sopenharmony_ci    }
18899da06d0Sopenharmony_ci    map.set(target, cloneTargets);
18999da06d0Sopenharmony_ci
19099da06d0Sopenharmony_ci    if (type === setType) {
19199da06d0Sopenharmony_ci      target.forEach((value) => {
19299da06d0Sopenharmony_ci        cloneTargets.add(this.clone(value, map));
19399da06d0Sopenharmony_ci      });
19499da06d0Sopenharmony_ci      return cloneTargets;
19599da06d0Sopenharmony_ci    }
19699da06d0Sopenharmony_ci
19799da06d0Sopenharmony_ci    if (type === mapType) {
19899da06d0Sopenharmony_ci      target.forEach((value, key) => {
19999da06d0Sopenharmony_ci        cloneTargets.set(key, this.clone(value, map));
20099da06d0Sopenharmony_ci      });
20199da06d0Sopenharmony_ci      return cloneTargets;
20299da06d0Sopenharmony_ci    }
20399da06d0Sopenharmony_ci
20499da06d0Sopenharmony_ci    const keys = type === arrayType ? undefined : Object.keys(target);
20599da06d0Sopenharmony_ci    this.forEach(keys || target, (value, key) => {
20699da06d0Sopenharmony_ci      if (keys) {
20799da06d0Sopenharmony_ci        key = value;
20899da06d0Sopenharmony_ci      }
20999da06d0Sopenharmony_ci      cloneTargets[key] = this.clone(target[key], map);
21099da06d0Sopenharmony_ci    });
21199da06d0Sopenharmony_ci
21299da06d0Sopenharmony_ci    return cloneTargets;
21399da06d0Sopenharmony_ci  }
21499da06d0Sopenharmony_ci}