Exemple #1
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());
        }
Exemple #2
0
        /// <summary>
        /// Does a split. In the right-to-left case we reorder the
        /// array to be forwards.
        /// </summary>
        private static string[] Split(Regex regex, string input, int count, int startat)
        {
            if (count < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.CountTooSmall);
            }
            if ((uint)startat > (uint)input.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startat, ExceptionResource.BeginIndexNotNegative);
            }

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

            count--;
            var state = (results : new List <string>(), prevat : 0, input, count);

            if (!regex.RightToLeft)
            {
                regex.RunAllMatchesWithCallback(input, startat, ref state, static (ref (List <string> results, int prevat, string input, int count)state, Match match) =>
                {
                    state.results.Add(state.input.Substring(state.prevat, match.Index - state.prevat));
                    state.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))
                        {
                            state.results.Add(match.Groups[i].Value);
                        }
                    }

                    return(--state.count != 0);
                }, RegexRunnerMode.FullMatchRequired, reuseMatchObject: true);
Exemple #3
0
        private readonly int[] _rules;      // negative -> group #, positive -> string #

        /// <summary>
        /// Since RegexReplacement shares the same parser as Regex,
        /// the constructor takes a RegexNode which is a concatenation
        /// of constant strings and backreferences.
        /// </summary>
        public RegexReplacement(string rep, RegexNode concat, Hashtable _caps)
        {
            if (concat.Kind != RegexNodeKind.Concatenate)
            {
                throw ThrowHelper.CreateArgumentException(ExceptionResource.ReplacementError);
            }

            Span <char>      vsbStack     = stackalloc char[256];
            var              vsb          = new ValueStringBuilder(vsbStack);
            FourStackStrings stackStrings = default;
            var              strings      = new ValueListBuilder <string>(MemoryMarshal.CreateSpan(ref stackStrings.Item1 !, 4));
            var              rules        = new ValueListBuilder <int>(stackalloc int[64]);

            int childCount = concat.ChildCount();

            for (int i = 0; i < childCount; i++)
            {
                RegexNode child = concat.Child(i);

                switch (child.Kind)
                {
                case RegexNodeKind.Multi:
                    vsb.Append(child.Str !);
                    break;

                case RegexNodeKind.One:
                    vsb.Append(child.Ch);
                    break;

                case RegexNodeKind.Backreference:
                    if (vsb.Length > 0)
                    {
                        rules.Append(strings.Length);
                        strings.Append(vsb.ToString());
                        vsb = new ValueStringBuilder(vsbStack);
                    }
                    int slot = child.M;

                    if (_caps != null && slot >= 0)
                    {
                        slot = (int)_caps[slot] !;
                    }

                    rules.Append(-Specials - 1 - slot);
                    break;

                default:
                    throw ThrowHelper.CreateArgumentException(ExceptionResource.ReplacementError);
                }
            }

            if (vsb.Length > 0)
            {
                rules.Append(strings.Length);
                strings.Append(vsb.ToString());
            }

            Pattern  = rep;
            _strings = strings.AsSpan().ToArray();
            _rules   = rules.AsSpan().ToArray();

            rules.Dispose();
        }