现在的位置: 首页 > 综合 > 正文

Regex.cs

2012年10月03日 ⁄ 综合 ⁄ 共 8657字 ⁄ 字号 评论关闭
//------------------------------------------------------------------------------
// <copyright file="Regex.cs" company="Microsoft">
//     
//      Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
//     
//      The use and distribution terms for this software are contained in the file
//      named license.txt, which can be found in the root of this distribution.
//      By using this software in any fashion, you are agreeing to be bound by the
//      terms of this license.
//     
//      You must not remove this notice, or any other, from this software.
//     
// </copyright>                                                                
//------------------------------------------------------------------------------

// The Regex class represents a single compiled instance of a regular
// expression.
//
#define ECMA

namespace System.Text.RegularExpressions {

    
using System;
    
using System.Threading;
    
using System.Collections;
    
using System.Runtime.Serialization;
    
using System.Reflection;
    
using System.Reflection.Emit;
    
using System.Globalization;

    
/// <include file='doc\Regex.uex' path='docs/doc[@for="Regex"]/*' />
    
/// <devdoc>
    
///    <para>
    
///       Represents an immutable, compiled regular expression. Also
    
///       contains static methods that allow use of regular expressions without instantiating
    
///       a Regex explicitly.
    
///    </para>
    
/// </devdoc>

    [ Serializable() ] 
    
public class Regex : ISerializable {

        
// Fields used by precompiled regexes
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.pattern"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal string pattern;
        
/// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.factory"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal RegexRunnerFactory factory;       // if compiled, this is the RegexRunner subclass
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.roptions"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal RegexOptions roptions;            // the top-level options from the options string
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.caps"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal Hashtable caps;                   // if captures are sparse, this is the hashtable capnum->index
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.capnames"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal Hashtable capnames;               // if named captures are used, this maps names->index
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.capslist"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal String[]  capslist;               // if captures are sparse or named captures are used, this is the sorted list of names
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.capsize"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        protected internal int       capsize;                // the size of the capture array

        
internal  ExclusiveReference runnerref;              // cached runner
        internal  SharedReference    replref;                // cached parsed replacement pattern
        internal  RegexCode          code;                   // if interpreted, this is the code for RegexIntepreter
        internal  CachedCodeEntry    cachedentry;
        
internal  bool refsInitialized = false;

        
internal static Hashtable livecode = new Hashtable();// the cached of code and factories that are currently loaded

        
internal const int MaxOptionShift = 10;

        
/// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.Regex2"]/*' />
        protected Regex() {
        }


        
// Compiles and returns a Regex object corresponding to the given pattern
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.Regex"]/*' />
        
/// <devdoc>
        
///    <para>
        
///       Creates and compiles a regular expression object for the specified regular
        
///       expression.
        
///    </para>
        
/// </devdoc>

        public Regex(String pattern) : this(pattern, RegexOptions.None) {
        }


        
// Returns a Regex object corresponding to the given pattern, compiled with
        
// the specified options.
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.Regex1"]/*' />
        
/// <devdoc>
        
///    <para>
        
///       Creates and compiles a regular expression object for the
        
///       specified regular expression
        
///       with options that modify the pattern.
        
///    </para>
        
/// </devdoc>

        public Regex(String pattern, RegexOptions options) {
            RegexTree tree;
            CachedCodeEntry cached;

            
if (pattern == null
                
throw new ArgumentNullException("pattern");


            
if (options < RegexOptions.None || ( ((int) options) >> MaxOptionShift) != 0)
                
throw new ArgumentOutOfRangeException("options");
            
if ((options &   RegexOptions.ECMAScript) != 0
             
&& (options & ~(RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled
#if DBG
                           
| RegexOptions.Debug
#endif
                                               )) 
!= 0)
                
throw new ArgumentOutOfRangeException("options");

            String key 
= ((int) options).ToString(NumberFormatInfo.InvariantInfo) + ":" + pattern;

            cached 
= LookupCached(key);

            
this.pattern = pattern;
            
this.roptions = options;

            
if (cached == null{
                
// Parse the input
                tree = RegexParser.Parse(pattern, roptions);

                
// Extract the relevant information
                capnames   = tree._capnames;
                capslist   
= tree._capslist;
                code       
= RegexWriter.Write(tree);
                caps       
= code._caps;
                capsize    
= code._capsize;

                InitializeReferences();

                tree 
= null;
                cachedentry
= CacheCode(key);
            }

            
else {
                caps       
= cached._caps;
                capnames   
= cached._capnames;
                capslist   
= cached._capslist;
                capsize    
= cached._capsize;
                code       
= cached._code;
                factory    
= cached._factory;
                runnerref  
= cached._runnerref;
                replref    
= cached._replref;
                refsInitialized 
= true;

                cachedentry     
= cached;
            }


            
// if the compile option is set, then compile the code if it's not already
            if (UseOptionC() && factory == null{
                factory 
= Compile(code, roptions);
                cachedentry.AddCompiled(factory);
                code 
= null;
            }

        }


        
//  ISerializable constructor
        private Regex(SerializationInfo info, StreamingContext context) : this(info.GetString("pattern"), (RegexOptions) info.GetInt32("options")) {
        }


        
//  ISerializable method
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.ISerializable.GetObjectData"]/*' />
        
/// <internalonly/>

        void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) {
            si.AddValue(
"pattern"this.ToString());
            si.AddValue(
"options"this.Options);
        }


       
// This method is here for perf reasons: if the call to RegexCompiler is NOT in the 
       
// Regex constructor, we don't load RegexCompiler and its reflection classes when
       
// instantiating a non-compiled regex
       
// This method is internal virtual so the jit does not inline it.
        internal virtual RegexRunnerFactory Compile(RegexCode code, RegexOptions roptions) {
            
return RegexCompiler.Compile(code, roptions);
        }


        
// No refs -> we can release our ref on the cached code
        /// <include file='doc\Regex.uex' path='docs/doc[@for="Regex.Finalize"]/*' />
        
/// <devdoc>
        
///    <para>[To be supplied.]</para>
        
/// </devdoc>

        ~Regex() {
            UncacheCode();
        }


        
// Escape metacharacters within the string

抱歉!评论已关闭.