Add new tests from Juraj
[mono.git] / mcs / class / System / System.Text.RegularExpressions / regex.cs
1 //\r
2 // assembly:    System\r
3 // namespace:   System.Text.RegularExpressions\r
4 // file:        regex.cs\r
5 //\r
6 // author:      Dan Lewis (dlewis@gmx.co.uk)\r
7 //              (c) 2002\r
8 \r
9 using System;\r
10 using System.Text;\r
11 using System.Collections;\r
12 using System.Reflection;\r
13 using System.Reflection.Emit;\r
14 using System.Runtime.Serialization;\r
15 \r
16 using RegularExpression = System.Text.RegularExpressions.Syntax.RegularExpression;\r
17 using Parser = System.Text.RegularExpressions.Syntax.Parser;\r
18 \r
19 namespace System.Text.RegularExpressions {\r
20         \r
21         public delegate string MatchEvaluator (Match match);\r
22 \r
23         [Flags]\r
24         public enum RegexOptions {\r
25                 None                            = 0x000,\r
26                 IgnoreCase                      = 0x001,\r
27                 Multiline                       = 0x002,\r
28                 ExplicitCapture                 = 0x004,\r
29                 Compiled                        = 0x008,\r
30                 Singleline                      = 0x010,\r
31                 IgnorePatternWhitespace         = 0x020,\r
32                 RightToLeft                     = 0x040,\r
33                 ECMAScript                      = 0x100\r
34         }\r
35         \r
36         [Serializable]\r
37         public class Regex : ISerializable {\r
38                 public static void CompileToAssembly\r
39                         (RegexCompilationInfo[] regexes, AssemblyName aname)\r
40                 {\r
41                         throw new Exception ("Not implemented.");\r
42                 }\r
43 \r
44                 public static void CompileToAssembly\r
45                         (RegexCompilationInfo[] regexes, AssemblyName aname,\r
46                          CustomAttributeBuilder[] attribs)\r
47                 {\r
48                         throw new Exception ("Not implemented.");\r
49                 }\r
50 \r
51                 public static void CompileToAssembly\r
52                         (RegexCompilationInfo[] regexes, AssemblyName aname,\r
53                          CustomAttributeBuilder[] attribs, string resourceFile)\r
54                 {\r
55                         throw new Exception ("Not implemented.");\r
56                 }\r
57                 \r
58                 public static string Escape (string str) {\r
59                         return Parser.Escape (str);\r
60                 }\r
61 \r
62                 public static string Unescape (string str) {\r
63                         return Parser.Unescape (str);\r
64                 }\r
65 \r
66                 public static bool IsMatch (string input, string pattern) {\r
67                         return IsMatch (input, pattern, RegexOptions.None);\r
68                 }\r
69 \r
70                 public static bool IsMatch (string input, string pattern, RegexOptions options) {\r
71                         Regex re = new Regex (pattern, options);\r
72                         return re.IsMatch (input);\r
73                 }\r
74 \r
75                 public static Match Match (string input, string pattern) {\r
76                         return Regex.Match (input, pattern, RegexOptions.None);\r
77                 }\r
78 \r
79                 public static Match Match (string input, string pattern, RegexOptions options) {\r
80                         Regex re = new Regex (pattern, options);\r
81                         return re.Match (input);\r
82                 }\r
83 \r
84                 public static MatchCollection Matches (string input, string pattern) {\r
85                         return Matches (input, pattern, RegexOptions.None);\r
86                 }\r
87 \r
88                 public static MatchCollection Matches (string input, string pattern, RegexOptions options) {\r
89                         Regex re = new Regex (pattern, options);\r
90                         return re.Matches (input);\r
91                 }\r
92 \r
93                 public static string Replace\r
94                         (string input, string pattern, MatchEvaluator evaluator)\r
95                 {\r
96                         return Regex.Replace (input, pattern, evaluator, RegexOptions.None);\r
97                 }\r
98 \r
99                 public static string Replace\r
100                         (string input, string pattern, MatchEvaluator evaluator,\r
101                          RegexOptions options)\r
102                 {\r
103                         Regex re = new Regex (pattern, options);\r
104                         return re.Replace (input, evaluator);\r
105                 }\r
106 \r
107                 public static string Replace\r
108                         (string input, string pattern, string replacement)\r
109                 {\r
110                         return Regex.Replace (input, pattern, replacement, RegexOptions.None);\r
111                 }\r
112 \r
113                 public static string Replace\r
114                         (string input, string pattern, string replacement,\r
115                          RegexOptions options)\r
116                 {\r
117                         Regex re = new Regex (pattern, options);\r
118                         return re.Replace (input, replacement);\r
119                 }\r
120 \r
121                 public static string[] Split (string input, string pattern) {\r
122                         return Regex.Split (input, pattern, RegexOptions.None);\r
123                 }\r
124 \r
125                 public static string[] Split (string input, string pattern, RegexOptions options) {\r
126                         Regex re = new Regex (pattern, options);\r
127                         return re.Split (input);\r
128                 }\r
129 \r
130                 // private\r
131 \r
132                 private static FactoryCache cache = new FactoryCache (200);     // TODO put some meaningful number here\r
133 \r
134                 // constructors\r
135 \r
136                 protected Regex () {\r
137                         // XXX what's this constructor for?\r
138                 }\r
139 \r
140                 public Regex (string pattern) : this (pattern, RegexOptions.None) {\r
141                 }\r
142 \r
143                 public Regex (string pattern, RegexOptions options) {\r
144                         this.pattern = pattern;\r
145                         this.options = options;\r
146                 \r
147                         this.factory = cache.Lookup (pattern, options);\r
148 \r
149                         if (this.factory == null) {\r
150                                 // parse and install group mapping\r
151 \r
152                                 Parser psr = new Parser ();\r
153                                 RegularExpression re = psr.ParseRegularExpression (pattern, options);\r
154                                 this.group_count = re.GroupCount;\r
155                                 this.mapping = psr.GetMapping ();\r
156 \r
157                                 // compile\r
158                                 \r
159                                 ICompiler cmp;\r
160                                 //if ((options & RegexOptions.Compiled) != 0)\r
161                                 //      throw new Exception ("Not implemented.");\r
162                                         //cmp = new CILCompiler ();\r
163                                 //else\r
164                                         cmp = new PatternCompiler ();\r
165 \r
166                                 re.Compile (cmp, RightToLeft);\r
167 \r
168                                 // install machine factory and add to pattern cache\r
169 \r
170                                 this.factory = cmp.GetMachineFactory ();\r
171                                 this.factory.Mapping = mapping;\r
172                                 cache.Add (pattern, options, this.factory);\r
173                         } else {\r
174                                 this.group_count = this.factory.GroupCount;\r
175                                 this.mapping = this.factory.Mapping;\r
176                         }\r
177                 }\r
178 \r
179                 protected Regex (SerializationInfo info, StreamingContext context) :\r
180                         this (info.GetString ("pattern"), \r
181                               (RegexOptions) info.GetValue ("options", typeof (RegexOptions))) {                        \r
182                 }\r
183 \r
184 \r
185                 // public instance properties\r
186                 \r
187                 public RegexOptions Options {\r
188                         get { return options; }\r
189                 }\r
190 \r
191                 public bool RightToLeft {\r
192                         get { return (options & RegexOptions.RightToLeft) != 0; }\r
193                 }\r
194 \r
195                 // public instance methods\r
196                 \r
197                 public string[] GetGroupNames () {\r
198                         string[] names = new string[mapping.Count];\r
199                         mapping.Keys.CopyTo (names, 0);\r
200 \r
201                         return names;\r
202                 }\r
203 \r
204                 public int[] GetGroupNumbers () {\r
205                         int[] numbers = new int[mapping.Count];\r
206                         mapping.Values.CopyTo (numbers, 0);\r
207 \r
208                         return numbers;\r
209                 }\r
210 \r
211                 public string GroupNameFromNumber (int i) {\r
212                         if (i >= group_count)\r
213                                 return "";\r
214                 \r
215                         foreach (string name in mapping.Keys) {\r
216                                 if ((int)mapping[name] == i)\r
217                                         return name;\r
218                         }\r
219 \r
220                         return "";\r
221                 }\r
222 \r
223                 public int GroupNumberFromName (string name) {\r
224                         if (mapping.Contains (name))\r
225                                 return (int)mapping[name];\r
226 \r
227                         return -1;\r
228                 }\r
229 \r
230                 // match methods\r
231                 \r
232                 public bool IsMatch (string input) {\r
233                         return IsMatch (input, 0);\r
234                 }\r
235 \r
236                 public bool IsMatch (string input, int startat) {\r
237                         return Match (input, startat).Success;\r
238                 }\r
239 \r
240                 public Match Match (string input) {\r
241                         return Match (input, 0);\r
242                 }\r
243 \r
244                 public Match Match (string input, int startat) {\r
245                         return CreateMachine ().Scan (this, input, startat, input.Length);\r
246                 }\r
247 \r
248                 public Match Match (string input, int startat, int length) {\r
249                         return CreateMachine ().Scan (this, input, startat, startat + length);\r
250                 }\r
251 \r
252                 public MatchCollection Matches (string input) {\r
253                         return Matches (input, 0);\r
254                 }\r
255 \r
256                 public MatchCollection Matches (string input, int startat) {\r
257                         MatchCollection ms = new MatchCollection ();\r
258                         Match m = Match (input, startat);\r
259                         while (m.Success) {\r
260                                 ms.Add (m);\r
261                                 m = m.NextMatch ();\r
262                         }\r
263 \r
264                         return ms;\r
265                 }\r
266 \r
267                 // replace methods\r
268 \r
269                 public string Replace (string input, MatchEvaluator evaluator) {\r
270                         return Replace (input, evaluator, Int32.MaxValue, 0);\r
271                 }\r
272 \r
273                 public string Replace (string input, MatchEvaluator evaluator, int count) {\r
274                         return Replace (input, evaluator, count, 0);\r
275                 }\r
276 \r
277                 public string Replace (string input, MatchEvaluator evaluator, int count, int startat)\r
278                 {\r
279                         StringBuilder result = new StringBuilder ();\r
280                         int ptr = startat;\r
281 \r
282                         Match m = Match (input, startat);\r
283                         while (m.Success && count -- > 0) {\r
284                                 result.Append (input.Substring (ptr, m.Index - ptr));\r
285                                 result.Append (evaluator (m));\r
286 \r
287                                 ptr = m.Index + m.Length;\r
288                                 m = m.NextMatch ();\r
289                         }\r
290                         result.Append (input.Substring (ptr));\r
291 \r
292                         return result.ToString ();\r
293                 }\r
294 \r
295                 public string Replace (string input, string replacement) {\r
296                         return Replace (input, replacement, Int32.MaxValue, 0);\r
297                 }\r
298 \r
299                 public string Replace (string input, string replacement, int count) {\r
300                         return Replace (input, replacement, count, 0);\r
301                 }\r
302 \r
303                 public string Replace (string input, string replacement, int count, int startat) {\r
304                         ReplacementEvaluator ev = new ReplacementEvaluator (this, replacement);\r
305                         return Replace (input, new MatchEvaluator (ev.Evaluate), count, startat);\r
306                 }\r
307 \r
308                 // split methods\r
309 \r
310                 public string[] Split (string input) {\r
311                         return Split (input, Int32.MaxValue, 0);\r
312                 }\r
313 \r
314                 public string[] Split (string input, int count) {\r
315                         return Split (input, count, 0);\r
316                 }\r
317 \r
318                 public string[] Split (string input, int count, int startat) {\r
319                         ArrayList splits = new ArrayList ();\r
320                         if (count == 0)\r
321                                 count = Int32.MaxValue;\r
322 \r
323                         int ptr = startat;\r
324                         while (--count > 0) {\r
325                                 Match m = Match (input, ptr);\r
326                                 if (!m.Success)\r
327                                         break;\r
328                         \r
329                                 splits.Add (input.Substring (ptr, m.Index - ptr));\r
330                                 int gcount = m.Groups.Count;\r
331                                 for (int gindex = 1; gindex < gcount; gindex++) {\r
332                                         Group grp = m.Groups [gindex];\r
333                                         splits.Add (input.Substring (grp.Index, grp.Length));\r
334                                 }\r
335 \r
336                                 ptr = m.Index + m.Length;\r
337                         }\r
338 \r
339                         if (ptr < input.Length) {\r
340                                 splits.Add (input.Substring (ptr));\r
341                         }\r
342 \r
343                         return (string []) splits.ToArray (typeof (string));\r
344                 }\r
345 \r
346                 // object methods\r
347                 \r
348                 public override string ToString () {\r
349                         return pattern;\r
350                 }\r
351 \r
352                 // ISerializable interface\r
353                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context) {\r
354                         info.AddValue ("pattern", this.ToString (), typeof (string));\r
355                         info.AddValue ("options", this.Options, typeof (RegexOptions));\r
356                 }\r
357 \r
358                 // internal\r
359 \r
360                 internal int GroupCount {\r
361                         get { return group_count; }\r
362                 }\r
363 \r
364                 // private\r
365 \r
366                 private IMachine CreateMachine () {\r
367                         return factory.NewInstance ();\r
368                 }\r
369 \r
370                 protected internal string pattern;\r
371                 private RegexOptions options;\r
372 \r
373                 private IMachineFactory factory;\r
374                 private IDictionary mapping;\r
375                 private int group_count;\r
376         }\r
377 \r
378         [Serializable]\r
379         public class RegexCompilationInfo {\r
380                 public RegexCompilationInfo (string pattern, RegexOptions options, string name, string full_namespace, bool is_public) {\r
381                         this.pattern = pattern;\r
382                         this.options = options;\r
383                         this.name = name;\r
384                         this.full_namespace = full_namespace;\r
385                         this.is_public = is_public;\r
386                 }\r
387 \r
388                 public bool IsPublic {\r
389                         get { return is_public; }\r
390                         set { is_public = value; }\r
391                 }\r
392 \r
393                 public string Name {\r
394                         get { return name; }\r
395                         set { name = value; }\r
396                 }\r
397 \r
398                 public string Namespace {\r
399                         get { return full_namespace; }\r
400                         set { full_namespace = value; }\r
401                 }\r
402 \r
403                 public RegexOptions Options {\r
404                         get { return options; }\r
405                         set { options = value; }\r
406                 }\r
407 \r
408                 public string Pattern {\r
409                         get { return pattern; }\r
410                         set { pattern = value; }\r
411                 }\r
412 \r
413                 // private\r
414 \r
415                 private string pattern, name, full_namespace;\r
416                 private RegexOptions options;\r
417                 private bool is_public;\r
418         }\r
419 }\r