public DirectoryIdentifier[] GetDirectories(DirectoryControlBlock dir, string searchPattern, SearchOption searchOptions)
        {
            List <DirectoryIdentifier> result;

            if (searchPattern.Contains(Path.DirectorySeparatorChar) ||
                searchPattern.Contains(Path.AltDirectorySeparatorChar))
            {
                var segments = searchPattern.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                if (HasIllegalChars(segments))
                {
                    throw new ArgumentException("Illegal characters in path");
                }

                result = GetDirectoryBySegments(dir, segments, 0);
                return(result.ToArray());
            }

            result = dir.Directories.Where(d => NamePredicate(d.Name, searchPattern)).ToList();
            if (searchOptions == SearchOption.TopDirectoryOnly)
            {
                return(result.ToArray());
            }

            foreach (var d in dir.Directories)
            {
                if (!_dirs.TryGet(d, out var b))
                {
                    continue;
                }
                result.AddRange(GetDirectories(b, searchPattern, searchOptions));
            }

            return(result.ToArray());
        }
        private List <FileIdentifier> GetFilesBySegments(DirectoryControlBlock dir, string[] segments, int level)
        {
            var result  = new List <FileIdentifier>();
            var current = dir;

            while (true)
            {
                if (level < 0 || level >= segments.Length)
                {
                    break;
                }

                if (level == segments.Length - 1)
                {
                    return(GetFiles(current, segments[level], SearchOption.TopDirectoryOnly).ToList());
                }

                var found = GetDirectories(current, segments[level], SearchOption.TopDirectoryOnly).ToList();
                if (!found.Any())
                {
                    throw new DirectoryNotFoundException($"Could not find part of the path '{current.Idendifier.FullName}'");
                }

                var nextDirId = found.First();
                if (!_dirs.TryGet(nextDirId, out current))
                {
                    throw new InvalidOperationException($"control block container is in corrupted state. failed to find control block for {nextDirId.FullName}");
                }

                ++level;
            }
            return(result);
        }
        private bool AddOrGetSingle(DirectoryIdentifier key, out DirectoryControlBlock result)
        {
            var added = false;

            if (!_collection.TryGetValue(key, out result))
            {
                result           = new DirectoryControlBlock(key);
                _collection[key] = result;
                added            = true;
            }
            return(added);
        }
        public void ForEach(DirectoryControlBlock dir, Action <DirectoryControlBlock> action)
        {
            action(dir);

            foreach (var d in dir.Directories)
            {
                if (!_dirs.TryGet(d, out var b))
                {
                    throw new InvalidOperationException($"control block container is in corrupted state. failed to find control block for {d.FullName}");
                }

                ForEach(b, action);
            }
        }
 public bool TryGet(DirectoryIdentifier id, out DirectoryControlBlock result)
 {
     return(_collection.TryGetValue(id, out result));
 }