/// <summary>
        /// Browse a directory for file and subdirectory entries.
        /// </summary>
        /// <param name="path">path to directory, "" is root, separator is "/"</param>
        /// <param name="option">(optional) operation specific option; capability constraint, a session, security token or credential. Used for authenticating, authorizing or restricting the operation.</param>
        /// <returns>a snapshot of file and directory entries</returns>
        /// <exception cref="IOException">On unexpected IO error</exception>
        /// <exception cref="SecurityException">If caller did not have permission</exception>
        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null</exception>
        /// <exception cref="ArgumentException"><paramref name="path"/> contains only white space, or contains one or more invalid characters</exception>
        /// <exception cref="NotSupportedException">The <see cref="IFileSystem"/> doesn't support browse</exception>
        /// <exception cref="UnauthorizedAccessException">The access requested is not permitted by the operating system for the specified path, such as when access is Write or ReadWrite and the file or directory is set for read-only access.</exception>
        /// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters.</exception>
        /// <exception cref="InvalidOperationException">If <paramref name="path"/> refers to a non-file device, such as "con:", "com1:", "lpt1:", etc.</exception>
        /// <exception cref="ObjectDisposedException"/>
        public IDirectoryContent Browse(string path, IOption option = null)
        {
            // Assert supported
            if (!CanBrowse || !option.CanBrowse(true))
            {
                throw new NotSupportedException(nameof(Browse));
            }
            // Make path
            if (isPhysicalFileProvider && path.Contains(@"\"))
            {
                path = path.Replace(@"\", "/");
            }
            // Is disposed?
            IFileProvider fp = fileProvider;

            if (fp == null)
            {
                throw new ObjectDisposedException(nameof(FileProviderSystem));
            }
            // Browse
            IDirectoryContents contents = fp.GetDirectoryContents(path);

            // Not found
            if (!contents.Exists)
            {
                return(new DirectoryNotFound(this, path));
            }
            // Convert result
            StructList24 <IEntry> list = new StructList24 <IEntry>();

            foreach (IFileInfo info in contents)
            {
                if (info.IsDirectory)
                {
                    IEntry e = new DirectoryEntry(this, String.IsNullOrEmpty(path) ? info.Name + "/" : (path.EndsWith("/") ?path + info.Name + "/":path + "/" + info.Name + "/"), info.Name, info.LastModified, DateTimeOffset.MinValue, info.PhysicalPath);
                    list.Add(e);
                }
                else
                {
                    IEntry e = new FileEntry(this, String.IsNullOrEmpty(path) ? info.Name : (path.EndsWith("/") ? path + info.Name : path + "/" + info.Name), info.Name, info.LastModified, DateTimeOffset.MinValue, info.Length, info.PhysicalPath);
                    list.Add(e);
                }
            }
            // Return contents
            return(new DirectoryContent(this, path, list.ToArray()));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create intersections of <paramref name="leftPattern"/> and <paramref name="rightPattern"/>.
        /// </summary>
        /// <param name="leftPattern"></param>
        /// <param name="rightPattern"></param>
        /// <returns>intersections</returns>
        public static IEnumerable <String> Intersections(string leftPattern, string rightPattern)
        {
            // Read in the tokens
            StructList24 <Token> leftTokens = new StructList24 <Token>(), rightTokens = new StructList24 <Token>();

            Token.Enumerator leftEnumerator = new Token.Enumerator(leftPattern), rightEnumerator = new Token.Enumerator(rightPattern);
            while (leftEnumerator.MoveNext())
            {
                leftTokens.Add(leftEnumerator.Current);
            }
            while (rightEnumerator.MoveNext())
            {
                rightTokens.Add(rightEnumerator.Current);
            }

            // Queue of scenarios as index pairs and result so far.
            List <Line> queue = new List <Line>();
            // List of already yielded strings
            HashSet <Line> visited = new HashSet <Line>();

            // Queue the starting position
            Queue(queue, visited, 0, 0, null);
            // Process queue
            while (queue.Count > 0)
            {
                // Take indices from queue
                Line line = queue[queue.Count - 1];
                int  li = line.li, ri = line.ri; List <Token> result = line.tokens;
                queue.RemoveAt(queue.Count - 1);
                // Has more tokens
                bool leftHasMore = li < leftTokens.Count, rightHasMore = ri < rightTokens.Count;

                // End of tokens on both streams
                if (!leftHasMore && !rightHasMore)
                {
                    // Print to string
                    string pattern = Print(result);
                    // yield result
                    yield return(pattern);
                }

                // left still has tokens, right is at end
                else if (leftHasMore && !rightHasMore)
                {
                    // Take token
                    Token l = leftTokens[li];
                    // "*" and "**" matches against ""
                    if (l == Token.Type.Star || l == Token.Type.StarStar)
                    {
                        Queue(queue, visited, li + 1, ri, result);
                    }
                }

                // left is at end, right still has tokens
                else if (!leftHasMore && rightHasMore)
                {
                    // Take token and type
                    Token r = rightTokens[ri];
                    // "" matches against "*" and "**"
                    if (r == Token.Type.Star || r == Token.Type.StarStar)
                    {
                        Queue(queue, visited, li, ri + 1, result);
                    }
                }

                // left and right have tokens
                if (leftHasMore && rightHasMore)
                {
                    // Take tokens
                    Token l = leftTokens[li], r = rightTokens[ri];

                    // l == **
                    if (l == Token.Type.StarStar)
                    {
                        // Match one and more later
                        CloneAndAppend(queue, visited, li, ri + 1, result, r);
                        // r = *, r = **
                        if (r == Token.Type.Star || r == Token.Type.StarStar)
                        {
                            //
                            Append(queue, visited, li + 1, ri, result, r);
                        }
                        else
                        // r = x
                        {
                            // Match to nothing
                            Queue(queue, visited, li + 1, ri, result);
                        }
                        // Next scenario
                        continue;
                    }

                    // r == **
                    if (r == Token.Type.StarStar)
                    {
                        // Match one and more later
                        CloneAndAppend(queue, visited, li + 1, ri, result, l);
                        // l = *, l = **
                        if (l == Token.Type.Star || l == Token.Type.StarStar)
                        {
                            //
                            Append(queue, visited, li, ri + 1, result, l);
                        }
                        else
                        {
                            // Match to nothing
                            Queue(queue, visited, li, ri + 1, result);
                        }
                        // Next scenario
                        continue;
                    }

                    // l == *
                    if (l == Token.Type.Star)
                    {
                        // * & /
                        if (r == Token.Type.Slash)
                        {
                            // Match / to nothing
                            Queue(queue, visited, li + 1, ri, result);
                            continue;
                        }
                        // Match to one and more later
                        CloneAndAppend(queue, visited, li, ri + 1, result, r);
                        // Match to r = *
                        if (r == Token.Type.Star)
                        {
                            Append(queue, visited, li + 1, ri, result, r);
                        }
                        else
                        {
                            // Match to nothing
                            Queue(queue, visited, li + 1, ri, result);
                        }
                        // Next scenario
                        continue;
                    }

                    // r == *
                    if (r == Token.Type.Star)
                    {
                        // / & *
                        if (l == Token.Type.Slash)
                        {
                            // Match / to nothing
                            Queue(queue, visited, li, ri + 1, result);
                            continue;
                        }

                        // Match one, and more later
                        CloneAndAppend(queue, visited, li + 1, ri, result, l);
                        if (l == Token.Type.Star)
                        {
                            Append(queue, visited, li, ri + 1, result, l);
                        }
                        else
                        {
                            // Match to nothing
                            Queue(queue, visited, li, ri + 1, result);
                        }
                        // Next scenario
                        continue;
                    }

                    // l == ?
                    if (l == Token.Type.QuestionMark)
                    {
                        // ? & /
                        if (r == Token.Type.Slash)
                        {
                            continue;
                        }
                        // Downgrade '*' and '**' to '?'
                        if (r.Kind == Token.Type.Star || r.Kind == Token.Type.StarStar)
                        {
                            r = Token.Type.QuestionMark;
                        }
                        // Append what ever is in right token
                        Append(queue, visited, li + 1, ri + 1, result, r);
                        // Next scenario
                        continue;
                    }

                    // r == ?
                    if (r == Token.Type.QuestionMark)
                    {
                        // / & ?
                        if (l == Token.Type.Slash)
                        {
                            continue;
                        }
                        // Downgrade '*' and '**' to '?'
                        if (l.Kind == Token.Type.Star || l.Kind == Token.Type.StarStar)
                        {
                            l = Token.Type.QuestionMark;
                        }
                        // Append what ever is in left token
                        Append(queue, visited, li + 1, ri + 1, result, l);
                        // Next scenario
                        continue;
                    }

                    // l == r
                    if (l == r)
                    {
                        // Append, move indices and queue.
                        Append(queue, visited, li + 1, ri + 1, result, l);
                        // Next scenario
                        continue;
                    }
                }
            }

            //Console.Write($" (visited={visited.Count}) ");
        }
Exemplo n.º 3
0
        /// <summary>
        /// Create union of <paramref name="leftPattern"/> and <paramref name="rightPattern"/>.
        /// </summary>
        /// <param name="leftPattern"></param>
        /// <param name="rightPattern"></param>
        /// <returns>union that contains <paramref name="leftPattern"/> and <paramref name="rightPattern"/>. May return broader union that minimal due to lack of expression capability to hold in a single pattern string.</returns>
        public static string Union(string leftPattern, string rightPattern)
        {
            // Same pattern
            if (leftPattern == rightPattern)
            {
                return(leftPattern);
            }

            // Read in the tokens
            StructList24 <Token> leftTokens = new StructList24 <Token>(), rightTokens = new StructList24 <Token>();

            Token.Enumerator leftEnumerator = new Token.Enumerator(leftPattern), rightEnumerator = new Token.Enumerator(rightPattern);
            while (leftEnumerator.MoveNext())
            {
                leftTokens.Add(leftEnumerator.Current);
            }
            while (rightEnumerator.MoveNext())
            {
                rightTokens.Add(rightEnumerator.Current);
            }

            // Queue of scenarios as index pairs and result so far.
            List <Line> queue = new List <Line>();
            // List of already yielded strings
            HashSet <Line> visited = new HashSet <Line>();

            // Queue the starting position
            Queue(queue, visited, 0, 0, null);
            // Final result
            List <Token> finalresult = null; int finalscore = int.MinValue;

            // Process queue
            while (queue.Count > 0)
            {
                // Take indices from queue
                Line line = queue[queue.Count - 1];
                int  li = line.li, ri = line.ri; List <Token> result = line.tokens;
                queue.RemoveAt(queue.Count - 1);
                // Has more tokens
                bool leftHasMore = li < leftTokens.Count, rightHasMore = ri < rightTokens.Count;

                // l = Left input, r = right input, _ = last in result
                Token l = leftHasMore ? leftTokens[li] : (Token)Token.Type.None, r = rightHasMore ? rightTokens[ri] : (Token)Token.Type.None, _ = result == null || result.Count == 0 ? (Token)Token.Type.None : result[result.Count - 1];

                // End of tokens on both streams
                if (!leftHasMore && !rightHasMore)
                {
                    int score = Score(result);
                    if (score > finalscore)
                    {
                        finalresult = result; finalscore = score;
                    }
                    continue;
                }

                // left or right have tokens
                if (leftHasMore || rightHasMore)
                {
                    // l == **
                    if (l == Token.Type.StarStar)
                    {
                        if (_ == Token.Type.StarStar)
                        {
                            Queue(queue, visited, li + 1, ri, result);
                        }
                        else
                        {
                            Append(queue, visited, li + 1, ri, result, l);
                        }
                        continue;
                    }

                    // r == **
                    if (r == Token.Type.StarStar)
                    {
                        if (_ == Token.Type.StarStar)
                        {
                            Queue(queue, visited, li, ri + 1, result);
                        }
                        else
                        {
                            Append(queue, visited, li, ri + 1, result, r);
                        }
                        continue;
                    }

                    // l == *
                    if (l == Token.Type.Star)
                    {
                        if (_ == Token.Type.Star || _ == Token.Type.StarStar)
                        {
                            Queue(queue, visited, li + 1, ri, result);
                        }
                        else
                        {
                            Append(queue, visited, li + 1, ri, result, l);
                        }
                        continue;
                    }

                    // r == *
                    if (r == Token.Type.Star)
                    {
                        if (_ == Token.Type.Star || _ == Token.Type.StarStar)
                        {
                            Queue(queue, visited, li, ri + 1, result);
                        }
                        else
                        {
                            Append(queue, visited, li, ri + 1, result, r);
                        }
                        continue;
                    }

                    // l == r
                    if (l == r)
                    {
                        Append(queue, visited, li + 1, ri + 1, result, l);
                        continue;
                    }

                    // l == ? && r == c
                    if (l == Token.Type.QuestionMark && r.Kind == Token.Type.Char)
                    {
                        Append(queue, visited, li + 1, ri + 1, result, l);
                        continue;
                    }

                    // l == c && r == ?
                    if (l.Kind == Token.Type.Char && r == Token.Type.QuestionMark)
                    {
                        Append(queue, visited, li + 1, ri + 1, result, l);
                        continue;
                    }

                    // l == c || r == c
                    if (l.Kind == Token.Type.Char || r.Kind == Token.Type.Char)
                    {
                        // Add ?
                        if (l.Kind == Token.Type.Char && r.Kind == Token.Type.Char)
                        {
                            CloneAndAppend(queue, visited, li + 1, ri + 1, result, Token.Type.QuestionMark);
                        }
                        // Add *
                        if (_ != Token.Type.Star && _ != Token.Type.StarStar)
                        {
                            if (l.Kind == Token.Type.Char)
                            {
                                CloneAndAppend(queue, visited, li + 1, ri, result, Token.Type.Star);
                            }
                            if (r.Kind == Token.Type.Char)
                            {
                                Append(queue, visited, li, ri + 1, result, Token.Type.Star);
                            }
                        }
                        else
                        // Use previous *
                        {
                            if (l.Kind == Token.Type.Char)
                            {
                                CloneAndAppend(queue, visited, li + 1, ri, result, Token.Type.None);
                            }
                            if (r.Kind == Token.Type.Char)
                            {
                                Queue(queue, visited, li, ri + 1, result);
                            }
                        }
                        continue;
                    }

                    {
                        // Replace * with **
                        if (_ == Token.Type.Star)
                        {
                            result[result.Count - 1] = Token.Type.StarStar;
                            if (l != Token.Type.None)
                            {
                                CloneAndAppend(queue, visited, li + 1, ri, result, Token.Type.None);
                            }
                            if (r != Token.Type.None)
                            {
                                Queue(queue, visited, li, ri + 1, result);
                            }
                        }
                        // Add **
                        else if (_ != Token.Type.StarStar)
                        {
                            if (l != Token.Type.None)
                            {
                                CloneAndAppend(queue, visited, li + 1, ri, result, Token.Type.StarStar);
                            }
                            if (r != Token.Type.None)
                            {
                                Append(queue, visited, li, ri + 1, result, Token.Type.StarStar);
                            }
                        }
                        else
                        // Use previous **
                        {
                            if (l != Token.Type.None)
                            {
                                CloneAndAppend(queue, visited, li + 1, ri, result, Token.Type.None);
                            }
                            if (r != Token.Type.None)
                            {
                                Queue(queue, visited, li, ri + 1, result);
                            }
                        }
                    }
                }
            }
            //Console.Write($" (visited={visited.Count}) ");

            return(Print(finalresult));

            // Heuristic score
            int Score(List <Token> result)
            {
                if (result == null)
                {
                    return(int.MinValue);
                }
                int x = 0;

                foreach (Token t in result)
                {
                    if (t.Kind == Token.Type.Char)
                    {
                        x += 256;
                    }
                    else if (t.Kind == Token.Type.QuestionMark)
                    {
                        x += 16;
                    }
                    else if (t.Kind == Token.Type.Slash)
                    {
                        x += 1024;
                    }
                    else if (t.Kind == Token.Type.Star)
                    {
                        x -= 4;
                    }
                    else if (t.Kind == Token.Type.StarStar)
                    {
                        x -= 16;
                    }
                }
                return(x);
            }
        }