[System] Added NetworkCredential.SecurePassword.
[mono.git] / mcs / class / System / System.Collections.Generic / Queue.cs
1 //
2 // System.Collections.Generic.Queue
3 //
4 // Author:
5 //    Martin Baulig (martin@ximian.com)
6 //    Ben Maurer (bmaurer@ximian.com)
7 //
8 // (C) 2003, 2004 Novell, Inc.
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Runtime.InteropServices;
36 using System.Diagnostics;
37
38 namespace System.Collections.Generic
39 {
40         [ComVisible(false)]
41         [Serializable]
42         [DebuggerDisplay ("Count={Count}")]
43         [DebuggerTypeProxy (typeof (CollectionDebuggerView))]   
44         public class Queue<T> : IEnumerable <T>, ICollection, IEnumerable
45         {
46                 T [] _array;
47                 int _head;
48                 int _tail;
49                 int _size;
50                 int _version;
51                 
52                 public Queue ()
53                 {
54                         _array = new T [0];
55                 }
56                 
57                 public Queue (int capacity)
58                 {
59                         if (capacity < 0)
60                                 throw new ArgumentOutOfRangeException ("capacity");
61
62                         _array = new T [capacity];
63                 }
64                 
65                 public Queue (IEnumerable <T> collection)
66                 {
67                         if (collection == null)
68                                 throw new ArgumentNullException ("collection");
69
70                         var icoll = collection as ICollection<T>;
71                         var size = icoll != null ? icoll.Count : 0;
72
73                         _array = new T [size];
74
75                         foreach (T t in collection)
76                                 Enqueue (t);
77                 }
78                 
79                 public void Clear ()
80                 {
81                         Array.Clear (_array, 0, _array.Length);
82                         
83                         _head = _tail = _size = 0;
84                         _version++;
85                 }
86                 
87                 public bool Contains (T item)
88                 {
89                         if (item == null) {
90                                 foreach (T t in this)
91                                         if (t == null)
92                                                 return true;
93                         } else {
94                                 foreach (T t in this)
95                                         if (item.Equals (t))
96                                                 return true;
97                         }
98                         
99                         return false;
100                 }
101                 
102                 public void CopyTo (T [] array, int arrayIndex)
103                 {
104                         if (array == null)
105                                 throw new ArgumentNullException ();
106
107                         ((ICollection) this).CopyTo (array, arrayIndex);
108                 }
109                 
110                 void ICollection.CopyTo (Array array, int idx)
111                 {
112                         if (array == null)
113                                 throw new ArgumentNullException ();
114                         
115                         if ((uint) idx > (uint) array.Length)
116                                 throw new ArgumentOutOfRangeException ();
117                         
118                         if (array.Length - idx < _size)
119                                 throw new ArgumentOutOfRangeException ();
120                         
121                         if (_size == 0)
122                                 return;
123                         
124                         try {
125                                 int contents_length = _array.Length;
126                                 int length_from_head = contents_length - _head;
127                                 
128                                 Array.Copy (_array, _head, array, idx, Math.Min (_size, length_from_head));
129                                 if (_size > length_from_head)
130                                         Array.Copy (_array, 0, array, 
131                                                     idx  + length_from_head,
132                                                     _size - length_from_head);
133                         } catch (ArrayTypeMismatchException) {
134                                 throw new ArgumentException ();
135                         }
136                 }
137                 
138                 public T Dequeue ()
139                 {
140                         T ret = Peek ();
141                         
142                         // clear stuff out to make the GC happy
143                         _array [_head] = default (T);
144                         
145                         if (++_head == _array.Length)
146                                 _head = 0;
147                         _size --;
148                         _version ++;
149                         
150                         return ret;
151                 }
152                 
153                 public T Peek ()
154                 {
155                         if (_size == 0)
156                                 throw new InvalidOperationException ();
157                         
158                         return _array [_head];
159                 }
160                 
161                 public void Enqueue (T item)
162                 {
163                         if (_size == _array.Length || _tail == _array.Length)
164                                 SetCapacity (Math.Max (Math.Max (_size, _tail) * 2, 4));
165                         
166                         _array [_tail] = item;
167                         
168                         if (++_tail == _array.Length)
169                                 _tail = 0;
170                         
171                         _size ++;
172                         _version ++;
173                 }
174                 
175                 public T [] ToArray ()
176                 {
177                         T [] t = new T [_size];
178                         CopyTo (t, 0);
179                         return t;
180                 }
181
182                 public void TrimExcess ()
183                 {
184                         if (_size < _array.Length * 0.9)
185                                 SetCapacity (_size);
186                 }
187                 
188                 void SetCapacity (int new_size)
189                 {
190                         if (new_size == _array.Length)
191                                 return;
192                         
193                         if (new_size < _size)
194                                 throw new InvalidOperationException ("shouldnt happen");
195                         
196                         T [] new_data = new T [new_size];
197                         if (_size > 0)
198                                 CopyTo (new_data, 0);
199                         
200                         _array = new_data;
201                         _tail = _size;
202                         _head = 0;
203                         _version ++;
204                 }
205                 
206                 public int Count {
207                         get { return _size; }
208                 }
209                 
210                 bool ICollection.IsSynchronized {
211                         get { return false; }
212                 }
213                 
214                 object ICollection.SyncRoot {
215                         get { return this; }
216                 }
217                 
218                 public Enumerator GetEnumerator ()
219                 {
220                         return new Enumerator (this);
221                 }
222
223                 IEnumerator <T> IEnumerable<T>.GetEnumerator ()
224                 {
225                         return GetEnumerator ();
226                 }
227
228                 IEnumerator IEnumerable.GetEnumerator ()
229                 {
230                         return GetEnumerator ();
231                 }
232                 
233                 [Serializable]
234                 public struct Enumerator : IEnumerator <T>, IEnumerator, IDisposable {
235                         const int NOT_STARTED = -2;
236                         
237                         // this MUST be -1, because we depend on it in move next.
238                         // we just decr the _size, so, 0 - 1 == FINISHED
239                         const int FINISHED = -1;
240                         
241                         Queue <T> q;
242                         int idx;
243                         int ver;
244                         
245                         internal Enumerator (Queue <T> q)
246                         {
247                                 this.q = q;
248                                 idx = NOT_STARTED;
249                                 ver = q._version;
250                         }
251                         
252                         // for some fucked up reason, MSFT added a useless dispose to this class
253                         // It means that in foreach, we must still do a try/finally. Broken, very
254                         // broken.
255                         public void Dispose ()
256                         {
257                                 idx = NOT_STARTED;
258                         }
259                         
260                         public bool MoveNext ()
261                         {
262                                 if (ver != q._version)
263                                         throw new InvalidOperationException ();
264                                 
265                                 if (idx == NOT_STARTED)
266                                         idx = q._size;
267                                 
268                                 return idx != FINISHED && -- idx != FINISHED;
269                         }
270                         
271                         public T Current {
272                                 get {
273                                         if (idx < 0)
274                                                 throw new InvalidOperationException ();
275                                         
276                                         return q._array [(q._size - 1 - idx + q._head) % q._array.Length];
277                                 }
278                         }
279                         
280                         void IEnumerator.Reset ()
281                         {
282                                 if (ver != q._version)
283                                         throw new InvalidOperationException ();
284                                 
285                                 idx = NOT_STARTED;
286                         }
287                         
288                         object IEnumerator.Current {
289                                 get { return Current; }
290                         }
291                         
292                 }
293         }
294 }