stack several files and return the stacked *MDF* object

        Parameters
        ----------
        files : list | tuple
            list of *MDF* file names or *MDF* instances
        version : str
            merged file version
        sync : bool
            sync the files based on the start of measurement, default *True*

        Returns
        -------
        stacked : MDF
            new *MDF* object with stacked channels

def stack(files, version="4.10", sync=True, **kwargs):
        """ stack several files and return the stacked *MDF* object

        Parameters
        ----------
        files : list | tuple
            list of *MDF* file names or *MDF* instances
        version : str
            merged file version
        sync : bool
            sync the files based on the start of measurement, default *True*

        Returns
        -------
        stacked : MDF
            new *MDF* object with stacked channels

        """
        if not files:
            raise MdfException("No files given for stack")

        version = validate_version_argument(version)

        callback = kwargs.get("callback", None)

        stacked = MDF(version=version, callback=callback)

        files_nr = len(files)

        if callback:
            callback(0, files_nr)

        if sync:
            timestamps = []
            for file in files:
                if isinstance(file, MDF):
                    timestamps.append(file.header.start_time)
                else:
                    with open(file, "rb") as mdf:
                        mdf.seek(64)
                        blk_id = mdf.read(2)
                        if blk_id == b"HD":
                            header = HeaderV3
                        else:
                            blk_id += mdf.read(2)
                            if blk_id == b"##HD":
                                header = HeaderV4
                            else:
                                raise MdfException(f'"{file}" is not a valid MDF file')

                        header = header(address=64, stream=mdf)

                        timestamps.append(header.start_time)

            try:
                oldest = min(timestamps)
            except TypeError:
                timestamps = [
                    timestamp.astimezone(timezone.utc)
                    for timestamp in timestamps
                ]
                oldest = min(timestamps)

            offsets = [(timestamp - oldest).total_seconds() for timestamp in timestamps]

            stacked.header.start_time = oldest
        else:
            offsets = [0 for file in files]

        cg_nr = -1
        for offset, mdf in zip(offsets, files):
            if not isinstance(mdf, MDF):
                mdf = MDF(mdf)

            cg_offset = cg_nr + 1

            for i, group in enumerate(mdf.groups):
                idx = 0
                if version < "4.00":
                    encodings = []
                included_channels = mdf._included_channels(i)
                if included_channels:
                    cg_nr += 1
                else:
                    continue

                try:
                    for can_id, info in mdf.can_logging_db.items():
                        if can_id not in mdf.can_logging_db:
                            mdf.can_logging_db[can_id] = {}
                        mdf.can_logging_db[can_id].update(
                            {
                                message_id: cg_index + cg_offset
                                for message_id, cg_index in info.items()
                            }
                        )
                except AttributeError:
                    pass

                _, dtypes = mdf._prepare_record(group)

                data = mdf._load_data(group)

                for fragment in data:

                    if dtypes.itemsize:
                        group.record = np.core.records.fromstring(
                            fragment[0], dtype=dtypes
                        )
                    else:
                        group.record = None
                    if idx == 0:
                        signals = []
                        for j in included_channels:
                            sig = mdf.get(
                                group=i,
                                index=j,
                                data=fragment,
                                raw=True,
                                ignore_invalidation_bits=True,
                                copy_master=False,
                            )

                            if version < "4.00":
                                if sig.samples.dtype.kind == "S":
                                    encodings.append(sig.encoding)
                                    strsig = mdf.get(
                                        group=i,
                                        index=j,
                                        samples_only=True,
                                        ignore_invalidation_bits=True,
                                    )[0]
                                    sig.samples = sig.samples.astype(strsig.dtype)
                                    del strsig
                                    if sig.encoding != "latin-1":

                                        if sig.encoding == "utf-16-le":
                                            sig.samples = (
                                                sig.samples.view(np.uint16)
                                                .byteswap()
                                                .view(sig.samples.dtype)
                                            )
                                            sig.samples = encode(
                                                decode(sig.samples, "utf-16-be"),
                                                "latin-1",
                                            )
                                        else:
                                            sig.samples = encode(
                                                decode(sig.samples, sig.encoding),
                                                "latin-1",
                                            )
                                else:
                                    encodings.append(None)

                            if not sig.samples.flags.writeable:
                                sig.samples = sig.samples.copy()
                            signals.append(sig)

                        if signals:
                            if sync:
                                timestamps = signals[0].timestamps + offset
                                for sig in signals:
                                    sig.timestamps = timestamps
                            stacked.append(signals, common_timebase=True)
                            try:
                                if group.channel_group.flags & v4c.FLAG_CG_BUS_EVENT:
                                    stacked.groups[-1].channel_group.flags = group.channel_group.flags
                                    stacked.groups[-1].channel_group.acq_name = group.channel_group.acq_name
                                    stacked.groups[-1].channel_group.acq_source = group.channel_group.acq_source
                                    stacked.groups[-1].channel_group.comment = group.channel_group.comment
                            except AttributeError:
                                pass
                        idx += 1
                    else:
                        master = mdf.get_master(i, fragment, copy_master=False)
                        if sync:
                            master = master + offset
                        if len(master):

                            signals = [(master, None)]

                            for k, j in enumerate(included_channels):
                                sig = mdf.get(
                                    group=i,
                                    index=j,
                                    data=fragment,
                                    raw=True,
                                    samples_only=True,
                                    ignore_invalidation_bits=True,
                                )
                                signals.append(sig)

                                if version < "4.00":
                                    encoding = encodings[k]
                                    samples = sig[0]
                                    if encoding:
                                        if encoding != "latin-1":

                                            if encoding == "utf-16-le":
                                                samples = (
                                                    samples.view(np.uint16)
                                                    .byteswap()
                                                    .view(samples.dtype)
                                                )
                                                samples = encode(
                                                    decode(samples, "utf-16-be"),
                                                    "latin-1",
                                                )
                                            else:
                                                samples = encode(
                                                    decode(samples, encoding), "latin-1"
                                                )
                                            sig.samples = samples

                            if signals:
                                stacked.extend(cg_nr, signals)
                        idx += 1

                    group.record = None

                stacked.groups[
                    -1
                ].channel_group.comment = (
                    f'stacked from channel group {i} of "{mdf.name.parent}"'
                )

            if callback:
                callback(idx, files_nr)

            if MDF._terminate:
                return

        return stacked