예제 #1
0
        /// <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>
        private static string Replace(MatchEvaluator evaluator, Regex regex, string input, int count, int startat)
        {
            if (evaluator is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.evaluator);
            }
            if (count < -1)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.CountTooSmall);
            }
            if ((uint)startat > (uint)input.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startat, ExceptionResource.BeginIndexNotNegative);
            }

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

            var state = (segments : SegmentStringBuilder.Create(), evaluator, prevat : 0, input, count);

            if (!regex.RightToLeft)
            {
                regex.Run(input, startat, ref state, static (ref (SegmentStringBuilder segments, MatchEvaluator evaluator, int prevat, string input, int count)state, Match match) =>
                {
                    state.segments.Add(state.input.AsMemory(state.prevat, match.Index - state.prevat));
                    state.prevat = match.Index + match.Length;
                    state.segments.Add(state.evaluator(match).AsMemory());
                    return(--state.count != 0);
                }, reuseMatchObject: false);
예제 #2
0
        /// <summary>
        /// Given a Match, emits into the builder the evaluated
        /// Right-to-Left substitution pattern.
        /// </summary>
        public void ReplacementImplRTL(ref SegmentStringBuilder segments, Match match)
        {
            for (int i = _rules.Length - 1; i >= 0; i--)
            {
                int rule = _rules[i];

                ReadOnlyMemory <char> segment =
                    rule >= 0 ? _strings[rule].AsMemory() :                          // string lookup
                    rule < -Specials?match.GroupToStringImpl(-Specials - 1 - rule) : // group lookup
                        (-Specials - 1 - rule) switch                                // special insertion patterns
                {
                    LeftPortion => match.GetLeftSubstring(),
                    RightPortion => match.GetRightSubstring(),
                    LastGroup => match.LastGroupToStringImpl(),
                    WholeString => match.Text.AsMemory(),
                    _ => default
                };

                // Add the segment to the list if it's not empty.  A common case for it being
                // empty is if the developer is using Regex.Replace as a way to implement
                // Regex.Remove, where the replacement string is empty.
                if (segment.Length != 0)
                {
                    segments.Add(segment);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Replaces all occurrences of the regex in the string with the
        /// replacement pattern.
        ///
        /// 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>
        public string Replace(Regex regex, string input, int count, int startat)
        {
            if (count < -1)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.CountTooSmall);
            }
            if ((uint)startat > (uint)input.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startat, ExceptionResource.BeginIndexNotNegative);
            }

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

            var state = (replacement : this, segments : SegmentStringBuilder.Create(), inputMemory : input.AsMemory(), prevat : 0, count);

            if (!regex.RightToLeft)
            {
                regex.Run(input, startat, ref state, (ref (RegexReplacement thisRef, SegmentStringBuilder segments, ReadOnlyMemory <char> inputMemory, int prevat, int count)state, Match match) =>
                {
                    state.segments.Add(state.inputMemory.Slice(state.prevat, match.Index - state.prevat));
                    state.prevat = match.Index + match.Length;
                    state.thisRef.ReplacementImpl(ref state.segments, match);
                    return(--state.count != 0);
                }, reuseMatchObject: true);
예제 #4
0
        /// <summary>
        /// Returns the expansion of the passed replacement pattern. For
        /// example, if the replacement pattern is ?$1$2?, Result returns the concatenation
        /// of Group(1).ToString() and Group(2).ToString().
        /// </summary>
        public virtual string Result(string replacement)
        {
            if (replacement is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.replacement);
            }

            Regex?regex = _regex;

            if (regex is null)
            {
                throw new NotSupportedException(SR.NoResultOnFailed);
            }

            // Gets the weakly cached replacement helper or creates one if there isn't one already.
            RegexReplacement     repl     = RegexReplacement.GetOrCreate(regex.RegexReplacementWeakReference, replacement, regex.caps !, regex.capsize, regex.capnames !, regex.roptions);
            SegmentStringBuilder segments = SegmentStringBuilder.Create();

            repl.ReplacementImpl(ref segments, this);
            return(segments.ToString());
        }
예제 #5
0
        /// <summary>
        /// Given a Match, emits into the builder the evaluated
        /// Right-to-Left substitution pattern.
        /// </summary>
        public void ReplacementImplRTL(ref SegmentStringBuilder segments, Match match)
        {
            for (int i = _rules.Length - 1; i >= 0; i--)
            {
                int r = _rules[i];
                if (r >= 0)
                {
                    // string lookup
                    segments.Add(_strings[r].AsMemory());
                }
                else if (r < -Specials)
                {
                    // group lookup
                    segments.Add(match.GroupToStringImpl(-Specials - 1 - r));
                }
                else
                {
                    // special insertion patterns
                    switch (-Specials - 1 - r)
                    {
                    case LeftPortion:
                        segments.Add(match.GetLeftSubstring());
                        break;

                    case RightPortion:
                        segments.Add(match.GetRightSubstring());
                        break;

                    case LastGroup:
                        segments.Add(match.LastGroupToStringImpl());
                        break;

                    case WholeString:
                        segments.Add(match.Text.AsMemory());
                        break;
                    }
                }
            }
        }