2 // System.Collections.Stack
\r
5 // Garrett Rooney (rooneg@electricjellyfish.net)
\r
7 // (C) 2001 Garrett Rooney
\r
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
33 namespace System.Collections {
\r
35 [MonoTODO ("Fix serialization compatibility with MS.NET")]
\r
36 public class Stack : ICollection, IEnumerable, ICloneable {
\r
39 private object[] contents;
\r
40 private int current = -1;
\r
41 private int count = 0;
\r
42 private int capacity;
\r
43 private int modCount = 0;
\r
45 private void Resize(int ncapacity) {
47 ncapacity = Math.Max (ncapacity, 16);
\r
48 object[] ncontents = new object[ncapacity];
\r
50 Array.Copy(contents, ncontents, count);
\r
52 capacity = ncapacity;
\r
53 contents = ncontents;
\r
56 public Stack () : this (16) {}
\r
58 public Stack(ICollection col) : this (col == null ? 16 : col.Count) {
60 throw new ArgumentNullException("col");
62 current = col.Count - 1;
\r
65 col.CopyTo(contents, 0);
\r
68 public Stack (int initialCapacity) {
69 if (initialCapacity < 0)
70 throw new ArgumentOutOfRangeException ("initialCapacity");
72 capacity = Math.Max (initialCapacity, 16);
\r
73 contents = new object[capacity];
\r
77 private class SyncStack : Stack {
\r
81 internal SyncStack(Stack s) {
\r
85 public override int Count {
\r
88 return stack.Count;
\r
94 public override bool IsReadOnly {
\r
97 return stack.IsReadOnly;
\r
103 public override bool IsSynchronized {
\r
104 get { return true; }
\r
107 public override object SyncRoot {
\r
108 get { return stack.SyncRoot; }
\r
111 public override void Clear() {
\r
112 lock(stack) { stack.Clear(); }
\r
115 public override object Clone() {
\r
117 return Stack.Synchronized((Stack)stack.Clone());
\r
121 public override bool Contains(object obj) {
\r
122 lock (stack) { return stack.Contains(obj); }
\r
125 public override void CopyTo(Array array, int index) {
\r
126 lock (stack) { stack.CopyTo(array, index); }
\r
129 public override IEnumerator GetEnumerator() {
\r
131 return new Enumerator(stack);
\r
135 public override object Peek() {
\r
136 lock (stack) { return stack.Peek(); }
\r
139 public override object Pop() {
\r
140 lock (stack) { return stack.Pop(); }
\r
143 public override void Push(object obj) {
\r
144 lock (stack) { stack.Push(obj); }
\r
147 public override object[] ToArray() {
\r
148 lock (stack) { return stack.ToArray(); }
\r
152 public static Stack Synchronized(Stack s) {
\r
154 throw new ArgumentNullException();
\r
157 return new SyncStack(s);
\r
160 public virtual int Count {
\r
161 get { return count; }
\r
165 public virtual bool IsReadOnly {
\r
166 get { return false; }
\r
170 public virtual bool IsSynchronized {
\r
171 get { return false; }
\r
174 public virtual object SyncRoot {
\r
175 get { return this; }
\r
178 public virtual void Clear() {
\r
181 for (int i = 0; i < count; i++) {
\r
182 contents[i] = null;
\r
189 public virtual object Clone() {
\r
190 Stack stack = new Stack (contents);
\r
191 stack.current = current;
196 public virtual bool Contains(object obj) {
\r
201 for (int i = 0; i < count; i++) {
202 if (contents[i] == null)
206 for (int i = 0; i < count; i++) {
\r
207 if (contents[i].Equals(obj))
\r
215 public virtual void CopyTo (Array array, int index) {
\r
216 if (array == null) {
\r
217 throw new ArgumentNullException("array");
\r
221 throw new ArgumentOutOfRangeException("index");
\r
224 if (array.Rank > 1 ||
\r
225 index >= array.Length ||
\r
226 count > array.Length - index) {
\r
227 throw new ArgumentException();
\r
230 for (int i = current; i != -1; i--) {
\r
231 array.SetValue(contents[i],
\r
232 count - (i + 1) + index);
\r
236 private class Enumerator : IEnumerator, ICloneable {
239 const int BOF = -2;
\r
242 private int modCount;
\r
243 private int current;
\r
245 internal Enumerator(Stack s) {
\r
247 modCount = s.modCount;
251 public object Clone ()
253 return MemberwiseClone ();
256 public virtual object Current {
\r
258 if (modCount != stack.modCount
\r
261 || current > stack.count)
\r
262 throw new InvalidOperationException();
\r
263 return stack.contents[current];
\r
267 public virtual bool MoveNext() {
\r
268 if (modCount != stack.modCount)
\r
269 throw new InvalidOperationException();
273 current = stack.current;
274 return current != -1;
281 return current != -1;
285 public virtual void Reset() {
\r
286 if (modCount != stack.modCount) {
\r
287 throw new InvalidOperationException();
\r
294 public virtual IEnumerator GetEnumerator() {
\r
295 return new Enumerator(this);
\r
298 public virtual object Peek() {
\r
299 if (current == -1) {
\r
300 throw new InvalidOperationException();
\r
302 return contents[current];
\r
306 public virtual object Pop() {
\r
307 if (current == -1) {
\r
308 throw new InvalidOperationException();
\r
312 object ret = contents[current];
\r
313 contents [current] = null;
318 // if we're down to capacity/4, go back to a
\r
319 // lower array size. this should keep us from
\r
320 // sucking down huge amounts of memory when
\r
321 // putting large numbers of items in the Stack.
\r
322 // if we're lower than 16, don't bother, since
\r
323 // it will be more trouble than it's worth.
\r
324 if (count <= (capacity/4) && count > 16) {
\r
325 Resize(capacity/2);
\r
332 public virtual void Push(Object o) {
\r
335 if (capacity == count) {
\r
336 Resize(capacity * 2);
\r
342 contents[current] = o;
\r
345 public virtual object[] ToArray() {
\r
346 object[] ret = new object[count];
\r
348 Array.Copy(contents, ret, count);
\r
350 // ret needs to be in LIFO order
\r
351 Array.Reverse(ret);
\r