public bool IsMatch(string allChars, int currentPosition, out int newPosition)
        {
            var currentChar = allChars[currentPosition];

            newPosition = currentPosition + 1;
            return(GlobStringReader.IsPathSeperator(currentChar));
        }
Ejemplo n.º 2
0
        public MatchInfo Evaluate(string text)
        {
            EnqueueTokens(_Tokens);
            _text = text;
            IGlobToken token = null;

            using (_Reader = new GlobStringReader(text))
            {
                while (_TokenQueue.Any())
                {
                    token = _TokenQueue.Dequeue();
                    token.Accept(this);
                    if (!Success)
                    {
                        return(FailedResult(token));
                    }
                }

                // if all tokens matched but still more text then fail!
                if (_Reader.Peek() != -1)
                {
                    return(FailedResult(null));
                }

                // Success.
                return(SuccessfulResult());
            }
        }
        public bool IsMatch(string allChars, int currentPosition, out int newPosition)
        {
            newPosition = currentPosition + 1;
            var currentChar = allChars[currentPosition];

            if (GlobStringReader.IsPathSeperator(currentChar))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 4
0
        public void Visit(AnyCharacterToken token)
        {
            Success = false;
            var read = _Reader.Read();

            if (read == -1)
            {
                return;
            }
            var currentChar = (char)read;

            if (GlobStringReader.IsPathSeparator(currentChar))
            {
                return;
            }

            AddMatch(new GlobTokenMatch()
            {
                Token = token, Value = currentChar.ToString()
            });
        }
Ejemplo n.º 5
0
        public void Visit(WildcardToken token)
        {
            // When * encountered,
            // Dequees all remaining tokens and passes them to a nested Evaluator.
            // Keeps seing if the nested evaluator will match, and if it doesn't then
            // will consume / match against one character, and retry.
            // Exits when match successful, or when the end of the current path segment is reached.
            GlobTokenMatch match = null;

            match = new GlobTokenMatch()
            {
                Token = token
            };
            AddMatch(match);


            var remainingText = _Reader.ReadToEnd();
            int endOfSegmentPos;

            using (var pathReader = new GlobStringReader(remainingText))
            {
                var thisPath = pathReader.ReadPathSegment();
                endOfSegmentPos = pathReader.CurrentIndex;
            }

            var remaining = _TokenQueue.ToArray();

            // if no more tokens remaining then just return as * matches the rest of the segment.
            if (remaining.Length == 0)
            {
                this.Success = true;

                match.Value = remainingText;


                return;
            }

            // we have to attempt to match the remaining tokens, and if they dont all match,
            // then consume a character, until we have matched the entirity of this segment.
            var matchedText  = new StringBuilder(endOfSegmentPos);
            var nestedEval   = new GlobTokenMatchAnalysisEvaluator(remaining);
            var pathSegments = new List <string>();

            // we keep a record of text that this wildcard matched in order to satisfy the
            // greatest number of child token matches.
            var bestMatchText = new StringBuilder(endOfSegmentPos);
            IList <GlobTokenMatch> bestMatches = null; // the most tokens that were matched.

            for (int i = 0; i <= endOfSegmentPos; i++)
            {
                var matchInfo = nestedEval.Evaluate(remainingText);
                if (matchInfo.Success)
                {
                    break;
                }

                // match a single character
                matchedText.Append(remainingText[0]);
                // re-attempt matching of child tokens against this remaining string.
                remainingText = remainingText.Substring(1);
                // If we have come closer to matching, record our best results.
                if ((bestMatches == null && matchInfo.Matches.Any()) || (bestMatches != null && bestMatches.Count < matchInfo.Matches.Length))
                {
                    bestMatches = matchInfo.Matches.ToArray();
                    bestMatchText.Clear();
                    bestMatchText.Append(matchedText.ToString());
                }
            }

            this.Success = nestedEval.Success;
            if (nestedEval.Success)
            {
                // add all child matches.
                this.MatchedTokens.AddRange(nestedEval.MatchedTokens);
            }
            else
            {
                // add the most tokens we managed to match.
                if (bestMatches != null && bestMatches.Any())
                {
                    this.MatchedTokens.AddRange(bestMatches);
                }
            }

            match.Value = matchedText.ToString();
            _TokenQueue.Clear();
        }
        public bool IsMatch(string allChars, int currentPosition, out int newPosition)
#endif
        {
            // We shortcut to success for a ** in some special cases:-
            //  1. The remaining tokens don't need to consume a minimum number of chracters in order to match.

            // We shortcut to failure for a ** in some special cases:-
            // A) The token was parsed with a leading path separator (i.e '/**' and the current charater we are matching from isn't a path separator.

            newPosition = currentPosition;

            // A) If leading seperator then current character needs to be that seperator.
            char currentChar = allChars[currentPosition];

            if (_token.LeadingPathSeparator != null)
            {
                if (!GlobStringReader.IsPathSeparator(currentChar))
                {
                    // expected separator.
                    return(false);
                }
                //else
                //{
                // advance current position to match the leading separator.
                currentPosition = currentPosition + 1;
                //}
            }
            else
            {
                // no leading seperator, means ** used at start of pattern not /** used within pattern.
                // If **/ is used for start of pattern then input string doesn't need to start with a / or \ and it will be matched.
                // i.e **/foo/bar will match foo/bar or /foo/bar.
                //     where as /**/foo/bar will not match foo/bar it will only match /foo/bar.
                currentChar = allChars[currentPosition];
                if (GlobStringReader.IsPathSeparator(currentChar))
                {
                    // advance current position to match the leading separator.
                    currentPosition = currentPosition + 1;
                }
            }

            // 1. if no more tokens require matching we match.
            if (_subEvaluator.ConsumesMinLength == 0)
            {
                newPosition = allChars.Length;
                return(true);
            }

            // Because we know we have more tokens in the pattern (subevaluators) - those will require a minimum amount of characters to match (could be 0 too).
            // We can therefore calculate a "max" character position that we can match to, as if we exceed that position the remaining tokens cant possibly match.
            int maxPos = (allChars.Length - _subEvaluator.ConsumesMinLength);

            // If all of the remaining tokens have a precise length, we can calculate the exact character that we need to macth to in the string.
            // Otherwise we have to test at multiple character positions until we find a match (less efficient)
            if (!_subEvaluator.ConsumesVariableLength)
            {
                // Fixed length.
                // As we can only match full segments, make sure character before chacracter at max pos is a separator,
                if (maxPos > 0)
                {
                    char mustMatchUntilChar = allChars[maxPos - 1];
                    if (!GlobStringReader.IsPathSeparator(mustMatchUntilChar))
                    {
                        // can only match full segments.
                        return(false);
                    }
                }

                // Advance position to max pos.
                currentPosition = maxPos;
                return(_subEvaluator.IsMatch(allChars, currentPosition, out newPosition));
            }
            else
            {
                // Remaining tokens match a variable length of the test string.
                // We iterate each position (within acceptable range) and test at each position.
                bool isMatch;

                currentChar = allChars[currentPosition];

                // If the ** token was parsed with a trailing slash - i.e "**/" then we need to match past it before we test remainijng tokens.
                // special exception if **/ is at start of pattern, as then the input string need not have any path separators.
                if (_token.TrailingPathSeparator != null)
                {
                    if (GlobStringReader.IsPathSeparator(currentChar))
                    {
                        // match the separator.
                        currentPosition = currentPosition + 1;
                    }
                }

                // Match until maxpos, is reached.
                while (currentPosition <= maxPos)
                {
                    // Test at current position.
                    isMatch = _subEvaluator.IsMatch(allChars, currentPosition, out newPosition);
                    if (isMatch)
                    {
                        return(isMatch);
                    }

                    if (currentPosition == maxPos)
                    {
                        return(false);
                    }

                    // Iterate until we hit a separator or maxPos.
                    while (currentPosition < maxPos)
                    {
                        currentPosition = currentPosition + 1;
                        currentChar     = allChars[currentPosition];

                        if (GlobStringReader.IsPathSeparator(currentChar))
                        {
                            // match the separator.
                            currentPosition = currentPosition + 1;
                            break;
                        }
                    }
                }
            }

            return(false);
        }