示例#1
0
        /// <summary>
        /// Goes through <paramref name="m"/> matches and fill <paramref name="matches"/> array with results
        /// according to Set Order.
        /// </summary>
        /// <param name="r"><see cref="Regex"/> that produced the match</param>
        /// <param name="m"><see cref="Match"/> to iterate through all matches by NextMatch() call.</param>
        /// <param name="matches">Array for storing results.</param>
        /// <param name="addOffsets">Whether or not add arrays with offsets instead of strings.</param>
        /// <returns>Number of full pattern matches.</returns>
        static int FillMatchesArrayAllSetOrder(PerlRegex.Regex r, PerlRegex.Match m, ref PhpArray matches, bool addOffsets)
        {
            // first index, increases at each match in set order
            int i = 0;

            while (m.Success)
            {
                var pa = new PhpArray(m.Groups.Count);

                // add all groups
                for (int j = 0; j < m.Groups.Count; j++)
                {
                    var arr = NewArrayItem(m.Groups[j].Value, m.Groups[j].Index, addOffsets);

                    AddGroupNameToResult(r, pa, j, (p, groupName) =>
                    {
                        p[groupName] = arr;
                    });

                    pa[j] = arr;
                }

                matches[i] = (PhpValue)pa;
                i++;
                m = m.NextMatch();
            }

            return(i);
        }
示例#2
0
        /// <summary>
        /// Goes through <paramref name="m"/> matches and fill <paramref name="matches"/> array with results
        /// according to Pattern Order.
        /// </summary>
        /// <param name="r"><see cref="Regex"/> that produced the match</param>
        /// <param name="m"><see cref="Match"/> to iterate through all matches by NextMatch() call.</param>
        /// <param name="matches">Array for storing results.</param>
        /// <param name="addOffsets">Whether or not add arrays with offsets instead of strings.</param>
        /// <returns>Number of full pattern matches.</returns>
        static int FillMatchesArrayAllPatternOrder(PerlRegex.Regex r, PerlRegex.Match m, ref PhpArray matches, bool addOffsets)
        {
            // second index, increases at each match in pattern order
            int j = 0;

            while (m.Success)
            {
                // add all groups
                for (int i = 0; i < m.Groups.Count; i++)
                {
                    var arr = NewArrayItem(m.Groups[i].Value, m.Groups[i].Index, addOffsets);

                    AddGroupNameToResult(r, matches, i, (ms, groupName) =>
                    {
                        if (j == 0)
                        {
                            ms[groupName] = (PhpValue) new PhpArray();
                        }
                        ((PhpArray)ms[groupName])[j] = arr;
                    });

                    if (j == 0)
                    {
                        matches[i] = (PhpValue) new PhpArray();
                    }
                    ((PhpArray)matches[i])[j] = arr;
                }

                j++;
                m = m.NextMatch();
            }

            return(j);
        }
        /// <summary>
        /// Does a split. In the right-to-left case we reorder the
        /// array to be forwards.
        /// </summary>
        internal static string[] Split(Regex regex, string input, int count, int startat)
        {
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), SR.CountTooSmall);
            }
            if (startat < 0 || startat > input.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startat), SR.BeginIndexNotNegative);
            }

            string[] result;

            if (count == 1)
            {
                result    = new string[1];
                result[0] = input;
                return(result);
            }

            count -= 1;

            Match match = regex.Match(input, startat);

            if (!match.Success)
            {
                result    = new string[1];
                result[0] = input;
                return(result);
            }
            else
            {
                List <string> al = new List <string>();

                if (!regex.RightToLeft)
                {
                    int prevat = 0;

                    for (; ;)
                    {
                        al.Add(input.Substring(prevat, match.Index - prevat));

                        prevat = match.Index + match.Length;

                        // add all matched capture groups to the list.
                        for (int i = 1; i < match.Groups.Count; i++)
                        {
                            if (match.IsMatched(i))
                            {
                                al.Add(match.Groups[i].ToString());
                            }
                        }

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();

                        if (!match.Success)
                        {
                            break;
                        }
                    }

                    al.Add(input.Substring(prevat, input.Length - prevat));
                }
                else
                {
                    int prevat = input.Length;

                    for (; ;)
                    {
                        al.Add(input.Substring(match.Index + match.Length, prevat - match.Index - match.Length));

                        prevat = match.Index;

                        // add all matched capture groups to the list.
                        for (int i = 1; i < match.Groups.Count; i++)
                        {
                            if (match.IsMatched(i))
                            {
                                al.Add(match.Groups[i].ToString());
                            }
                        }

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();

                        if (!match.Success)
                        {
                            break;
                        }
                    }

                    al.Add(input.Substring(0, prevat));

                    al.Reverse(0, al.Count);
                }

                return(al.ToArray());
            }
        }
        /// <summary>
        /// Replaces all occurrences of the regex in the string with the
        /// replacement evaluator.
        ///
        /// Note that the special case of no matches is handled on its own:
        /// with no matches, the input string is returned unchanged.
        /// The right-to-left case is split out because StringBuilder
        /// doesn't handle right-to-left string building directly very well.
        /// </summary>
        internal static string Replace(MatchEvaluator evaluator, Regex regex,
                                       string input, int count, int startat,
                                       ref long replacements)
        {
            if (evaluator == null)
            {
                throw new ArgumentNullException(nameof(evaluator));
            }
            if (count < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(count), SR.CountTooSmall);
            }
            if (startat < 0 || startat > input.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startat), SR.BeginIndexNotNegative);
            }

            if (count == 0)
            {
                return(input);
            }

            Match match = regex.Match(input, startat);

            if (!match.Success)
            {
                return(input);
            }
            else
            {
                Span <char> charInitSpan = stackalloc char[ReplaceBufferSize];
                var         vsb          = new ValueStringBuilder(charInitSpan);

                if (!regex.RightToLeft)
                {
                    int prevat = 0;

                    do
                    {
                        if (match.Index != prevat)
                        {
                            vsb.Append(input.AsSpan(prevat, match.Index - prevat));
                        }

                        prevat = match.Index + match.Length;
                        string result = evaluator(match);
                        if (!string.IsNullOrEmpty(result))
                        {
                            vsb.Append(evaluator(match));
                        }

                        ++replacements;

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();
                    } while (match.Success);

                    if (prevat < input.Length)
                    {
                        vsb.Append(input.AsSpan(prevat, input.Length - prevat));
                    }
                }
                else
                {
                    // In right to left mode append all the inputs in reversed order to avoid an extra dynamic data structure
                    // and to be able to work with Spans. A final reverse of the transformed reversed input string generates
                    // the desired output. Similar to Tower of Hanoi.

                    int prevat = input.Length;

                    do
                    {
                        if (match.Index + match.Length != prevat)
                        {
                            vsb.AppendReversed(input.AsSpan(match.Index + match.Length, prevat - match.Index - match.Length));
                        }

                        prevat = match.Index;
                        vsb.AppendReversed(evaluator(match).AsSpan());

                        ++replacements;

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();
                    } while (match.Success);

                    if (prevat > 0)
                    {
                        vsb.AppendReversed(input.AsSpan(0, prevat));
                    }

                    vsb.Reverse();
                }

                return(vsb.ToString());
            }
        }