added missing [Serializable] attribute
[mono.git] / mcs / class / System / System.Text.RegularExpressions / match.cs
1 //\r
2 // assembly:    System\r
3 // namespace:   System.Text.RegularExpressions\r
4 // file:        match.cs\r
5 //\r
6 // author:      Dan Lewis (dlewis@gmx.co.uk)\r
7 //              (c) 2002\r
8 \r
9 using System;\r
10 \r
11 namespace System.Text.RegularExpressions {\r
12 \r
13         [Serializable]\r
14         public class Capture {\r
15                 public int Index {\r
16                         get {\r
17                                 if (!IsDefined)\r
18                                         return 0;               // capture not completed\r
19                                 else if (start <= end)\r
20                                         return start;           // normal capture\r
21                                 else\r
22                                         return end;             // reverse capture\r
23                         }\r
24                 }\r
25 \r
26                 public int Length {\r
27                         get {\r
28                                 if (!IsDefined)\r
29                                         return 0;\r
30                                 else if (start <= end)\r
31                                         return end - start;\r
32                                 else\r
33                                         return start - end;\r
34                         }\r
35                 }\r
36 \r
37                 public string Value {\r
38                         get { return IsDefined ? text.Substring (Index, Length) : ""; }\r
39                 }\r
40 \r
41                 public override string ToString () {\r
42                         return Value;\r
43                 }\r
44 \r
45                 // internal members\r
46 \r
47                 internal Capture () {                   // empty capture\r
48                         this.previous = null;\r
49                         this.text = null;\r
50                         this.checkpoint = 0;\r
51 \r
52                         this.start = -1;\r
53                         this.end = -1;\r
54                 }\r
55 \r
56                 internal Capture (Capture cap) {        // copy constructor\r
57                         this.previous = cap.previous;\r
58                         this.text = cap.text;\r
59                         this.checkpoint = cap.checkpoint;\r
60 \r
61                         this.start = cap.start;\r
62                         this.end = cap.end;\r
63                 }\r
64 \r
65                 internal Capture (string text) {        // first capture\r
66                         this.previous = null;\r
67                         this.text = text;\r
68                         this.checkpoint = 0;\r
69 \r
70                         this.start = -1;\r
71                         this.end = -1;\r
72                 }\r
73                 \r
74                 internal Capture (Capture previous, int checkpoint) {\r
75                         this.previous = previous;\r
76                         this.text = previous.text;\r
77                         this.checkpoint = checkpoint;\r
78 \r
79                         this.start = -1;\r
80                         this.end = -1;\r
81                 }\r
82 \r
83                 internal Capture Previous {\r
84                         get { return previous; }\r
85                 }\r
86 \r
87                 internal string Text {\r
88                         get { return text; }\r
89                 }\r
90 \r
91                 internal int Checkpoint {\r
92                         get { return checkpoint; }\r
93                 }\r
94 \r
95                 internal bool IsDefined {\r
96                         get { return start >= 0 && end >= 0; }\r
97                 }\r
98 \r
99                 internal Capture GetLastDefined () {\r
100                         Capture cap = this;\r
101                         while (cap != null && !cap.IsDefined)\r
102                                 cap = cap.Previous;\r
103 \r
104                         return cap;\r
105                 }\r
106 \r
107                 internal void Open (int ptr) {\r
108                         this.start = ptr;\r
109                 }\r
110 \r
111                 internal void Close (int ptr) {\r
112                         this.end = ptr;\r
113                 }\r
114 \r
115                 // private\r
116 \r
117                 private int start, end;\r
118                 private string text;\r
119                 private int checkpoint;\r
120                 private Capture previous;\r
121         }\r
122 \r
123         public class Group : Capture {\r
124                 public static Group Synchronized (Group inner) {\r
125                         return inner;   // is this enough?\r
126                 }\r
127 \r
128                 public CaptureCollection Captures {\r
129                         get { return captures; }\r
130                 }\r
131 \r
132                 public bool Success {\r
133                         get { return GetLastDefined () != null; }\r
134                 }\r
135 \r
136                 // internal\r
137 \r
138                 internal Group () : base () {\r
139                 }\r
140                 \r
141                 internal Group (Capture last) : base (last) {\r
142                         captures = new CaptureCollection (last);\r
143 \r
144                         // TODO make construction of captures lazy\r
145                 }\r
146 \r
147                 private CaptureCollection captures;\r
148         }\r
149 \r
150         public class Match : Group {\r
151                 public static Match Empty {\r
152                         get { return empty; }\r
153                 }\r
154                 \r
155                 public static Match Synchronized (Match inner) {\r
156                         return inner;   // FIXME need to sync on machine access\r
157                 }\r
158                 \r
159                 public GroupCollection Groups {\r
160                         get { return groups; }\r
161                 }\r
162 \r
163                 public Match NextMatch () {\r
164                         if (this == Empty)\r
165                                 return Empty;\r
166 \r
167                         int scan_ptr = regex.RightToLeft ? Index : Index + Length;\r
168 \r
169                         // next match after an empty match: make sure scan ptr makes progress\r
170                         \r
171                         if (Length == 0)\r
172                                 scan_ptr += regex.RightToLeft ? -1 : +1;\r
173 \r
174                         return machine.Scan (regex, Text, scan_ptr, text_length);\r
175                 }\r
176 \r
177                 public virtual string Result (string replacement) {\r
178                         return ReplacementEvaluator.Evaluate (replacement, this);\r
179                 }\r
180 \r
181                 // internal\r
182 \r
183                 internal Match () : base () {\r
184                         this.regex = null;\r
185                         this.machine = null;\r
186                         this.text_length = 0;\r
187                         this.groups = new GroupCollection ();\r
188 \r
189                         groups.Add (this);\r
190                 }\r
191                 \r
192                 internal Match (Regex regex, IMachine machine, int text_length, Capture[] captures) : base (captures[0]) {\r
193                         this.regex = regex;\r
194                         this.machine = machine;\r
195                         this.text_length = text_length;\r
196                         this.groups = new GroupCollection ();\r
197 \r
198                         groups.Add (this);\r
199                         for (int i = 1; i < captures.Length; ++ i)\r
200                                 groups.Add (new Group (captures[i]));\r
201                 }\r
202 \r
203                 internal Regex Regex {\r
204                         get { return regex; }\r
205                 }\r
206 \r
207                 // private\r
208 \r
209                 private Regex regex;\r
210                 private IMachine machine;\r
211                 private int text_length;\r
212                 private GroupCollection groups;\r
213 \r
214                 private static Match empty = new Match ();\r
215         }\r
216 }\r