Provides a filter function that can be used as filter argument on ``tarfile.add``. Generates the filter based on
    the patterns and prefix provided. Patterns should be a list of tuples. Each tuple consists of a compiled RegEx
    pattern and a boolean, indicating if it is an ignore entry or a negative exclusion (i.e. an exemption from
    exclusions). The prefix is used to match relative paths inside the tar file, and is removed from every entry
    passed into the functions.

    Note that all names passed into the returned function must be paths under the provided prefix. This condition is
    not checked!

    :param patterns: List of patterns and negative indicator.
    :type patterns: list[(__RegEx, bool)]
    :param prefix: Prefix to strip from all file names passed in. Leading and trailing path separators are removed.
    :type prefix: unicode | str
    :return: tarinfo.TarInfo -> tarinfo.TarInfo | NoneType

def get_filter_func(patterns, prefix):
    """
    Provides a filter function that can be used as filter argument on ``tarfile.add``. Generates the filter based on
    the patterns and prefix provided. Patterns should be a list of tuples. Each tuple consists of a compiled RegEx
    pattern and a boolean, indicating if it is an ignore entry or a negative exclusion (i.e. an exemption from
    exclusions). The prefix is used to match relative paths inside the tar file, and is removed from every entry
    passed into the functions.

    Note that all names passed into the returned function must be paths under the provided prefix. This condition is
    not checked!

    :param patterns: List of patterns and negative indicator.
    :type patterns: list[(__RegEx, bool)]
    :param prefix: Prefix to strip from all file names passed in. Leading and trailing path separators are removed.
    :type prefix: unicode | str
    :return: tarinfo.TarInfo -> tarinfo.TarInfo | NoneType
    """
    prefix_len = len(prefix.strip(os.path.sep)) + 1
    if any(i[1] for i in patterns):
        def _exclusion_func(tarinfo):
            name = tarinfo.name[prefix_len:]
            exclude = False
            for match_str, is_negative in patterns:
                if is_negative:
                    if not exclude:
                        continue
                    if match_str.match(name) is not None:
                        exclude = False
                elif exclude:
                    continue
                elif match_str.match(name) is not None:
                    exclude = True
            if exclude:
                return None
            return tarinfo
    else:
        # Optimized version: If there are no exemptions from matches, not all matches have to be processed.
        exclusions = [i[0] for i in patterns]

        def _exclusion_func(tarinfo):
            name = tarinfo.name[prefix_len:]
            if any(match_str.match(name) is not None for match_str in exclusions):
                return None
            return tarinfo

    return _exclusion_func