RegexReplacement.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Regex / System / Text / RegularExpressions / RegexReplacement.cs / 1305376 / RegexReplacement.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

// The RegexReplacement class represents a substitution string for 
// use when using regexs to search/replace, etc. It's logically 
// a sequence intermixed (1) constant strings and (2) group numbers.
 
namespace System.Text.RegularExpressions {

    using System.Collections;
    using System.Collections.Generic; 

    internal sealed class RegexReplacement { 
        /* 
         * Since RegexReplacement shares the same parser as Regex,
         * the constructor takes a RegexNode which is a concatenation 
         * of constant strings and backreferences.
         */
#if SILVERLIGHT
        internal RegexReplacement(String rep, RegexNode concat, Dictionary _caps) { 
#else
        internal RegexReplacement(String rep, RegexNode concat, Hashtable _caps) { 
#endif 
            StringBuilder sb;
            List strings; 
            List rules;
            int slot;

            _rep = rep; 

            if (concat.Type() != RegexNode.Concatenate) 
                throw new ArgumentException(SR.GetString(SR.ReplacementError)); 

            sb = new StringBuilder(); 
            strings = new List();
            rules = new List();

            for (int i = 0; i < concat.ChildCount(); i++) { 
                RegexNode child = concat.Child(i);
 
                switch (child.Type()) { 
                    case RegexNode.Multi:
                        sb.Append(child._str); 
                        break;
                    case RegexNode.One:
                        sb.Append(child._ch);
                        break; 
                    case RegexNode.Ref:
                        if (sb.Length > 0) { 
                            rules.Add(strings.Count); 
                            strings.Add(sb.ToString());
                            sb.Length = 0; 
                        }
                        slot = child._m;

                        if (_caps != null && slot >= 0) 
                            slot = (int)_caps[slot];
 
                        rules.Add(-Specials - 1 - slot); 
                        break;
                    default: 
                        throw new ArgumentException(SR.GetString(SR.ReplacementError));
                }
            }
 
            if (sb.Length > 0) {
                rules.Add(strings.Count); 
                strings.Add(sb.ToString()); 
            }
 
            _strings = strings;
            _rules = rules;
        }
 
        internal String _rep;
        internal List  _strings;          // table of string constants 
        internal List  _rules;            // negative -> group #, positive -> string # 

        // constants for special insertion patterns 

        internal const int Specials       = 4;
        internal const int LeftPortion    = -1;
        internal const int RightPortion   = -2; 
        internal const int LastGroup      = -3;
        internal const int WholeString    = -4; 
 
        /*
         * Given a Match, emits into the StringBuilder the evaluated 
         * substitution pattern.
         */
        private void ReplacementImpl(StringBuilder sb, Match match) {
            for (int i = 0; i < _rules.Count; i++) { 
                int r = _rules[i];
                if (r >= 0)   // string lookup 
                    sb.Append(_strings[r]); 
                else if (r < -Specials) // group lookup
                    sb.Append(match.GroupToStringImpl(-Specials - 1 - r)); 
                else {
                    switch (-Specials - 1 - r) { // special insertion patterns
                        case LeftPortion:
                            sb.Append(match.GetLeftSubstring()); 
                            break;
                        case RightPortion: 
                            sb.Append(match.GetRightSubstring()); 
                            break;
                        case LastGroup: 
                            sb.Append(match.LastGroupToStringImpl());
                            break;
                        case WholeString:
                            sb.Append(match.GetOriginalString()); 
                            break;
                    } 
                } 
            }
        } 

        /*
         * Given a Match, emits into the List the evaluated
         * Right-to-Left substitution pattern. 
         */
        private void ReplacementImplRTL(List al, Match match) { 
            for (int i = _rules.Count - 1; i >= 0; i--) { 
                int r = _rules[i];
                if (r >= 0)  // string lookup 
                    al.Add(_strings[r]);
                else if (r < -Specials) // group lookup
                    al.Add(match.GroupToStringImpl(-Specials - 1 - r));
                else { 
                    switch (-Specials - 1 - r) { // special insertion patterns
                        case LeftPortion: 
                            al.Add(match.GetLeftSubstring()); 
                            break;
                        case RightPortion: 
                            al.Add(match.GetRightSubstring());
                            break;
                        case LastGroup:
                            al.Add(match.LastGroupToStringImpl()); 
                            break;
                        case WholeString: 
                            al.Add(match.GetOriginalString()); 
                            break;
                    } 
                }
            }
        }
 
        /*
         * The original pattern string 
         */ 
        internal String Pattern {
            get { 
                return _rep;
            }
        }
 
        /*
         * Returns the replacement result for a single match 
         */ 
        internal String Replacement(Match match) {
            StringBuilder sb = new StringBuilder(); 

            ReplacementImpl(sb, match);

            return sb.ToString(); 
        }
 
        /* 
         * Three very similar algorithms appear below: replace (pattern),
         * replace (evaluator), and split. 
         */


        /* 
         * Replaces all ocurrances 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.
         */
        internal String Replace(Regex regex, String input, int count, int startat) { 
            Match match;
 
            if (count < -1) 
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall));
            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));

            if (count == 0)
                return input; 

            match = regex.Match(input, startat); 
            if (!match.Success) { 
                return input;
            } 
            else {
                StringBuilder sb;

                if (!regex.RightToLeft) { 
                    sb = new StringBuilder();
                    int prevat = 0; 
 
                    do {
                        if (match.Index != prevat) 
                            sb.Append(input, prevat, match.Index - prevat);

                        prevat = match.Index + match.Length;
                        ReplacementImpl(sb, match); 
                        if (--count == 0)
                            break; 
 
                        match = match.NextMatch();
                    } while (match.Success); 

                    if (prevat < input.Length)
                        sb.Append(input, prevat, input.Length - prevat);
                } 
                else {
                    List al = new List(); 
                    int prevat = input.Length; 

                    do { 
                        if (match.Index + match.Length != prevat)
                            al.Add(input.Substring(match.Index + match.Length, prevat - match.Index - match.Length));

                        prevat = match.Index; 
                        ReplacementImplRTL(al, match);
                        if (--count == 0) 
                            break; 

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

                    sb = new StringBuilder();
 
                    if (prevat > 0)
                        sb.Append(input, 0, prevat); 
 
                    for (int i = al.Count - 1; i >= 0; i--) {
                        sb.Append(al[i]); 
                    }
                }

                return sb.ToString(); 
            }
        } 
 
        /*
         * Replaces all ocurrances 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. 
         */ 
        internal static String Replace(MatchEvaluator evaluator, Regex regex,
                                       String input, int count, int startat) { 
            Match match;

            if (evaluator == null)
                throw new ArgumentNullException("evaluator"); 
            if (count < -1)
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall)); 
            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));
 
            if (count == 0)
                return input;

            match = regex.Match(input, startat); 

            if (!match.Success) { 
                return input; 
            }
            else { 
                StringBuilder sb;

                if (!regex.RightToLeft) {
                    sb = new StringBuilder(); 
                    int prevat = 0;
 
                    do { 
                        if (match.Index != prevat)
                            sb.Append(input, prevat, match.Index - prevat); 

                        prevat = match.Index + match.Length;

                        sb.Append(evaluator(match)); 

                        if (--count == 0) 
                            break; 

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

                    if (prevat < input.Length)
                        sb.Append(input, prevat, input.Length - prevat); 
                }
                else { 
                    List al = new List(); 
                    int prevat = input.Length;
 
                    do {
                        if (match.Index + match.Length != prevat)
                            al.Add(input.Substring(match.Index + match.Length, prevat - match.Index - match.Length));
 
                        prevat = match.Index;
 
                        al.Add(evaluator(match)); 

                        if (--count == 0) 
                            break;

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

                    sb = new StringBuilder(); 
 
                    if (prevat > 0)
                        sb.Append(input, 0, prevat); 

                    for (int i = al.Count - 1; i >= 0; i--) {
                        sb.Append(al[i]);
                    } 
                }
 
                return sb.ToString(); 
            }
        } 

        /*
         * Does a split. In the right-to-left case we reorder the
         * array to be forwards. 
         */
        internal static String[] Split(Regex regex, String input, int count, int startat) { 
            Match match; 
            String[] result;
 
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall));

            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));
 
            if (count == 1) { 
                result = new String[1];
                result[0] = input; 
                return result;
            }

            count -= 1; 

            match = regex.Match(input, startat); 
 
            if (!match.Success) {
                result = new String[1]; 
                result[0] = input;
                return result;
            }
            else { 
                List al = new List();
 
                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
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

// The RegexReplacement class represents a substitution string for 
// use when using regexs to search/replace, etc. It's logically 
// a sequence intermixed (1) constant strings and (2) group numbers.
 
namespace System.Text.RegularExpressions {

    using System.Collections;
    using System.Collections.Generic; 

    internal sealed class RegexReplacement { 
        /* 
         * Since RegexReplacement shares the same parser as Regex,
         * the constructor takes a RegexNode which is a concatenation 
         * of constant strings and backreferences.
         */
#if SILVERLIGHT
        internal RegexReplacement(String rep, RegexNode concat, Dictionary _caps) { 
#else
        internal RegexReplacement(String rep, RegexNode concat, Hashtable _caps) { 
#endif 
            StringBuilder sb;
            List strings; 
            List rules;
            int slot;

            _rep = rep; 

            if (concat.Type() != RegexNode.Concatenate) 
                throw new ArgumentException(SR.GetString(SR.ReplacementError)); 

            sb = new StringBuilder(); 
            strings = new List();
            rules = new List();

            for (int i = 0; i < concat.ChildCount(); i++) { 
                RegexNode child = concat.Child(i);
 
                switch (child.Type()) { 
                    case RegexNode.Multi:
                        sb.Append(child._str); 
                        break;
                    case RegexNode.One:
                        sb.Append(child._ch);
                        break; 
                    case RegexNode.Ref:
                        if (sb.Length > 0) { 
                            rules.Add(strings.Count); 
                            strings.Add(sb.ToString());
                            sb.Length = 0; 
                        }
                        slot = child._m;

                        if (_caps != null && slot >= 0) 
                            slot = (int)_caps[slot];
 
                        rules.Add(-Specials - 1 - slot); 
                        break;
                    default: 
                        throw new ArgumentException(SR.GetString(SR.ReplacementError));
                }
            }
 
            if (sb.Length > 0) {
                rules.Add(strings.Count); 
                strings.Add(sb.ToString()); 
            }
 
            _strings = strings;
            _rules = rules;
        }
 
        internal String _rep;
        internal List  _strings;          // table of string constants 
        internal List  _rules;            // negative -> group #, positive -> string # 

        // constants for special insertion patterns 

        internal const int Specials       = 4;
        internal const int LeftPortion    = -1;
        internal const int RightPortion   = -2; 
        internal const int LastGroup      = -3;
        internal const int WholeString    = -4; 
 
        /*
         * Given a Match, emits into the StringBuilder the evaluated 
         * substitution pattern.
         */
        private void ReplacementImpl(StringBuilder sb, Match match) {
            for (int i = 0; i < _rules.Count; i++) { 
                int r = _rules[i];
                if (r >= 0)   // string lookup 
                    sb.Append(_strings[r]); 
                else if (r < -Specials) // group lookup
                    sb.Append(match.GroupToStringImpl(-Specials - 1 - r)); 
                else {
                    switch (-Specials - 1 - r) { // special insertion patterns
                        case LeftPortion:
                            sb.Append(match.GetLeftSubstring()); 
                            break;
                        case RightPortion: 
                            sb.Append(match.GetRightSubstring()); 
                            break;
                        case LastGroup: 
                            sb.Append(match.LastGroupToStringImpl());
                            break;
                        case WholeString:
                            sb.Append(match.GetOriginalString()); 
                            break;
                    } 
                } 
            }
        } 

        /*
         * Given a Match, emits into the List the evaluated
         * Right-to-Left substitution pattern. 
         */
        private void ReplacementImplRTL(List al, Match match) { 
            for (int i = _rules.Count - 1; i >= 0; i--) { 
                int r = _rules[i];
                if (r >= 0)  // string lookup 
                    al.Add(_strings[r]);
                else if (r < -Specials) // group lookup
                    al.Add(match.GroupToStringImpl(-Specials - 1 - r));
                else { 
                    switch (-Specials - 1 - r) { // special insertion patterns
                        case LeftPortion: 
                            al.Add(match.GetLeftSubstring()); 
                            break;
                        case RightPortion: 
                            al.Add(match.GetRightSubstring());
                            break;
                        case LastGroup:
                            al.Add(match.LastGroupToStringImpl()); 
                            break;
                        case WholeString: 
                            al.Add(match.GetOriginalString()); 
                            break;
                    } 
                }
            }
        }
 
        /*
         * The original pattern string 
         */ 
        internal String Pattern {
            get { 
                return _rep;
            }
        }
 
        /*
         * Returns the replacement result for a single match 
         */ 
        internal String Replacement(Match match) {
            StringBuilder sb = new StringBuilder(); 

            ReplacementImpl(sb, match);

            return sb.ToString(); 
        }
 
        /* 
         * Three very similar algorithms appear below: replace (pattern),
         * replace (evaluator), and split. 
         */


        /* 
         * Replaces all ocurrances 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.
         */
        internal String Replace(Regex regex, String input, int count, int startat) { 
            Match match;
 
            if (count < -1) 
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall));
            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));

            if (count == 0)
                return input; 

            match = regex.Match(input, startat); 
            if (!match.Success) { 
                return input;
            } 
            else {
                StringBuilder sb;

                if (!regex.RightToLeft) { 
                    sb = new StringBuilder();
                    int prevat = 0; 
 
                    do {
                        if (match.Index != prevat) 
                            sb.Append(input, prevat, match.Index - prevat);

                        prevat = match.Index + match.Length;
                        ReplacementImpl(sb, match); 
                        if (--count == 0)
                            break; 
 
                        match = match.NextMatch();
                    } while (match.Success); 

                    if (prevat < input.Length)
                        sb.Append(input, prevat, input.Length - prevat);
                } 
                else {
                    List al = new List(); 
                    int prevat = input.Length; 

                    do { 
                        if (match.Index + match.Length != prevat)
                            al.Add(input.Substring(match.Index + match.Length, prevat - match.Index - match.Length));

                        prevat = match.Index; 
                        ReplacementImplRTL(al, match);
                        if (--count == 0) 
                            break; 

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

                    sb = new StringBuilder();
 
                    if (prevat > 0)
                        sb.Append(input, 0, prevat); 
 
                    for (int i = al.Count - 1; i >= 0; i--) {
                        sb.Append(al[i]); 
                    }
                }

                return sb.ToString(); 
            }
        } 
 
        /*
         * Replaces all ocurrances 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. 
         */ 
        internal static String Replace(MatchEvaluator evaluator, Regex regex,
                                       String input, int count, int startat) { 
            Match match;

            if (evaluator == null)
                throw new ArgumentNullException("evaluator"); 
            if (count < -1)
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall)); 
            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));
 
            if (count == 0)
                return input;

            match = regex.Match(input, startat); 

            if (!match.Success) { 
                return input; 
            }
            else { 
                StringBuilder sb;

                if (!regex.RightToLeft) {
                    sb = new StringBuilder(); 
                    int prevat = 0;
 
                    do { 
                        if (match.Index != prevat)
                            sb.Append(input, prevat, match.Index - prevat); 

                        prevat = match.Index + match.Length;

                        sb.Append(evaluator(match)); 

                        if (--count == 0) 
                            break; 

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

                    if (prevat < input.Length)
                        sb.Append(input, prevat, input.Length - prevat); 
                }
                else { 
                    List al = new List(); 
                    int prevat = input.Length;
 
                    do {
                        if (match.Index + match.Length != prevat)
                            al.Add(input.Substring(match.Index + match.Length, prevat - match.Index - match.Length));
 
                        prevat = match.Index;
 
                        al.Add(evaluator(match)); 

                        if (--count == 0) 
                            break;

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

                    sb = new StringBuilder(); 
 
                    if (prevat > 0)
                        sb.Append(input, 0, prevat); 

                    for (int i = al.Count - 1; i >= 0; i--) {
                        sb.Append(al[i]);
                    } 
                }
 
                return sb.ToString(); 
            }
        } 

        /*
         * Does a split. In the right-to-left case we reorder the
         * array to be forwards. 
         */
        internal static String[] Split(Regex regex, String input, int count, int startat) { 
            Match match; 
            String[] result;
 
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.CountTooSmall));

            if (startat < 0 || startat > input.Length) 
                throw new ArgumentOutOfRangeException("startat", SR.GetString(SR.BeginIndexNotNegative));
 
            if (count == 1) { 
                result = new String[1];
                result[0] = input; 
                return result;
            }

            count -= 1; 

            match = regex.Match(input, startat); 
 
            if (!match.Success) {
                result = new String[1]; 
                result[0] = input;
                return result;
            }
            else { 
                List al = new List();
 
                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

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK