* System.Text.RegularExpressions/Regex.cs (Replace): Check that input &
[mono.git] / mcs / class / System / System.Text.RegularExpressions / JvmReMachine.jvm.cs
1 //
2 // JvmReMachine.jvm.cs
3 //
4 // Author:
5 //      Arina Itkes  <arinai@mainsoft.com>
6 //
7 // Copyright (C) 2007 Mainsoft, Inc.
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Collections.Generic;
33 using System.Collections;
34 using System.Text;
35 using java.util.regex;
36 using java.lang;
37
38 namespace System.Text.RegularExpressions
39 {
40         sealed class JvmReMachine : BaseMachine
41         {
42                 readonly PatternData _patternData;
43
44                 internal JvmReMachine (PatternData patternData) {
45                         this._patternData = patternData;
46                 }
47
48                 #region Properties
49
50                 internal PatternData PatternData {
51                         get { return _patternData; }
52                 }
53
54                 internal Pattern JavaPattern {
55                         get { return _patternData.JavaPattern; }
56                 }
57
58                 internal IDictionary Mapping {
59                         get { return _patternData.GroupNameToNumberMap; }
60                         set { throw new NotImplementedException ("Mapping setter of JvmReMachine should not be called."); }//We must implement the setter of interface but it is not in use
61                 }
62
63                 internal string [] NamesMapping {
64                         get { return _patternData.GroupNumberToNameMap; }
65                         set { throw new NotImplementedException ("NamesMapping setter of JvmReMachine should not be called."); }//We must implement the setter of interface but it is not in use
66                 }
67
68                 internal int GroupCount {
69                         get { return _patternData.GroupCount; }
70                 }
71
72                 #endregion Properties
73
74                 #region Implementations of IMachine Interface
75
76                 public override Match Scan (Regex regex, string text, int start, int end) {
77
78                         if (start > end)
79                                 return Match.Empty;
80
81                         Matcher m = JavaPattern.matcher (((CharSequence) (object) text).subSequence(0, end));
82
83                         if (!m.find (start)) {
84                                 return System.Text.RegularExpressions.Match.Empty;
85                         }
86
87                         GroupCollection groups = new GroupCollection (regex.GroupCount + 1);
88                         Match match = new Match (regex, this, groups, text, text.Length,
89                                                                                 m.start (), m.end () - m.start ());
90                         for (int javaGroupNumber = 1; javaGroupNumber <= m.groupCount (); ++javaGroupNumber) {
91                                 AddGroup (m, groups, javaGroupNumber, text, match);
92                         }
93
94                         return match;
95                 }
96
97                 public override string [] Split (Regex regex, string input, int count, int startat) {
98                         
99                         string [] splitArray = JavaPattern.split ((CharSequence) (object) input.Substring (startat), count);
100                         
101                         if (regex.GroupCount == 0 || splitArray.Length == 1) {
102                                 return splitArray;
103                         }
104
105                         if (count == 0)
106                                 count = Int32.MaxValue;
107
108                         Matcher m = JavaPattern.matcher ((CharSequence) (object) input.Substring (startat));
109
110                         int splitArrayIndex = 1;
111
112                         List<string> splits = new List<string> (splitArray.Length * (1 + regex.GroupCount));
113                         splits.Add (splitArray [0]);
114
115                         for (int number = 0; number < count; ++number) {
116                                 
117                                 if (!m.find ())
118                                         break;
119                                 
120                                 for (int i = 1; i <= m.groupCount (); ++i) {
121                                         splits.Add (m.group (i));
122                                 }
123
124                                 splits.Add (splitArray [splitArrayIndex++]);
125                         }
126
127                         return splits.ToArray ();
128                 }
129
130                 public override string Replace (Regex regex, string input, string replacement, int count, int startat) {
131                         
132                         if (regex.SameGroupNamesFlag) {
133                                 return base.Replace (regex, input, replacement, count, startat);
134                         }
135
136                         if (count < 0) {
137                                 count = Int32.MaxValue;
138                         }
139
140                         string replacementPattern = ReplacementData.Reformat (regex, replacement);
141                         Matcher m = JavaPattern.matcher ((CharSequence) (object) input);
142
143                         StringBuffer sb = new StringBuffer ();
144                         if (count > 0 && m.find (startat)) {
145                                 ReplacementData.ReplaceMatch (replacementPattern, m, sb, input, _patternData);
146                         }
147
148                         for (int matchesCounter = 1; matchesCounter < count; ++matchesCounter) {
149                                 if (!m.find ()) {
150                                         break;
151                                 }
152                                 ReplacementData.ReplaceMatch (replacementPattern, m, sb, input, _patternData);
153                         }
154
155
156                         m.appendTail (sb);
157                         return sb.ToString ();
158
159                 }
160
161                 public override string Result (string replacement, Match match) {
162                         if (match.Length == 0)
163                                 return String.Empty;
164
165                         string result = Replace (match.Regex, match.Text, replacement, 1, 0);
166                         return result.Substring (match.Index, result.Length - (match.Text.Length - match.Length));
167
168                 }
169
170                 #endregion Implementations of IMachine Interface
171
172                 private void AddGroup (Matcher m, GroupCollection groups, int javaGroupNumber, string text, Match match) {
173                         int netGroupNumber = _patternData.JavaToNetGroupNumbersMap [javaGroupNumber];
174                         if (netGroupNumber == -1) {
175                                 return;
176                         }
177
178                         int index = m.start (javaGroupNumber);
179
180                         if (index < 0){
181                                 if(groups[netGroupNumber] == null) 
182                                         groups.SetValue (new Group (), netGroupNumber);
183                                 return;
184                         }
185
186                         Group group = new Group (text, index, m.end (javaGroupNumber) - index, match, netGroupNumber);
187
188                         groups.SetValue (group, netGroupNumber);
189                 }
190         }
191 }