eol style
[mono.git] / mcs / class / corlib / System.Collections / Stack.cs
index 70470935094819559c3bfb1cea2a053ce2a8ce2a..9bc997e51adbd78cd903b69603b45ce16019a9a6 100644 (file)
@@ -1,4 +1,3 @@
-// -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*-
 //
 // System.Collections.Stack
 //
@@ -8,18 +7,44 @@
 // (C) 2001 Garrett Rooney
 //
 
-namespace System.Collections {
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
 
+namespace System.Collections {
+       [Serializable]
+       [MonoTODO ("Fix serialization compatibility with MS.NET")]
        public class Stack : ICollection, IEnumerable, ICloneable {
 
                // properties
                private object[] contents;
                private int current = -1;
                private int count = 0;
-               private int capacity = 16;
+               private int capacity;
                private int modCount = 0;
 
                private void Resize(int ncapacity) {
+                       
+                       ncapacity = Math.Max (ncapacity, 16);
                        object[] ncontents = new object[ncapacity];
 
                        Array.Copy(contents, ncontents, count);
@@ -28,29 +53,33 @@ namespace System.Collections {
                        contents = ncontents;
                }
 
-               public Stack() {
-                       contents = new object[capacity];
-               }
+               public Stack () : this (16) {}
 
-               public Stack(ICollection collection) {
-                       capacity = collection.Count;
-                       contents = new object[capacity];
-                       current = capacity - 1;
-                       count = capacity;
-
-                       collection.CopyTo(contents, 0);
+               public Stack(ICollection col) : this (col == null ? 16 : col.Count) {
+                       if (col == null)
+                               throw new ArgumentNullException("col");
+                       
+                        // We have to do this because msft seems to call the
+                        // enumerator rather than CopyTo. This affects classes
+                        // like bitarray.
+                       foreach (object o in col)
+                               Push (o);
                }
 
-               public Stack(int c) {
-                       capacity = c;
+               public Stack (int initialCapacity) {
+                       if (initialCapacity < 0)
+                               throw new ArgumentOutOfRangeException ("initialCapacity");
+                       
+                       capacity = Math.Max (initialCapacity, 16);
                        contents = new object[capacity];
                }
 
+               [Serializable]
                private class SyncStack : Stack {
 
                        Stack stack;
 
-                       public SyncStack(Stack s) {
+                       internal SyncStack(Stack s) {
                                stack = s;
                        }
                        
@@ -62,10 +91,16 @@ namespace System.Collections {
                                }
                        }
                        
+/*
                        public override bool IsReadOnly {
-                               get { return false; }
+                               get { 
+                                       lock (stack) {
+                                               return stack.IsReadOnly; 
+                                       }
+                               }
                        }
-
+*/
+                       
                        public override bool IsSynchronized {
                                get { return true; }
                        }
@@ -127,9 +162,11 @@ namespace System.Collections {
                        get { return count; }
                }
 
+/*
                public virtual bool IsReadOnly {
                        get { return false; }
                }
+*/
 
                public virtual bool IsSynchronized {
                        get { return false; }
@@ -151,29 +188,26 @@ namespace System.Collections {
                }
 
                public virtual object Clone() {
-                       Stack stack;
-
-                       if (IsSynchronized) {
-                               stack = new Stack();
-
-                               stack.current = current;
-                               stack.contents = contents;
-                               stack.count = count;
-                               stack.capacity = capacity;
-                       } else {
-                               stack = new SyncStack(this);
-                       }
-
+                       Stack stack = new Stack (contents);
+                       stack.current = current;
+                       stack.count = count;
                        return stack;
                }
 
                public virtual bool Contains(object obj) {
                        if (count == 0)
                                return false;
-
-                       for (int i = 0; i < count; i++) {
-                               if (contents[i].Equals(obj))
-                                       return true; 
+                       
+                       if (obj == null) {
+                                       for (int i = 0; i < count; i++) {
+                                               if (contents[i] == null)
+                                                       return true; 
+                                       }
+                       } else {
+                                       for (int i = 0; i < count; i++) {
+                                               if (obj.Equals (contents[i]))
+                                                       return true; 
+                                       }
                        }
 
                        return false;
@@ -181,15 +215,15 @@ namespace System.Collections {
 
                public virtual void CopyTo (Array array, int index) {
                        if (array == null) {
-                               throw new ArgumentNullException();
+                               throw new ArgumentNullException("array");
                        }
 
                        if (index < 0) {
-                               throw new ArgumentOutOfRangeException();
+                               throw new ArgumentOutOfRangeException("index");
                        }
 
                        if (array.Rank > 1 || 
-                           index >= array.Length || 
+                           array.Length > 0 && index >= array.Length || 
                            count > array.Length - index) {
                                throw new ArgumentException();
                        }
@@ -200,26 +234,31 @@ namespace System.Collections {
                        }
                }
 
-               private class Enumerator : IEnumerator {
+               private class Enumerator : IEnumerator, ICloneable {
+                       
+                       const int EOF = -1;
+                       const int BOF = -2;
 
                        Stack stack;
                        private int modCount;
                        private int current;
 
                        internal Enumerator(Stack s) {
-                               // this is odd.  it seems that you need to 
-                               // start one further ahead than current, since 
-                               // MoveNext() gets called first when using an 
-                               // Enumeration...
                                stack = s;
                                modCount = s.modCount;
-                               current = s.current + 1;
+                               current = BOF;
+                       }
+                       
+                       public object Clone ()
+                       {
+                               return MemberwiseClone ();
                        }
 
                        public virtual object Current {
                                get {
                                        if (modCount != stack.modCount 
-                                           || current == -1 
+                                           || current == BOF
+                                           || current == EOF
                                            || current > stack.count)
                                                throw new InvalidOperationException();
                                        return stack.contents[current];
@@ -227,17 +266,20 @@ namespace System.Collections {
                        }
 
                        public virtual bool MoveNext() {
-                               if (modCount != stack.modCount 
-                                   || current == -1) {
+                               if (modCount != stack.modCount)
                                        throw new InvalidOperationException();
-                               }
-
-                               current--;
-
-                               if (current == -1) {
+                               
+                               switch (current) {
+                               case BOF:
+                                       current = stack.current;
+                                       return current != -1;
+                               
+                               case EOF:
                                        return false;
-                               } else {
-                                       return true;
+                               
+                               default:
+                                       current--; 
+                                       return current != -1;
                                }
                        }
 
@@ -246,9 +288,7 @@ namespace System.Collections {
                                        throw new InvalidOperationException();
                                }
 
-                               // start one ahead of stack.current, so the 
-                               // first MoveNext() will put us at the top
-                               current = stack.current + 1;
+                               current = BOF;
                        }
                }
 
@@ -271,17 +311,25 @@ namespace System.Collections {
                                modCount++;
 
                                object ret = contents[current];
+                               contents [current] = null;
                
                                count--;
                                current--;
-               
+
+                               // if we're down to capacity/4, go back to a 
+                               // lower array size.  this should keep us from 
+                               // sucking down huge amounts of memory when 
+                               // putting large numbers of items in the Stack.
+                               // if we're lower than 16, don't bother, since 
+                               // it will be more trouble than it's worth.
+                               if (count <= (capacity/4) && count > 16) {
+                                       Resize(capacity/2);
+                               }
+
                                return ret;
                        }
                }
 
-               // FIXME: We should probably be a bit smarter about our 
-               // resizing.  After a certain point, doubling isn't that smart.
-               // We just need to find out what that point is...
                public virtual void Push(Object o) {
                        modCount++;
 
@@ -307,4 +355,3 @@ namespace System.Collections {
                }
        }
 }
-