Esempio n. 1
0
        private void AddRules(IEnumerable <string> rules, MatchFlags flags, bool loadedFromFile)
        {
            var ruleList = GetValidRuleLines(rules, loadedFromFile)
                           .Select(line => new IgnoreRule(line.Pattern, flags, line.LineNumber));

            _rules.AddRange(ruleList);
        }
Esempio n. 2
0
 public MatchState(MatchState parent, int nextSegmentIndex, MatchFlags flags, string segment, MatchedVariable[] variables)
 {
     NextSegmentIndex = nextSegmentIndex;
     Flags            = flags;
     this.parent      = parent;
     this.segment     = segment;
     this.variables   = variables;
 }
Esempio n. 3
0
        /// <summary>
        /// Create an individual ignore rule for the specified pattern
        /// </summary>
        /// <param name="pattern">A glob pattern specifying file(s) this rule should ignore</param>
        /// <param name="flags">Optional flags determining pattern matching behaviour</param>
        public IgnoreRule(string pattern, MatchFlags flags = MatchFlags.PATHNAME)
        {
            if (Utils.IsNullOrWhiteSpace(pattern))
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            // Keep track of the original pattern before modifications (for display purposes)
            OriginalPattern = pattern;
            Pattern         = pattern;
            MatchFlags      = flags;

            // First, let's figure out some things about the pattern and set flags to pass to our match function
            PatternFlags = PatternFlags.NONE;

            // If the pattern starts with an exclamation mark, it's a negation pattern
            // Once we know that, we can remove the exclamation mark (so the pattern behaves just like any other),
            // then just negate the match result when we return it
            if (Pattern.StartsWith("!", sc))
            {
                PatternFlags |= PatternFlags.NEGATION;
                Pattern       = Pattern.Substring(1);
            }

            // If the pattern starts with a forward slash, it should only match an absolute path
            if (Pattern.StartsWith("/", sc))
            {
                PatternFlags |= PatternFlags.ABSOLUTE_PATH;
                Pattern       = Pattern.Substring(1);
            }

            // If the pattern ends with a forward slash, it should only match a directory
            // Again though, once we know that we can remove the slash to normalise the pattern
            if (Pattern.EndsWith("/", sc))
            {
                PatternFlags |= PatternFlags.DIRECTORY;
                Pattern       = Pattern.Substring(0, Pattern.Length - 1);
            }

            _wildcardIndex = Pattern.IndexOfAny(new char[] { '*', '[', '?' });

            // If CASEFOLD is set, string comparisons should ignore case too
            if (MatchFlags.HasFlag(MatchFlags.CASEFOLD))
            {
                sc = StringComparison.OrdinalIgnoreCase;
            }

            // If PATHNAME is set, single asterisks should not match slashes
            if (!MatchFlags.HasFlag(MatchFlags.PATHNAME))
            {
                MatchFlags |= MatchFlags.PATHNAME;
            }

            // TODO: Currently, we are just setting PATHNAME for every rule, because it seems to match the original behaviour
            // See here for a clue: https://github.com/git/git/blob/c2c5f6b1e479f2c38e0e01345350620944e3527f/dir.c#L99
        }
Esempio n. 4
0
        protected void GetMatchFlagsAndOptions(ContentFlags contentFlags, out MatchFlags matchFlags, out MatchOptions matchOptions)
        {
            ContentFlags contentFlags2 = contentFlags & (ContentFlags)51;

            switch (contentFlags2)
            {
            case ContentFlags.SubString:
                matchOptions = MatchOptions.SubString;
                break;

            case ContentFlags.Prefix:
                matchOptions = MatchOptions.Prefix;
                break;

            default:
                if (contentFlags2 != ContentFlags.PrefixOnWords)
                {
                    if (contentFlags2 != ContentFlags.ExactPhrase)
                    {
                        matchOptions = MatchOptions.FullString;
                    }
                    else
                    {
                        matchOptions = MatchOptions.ExactPhrase;
                    }
                }
                else
                {
                    matchOptions = MatchOptions.PrefixOnWords;
                }
                break;
            }
            matchFlags = MatchFlags.Default;
            if ((contentFlags & ContentFlags.IgnoreCase) != ContentFlags.FullString)
            {
                matchFlags |= MatchFlags.IgnoreCase;
            }
            if ((contentFlags & ContentFlags.IgnoreNonSpace) != ContentFlags.FullString)
            {
                matchFlags |= MatchFlags.IgnoreNonSpace;
            }
            if ((contentFlags & ContentFlags.Loose) != ContentFlags.FullString)
            {
                matchFlags |= MatchFlags.Loose;
            }
        }
