unused var
[mcs.git] / class / System / System.Text.RegularExpressions / Regex.cs
blobdf5e086ac3b0186eeb8d948e851eb782c3d0c7ee
1 //
2 // assembly: System
3 // namespace: System.Text.RegularExpressions
4 // file: regex.cs
5 //
6 // author: Dan Lewis (dlewis@gmx.co.uk)
7 // (c) 2002
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.Text;
32 using System.Collections;
33 using System.Reflection;
34 using System.Reflection.Emit;
35 using System.Runtime.Serialization;
37 using RegularExpression = System.Text.RegularExpressions.Syntax.RegularExpression;
38 using Parser = System.Text.RegularExpressions.Syntax.Parser;
40 using System.Diagnostics;
43 namespace System.Text.RegularExpressions {
45 [Serializable]
46 public partial class Regex : ISerializable {
48 #if !TARGET_JVM
49 [MonoTODO]
50 public static void CompileToAssembly (RegexCompilationInfo [] regexes, AssemblyName aname)
52 Regex.CompileToAssembly(regexes, aname, new CustomAttributeBuilder [] {}, null);
55 [MonoTODO]
56 public static void CompileToAssembly (RegexCompilationInfo [] regexes, AssemblyName aname,
57 CustomAttributeBuilder [] attribs)
59 Regex.CompileToAssembly(regexes, aname, attribs, null);
62 [MonoTODO]
63 public static void CompileToAssembly (RegexCompilationInfo [] regexes, AssemblyName aname,
64 CustomAttributeBuilder [] attribs, string resourceFile)
66 throw new NotImplementedException ();
67 // TODO : Make use of attribs and resourceFile parameters
69 AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.RunAndSave);
70 ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("InnerRegexModule",aname.Name);
71 Parser psr = new Parser ();
73 System.Console.WriteLine("CompileToAssembly");
75 for(int i=0; i < regexes.Length; i++)
77 System.Console.WriteLine("Compiling expression :" + regexes[i].Pattern);
78 RegularExpression re = psr.ParseRegularExpression (regexes[i].Pattern, regexes[i].Options);
80 // compile
82 CILCompiler cmp = new CILCompiler (modBuilder, i);
83 bool reverse = (regexes[i].Options & RegexOptions.RightToLeft) !=0;
84 re.Compile (cmp, reverse);
85 cmp.Close();
90 // Define a runtime class with specified name and attributes.
91 TypeBuilder builder = modBuilder.DefineType("ITest");
92 builder.CreateType();
93 asmBuilder.Save(aname.Name);
96 #endif
98 public static string Escape (string str)
100 return Parser.Escape (str);
103 public static string Unescape (string str)
105 return Parser.Unescape (str);
108 public static bool IsMatch (string input, string pattern)
110 return IsMatch (input, pattern, RegexOptions.None);
113 public static bool IsMatch (string input, string pattern, RegexOptions options)
115 Regex re = new Regex (pattern, options);
116 return re.IsMatch (input);
119 public static Match Match (string input, string pattern)
121 return Regex.Match (input, pattern, RegexOptions.None);
124 public static Match Match (string input, string pattern, RegexOptions options)
126 Regex re = new Regex (pattern, options);
127 return re.Match (input);
130 public static MatchCollection Matches (string input, string pattern)
132 return Matches (input, pattern, RegexOptions.None);
135 public static MatchCollection Matches (string input, string pattern, RegexOptions options)
137 Regex re = new Regex (pattern, options);
138 return re.Matches (input);
141 public static string Replace (string input, string pattern, MatchEvaluator evaluator)
143 return Regex.Replace (input, pattern, evaluator, RegexOptions.None);
146 public static string Replace (string input, string pattern, MatchEvaluator evaluator,
147 RegexOptions options)
149 Regex re = new Regex (pattern, options);
150 return re.Replace (input, evaluator);
153 public static string Replace (string input, string pattern, string replacement)
155 return Regex.Replace (input, pattern, replacement, RegexOptions.None);
158 public static string Replace (string input, string pattern, string replacement,
159 RegexOptions options)
161 Regex re = new Regex (pattern, options);
162 return re.Replace (input, replacement);
165 public static string [] Split (string input, string pattern)
167 return Regex.Split (input, pattern, RegexOptions.None);
170 public static string [] Split (string input, string pattern, RegexOptions options)
172 Regex re = new Regex (pattern, options);
173 return re.Split (input);
176 #if NET_2_0
177 static FactoryCache cache = new FactoryCache (15);
178 public static int CacheSize {
179 get { return cache.Capacity; }
180 set {
181 if (value < 0)
182 throw new ArgumentOutOfRangeException ("CacheSize");
184 cache.Capacity = value;
187 #else
188 static FactoryCache cache = new FactoryCache (200);
189 #endif
191 // private
194 // constructors
196 // This constructor is used by compiled regular expressions that are
197 // classes derived from Regex class. No initialization required.
198 protected Regex ()
202 public Regex (string pattern) : this (pattern, RegexOptions.None)
206 public Regex (string pattern, RegexOptions options)
208 this.pattern = pattern;
209 this.roptions = options;
210 Init ();
212 #if !TARGET_JVM
213 private void Init ()
215 this.machineFactory = cache.Lookup (this.pattern, this.roptions);
217 if (this.machineFactory == null) {
218 InitNewRegex();
219 } else {
220 this.group_count = this.machineFactory.GroupCount;
221 this.mapping = this.machineFactory.Mapping;
222 this._groupNumberToNameMap = this.machineFactory.NamesMapping;
225 #endif
227 private void InitNewRegex ()
229 this.machineFactory = CreateMachineFactory (this.pattern, this.roptions);
230 cache.Add (this.pattern, this.roptions, this.machineFactory);
231 this.group_count = machineFactory.GroupCount;
232 this.mapping = machineFactory.Mapping;
233 this._groupNumberToNameMap = this.machineFactory.NamesMapping;
236 // The new rx engine has blocking bugs like
237 // https://bugzilla.novell.com/show_bug.cgi?id=470827
238 static readonly bool old_rx =
239 #if !NET_2_1
240 Environment.GetEnvironmentVariable ("MONO_NEW_RX") == null;
241 #else
242 true;
243 #endif
245 private static IMachineFactory CreateMachineFactory (string pattern, RegexOptions options)
247 Parser psr = new Parser ();
248 RegularExpression re = psr.ParseRegularExpression (pattern, options);
250 ICompiler cmp;
251 if (!old_rx) {
252 if ((options & RegexOptions.Compiled) != 0)
253 cmp = new CILCompiler ();
254 else
255 cmp = new RxCompiler ();
256 } else {
257 cmp = new PatternCompiler ();
260 re.Compile (cmp, (options & RegexOptions.RightToLeft) != 0);
262 IMachineFactory machineFactory = cmp.GetMachineFactory ();
263 machineFactory.Mapping = psr.GetMapping ();
264 machineFactory.NamesMapping = GetGroupNamesArray (machineFactory.GroupCount, machineFactory.Mapping);
266 return machineFactory;
269 #if NET_2_0
270 protected
271 #else
272 private
273 #endif
274 Regex (SerializationInfo info, StreamingContext context) :
275 this (info.GetString ("pattern"),
276 (RegexOptions) info.GetValue ("options", typeof (RegexOptions)))
280 #if ONLY_1_1 && !TARGET_JVM
281 // fixes public API signature
282 ~Regex ()
285 #endif
286 // public instance properties
288 public RegexOptions Options {
289 get { return roptions; }
292 public bool RightToLeft {
293 get { return (roptions & RegexOptions.RightToLeft) != 0; }
296 // public instance methods
298 public string [] GetGroupNames ()
300 string [] names = new string [mapping.Count];
301 mapping.Keys.CopyTo (names, 0);
303 return names;
306 public int[] GetGroupNumbers ()
308 int[] numbers = new int [mapping.Count];
309 mapping.Values.CopyTo (numbers, 0);
311 return numbers;
314 public string GroupNameFromNumber (int i)
316 if (i < 0 || i > group_count)
317 return "";
319 return _groupNumberToNameMap [i];
322 public int GroupNumberFromName (string name)
324 if (mapping.Contains (name))
325 return (int) mapping [name];
327 return -1;
330 // match methods
332 public bool IsMatch (string input)
334 return IsMatch (input, RightToLeft ? input.Length : 0);
337 public bool IsMatch (string input, int startat)
339 return Match (input, startat).Success;
342 public Match Match (string input)
344 return Match (input, RightToLeft ? input.Length : 0);
347 public Match Match (string input, int startat)
349 return CreateMachine ().Scan (this, input, startat, input.Length);
352 public Match Match (string input, int startat, int length)
354 return CreateMachine ().Scan (this, input, startat, startat + length);
357 public MatchCollection Matches (string input)
359 return Matches (input, RightToLeft ? input.Length : 0);
362 public MatchCollection Matches (string input, int startat)
364 Match m = Match (input, startat);
365 return new MatchCollection (m);
368 // replace methods
370 public string Replace (string input, MatchEvaluator evaluator)
372 return Replace (input, evaluator, Int32.MaxValue, RightToLeft ? input.Length : 0);
375 public string Replace (string input, MatchEvaluator evaluator, int count)
377 return Replace (input, evaluator, count, RightToLeft ? input.Length : 0);
380 class Adapter {
381 MatchEvaluator ev;
382 public Adapter (MatchEvaluator ev) { this.ev = ev; }
383 public void Evaluate (Match m, StringBuilder sb) { sb.Append (ev (m)); }
386 public string Replace (string input, MatchEvaluator evaluator, int count, int startat)
388 if (input == null)
389 throw new ArgumentNullException ("null");
390 if (evaluator == null)
391 throw new ArgumentNullException ("evaluator");
393 BaseMachine m = (BaseMachine)CreateMachine ();
395 if (RightToLeft)
396 return m.RTLReplace (this, input, evaluator, count, startat);
398 // NOTE: If this is a cause of a lot of allocations, we can convert it to
399 // use a ThreadStatic allocation mitigator
400 Adapter a = new Adapter (evaluator);
402 return m.LTRReplace (this, input, new BaseMachine.MatchAppendEvaluator (a.Evaluate),
403 count, startat);
406 public string Replace (string input, string replacement)
408 return Replace (input, replacement, Int32.MaxValue, RightToLeft ? input.Length : 0);
411 public string Replace (string input, string replacement, int count)
413 return Replace (input, replacement, count, RightToLeft ? input.Length : 0);
416 public string Replace (string input, string replacement, int count, int startat)
418 return CreateMachine ().Replace (this, input, replacement, count, startat);
421 // split methods
423 public string [] Split (string input)
425 return Split (input, Int32.MaxValue, RightToLeft ? input.Length : 0);
428 public string [] Split (string input, int count)
430 return Split (input, count, RightToLeft ? input.Length : 0);
433 public string [] Split (string input, int count, int startat)
435 return CreateMachine ().Split (this, input, count, startat);
438 // This method is called at the end of the constructor of compiled
439 // regular expression classes to do internal initialization.
440 protected void InitializeReferences ()
442 if (refsInitialized)
443 throw new NotSupportedException ("This operation is only allowed once per object.");
445 refsInitialized = true;
447 // Compile pattern that results in performance loss as existing
448 // CIL code is ignored but provides support for regular
449 // expressions compiled to assemblies.
450 Init ();
453 protected bool UseOptionC ()
455 return ((roptions & RegexOptions.Compiled) != 0);
458 protected bool UseOptionR ()
460 return ((roptions & RegexOptions.RightToLeft) != 0);
463 // object methods
465 public override string ToString ()
467 return pattern;
470 // ISerializable interface
471 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
473 info.AddValue ("pattern", this.ToString (), typeof (string));
474 info.AddValue ("options", this.Options, typeof (RegexOptions));
477 // internal
479 internal int GroupCount {
480 get { return group_count; }
483 // private
485 private IMachine CreateMachine ()
487 return machineFactory.NewInstance ();
490 private static string [] GetGroupNamesArray (int groupCount, IDictionary mapping)
492 string [] groupNumberToNameMap = new string [groupCount + 1];
493 foreach (string name in mapping.Keys) {
494 groupNumberToNameMap [(int) mapping [name]] = name;
496 return groupNumberToNameMap;
499 private IMachineFactory machineFactory;
500 private IDictionary mapping;
501 private int group_count;
502 private bool refsInitialized;
503 private string [] _groupNumberToNameMap;
506 // protected members
508 protected internal string pattern;
509 protected internal RegexOptions roptions;
511 // MS undocumented members
512 #if NET_2_1
513 [MonoTODO]
514 protected internal System.Collections.Generic.Dictionary<string, int> capnames;
515 [MonoTODO]
516 protected internal System.Collections.Generic.Dictionary<int, int> caps;
517 #else
518 [MonoTODO]
519 protected internal System.Collections.Hashtable capnames;
520 [MonoTODO]
521 protected internal System.Collections.Hashtable caps;
522 #endif
523 [MonoTODO]
524 protected internal int capsize;
525 [MonoTODO]
526 protected internal string [] capslist;
527 [MonoTODO]
528 protected internal RegexRunnerFactory factory;