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