Esempio n. 5
0
        private static StringComparison GetStringComparison(MatchFlags flags)
        {
            bool flag  = MatchFlags.Default != (flags & MatchFlags.IgnoreCase);
            bool flag2 = MatchFlags.Default != (flags & MatchFlags.IgnoreNonSpace);

            if (flag && flag2)
            {
                return(StringComparison.OrdinalIgnoreCase);
            }
            if (!flag && flag2)
            {
                return(StringComparison.Ordinal);
            }
            if (flag && !flag2)
            {
                return(StringComparison.OrdinalIgnoreCase);
            }
            return(StringComparison.Ordinal);
        }
Esempio n. 6
0
        protected ContentFlags GetContentFlags(MatchFlags matchFlags, MatchOptions matchOptions)
        {
            ContentFlags contentFlags;

            switch (matchOptions)
            {
            case MatchOptions.SubString:
                contentFlags = ContentFlags.SubString;
                goto IL_34;

            case MatchOptions.Prefix:
                contentFlags = ContentFlags.Prefix;
                goto IL_34;

            case MatchOptions.PrefixOnWords:
                contentFlags = ContentFlags.PrefixOnWords;
                goto IL_34;

            case MatchOptions.ExactPhrase:
                contentFlags = ContentFlags.ExactPhrase;
                goto IL_34;
            }
            contentFlags = ContentFlags.FullString;
IL_34:
            if ((matchFlags & MatchFlags.IgnoreCase) != MatchFlags.Default)
            {
                contentFlags |= ContentFlags.IgnoreCase;
            }
            if ((matchFlags & MatchFlags.IgnoreNonSpace) != MatchFlags.Default)
            {
                contentFlags |= ContentFlags.IgnoreNonSpace;
            }
            if ((matchFlags & MatchFlags.Loose) != MatchFlags.Default)
            {
                contentFlags |= ContentFlags.Loose;
            }
            return(contentFlags);
        }
Esempio n. 7
0
 /// <summary>
 /// Create a list of ignore rules to check paths against
 /// </summary>
 /// <param name="rules">A list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public IgnoreList(IEnumerable <string> rules, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(rules, flags);
 }
Esempio n. 8
0
 /// <summary>
 /// Create a list of ignore rules to check paths against
 /// </summary>
 /// <param name="ignoreFilePath">Path to a text file containing a list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public IgnoreList(string ignoreFilePath, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(ignoreFilePath, flags);
 }
