Пример #1
0
        /// <summary>
        /// Preprocesses the search options and returns an opaque object
        /// that holds the state needed to efficiently search many times using the search options.
        /// Different threads can not share the returned state object. Each thread has to call this method.
        /// </summary>
        public static SearchState BeginSearch(this Options options, IRegexFactory regexFactory, bool timeboxedMatching = false)
        {
            SearchState ret = new SearchState()
            {
                options         = options,
                contentTypeMask = MessageFlag.ContentTypeMask & options.ContentTypes,
            };

            if (!string.IsNullOrEmpty(options.Template))
            {
                if (options.Regexp || useRegexsForSimpleTemplates)
                {
                    ReOptions reOpts = ReOptions.AllowPatternWhitespaces;
                    if (!options.MatchCase)
                    {
                        reOpts |= ReOptions.IgnoreCase;
                    }
                    if (options.ReverseSearch)
                    {
                        reOpts |= ReOptions.RightToLeft;
                    }
                    if (timeboxedMatching)
                    {
                        reOpts |= ReOptions.Timeboxed;
                    }
                    try
                    {
                        ret.re = regexFactory.Create(
                            options.Regexp ? options.Template : System.Text.RegularExpressions.Regex.Escape(options.Template), reOpts);
                    }
                    catch (Exception)
                    {
                        throw new TemplateException();
                    }
                }
                else
                {
                    if (!options.MatchCase)
                    {
                        ret.options.Template = ret.options.Template.ToLower();
                    }
                }
            }
            return(ret);
        }
Пример #2
0
        public static MatchedTextRange?SearchInMessageText(
            this SearchState state,
            IMessage msg,
            int?startTextPosition = null)
        {
            MessageFlag msgFlags = msg.Flags;

            if ((msgFlags & state.contentTypeMask) == 0)
            {
                return(null);
            }

            if (!state.options.Scope.ContainsMessage(msg))
            {
                return(null);
            }

            StringSlice sourceText = state.options.MessageTextGetter(msg).Text;

            return(SearchInText(state, sourceText, startTextPosition));
        }
Пример #3
0
        public static MatchedTextRange?SearchInText(
            this SearchState state,
            StringSlice text,
            int?startTextPosition)
        {
            IRegex re = state.re;

            // matched string position
            int  matchBegin       = 0;    // index of the first matched char
            int  matchEnd         = 0;    // index of following after the last matched one
            bool wholeTextMatched = false;

            if (!string.IsNullOrEmpty(state.options.Template))             // empty/null template means that text matching isn't required, i.e. match any input
            {
                int textPos;

                if (startTextPosition.HasValue)
                {
                    textPos = startTextPosition.Value;
                }
                else if (state.options.ReverseSearch)
                {
                    textPos = text.Length;
                }
                else
                {
                    textPos = 0;
                }

                for (; ;)
                {
                    if (re != null)
                    {
                        if (!re.Match(text, textPos, ref state.searchMatch))
                        {
                            return(null);
                        }
                        matchBegin = state.searchMatch.Index;
                        matchEnd   = matchBegin + state.searchMatch.Length;
                    }
                    else
                    {
                        StringComparison cmp = state.options.MatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
                        int i;
                        // todo: use running hash
                        if (state.options.ReverseSearch)
                        {
                            i = text.LastIndexOf(state.options.Template, textPos, cmp);
                        }
                        else
                        {
                            i = text.IndexOf(state.options.Template, textPos, cmp);
                        }
                        if (i < 0)
                        {
                            return(null);
                        }
                        matchBegin = i;
                        matchEnd   = matchBegin + state.options.Template.Length;
                    }

                    if (state.options.WholeWord && !IsWordBoundary(text, matchBegin, matchEnd))
                    {
                        textPos = state.options.ReverseSearch ? matchBegin : matchEnd;
                        continue;
                    }

                    break;
                }
            }
            else
            {
                matchBegin       = 0;
                matchEnd         = text.Length;
                wholeTextMatched = true;
            }

            return(new MatchedTextRange(text, matchBegin, matchEnd, wholeTextMatched));
        }