Exemple #1
0
 public NamePart(string path, int index, int length, NamePartKind kind)
 {
     Path   = path ?? throw new ArgumentNullException(nameof(path));
     Index  = index;
     Length = length;
     Kind   = kind;
 }
Exemple #2
0
        internal static FileSystemFinderResult?MatchFile(
            string path,
            Filter nameFilter,
            Filter extensionFilter,
            FileSystemFinderOptions options,
            IProgress <FileSystemFinderProgress> progress,
            NamePartKind namePartKind)
        {
            if (options.Attributes != 0 &&
                (File.GetAttributes(path) & options.Attributes) != options.Attributes)
            {
                return(null);
            }

            progress?.Report(new FileSystemFinderProgress(path, ProgressKind.File));

            if (extensionFilter?.IsMatch(NamePart.FromFile(path, extensionFilter.NamePart)) == false)
            {
                return(null);
            }

            NamePart namePart = NamePart.FromFile(path, namePartKind);
            Match    match    = null;

            if (nameFilter != null)
            {
                match = (options.PartOnly)
                    ? nameFilter.Regex.Match(namePart.ToString())
                    : nameFilter.Regex.Match(path, namePart.Index, namePart.Length);

                if (!nameFilter.IsMatch(match))
                {
                    return(null);
                }
            }

            if (options.Empty != null)
            {
                try
                {
                    if ((options.Empty.Value)
                        ? !FileSystemHelpers.IsEmptyFile(path)
                        : FileSystemHelpers.IsEmptyFile(path))
                    {
                        return(null);
                    }
                }
                catch (Exception ex) when(ex is IOException ||
                                          ex is UnauthorizedAccessException)
                {
                    progress?.Report(new FileSystemFinderProgress(path, ProgressKind.File, ex));
                    return(null);
                }
            }

            return(new FileSystemFinderResult(namePart, match));
        }
        internal static FileSystemFinderResult MatchDirectory(
            string path,
            Filter nameFilter,
            FileSystemFinderOptions options,
            IProgress <FileSystemFinderProgress> progress,
            NamePartKind namePartKind)
        {
            if (options.Attributes != 0 &&
                (File.GetAttributes(path) & options.Attributes) != options.Attributes)
            {
                return(null);
            }

            progress?.Report(new FileSystemFinderProgress(path, ProgressKind.Directory));

            NamePart namePart = NamePart.FromDirectory(path, namePartKind);
            Match    match    = null;

            if (nameFilter != null)
            {
                match = (options.PartOnly)
                    ? nameFilter.Regex.Match(namePart.ToString())
                    : nameFilter.Regex.Match(path, namePart.Index, namePart.Length);

                if (!nameFilter.IsMatch(match))
                {
                    return(null);
                }
            }

            if (options.Empty != null)
            {
                try
                {
                    if ((options.Empty.Value)
                        ? !IsEmptyDirectory(path)
                        : IsEmptyDirectory(path))
                    {
                        return(null);
                    }
                }
                catch (Exception ex) when(ex is IOException ||
                                          ex is UnauthorizedAccessException)
                {
                    progress?.Report(new FileSystemFinderProgress(path, ProgressKind.Directory, ex));
                    return(null);
                }
            }

            return(new FileSystemFinderResult(namePart, match, isDirectory: true));
        }
Exemple #4
0
        public Filter(
            Regex regex,
            NamePartKind namePart          = NamePartKind.Name,
            int groupNumber                = -1,
            bool isNegative                = false,
            Func <Capture, bool> predicate = null)
        {
            Regex = regex ?? throw new ArgumentNullException(nameof(regex));

            Debug.Assert(groupNumber < 0 || regex.GetGroupNumbers().Contains(groupNumber), groupNumber.ToString());

            GroupNumber = groupNumber;
            IsNegative  = isNegative;
            NamePart    = namePart;
            Predicate   = predicate;
        }
Exemple #5
0
        public static NamePart FromFile(string path, NamePartKind kind)
        {
            switch (kind)
            {
            case NamePartKind.Name:
            {
                int index = FileSystemHelpers.GetFileNameIndex(path);

                return(new NamePart(path, index, path.Length - index, kind));
            }

            case NamePartKind.FullName:
            {
                return(new NamePart(path, 0, path.Length, kind));
            }

            case NamePartKind.NameWithoutExtension:
            {
                int index = FileSystemHelpers.GetFileNameIndex(path);

                int dotIndex = GetExtensionIndex(path);

                return(new NamePart(path, index, dotIndex - index, kind));
            }

            case NamePartKind.Extension:
            {
                int dotIndex = GetExtensionIndex(path);

                if (dotIndex >= path.Length - 1)
                {
                    return(new NamePart(path, path.Length, 0, kind));
                }

                return(new NamePart(path, dotIndex + 1, path.Length - dotIndex - 1, kind));
            }

            default:
            {
                throw new ArgumentException("", nameof(kind));
            }
            }
        }