Esempio n. 9
0
        private static int Match(char[] pattern, char[] text, int p, int t, MatchFlags flags)
        {
            int p_len = pattern.Length;
            int p_EOP = p_len - 1;

            int t_len = text.Length;
            int t_EOP = t_len - 1;

            char p_ch;

            for (; p < p_len && (p_ch = pattern[p]) != -1; p++, t++)
            {
                int  match, negated;
                bool match_slash;

                char t_ch, prev_ch;

                if (t == t_len && p_ch != '*')
                {
                    return(ABORT_ALL);
                }

                t_ch = text[t];

                if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsUpper(t_ch))
                {
                    t_ch = Char.ToLower(t_ch);
                }
                if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsUpper(p_ch))
                {
                    p_ch = Char.ToLower(p_ch);
                }

                switch (p_ch)
                {
                // Escape character: require literal match of next char
                case '\\':
                    p_ch = pattern[++p];
                    goto default;

                // Normal character: literal match
                default:
                    if (t_ch != p_ch)
                    {
                        return(NOMATCH);
                    }
                    continue;

                // Match any character except slash
                case '?':
                    if (t_ch == '/')
                    {
                        return(NOMATCH);
                    }
                    continue;

                // Match any character unless PATHNAME flag is set, then match any char except slash
                case '*':
                    // If the *next* character is a star as well...
                    if ((++p) < p_len && pattern[p] == '*')
                    {
                        // Figure out what the character *before* the first star is
                        // (using null char to represent the beginning of the pattern)
                        char pre_star_ch = (p - 2) >= 0 ? pattern[p - 2] : '\0';
                        // Advance through the pattern until we get to something which *isn't* a star
                        while ((++p) < p_len && pattern[p] == '*')
                        {
                        }
                        // If PATHNAME isn't set, a single star also matches slashes
                        if (!flags.HasFlag(MatchFlags.PATHNAME))
                        {
                            match_slash = true;
                        }
                        // If the character before the first star is either the beginning of the pattern or a slash,
                        // and the character after the last star is either the end of the pattern or a slash
                        else if ((pre_star_ch == '\0' || pre_star_ch == '/') && (p == p_len || pattern[p] == '/'))
                        {
                            if ((p == p_len || pattern[p] == '/') && Match(pattern, text, p + 1, t, flags) == MATCH)
                            {
                                return(MATCH);
                            }

                            match_slash = true;
                        }
                        else
                        {
                            // The pattern is invalid (double-star wildcards are only valid
                            // if bounded by slashes or beginning/end of line)
                            return(ABORT_MALFORMED);
                        }
                    }
                    else
                    {
                        // It's only a single star, so use PATHNAME to determine whether to match slashes
                        match_slash = !flags.HasFlag(MatchFlags.PATHNAME);
                    }

                    // If we're at the end of the pattern
                    if (p == p_len)
                    {
                        // If there was only one star and PATHNAME was set, match_slash will be false
                        // Trailing "*" matches only if there are no more slash characters
                        if (!match_slash && Array.IndexOf(text, '/', t) != -1)
                        {
                            return(NOMATCH);
                        }

                        // Trailing "**" matches everything
                        return(MATCH);
                    }
                    else if (!match_slash && pattern[p] == '/')
                    {
                        // We're at a slash, so consume the text until the next slash
                        int nextSlashIndex = Array.IndexOf(text, '/', t);
                        // If there aren't any more slashes, this can't be a match
                        if (nextSlashIndex == -1)
                        {
                            return(NOMATCH);
                        }

                        t = nextSlashIndex;
                        break;
                    }

                    // Try to match the remaining text
                    // Each time the match fails, remove the first character from the text and retry
                    while (true)
                    {
                        if (t == t_EOP)
                        {
                            break;
                        }

                        // Try to advance faster when an asterisk is followed by a literal.
                        // We know in this case that the string before the literal must belong to "*".
                        // If match_slash is false, do not look past the first slash as it cannot belong to '*'.
                        if (!IsGlobSpecial(pattern[p]))
                        {
                            p_ch = pattern[p];

                            if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsUpper(p_ch))
                            {
                                p_ch = Char.ToLower(p_ch);
                            }

                            while (t < t_len && ((t_ch = text[t]) != '/' || match_slash))
                            {
                                if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsUpper(t_ch))
                                {
                                    t_ch = Char.ToLower(t_ch);
                                }

                                if (t_ch == p_ch)
                                {
                                    break;
                                }

                                t++;
                            }

                            if (t_ch != p_ch)
                            {
                                return(NOMATCH);
                            }
                        }

                        if ((match = Match(pattern, text, p, t, flags)) != NOMATCH)
                        {
                            if (!match_slash || match != ABORT_TO_STARSTAR)
                            {
                                return(match);
                            }
                        }
                        else if (!match_slash && t_ch == '/')
                        {
                            return(ABORT_TO_STARSTAR);
                        }

                        t_ch = text[++t];
                    }

                    return(ABORT_ALL);

                // Match character ranges
                case '[':
                    p_ch = pattern[++p];

                    negated = (p_ch == NEGATE_CLASS || p_ch == NEGATE_CLASS2) ? 1 : 0;

                    if (negated == 1)
                    {
                        p_ch = pattern[++p];
                    }

                    prev_ch = '\0';
                    match   = 0;

                    do
                    {
                        if (p == p_len)
                        {
                            return(ABORT_ALL);
                        }

                        if (p_ch == '\\')
                        {
                            if (++p == p_len)
                            {
                                return(ABORT_ALL);
                            }

                            p_ch = pattern[p];

                            if (t_ch == p_ch)
                            {
                                match = 1;
                            }
                        }
                        else if (p_ch == '-' && prev_ch != '\0' && p < p_EOP && pattern[p + 1] != ']')
                        {
                            p_ch = pattern[++p];

                            if (p_ch == '\\')
                            {
                                if (++p == p_len)
                                {
                                    return(ABORT_ALL);
                                }

                                p_ch = pattern[p];
                            }

                            if (t_ch <= p_ch && t_ch >= prev_ch)
                            {
                                match = 1;
                            }
                            else if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsLower(t_ch))
                            {
                                char t_ch_upper = Char.ToUpper(t_ch);
                                if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch)
                                {
                                    match = 1;
                                }
                            }

                            p_ch = '\0';     // This makes "prev_ch" get set to 0
                        }
                        else if (p_ch == '[' && p < p_EOP && pattern[p + 1] == ':')
                        {
                            int s;
                            int i;

                            // SHARED ITERATOR
                            for (s = p + 2; p < p_len && (p_ch = pattern[p]) != ']'; p++)
                            {
                            }

                            if (p == p_EOP)
                            {
                                return(ABORT_ALL);
                            }

                            i = p - s - 1;

                            if (i < 0 || pattern[p - 1] != ':')
                            {
                                // Didn't find ":]", so treat like a normal set
                                p    = s - 2;
                                p_ch = '[';
                                if (t_ch == p_ch)
                                {
                                    match = 1;
                                }
                                continue;
                            }

                            if (CC_EQ(pattern, s, i, "alnum"))
                            {
                                if (Char.IsLetterOrDigit(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "alpha"))
                            {
                                if (Char.IsLetter(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "blank"))
                            {
                                if (Char.IsWhiteSpace(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "cntrl"))
                            {
                                if (Char.IsControl(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "digit"))
                            {
                                if (Char.IsDigit(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            //				        else if (CC_EQ(pattern, s, i, "graph"))
                            //				        {
                            //				            if (ISGRAPH(t_ch))
                            //				                match = 1;
                            //				        }
                            else if (CC_EQ(pattern, s, i, "lower"))
                            {
                                if (Char.IsLower(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            //				        else if (CC_EQ(pattern, s, i, "print"))
                            //				        {
                            //				            if (ISPRINT(t_ch))
                            //				                match = 1;
                            //				        }
                            else if (CC_EQ(pattern, s, i, "punct"))
                            {
                                if (Char.IsPunctuation(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "space"))
                            {
                                if (Char.IsWhiteSpace(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "upper"))
                            {
                                if (Char.IsUpper(t_ch))
                                {
                                    match = 1;
                                }
                                else if (flags.HasFlag(MatchFlags.CASEFOLD) && Char.IsLower(t_ch))
                                {
                                    match = 1;
                                }
                            }
                            else if (CC_EQ(pattern, s, i, "xdigit"))
                            {
                                if (Char.IsDigit(t_ch) || (Char.ToLower(t_ch) >= 'a' && Char.ToLower(t_ch) <= 'f'))
                                {
                                    match = 1;
                                }
                            }
                            else     // Malformed [:class:] string
                            {
                                return(ABORT_ALL);
                            }

                            p_ch = '\0';     // This makes "prev_ch" get set to 0
                        }
                        else if (t_ch == p_ch)
                        {
                            match = 1;
                        }

                        prev_ch = p_ch;
                    } while (p < p_len && (p_ch = pattern[++p]) != ']');

                    if (match == negated || (flags.HasFlag(MatchFlags.PATHNAME) && t_ch == '/'))
                    {
                        return(NOMATCH);
                    }

                    continue;
                }
            }

            return(t == text.Length ? MATCH : NOMATCH);
        }
Esempio n. 10
0
 internal static bool HasMatchFlag(this MatchFlags flags, MatchFlags flag) => (flags & flag) != 0;
Esempio n. 11
0
 private QueryFilter BuildTextFilter(PropertyDefinition[] properties, string propertyValue, MatchOptions matchOption, MatchFlags matchFlags)
 {
     if (string.IsNullOrEmpty(propertyValue))
     {
         return(null);
     }
     if (properties.Length == 1)
     {
         return(new TextFilter(properties[0], propertyValue, matchOption, matchFlags));
     }
     if (properties.Length > 1)
     {
         QueryFilter[] array = new QueryFilter[properties.Length];
         for (int i = 0; i < properties.Length; i++)
         {
             array[i] = new TextFilter(properties[i], propertyValue, matchOption, matchFlags);
         }
         return(new OrFilter(array));
     }
     return(null);
 }
Esempio n. 12
0
 internal static int IsMatch(string pattern, string text, MatchFlags flags)
 {
     return(Match(pattern.ToCharArray(), text.ToCharArray(), 0, 0, flags));
 }
Esempio n. 13
0
		public static int MatchAll(object pattern, object data, out PhpArray matches, MatchFlags flags, int offset)
		{
			return Match(pattern, data, out matches, flags, offset, true);
		}
Esempio n. 14
0
 /// <summary>
 /// Add multiple rules to the ignore list
 /// </summary>
 /// <param name="rules">A list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public void AddRules(IEnumerable <string> rules, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(rules, flags, false);
 }
Esempio n. 15
0
 /// <summary>
 /// Create a list of ignore rules to check paths against
 /// </summary>
 /// <param name="ignoreFilePath">Path to a text file containing a list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public IgnoreList(string ignoreFilePath, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(File.ReadAllLines(ignoreFilePath), flags);
 }
Esempio n. 16
0
 public TextFilter(PropertyDefinition property, string text, MatchOptions matchOptions, MatchFlags matchFlags) : base(property, matchOptions, matchFlags)
 {
     this.text = text;
 }
Esempio n. 17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="IgnoreList"/> class.
 /// </summary>
 /// <param name="ignoreFilePath">Path to a text file containing a list of ignore patterns as strings.</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour.</param>
 public IgnoreList(string ignoreFilePath, MatchFlags flags = MatchFlags.PATHNAME) =>
Esempio n. 18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="IgnoreList"/> class.
 /// </summary>
 /// <param name="rules">A list of glob ignore patterns as strings.</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour.</param>
 public IgnoreList(IEnumerable <string> rules, MatchFlags flags = MatchFlags.PATHNAME) =>
Esempio n. 19
0
 public BinaryFilter(PropertyDefinition property, byte[] binaryData, MatchOptions matchOptions, MatchFlags matchFlags) : base(property, matchOptions, matchFlags)
 {
     this.binaryData = binaryData;
 }
Esempio n. 20
0
 /// <summary>
 /// Add a rule to the ignore list
 /// </summary>
 /// <param name="rule">Glob ignore pattern as string</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public void AddRule(string rule, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(new string[] { rule }, flags, false);
 }
Esempio n. 21
0
        private static MatchResult DoWild(CharPointer p, CharPointer text, MatchFlags flags)
        {
            char p_ch;
            var  pattern = p;

            for ( ; (p_ch = p.Value) != '\0'; text = text.Increment(), p = p.Increment())
            {
                int  matched;
                char t_ch;

                if ((t_ch = text.Value) == '\0' && p_ch != '*')
                {
                    return(MatchResult.AbortAll);
                }

                if (flags.HasFlag(MatchFlags.CaseFold))
                {
                    if (char.IsUpper(t_ch))
                    {
                        t_ch = char.ToLower(t_ch);
                    }
                    if (char.IsUpper(p_ch))
                    {
                        p_ch = char.ToLower(p_ch);
                    }
                }

                switch (p_ch)
                {
                case '\\':
                    p    = p.Increment();
                    p_ch = p.Value;
                    // fallthrough
                    goto default;

                default:
                    if (t_ch != p_ch)
                    {
                        return(MatchResult.NoMatch);
                    }
                    continue;

                case '?':
                    if (flags.HasFlag(MatchFlags.PathName) && t_ch == '/')
                    {
                        return(MatchResult.NoMatch);
                    }
                    continue;

                case '*':
                    p = p.Increment();
                    bool match_slash;
                    if (p.Value == '*')
                    {
                        var prev_p = p.Increment(-2);

                        p = p.Increment();
                        while (p.Value == '*')
                        {
                            p.Increment();
                        }

                        if (!flags.HasFlag(MatchFlags.PathName))
                        {
                            match_slash = true;
                        }
                        else if ((prev_p.Index < pattern.Index || prev_p.Value == '/') &&
                                 (p.Value == '\0' || p.Value == '/' ||
                                  (p.Value == '\\' && p.Increment().Value == '/')))
                        {
                            if (p.Value == '/' &&
                                DoWild(p.Increment(), text, flags) == MatchResult.Match)
                            {
                                return(MatchResult.Match);
                            }
                            match_slash = true;
                        }
                        else
                        {
                            return(MatchResult.AbortMalformed);
                        }
                    }
                    else
                    {
                        match_slash = !flags.HasFlag(MatchFlags.PathName);
                    }

                    if (p.Value == '\0')
                    {
                        /* Trailing "**" matches everything.  Trailing "*" matches
                         * only if there are no more slash characters. */
                        if (!match_slash)
                        {
                            if (text.Source.Substring(text.Index).Contains("/"))
                            {
                                return(MatchResult.NoMatch);
                            }
                        }
                        return((int)MatchResult.Match);
                    }
                    else if (!match_slash && p.Value == '/')
                    {
                        var nextIndex = text.Source.Substring(text.Index).IndexOf('/');
                        if (nextIndex == -1)
                        {
                            return(MatchResult.NoMatch);
                        }
                        text = text.Increment(nextIndex);
                        break;
                    }

                    while (true)
                    {
                        if (t_ch == '\0')
                        {
                            break;
                        }

                        if (!Sane.IsGlobSpecial(p.Value))
                        {
                            p_ch = p.Value;
                            if ((flags.HasFlag(MatchFlags.CaseFold)) && char.IsUpper(p_ch))
                            {
                                p_ch = char.ToLower(p_ch);
                            }

                            while ((t_ch = text.Value) != '\0' &&
                                   (match_slash || t_ch != '/'))
                            {
                                if (flags.HasFlag(MatchFlags.CaseFold) && char.IsUpper(t_ch))
                                {
                                    t_ch = char.ToLower(t_ch);
                                }
                                if (t_ch == p_ch)
                                {
                                    break;
                                }
                                text = text.Increment();
                            }
                            if (t_ch != p_ch)
                            {
                                return(MatchResult.NoMatch);
                            }
                        }

                        if ((matched = (int)DoWild(p, text, flags)) != (int)MatchResult.NoMatch)
                        {
                            if (!match_slash || matched != (int)MatchResult.AbortToStartStart)
                            {
                                return((MatchResult)matched);
                            }
                        }
                        else if (!match_slash && t_ch == '/')
                        {
                            return(MatchResult.AbortToStartStart);
                        }

                        text = text.Increment();
                        t_ch = text.Value;
                    }

                    return(MatchResult.AbortAll);

                case '[':
                    p    = p.Increment();
                    p_ch = p.Value;

                    if (p_ch == '^')
                    {
                        p_ch = '!';
                    }

                    var negated = p_ch == '!' ? 1 : 0;
                    if (negated == 1)
                    {
                        p    = p.Increment();
                        p_ch = p.Value;
                    }

                    var prev_ch = '\0';
                    matched = 0;

                    bool Next()
                    {
                        prev_ch = p_ch;
                        p       = p.Increment();
                        p_ch    = p.Value;
                        return(p_ch != ']');
                    }

                    do
                    {
                        if (p_ch == '\0')
                        {
                            return(MatchResult.AbortAll);
                        }

                        if (p_ch == '\\')
                        {
                            p    = p.Increment();
                            p_ch = p.Value;
                            if (p_ch == '\0')
                            {
                                return(MatchResult.AbortAll);
                            }
                            if (t_ch == p_ch)
                            {
                                matched = 1;
                            }
                        }
                        else if (p_ch == '-' && prev_ch != '\0' && p.Increment().Value != '\0' && p.Increment().Value != ']')
                        {
                            p    = p.Increment();
                            p_ch = p.Value;
                            if (p_ch == '\\')
                            {
                                p    = p.Increment();
                                p_ch = p.Value;
                                if (p_ch == '\0')
                                {
                                    return(MatchResult.AbortAll);
                                }
                            }
                            if (t_ch <= p_ch && t_ch >= prev_ch)
                            {
                                matched = 1;
                            }
                            else if (flags.HasFlag(MatchFlags.CaseFold) && char.IsLower(t_ch))
                            {
                                var t_ch_upper = char.ToUpper(t_ch);
                                if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch)
                                {
                                    matched = 1;
                                }
                            }

                            p_ch = '\0';
                        }
                        else if (p_ch == '[' && p.Increment().Value == ':')
                        {
                            CharPointer s;
                            for (s = p.Increment(2); (p_ch = p.Value) != '\0' && p_ch != ']'; p = p.Increment())
                            {
                            }

                            if (p_ch == '\0')
                            {
                                return(MatchResult.AbortAll);
                            }

                            var i = p.Index - s.Index - 1;
                            if (i < 0 || p.Increment(-1).Value != ':')
                            {
                                p    = s.Increment(-2);
                                p_ch = '[';
                                if (t_ch == p_ch)
                                {
                                    matched = 1;
                                }
                                continue;
                            }

                            var temp = s.Source.Substring(s.Index);
                            if (temp.StartsWith("alnum"))
                            {
                                if (Sane.IsAlNum(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("alpha"))
                            {
                                if (Sane.IsAlpha(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("blank"))
                            {
                                if (Sane.IsBlank(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("cntrl"))
                            {
                                if (Sane.IsCtrl(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("digit"))
                            {
                                if (Sane.IsDigit(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("graph"))
                            {
                                if (Sane.IsGraph(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("lower"))
                            {
                                if (char.IsLower(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("print"))
                            {
                                if (Sane.IsPrint(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("punct"))
                            {
                                if (Sane.IsPunc(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("space"))
                            {
                                if (Sane.IsSpace(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("upper"))
                            {
                                if (char.IsUpper(t_ch))
                                {
                                    matched = 1;
                                }
                                else if (flags.HasFlag(MatchFlags.CaseFold) && char.IsLower(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else if (temp.StartsWith("xdigit"))
                            {
                                if (Sane.IsXDigit(t_ch))
                                {
                                    matched = 1;
                                }
                            }
                            else
                            {
                                return(MatchResult.AbortAll);
                            }
                        }
                        else if (t_ch == p_ch)
                        {
                            matched = 1;
                        }
                    } while (Next());

                    if (matched == negated ||
                        (flags.HasFlag(MatchFlags.PathName) && t_ch == '/'))
                    {
                        return(MatchResult.NoMatch);
                    }
                    continue;
                }
            }

            return(text.Index < text.Source.Length ? MatchResult.NoMatch : MatchResult.Match);
        }
Esempio n. 22
0
 /// <summary>
 /// Add multiple rules to the ignore list
 /// </summary>
 /// <param name="ignoreFilePath">Path to a text file containing a list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public void AddRules(string ignoreFilePath, MatchFlags flags = MatchFlags.PATHNAME)
 {
     AddRules(File.ReadAllLines(ignoreFilePath), flags, true);
 }
Esempio n. 23
0
 public ContentFilter(PropertyDefinition property, MatchOptions matchOptions, MatchFlags matchFlags) : base(property)
 {
     this.matchOptions = matchOptions;
     this.matchFlags   = matchFlags;
 }
Esempio n. 24
0
 /// <summary>
 /// Add multiple rules to the ignore list
 /// </summary>
 /// <param name="ignoreFilePath">Path to a text file containing a list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public void AddRules(string ignoreFilePath, MatchFlags flags = MatchFlags.PATHNAME)
 {
     _rules.AddRange(CleanRules(File.ReadAllLines(ignoreFilePath)).Select(line => new IgnoreRule(line, flags)));
 }
Esempio n. 25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="IgnoreRule"/> class.
        /// </summary>
        /// <param name="pattern">A glob pattern specifying file(s) this rule should ignore.</param>
        /// <param name="flags">Optional flags determining pattern matching behaviour.</param>
        /// <param name="lineNumber">Optional line number for logging purposes.</param>
        public IgnoreRule(string pattern, MatchFlags flags = MatchFlags.PATHNAME, int?lineNumber = null)
        {
            if (string.IsNullOrWhiteSpace(pattern))
            {
                throw new ArgumentException("Pattern cannot be null or empty", nameof(pattern));
            }

            LineNumber = lineNumber;

            // Keep track of the original pattern before modifications (for display purposes)
            OriginalPattern = pattern;
            Pattern         = pattern;
            MatchFlags      = flags;

            // First, let's figure out some things about the pattern and set flags to pass to our match function
            PatternFlags = PatternFlags.NONE;

            // If the pattern starts with an exclamation mark, it's a negation pattern
            // Once we know that, we can remove the exclamation mark (so the pattern behaves
            // just like any other), then just negate the match result when we return it
            if (Pattern.StartsWithCI("!"))
            {
                PatternFlags |= PatternFlags.NEGATION;
                Pattern       = Pattern.Substring(1);
            }

            // If the pattern starts with a forward slash, it should only match an absolute path
            if (Pattern.StartsWithCI("/"))
            {
                PatternFlags |= PatternFlags.ABSOLUTE_PATH;
                Pattern       = Pattern.Substring(1);
            }

            // If the pattern ends with a forward slash, it should only match a directory
            // Again though, once we know that we can remove the slash to normalise the pattern
            if (Pattern.EndsWithCI("/"))
            {
                PatternFlags |= PatternFlags.DIRECTORY;
                Pattern       = Pattern.Substring(0, Pattern.Length - 1);
            }

            _wildcardIndex = Pattern.IndexOfAny(_wildcardChars);

            // If CASEFOLD is set, string comparisons should ignore case too
            if (MatchFlags.HasFlag(MatchFlags.CASEFOLD))
            {
                _sc = StringComparison.OrdinalIgnoreCase;
            }

            // TODO: Currently, we are just setting PATHNAME for every rule
            // This is because it seems to match the original behaviour:
            // https://github.com/git/git/blob/c2c5f6b1e479f2c38e0e01345350620944e3527f/dir.c#L99

            // If PATHNAME is set, single asterisks should not match slashes
            if (!MatchFlags.HasFlag(MatchFlags.PATHNAME))
            {
                MatchFlags |= MatchFlags.PATHNAME;
            }

            var rxPattern = Matcher.ToRegex(Pattern);

            // If rxPattern is null, an invalid pattern was passed to ToRegex, so it cannot match
            if (!string.IsNullOrEmpty(rxPattern))
            {
                var rxOptions = RegexOptions.Compiled;

                if (MatchFlags.HasFlag(MatchFlags.CASEFOLD))
                {
                    rxOptions |= RegexOptions.IgnoreCase;
                }

                _rx = new Regex(rxPattern, rxOptions);
            }
        }
Esempio n. 26
0
		public static int Match(object pattern, object data, out PhpArray matches, MatchFlags flags)
		{
			return Match(pattern, data, out matches, flags, 0, false);
		}
Esempio n. 27
0
 /// <summary>
 /// Add multiple rules to the ignore list
 /// </summary>
 /// <param name="rules">A list of glob ignore patterns as strings</param>
 /// <param name="flags">Optional flags determining pattern matching behaviour</param>
 public void AddRules(IEnumerable <string> rules, MatchFlags flags = MatchFlags.PATHNAME)
 {
     _rules.AddRange(CleanRules(rules).Select(line => new IgnoreRule(line, flags)));
 }
Esempio n. 28
0
		/// <summary>
		/// Private method implementing functions from match family.
		/// </summary>
		/// <param name="pattern">Perl regular expression match pattern.</param>
		/// <param name="data">String to search matches.</param>
		/// <param name="matches">An array containing matches found.</param>
		/// <param name="flags">Flags for searching.</param>
		/// <param name="offset">Offset to <paramref name="pattern"/> where the search should start.</param>
		/// <param name="matchAll"><B>True</B> if all matches should be found, <B>false</B> if only the first
		/// is enough.</param>
		/// <returns>Number of times the <paramref name="pattern"/> matches.</returns>
		private static int Match(object pattern, object data, out PhpArray matches, MatchFlags flags,
			int offset, bool matchAll)
		{
			// these two flags together do not make sense
			if ((flags & MatchFlags.PatternOrder) != 0 && (flags & MatchFlags.SetOrder) != 0)
			{
				PhpException.InvalidArgument("flags", LibResources.GetString("preg_match_pattern_set_order"));
				matches = null;
				return -1;
			}

			PerlRegExpConverter converter = ConvertPattern(pattern, null);
			if (converter == null)
			{
				matches = new PhpArray();
				return -1;
			}

			string converted = ConvertData(data, converter);
			Match m = converter.Regex.Match(converted, offset>converted.Length?converted.Length:offset);

			if ((converter.PerlOptions & PerlRegexOptions.Anchored) > 0 && m.Success && m.Index != offset)
			{
				matches = new PhpArray();
				return -1;
			}

			if (m.Success)
			{
				if (!matchAll || (flags & MatchFlags.PatternOrder) != 0)
                {
					matches = new PhpArray(m.Groups.Count);
                }
				else
					matches = new PhpArray();

				if (!matchAll)
				{
                    // Preg numbers groups sequentially, both named and unnamed.
                    // .Net only numbers unnamed groups.
                    // So we name unnamed groups (see ConvertRegex) to map correctly.
				    int lastSuccessfulGroupIndex = GetLastSuccessfulGroup(m.Groups);
                    var indexGroups = new List<Group>(m.Groups.Count);
                    var groupNameByIndex = new Dictionary<int, string>(m.Groups.Count);
                    for (int i = 0; i <= lastSuccessfulGroupIndex; i++)
                    {
                        // All groups should be named.
                        var groupName = GetGroupName(converter.Regex, i);

                        if (!string.IsNullOrEmpty(groupName))
                        {
                            matches[groupName] = NewArrayItem(m.Groups[i].Value, m.Groups[i].Index, (flags & MatchFlags.OffsetCapture) != 0);
                        }

                        matches[i] = NewArrayItem(m.Groups[i].Value, m.Groups[i].Index, (flags & MatchFlags.OffsetCapture) != 0);
                    }

					return 1;
				}

				// store all other matches in PhpArray matches
				if ((flags & MatchFlags.SetOrder) != 0) // cannot test PatternOrder, it is 0, SetOrder must be tested
					return FillMatchesArrayAllSetOrder(converter.Regex, m, ref matches, (flags & MatchFlags.OffsetCapture) != 0);
				else
					return FillMatchesArrayAllPatternOrder(converter.Regex, m, ref matches, (flags & MatchFlags.OffsetCapture) != 0);
			}

			// no match has been found
			if (matchAll && (flags & MatchFlags.SetOrder) == 0)
			{
				// in that case PHP returns an array filled with empty arrays according to parentheses count
				matches = new PhpArray(m.Groups.Count);
                for (int i = 0; i < converter.Regex.GetGroupNumbers().Length; i++)
                {
                    AddGroupNameToResult(converter.Regex, matches, i, (ms,groupName) =>
                    {
                        ms[groupName] = new PhpArray(0);
                    });

                    matches[i] = new PhpArray(0);
                }
			}
			else
			{
				matches = new PhpArray(0); // empty array
			}

			return 0;
		}
Esempio n. 29
0
 public static MatchResult Match(string pattern, string text, MatchFlags matchFlags)
 {
     return(DoWild(pattern, text, matchFlags));
 }