Implement MachineKey.Protect and MachineKey.Unprotect
[mono.git] / mcs / class / System / System.Text.RegularExpressions / MatchCollection.cs
1 //
2 // System.Text.RegularExpressions.MatchCollection
3 //
4 // Authors:
5 //      Dan Lewis (dlewis@gmx.co.uk)
6 //      Dick Porter (dick@ximian.com)
7 //
8 // (C) 2002 Dan Lewis
9 // (C) 2004 Novell, Inc.
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Collections;
35
36 namespace System.Text.RegularExpressions
37 {
38         [Serializable]
39         public class MatchCollection: ICollection, IEnumerable {
40                 private Match current;
41
42                 // Stores all the matches before 'current'.  If !current.Success, it has all the successful matches.
43                 private ArrayList list;
44
45                 /* No public constructor */
46                 internal MatchCollection (Match start)
47                 {
48                         current = start;
49                         list = new ArrayList ();
50                 }
51
52                 public int Count {
53                         get { return FullList.Count; }
54                 }
55
56                 public bool IsReadOnly {
57                         get { return true; }
58                 }
59
60                 public bool IsSynchronized {
61                         get { return false; }
62                 }
63
64
65                 public virtual Match this [int i] {
66                         get {
67                                 if (i < 0 || !TryToGet (i))
68                                         throw new ArgumentOutOfRangeException ("i");
69                                 return i < list.Count ? (Match) list [i] : current;
70                         }
71                 }
72
73                 public object SyncRoot {
74                         get { return list; }
75                 }
76
77                 public void CopyTo (Array array, int arrayIndex)
78                 {
79                         FullList.CopyTo (array, arrayIndex);
80                 }
81
82                 public IEnumerator GetEnumerator ()
83                 {
84                         // If !current.Success, the list is fully populated.  So, just use it.
85                         return current.Success ? new Enumerator (this) : list.GetEnumerator ();
86                 }
87
88                 // Returns true when: i < list.Count                     => this [i] == list [i]
89                 //                    i == list.Count && current.Success => this [i] == current
90                 private bool TryToGet (int i)
91                 {
92                         while (i > list.Count && current.Success) {
93                                 list.Add (current);
94                                 current = current.NextMatch ();
95                         }
96                         // Here we have: !(i > list.Count && current.Success)
97                         // or in a slightly more useful form: i > list.Count => current.Success == false
98                         return i < list.Count || current.Success;
99                 }
100
101                 private ICollection FullList {
102                         get {
103                                 if (TryToGet (Int32.MaxValue)) {
104                                         // list.Count == Int32.MaxValue && current.Success
105                                         // i.e., we have more than Int32.MaxValue matches.
106                                         // We can't represent that number with Int32.
107                                         throw new SystemException ("too many matches");
108                                 }
109                                 return list;
110                         }
111                 }
112
113                 class Enumerator : IEnumerator {
114                         int index;
115                         MatchCollection coll;
116
117                         internal Enumerator (MatchCollection coll)
118                         {
119                                 this.coll = coll;
120                                 index = -1;
121                         }
122
123                         void IEnumerator.Reset ()
124                         {
125                                 index = -1;
126                         }
127
128                         object IEnumerator.Current {
129                                 get {
130                                         if (index < 0)
131                                                 throw new InvalidOperationException ("'Current' called before 'MoveNext()'");
132                                         if (index > coll.list.Count)
133                                                 throw new SystemException ("MatchCollection in invalid state");
134                                         if (index == coll.list.Count && !coll.current.Success)
135                                                 throw new InvalidOperationException ("'Current' called after 'MoveNext()' returned false");
136                                         return index < coll.list.Count ? coll.list [index] : coll.current;
137                                 }
138                         }
139
140                         bool IEnumerator.MoveNext ()
141                         {
142                                 if (index > coll.list.Count)
143                                         throw new SystemException ("MatchCollection in invalid state");
144                                 if (index == coll.list.Count && !coll.current.Success)
145                                         return false;
146                                 return coll.TryToGet (++index);
147                         }
148                 }
149         }
150 }