2 // System.Collections.Stack
\r
5 // Garrett Rooney (rooneg@electricjellyfish.net)
\r
7 // (C) 2001 Garrett Rooney
\r
10 namespace System.Collections {
\r
13 public class Stack : ICollection, IEnumerable, ICloneable {
\r
16 private object[] contents;
\r
17 private int current = -1;
\r
18 private int count = 0;
\r
19 private int capacity;
\r
20 private int modCount = 0;
\r
22 private void Resize(int ncapacity) {
24 ncapacity = Math.Max (ncapacity, 16);
\r
25 object[] ncontents = new object[ncapacity];
\r
27 Array.Copy(contents, ncontents, count);
\r
29 capacity = ncapacity;
\r
30 contents = ncontents;
\r
33 public Stack () : this (16) {}
\r
35 public Stack(ICollection col) : this (col == null ? 16 : col.Count) {
37 throw new ArgumentNullException("col");
39 current = col.Count - 1;
\r
42 col.CopyTo(contents, 0);
\r
45 public Stack (int initialCapacity) {
46 if (initialCapacity < 0)
47 throw new ArgumentOutOfRangeException ("initialCapacity");
49 capacity = Math.Max (initialCapacity, 16);
\r
50 contents = new object[capacity];
\r
54 private class SyncStack : Stack {
\r
58 internal SyncStack(Stack s) {
\r
62 public override int Count {
\r
65 return stack.Count;
\r
71 public override bool IsReadOnly {
\r
74 return stack.IsReadOnly;
\r
80 public override bool IsSynchronized {
\r
81 get { return true; }
\r
84 public override object SyncRoot {
\r
85 get { return stack.SyncRoot; }
\r
88 public override void Clear() {
\r
89 lock(stack) { stack.Clear(); }
\r
92 public override object Clone() {
\r
94 return Stack.Synchronized((Stack)stack.Clone());
\r
98 public override bool Contains(object obj) {
\r
99 lock (stack) { return stack.Contains(obj); }
\r
102 public override void CopyTo(Array array, int index) {
\r
103 lock (stack) { stack.CopyTo(array, index); }
\r
106 public override IEnumerator GetEnumerator() {
\r
108 return new Enumerator(stack);
\r
112 public override object Peek() {
\r
113 lock (stack) { return stack.Peek(); }
\r
116 public override object Pop() {
\r
117 lock (stack) { return stack.Pop(); }
\r
120 public override void Push(object obj) {
\r
121 lock (stack) { stack.Push(obj); }
\r
124 public override object[] ToArray() {
\r
125 lock (stack) { return stack.ToArray(); }
\r
129 public static Stack Synchronized(Stack s) {
\r
131 throw new ArgumentNullException();
\r
134 return new SyncStack(s);
\r
137 public virtual int Count {
\r
138 get { return count; }
\r
142 public virtual bool IsReadOnly {
\r
143 get { return false; }
\r
147 public virtual bool IsSynchronized {
\r
148 get { return false; }
\r
151 public virtual object SyncRoot {
\r
152 get { return this; }
\r
155 public virtual void Clear() {
\r
158 for (int i = 0; i < count; i++) {
\r
159 contents[i] = null;
\r
166 public virtual object Clone() {
\r
167 Stack stack = new Stack (contents);
\r
168 stack.current = current;
173 public virtual bool Contains(object obj) {
\r
178 for (int i = 0; i < count; i++) {
179 if (contents[i] == null)
183 for (int i = 0; i < count; i++) {
\r
184 if (contents[i].Equals(obj))
\r
192 public virtual void CopyTo (Array array, int index) {
\r
193 if (array == null) {
\r
194 throw new ArgumentNullException("array");
\r
198 throw new ArgumentOutOfRangeException("index");
\r
201 if (array.Rank > 1 ||
\r
202 index >= array.Length ||
\r
203 count > array.Length - index) {
\r
204 throw new ArgumentException();
\r
207 for (int i = current; i != -1; i--) {
\r
208 array.SetValue(contents[i],
\r
209 count - (i + 1) + index);
\r
213 private class Enumerator : IEnumerator, ICloneable {
216 const int BOF = -2;
\r
219 private int modCount;
\r
220 private int current;
\r
222 internal Enumerator(Stack s) {
\r
224 modCount = s.modCount;
228 public object Clone ()
230 return MemberwiseClone ();
233 public virtual object Current {
\r
235 if (modCount != stack.modCount
\r
238 || current > stack.count)
\r
239 throw new InvalidOperationException();
\r
240 return stack.contents[current];
\r
244 public virtual bool MoveNext() {
\r
245 if (modCount != stack.modCount)
\r
246 throw new InvalidOperationException();
250 current = stack.current;
251 return current != -1;
258 return current != -1;
262 public virtual void Reset() {
\r
263 if (modCount != stack.modCount) {
\r
264 throw new InvalidOperationException();
\r
271 public virtual IEnumerator GetEnumerator() {
\r
272 return new Enumerator(this);
\r
275 public virtual object Peek() {
\r
276 if (current == -1) {
\r
277 throw new InvalidOperationException();
\r
279 return contents[current];
\r
283 public virtual object Pop() {
\r
284 if (current == -1) {
\r
285 throw new InvalidOperationException();
\r
289 object ret = contents[current];
\r
290 contents [current] = null;
295 // if we're down to capacity/4, go back to a
\r
296 // lower array size. this should keep us from
\r
297 // sucking down huge amounts of memory when
\r
298 // putting large numbers of items in the Stack.
\r
299 // if we're lower than 16, don't bother, since
\r
300 // it will be more trouble than it's worth.
\r
301 if (count <= (capacity/4) && count > 16) {
\r
302 Resize(capacity/2);
\r
309 public virtual void Push(Object o) {
\r
312 if (capacity == count) {
\r
313 Resize(capacity * 2);
\r
319 contents[current] = o;
\r
322 public virtual object[] ToArray() {
\r
323 object[] ret = new object[count];
\r
325 Array.Copy(contents, ret, count);
\r
327 // ret needs to be in LIFO order
\r
328 Array.Reverse(ret);
\r