Sat Jan 5 15:56:54 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System.Collections / Stack.cs
1 //\r
2 // System.Collections.Stack\r
3 //\r
4 // Author:\r
5 //    Garrett Rooney (rooneg@electricjellyfish.net)\r
6 //\r
7 // (C) 2001 Garrett Rooney\r
8 //\r
9 \r
10 namespace System.Collections {\r
11 \r
12         public class Stack : ICollection, IEnumerable, ICloneable {\r
13 \r
14                 // properties\r
15                 private object[] contents;\r
16                 private int current = -1;\r
17                 private int count = 0;\r
18                 private int capacity = 16;\r
19                 private int modCount = 0;\r
20 \r
21                 private void Resize(int ncapacity) {\r
22                         object[] ncontents = new object[ncapacity];\r
23 \r
24                         Array.Copy(contents, ncontents, count);\r
25 \r
26                         capacity = ncapacity;\r
27                         contents = ncontents;\r
28                 }\r
29 \r
30                 public Stack() {\r
31                         contents = new object[capacity];\r
32                 }\r
33 \r
34                 public Stack(ICollection collection) {\r
35                         capacity = collection.Count;\r
36                         contents = new object[capacity];\r
37                         current = capacity - 1;\r
38                         count = capacity;\r
39 \r
40                         collection.CopyTo(contents, 0);\r
41                 }\r
42 \r
43                 public Stack(int c) {\r
44                         capacity = c;\r
45                         contents = new object[capacity];\r
46                 }\r
47 \r
48                 private class SyncStack : Stack {\r
49 \r
50                         Stack stack;\r
51 \r
52                         public SyncStack(Stack s) {\r
53                                 stack = s;\r
54                         }\r
55                         \r
56                         public override int Count {\r
57                                 get { \r
58                                         lock (stack) {\r
59                                                 return stack.Count; \r
60                                         }\r
61                                 }\r
62                         }\r
63                         \r
64                         public override bool IsReadOnly {\r
65                                 get { \r
66                                         lock (stack) {\r
67                                                 return stack.IsReadOnly; \r
68                                         }\r
69                                 }\r
70                         }\r
71                         \r
72                         public override bool IsSynchronized {\r
73                                 get { return true; }\r
74                         }\r
75                         \r
76                         public override object SyncRoot {\r
77                                 get { return stack.SyncRoot; }\r
78                         }\r
79 \r
80                         public override void Clear() {\r
81                                 lock(stack) { stack.Clear(); }\r
82                         }\r
83 \r
84                         public override object Clone() {\r
85                                 lock (stack) { \r
86                                         return Stack.Synchronized((Stack)stack.Clone()); \r
87                                 }\r
88                         }\r
89 \r
90                         public override bool Contains(object obj) {\r
91                                 lock (stack) { return stack.Contains(obj); }\r
92                         }\r
93 \r
94                         public override void CopyTo(Array array, int index) {\r
95                                 lock (stack) { stack.CopyTo(array, index); }\r
96                         }\r
97 \r
98                         public override IEnumerator GetEnumerator() {\r
99                                 lock (stack) { \r
100                                         return new Enumerator(stack); \r
101                                 }\r
102                         }\r
103 \r
104                         public override object Peek() {\r
105                                 lock (stack) { return stack.Peek(); }\r
106                         }\r
107 \r
108                         public override object Pop() {\r
109                                 lock (stack) { return stack.Pop(); }\r
110                         }\r
111 \r
112                         public override void Push(object obj) {\r
113                                 lock (stack) { stack.Push(obj); }\r
114                         }\r
115 \r
116                         public override object[] ToArray() {\r
117                                 lock (stack) { return stack.ToArray(); }\r
118                         }\r
119                 }\r
120 \r
121                 public static Stack Synchronized(Stack s) {\r
122                         if (s == null) {\r
123                                 throw new ArgumentNullException();\r
124                         }\r
125 \r
126                         return new SyncStack(s);\r
127                 }\r
128 \r
129                 public virtual int Count {\r
130                         get { return count; }\r
131                 }\r
132 \r
133                 public virtual bool IsReadOnly {\r
134                         get { return false; }\r
135                 }\r
136 \r
137                 public virtual bool IsSynchronized {\r
138                         get { return false; }\r
139                 }\r
140 \r
141                 public virtual object SyncRoot {\r
142                         get { return this; }\r
143                 }\r
144 \r
145                 public virtual void Clear() {\r
146                         modCount++;\r
147 \r
148                         for (int i = 0; i < count; i++) {\r
149                                 contents[i] = null;\r
150                         }\r
151 \r
152                         count = 0;\r
153                         current = -1;\r
154                 }\r
155 \r
156                 public virtual object Clone() {\r
157                         Stack stack;\r
158 \r
159                         stack = new Stack();\r
160 \r
161                         stack.current = current;\r
162                         stack.contents = contents;\r
163                         stack.count = count;\r
164                         stack.capacity = capacity;\r
165 \r
166                         return stack;\r
167                 }\r
168 \r
169                 public virtual bool Contains(object obj) {\r
170                         if (count == 0)\r
171                                 return false;\r
172 \r
173                         for (int i = 0; i < count; i++) {\r
174                                 if (contents[i].Equals(obj))\r
175                                         return true; \r
176                         }\r
177 \r
178                         return false;\r
179                 }\r
180 \r
181                 public virtual void CopyTo (Array array, int index) {\r
182                         if (array == null) {\r
183                                 throw new ArgumentNullException();\r
184                         }\r
185 \r
186                         if (index < 0) {\r
187                                 throw new ArgumentOutOfRangeException();\r
188                         }\r
189 \r
190                         if (array.Rank > 1 || \r
191                             index >= array.Length || \r
192                             count > array.Length - index) {\r
193                                 throw new ArgumentException();\r
194                         }\r
195 \r
196                         for (int i = current; i != -1; i--) {\r
197                                 array.SetValue(contents[i], \r
198                                                count - (i + 1) + index);\r
199                         }\r
200                 }\r
201 \r
202                 private class Enumerator : IEnumerator {\r
203 \r
204                         Stack stack;\r
205                         private int modCount;\r
206                         private int current;\r
207 \r
208                         internal Enumerator(Stack s) {\r
209                                 // this is odd.  it seems that you need to \r
210                                 // start one further ahead than current, since \r
211                                 // MoveNext() gets called first when using an \r
212                                 // Enumeration...\r
213                                 stack = s;\r
214                                 modCount = s.modCount;\r
215                                 current = s.current + 1;\r
216                         }\r
217 \r
218                         public virtual object Current {\r
219                                 get {\r
220                                         if (modCount != stack.modCount \r
221                                             || current == -1 \r
222                                             || current > stack.count)\r
223                                                 throw new InvalidOperationException();\r
224                                         return stack.contents[current];\r
225                                 }\r
226                         }\r
227 \r
228                         public virtual bool MoveNext() {\r
229                                 if (modCount != stack.modCount \r
230                                     || current == -1) {\r
231                                         throw new InvalidOperationException();\r
232                                 }\r
233 \r
234                                 current--;\r
235 \r
236                                 if (current == -1) {\r
237                                         return false;\r
238                                 } else {\r
239                                         return true;\r
240                                 }\r
241                         }\r
242 \r
243                         public virtual void Reset() {\r
244                                 if (modCount != stack.modCount) {\r
245                                         throw new InvalidOperationException();\r
246                                 }\r
247 \r
248                                 // start one ahead of stack.current, so the \r
249                                 // first MoveNext() will put us at the top\r
250                                 current = stack.current + 1;\r
251                         }\r
252                 }\r
253 \r
254                 public virtual IEnumerator GetEnumerator() {\r
255                         return new Enumerator(this);\r
256                 }\r
257 \r
258                 public virtual object Peek() {\r
259                         if (current == -1) {\r
260                                 throw new InvalidOperationException();\r
261                         } else {\r
262                                 return contents[current];\r
263                         }\r
264                 }\r
265 \r
266                 public virtual object Pop() {\r
267                         if (current == -1) {\r
268                                 throw new InvalidOperationException();\r
269                         } else {\r
270                                 modCount++;\r
271 \r
272                                 object ret = contents[current];\r
273                 \r
274                                 count--;\r
275                                 current--;\r
276 \r
277                                 // if we're down to capacity/4, go back to a \r
278                                 // lower array size.  this should keep us from \r
279                                 // sucking down huge amounts of memory when \r
280                                 // putting large numbers of items in the Stack.\r
281                                 // if we're lower than 16, don't bother, since \r
282                                 // it will be more trouble than it's worth.\r
283                                 if (count <= (capacity/4) && count > 16) {\r
284                                         Resize(capacity/2);\r
285                                 }\r
286 \r
287                                 return ret;\r
288                         }\r
289                 }\r
290 \r
291                 public virtual void Push(Object o) {\r
292                         modCount++;\r
293 \r
294                         if (capacity == count) {\r
295                                 Resize(capacity * 2);\r
296                         }\r
297 \r
298                         count++;\r
299                         current++;\r
300 \r
301                         contents[current] = o;\r
302                 }\r
303 \r
304                 public virtual object[] ToArray() {\r
305                         object[] ret = new object[count];\r
306 \r
307                         Array.Copy(contents, ret, count);\r
308 \r
309                         // ret needs to be in LIFO order\r
310                         Array.Reverse(ret);\r
311 \r
312                         return ret;\r
313                 }\r
314         }\r
315 }\r