Exemple #6
0
        public static NamePart FromDirectory(string path, NamePartKind kind)
        {
            switch (kind)
            {
            case NamePartKind.Name:
            case NamePartKind.NameWithoutExtension:
            {
                int index = FileSystemHelpers.GetFileNameIndex(path);

                return(new NamePart(path, index, path.Length - index, kind));
            }

            case NamePartKind.FullName:
            {
                return(new NamePart(path, 0, path.Length, kind));
            }

            case NamePartKind.Extension:
            {
                return(default);
            }
Exemple #7
0
        public static bool TryParse(
            IEnumerable <string> values,
            string optionName,
            OptionValueProvider provider,
            out Filter filter,
            bool allowNull = false,
            NamePartKind defaultNamePart          = NamePartKind.Name,
            PatternOptions includedPatternOptions = PatternOptions.None)
        {
            filter = null;

            string pattern = values.FirstOrDefault();

            if (pattern == null)
            {
                if (allowNull)
                {
                    return(true);
                }
                else
                {
                    throw new InvalidOperationException($"Option '{OptionNames.GetHelpText(optionName)}' is required.");
                }
            }

            TimeSpan             matchTimeout = Regex.InfiniteMatchTimeout;
            string               groupName    = null;
            NamePartKind         namePart     = defaultNamePart;
            string               separator    = null;
            Func <Capture, bool> predicate    = null;

            List <string> options = null;

            foreach (string option in values.Skip(1))
            {
                int index = option.IndexOf("=");

                if (index != -1)
                {
                    string key   = option.Substring(0, index);
                    string value = option.Substring(index + 1);

                    if (OptionValues.Group.IsKeyOrShortKey(key))
                    {
                        groupName = value;
                        continue;
                    }
                    else if (OptionValues.ListSeparator.IsKeyOrShortKey(key))
                    {
                        separator = value;
                        continue;
                    }
                    else if (OptionValues.Part.IsKeyOrShortKey(key))
                    {
                        if (!TryParseAsEnum(value, out namePart, provider: OptionValueProviders.NamePartKindProvider))
                        {
                            string helpText = OptionValueProviders.NamePartKindProvider.GetHelpText();
                            WriteError($"Option '{OptionValues.Part.HelpValue}' has invalid value '{value}'. Allowed values: {helpText}.");
                            return(false);
                        }

                        continue;
                    }
                    else if (OptionValues.Timeout.IsKeyOrShortKey(key))
                    {
                        if (!TryParseMatchTimeout(value, out matchTimeout))
                        {
                            WriteError($"Option '{OptionValues.Timeout.HelpValue}' has invalid value '{value}'.");
                            return(false);
                        }

                        continue;
                    }
                }

                if (Expression.TryParse(option, out Expression expression))
                {
                    if (OptionValues.Length.IsKeyOrShortKey(expression.Identifier))
                    {
                        try
                        {
                            predicate = PredicateHelpers.GetLengthPredicate(expression);
                            continue;
                        }
                        catch (ArgumentException)
                        {
                            WriteError($"Option '{OptionNames.GetHelpText(optionName)}' has invalid value '{option}'.");
                            return(false);
                        }
                    }
                    else
                    {
                        WriteError($"Option '{OptionNames.GetHelpText(optionName)}' has invalid value '{option}'. Allowed values: {provider.GetHelpText()}.");
                        return(false);
                    }
                }

                (options ?? (options = new List <string>())).Add(option);
            }

            if (!TryParseRegexOptions(options, optionName, out RegexOptions regexOptions, out PatternOptions patternOptions, includedPatternOptions, provider))
            {
                return(false);
            }

            switch (patternOptions & (PatternOptions.WholeWord | PatternOptions.WholeLine))
            {
            case PatternOptions.None:
            case PatternOptions.WholeWord:
            case PatternOptions.WholeLine:
            {
                break;
            }

            default:
            {
                WriteError($"Values '{OptionValueProviders.PatternOptionsProvider.GetValue(nameof(PatternOptions.WholeWord)).HelpValue}' and '{OptionValueProviders.PatternOptionsProvider.GetValue(nameof(PatternOptions.WholeLine)).HelpValue}' cannot be combined.");
                return(false);
            }
            }

            if ((patternOptions & PatternOptions.FromFile) != 0 &&
                !FileSystemHelpers.TryReadAllText(pattern, out pattern))
            {
                return(false);
            }

            pattern = BuildPattern(pattern, patternOptions, separator);

            Regex regex = null;

            try
            {
                regex = new Regex(pattern, regexOptions, matchTimeout);
            }
            catch (ArgumentException ex)
            {
                WriteError(ex, $"Could not parse regular expression: {ex.Message}");
                return(false);
            }

            int groupIndex = -1;

            if (groupName != null)
            {
                groupIndex = regex.GroupNumberFromName(groupName);
                if (groupIndex == -1)
                {
                    string message = $"Group '{groupName}' does not exist.";

                    string[] groupNames = regex.GetGroupNames();

                    if (groupNames.Length > 1)
                    {
                        message += $" Existing group names: {TextHelpers.Join(", ", " and ", groupNames.Where(f => f != "0"))}.";
                    }

                    WriteError(message);
                    return(false);
                }
            }

            filter = new Filter(
                regex,
                namePart: namePart,
                groupNumber: groupIndex,
                isNegative: (patternOptions & PatternOptions.Negative) != 0,
                predicate);

            return(true);
        }
Exemple #8
0
        public static IEnumerable <FileSystemFinderResult> Find(
            string directoryPath,
            Filter nameFilter               = null,
            Filter extensionFilter          = null,
            Filter directoryFilter          = null,
            FileSystemFinderOptions options = null,
            IProgress <FileSystemFinderProgress> progress  = null,
            INotifyDirectoryChanged notifyDirectoryChanged = null,
            CancellationToken cancellationToken            = default)
        {
            if (options == null)
            {
                options = FileSystemFinderOptions.Default;
            }

            var enumerationOptions = new EnumerationOptions()
            {
                AttributesToSkip         = options.AttributesToSkip,
                IgnoreInaccessible       = options.IgnoreInaccessible,
                MatchCasing              = options.MatchCasing,
                MatchType                = options.MatchType,
                RecurseSubdirectories    = false,
                ReturnSpecialDirectories = options.ReturnSpecialDirectories
            };

            NamePartKind namePart          = nameFilter?.NamePart ?? NamePartKind.Name;
            NamePartKind directoryNamePart = directoryFilter?.NamePart ?? NamePartKind.Name;

            var            directories    = new Queue <string>();
            Queue <string> subDirectories = (options.RecurseSubdirectories) ? new Queue <string>() : null;

            string currentDirectory = null;

            if (notifyDirectoryChanged != null)
            {
                notifyDirectoryChanged.DirectoryChanged += (object sender, DirectoryChangedEventArgs e) => currentDirectory = e.NewName;
            }

            string dirPath = directoryPath;

            while (true)
            {
                progress?.Report(new FileSystemFinderProgress(dirPath, ProgressKind.SearchedDirectory));

                if (options.SearchTarget != SearchTarget.Directories)
                {
                    IEnumerator <string> fi = null;

                    try
                    {
                        fi = (options.CanEnumerate)
                            ? Directory.EnumerateFiles(dirPath, "*", enumerationOptions).GetEnumerator()
                            : ((IEnumerable <string>)Directory.GetFiles(dirPath, "*", enumerationOptions)).GetEnumerator();
                    }
                    catch (Exception ex) when(IsWellKnownException(ex))
                    {
                        progress?.Report(new FileSystemFinderProgress(dirPath, ProgressKind.SearchedDirectory, ex));
                    }

                    if (fi != null)
                    {
                        using (fi)
                        {
                            while (fi.MoveNext())
                            {
                                FileSystemFinderResult?result = MatchFile(fi.Current, nameFilter, extensionFilter, options, progress, namePart);

                                if (result != null)
                                {
                                    yield return(result.Value);
                                }

                                cancellationToken.ThrowIfCancellationRequested();
                            }
                        }
                    }
                }

                IEnumerator <string> di = null;

                try
                {
                    di = (options.CanEnumerate)
                        ? Directory.EnumerateDirectories(dirPath, "*", enumerationOptions).GetEnumerator()
                        : ((IEnumerable <string>)Directory.GetDirectories(dirPath, "*", enumerationOptions)).GetEnumerator();
                }
                catch (Exception ex) when(IsWellKnownException(ex))
                {
                    progress?.Report(new FileSystemFinderProgress(dirPath, ProgressKind.SearchedDirectory, ex));
                }

                if (di != null)
                {
                    using (di)
                    {
                        while (di.MoveNext())
                        {
                            currentDirectory = di.Current;

                            if (directoryFilter?.IsMatch(NamePart.FromDirectory(currentDirectory, directoryNamePart)) != false)
                            {
                                if (options.SearchTarget != SearchTarget.Files &&
                                    namePart != NamePartKind.Extension)
                                {
                                    FileSystemFinderResult?result = MatchDirectory(currentDirectory, nameFilter, options, progress);

                                    if (result != null)
                                    {
                                        yield return(result.Value);
                                    }
                                }

                                if (currentDirectory != null &&
                                    options.RecurseSubdirectories)
                                {
                                    subDirectories !.Enqueue(currentDirectory);
                                }
                            }

                            cancellationToken.ThrowIfCancellationRequested();
                        }
                    }

                    if (options.RecurseSubdirectories)
                    {
                        while (subDirectories !.Count > 0)
                        {
                            directories.Enqueue(subDirectories.Dequeue());
                        }
                    }
                }

                if (directories.Count > 0)
                {
                    dirPath = directories.Dequeue();
                }
                else
                {
                    break;
                }
            }
        }