Add locking to EventWaitHandle.Set/Reset to avoid crashes when another thread dispose...
[mono.git] / mcs / class / corlib / System.Collections / ArrayList.cs
index f3653eedcc39d17ff178bdd2e0ed17521f530c45..0a67c6a2c830e103b621716de866a21453f744e7 100644 (file)
@@ -3,29 +3,7 @@
 // Implementation of the ECMA ArrayList.
 //
 // Copyright (c) 2003 Thong (Tum) Nguyen [tum@veridicus.com]
-//
-// http://www.opensource.org/licenses/mit-license.html
-// 
-// 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.
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 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
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
-using System.Collections;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
 
 namespace System.Collections 
 {
        [Serializable]
-       public class ArrayList
-               : IList, ICloneable, ICollection, IEnumerable 
-       {
+#if INSIDE_CORLIB
+       [ComVisible(true)]
+       [DebuggerDisplay ("Count={Count}")]
+       [DebuggerTypeProxy (typeof (CollectionDebuggerView))]
+       public class ArrayList : IList, ICloneable, ICollection, IEnumerable {
+#else
+       internal class ArrayList : IList {
+#endif
                #region Enumerator
 
                private sealed class ArrayListEnumerator
                        : IEnumerator, ICloneable 
                {                       
+                       private object m_Current;
+                       private ArrayList m_List;
                        private int m_Pos;
                        private int m_Index;
                        private int m_Count;
-                       private object m_Current;
-                       private ArrayList m_List;
                        private int m_ExpectedStateChanges;
 
                        public ArrayListEnumerator(ArrayList list)
@@ -129,9 +112,9 @@ namespace System.Collections
                sealed class SimpleEnumerator : IEnumerator, ICloneable
                {
                        ArrayList list;
+                       object currentElement;
                        int index;
                        int version;
-                       object currentElement;
                        static object endFlag = new object ();
                                                        
                        public SimpleEnumerator (ArrayList list)
@@ -348,13 +331,13 @@ namespace System.Collections
                        {
                                if (startIndex < 0 || startIndex > m_Adaptee.Count) 
                                {
-                                       throw new ArgumentOutOfRangeException("startIndex", startIndex,
+                                       ThrowNewArgumentOutOfRangeException ("startIndex", startIndex,
                                                "Does not specify valid index.");
                                }
 
                                if (count < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("count", count,
+                                       ThrowNewArgumentOutOfRangeException ("count", count,
                                                "Can't be less than 0.");
                                }
 
@@ -403,17 +386,17 @@ namespace System.Collections
                        {
                                if (startIndex < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("startIndex", startIndex, "< 0");
+                                       ThrowNewArgumentOutOfRangeException ("startIndex", startIndex, "< 0");
                                }
 
                                if (count < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("count", count, "count is negative.");
+                                       ThrowNewArgumentOutOfRangeException ("count", count, "count is negative.");
                                }
 
                                if (startIndex - count  + 1 < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("count", count, "count is too large.");
+                                       ThrowNewArgumentOutOfRangeException ("count", count, "count is too large.");
                                }
 
                                if (value == null) 
@@ -454,7 +437,7 @@ namespace System.Collections
 
                                if (index > m_Adaptee.Count) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index must be >= 0 and <= Count.");
                                }
 
@@ -537,19 +520,19 @@ namespace System.Collections
                        {
                                if (index < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Can't be less than zero.");
                                }
 
                                if (arrayIndex < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex,
+                                       ThrowNewArgumentOutOfRangeException ("arrayIndex", arrayIndex,
                                                "Can't be less than zero.");
                                }
 
                                if (count < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Can't be less than zero.");
                                }
 
@@ -642,7 +625,8 @@ namespace System.Collections
 
                                while (x <= y) 
                                {
-                                       z = (x + y) / 2;
+                                       // Be careful with overflows
+                                       z = x + ((y - x) / 2);
                                
                                        r = comparer.Compare(value, m_Adaptee[z]);
                                
@@ -736,7 +720,8 @@ namespace System.Collections
 
                                // Pick the pivot using the median-of-three strategy.
 
-                               middle = (left + right) / 2;
+                               // Be careful with overflows
+                               middle = left + ((right - left) / 2);
 
                                if (comparer.Compare(list[middle], list[left]) < 0) 
                                {
@@ -1808,13 +1793,13 @@ namespace System.Collections
                        {
                                if (startIndex < 0 || startIndex > m_InnerCount) 
                                {
-                                       throw new ArgumentOutOfRangeException("startIndex", startIndex,
+                                       ThrowNewArgumentOutOfRangeException ("startIndex", startIndex,
                                                "Does not specify valid index.");
                                }
 
                                if (count < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("count", count,
+                                       ThrowNewArgumentOutOfRangeException ("count", count,
                                                "Can't be less than 0.");
                                }
 
@@ -1853,12 +1838,12 @@ namespace System.Collections
                        {
                                if (startIndex < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("startIndex", startIndex, "< 0");
+                                       ThrowNewArgumentOutOfRangeException ("startIndex", startIndex,  "< 0");
                                }
 
                                if (count < 0) 
                                {
-                                       throw new ArgumentOutOfRangeException("count", count, "count is negative.");
+                                       ThrowNewArgumentOutOfRangeException ("count", count, "count is negative.");
                                }
 
                                int retval = m_InnerArrayList.LastIndexOf(value, m_InnerIndex + startIndex, count);
@@ -1879,7 +1864,7 @@ namespace System.Collections
                                
                                if (index < 0 || index > m_InnerCount) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index must be >= 0 and <= Count.");
                                }
 
@@ -1896,7 +1881,7 @@ namespace System.Collections
 
                                if (index < 0 || index > m_InnerCount) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index must be >= 0 and <= Count.");
                                }
 
@@ -1927,7 +1912,7 @@ namespace System.Collections
 
                                if (index < 0 || index > m_InnerCount) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index must be >= 0 and <= Count.");
                                }
 
@@ -1972,7 +1957,7 @@ namespace System.Collections
 
                                if (index < 0 || index > m_InnerCount) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index must be >= 0 and <= Count.");
                                }
 
@@ -2082,7 +2067,7 @@ namespace System.Collections
 
                                array = new object[m_InnerCount];
 
-                               m_InnerArrayList.CopyTo(0, array, 0, m_InnerCount);
+                               m_InnerArrayList.CopyTo (m_InnerIndex, array, 0, m_InnerCount);
 
                                return array;
                        }
@@ -2093,7 +2078,7 @@ namespace System.Collections
 
                                array = Array.CreateInstance(elementType, m_InnerCount);
 
-                               m_InnerArrayList.CopyTo(0, array, 0, m_InnerCount);
+                               m_InnerArrayList.CopyTo(m_InnerIndex, array, 0, m_InnerCount);
 
                                return array;
                        }
@@ -2508,23 +2493,25 @@ namespace System.Collections
 
                #region Fields
 
-               private const int DefaultInitialCapacity = 0x10;
-               
-               /// <summary>
-               /// Number of items in the list.
-               /// </summary>
-               private int _size;
+               private const int DefaultInitialCapacity = 4;
 
                /// <summary>
                /// Array to store the items.
                /// </summary>
                private object[] _items;
-               
+                               
+               /// <summary>
+               /// Number of items in the list.
+               /// </summary>
+               private int _size;
+
                /// <summary>
                /// Total number of state changes.
                /// </summary>
                private int _version;
 
+               private static readonly object [] EmptyArray = new object [0]; 
+
                #endregion
                
                #region Constructors
@@ -2535,7 +2522,7 @@ namespace System.Collections
                /// </summary>
                public ArrayList()
                {
-                       _items = new object[DefaultInitialCapacity];
+                       _items = EmptyArray;
                }               
 
                /// <summary>
@@ -2574,25 +2561,25 @@ namespace System.Collections
                /// Initializes a new instance of the <see cref="ArrayList"/> class that is empty and
                /// has the specified initial capacity.
                /// </summary>
-               /// <param name="initialCapacity">
+               /// <param name="capacity">
                /// The number of elements that hte new list is initially capable of storing.
                /// </param>
                /// <exception cref="ArgumentOutOfRangeException">
                /// The <c>capacity</c> is less than zero.
                /// </exception>
-               public ArrayList(int initialCapacity) 
+               public ArrayList(int capacity) 
                {
-                       if (initialCapacity < 0) 
+                       if (capacity < 0) 
                        {
-                               throw new ArgumentOutOfRangeException("initialCapacity",
-                                       initialCapacity, "The initial capacity can't be smaller than zero.");
+                               ThrowNewArgumentOutOfRangeException ("capacity",
+                                       capacity, "The initial capacity can't be smaller than zero.");
                        }
 
-                       if (initialCapacity == 0) 
+                       if (capacity == 0) 
                        {
-                               initialCapacity = DefaultInitialCapacity;
+                               capacity = DefaultInitialCapacity;
                        }
-                       _items = new object[initialCapacity];
+                       _items = new object [capacity];
                }
 
                /// <summary>
@@ -2647,7 +2634,7 @@ namespace System.Collections
                        {
                                if (index < 0 || index >= _size) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index is less than 0 or more than or equal to the list count.");
                                }
 
@@ -2658,7 +2645,7 @@ namespace System.Collections
                        {
                                if (index < 0 || index >= _size) 
                                {
-                                       throw new ArgumentOutOfRangeException("index", index,
+                                       ThrowNewArgumentOutOfRangeException ("index", index,
                                                "Index is less than 0 or more than or equal to the list count.");
                                }
 
@@ -2702,7 +2689,7 @@ namespace System.Collections
                        {
                                if (value < _size) 
                                {
-                                       throw new ArgumentOutOfRangeException("Capacity", value,
+                                       ThrowNewArgumentOutOfRangeException ("Capacity", value,
                                                "Must be more than count.");
                                }
 
@@ -2839,6 +2826,7 @@ namespace System.Collections
                                int x = index - count ;
 
                                Array.Copy(_items, x, _items, index, _size - x);
+                               Array.Clear(_items, _size + count, - count);
                        }
                }
 
@@ -2868,9 +2856,9 @@ namespace System.Collections
                        _version++;
                }
 
-               public virtual bool Contains(object value
+               public virtual bool Contains(object item
                {
-                       return IndexOf(value, 0, _size) > -1;
+                       return IndexOf(item, 0, _size) > -1;
                }
 
                internal virtual bool Contains(object value, int startIndex, int count) 
@@ -2892,13 +2880,13 @@ namespace System.Collections
                {
                        if (startIndex < 0 || startIndex > _size) 
                        {
-                               throw new ArgumentOutOfRangeException("startIndex", startIndex,
+                               ThrowNewArgumentOutOfRangeException ("startIndex", startIndex,
                                        "Does not specify valid index.");
                        }
 
                        if (count < 0) 
                        {
-                               throw new ArgumentOutOfRangeException("count", count,
+                               ThrowNewArgumentOutOfRangeException ("count", count,
                                        "Can't be less than 0.");
                        }
 
@@ -2934,7 +2922,7 @@ namespace System.Collections
                {
                        if (index < 0 || index > _size) 
                        {
-                               throw new ArgumentOutOfRangeException("index", index,
+                               ThrowNewArgumentOutOfRangeException ("index", index,
                                        "Index must be >= 0 and <= Count.");
                        }
 
@@ -2956,7 +2944,7 @@ namespace System.Collections
 
                        if (index < 0 || index > _size) 
                        {
-                               throw new ArgumentOutOfRangeException("index", index,
+                               ThrowNewArgumentOutOfRangeException ("index", index,
                                        "Index must be >= 0 and <= Count.");
                        }
 
@@ -2995,11 +2983,11 @@ namespace System.Collections
                        _version++;
                }
 
-               public virtual void Remove(object value
+               public virtual void Remove(object obj
                {
                        int x;
 
-                       x = IndexOf(value);
+                       x = IndexOf(obj);
 
                        if (x > -1) 
                        {
@@ -3013,7 +3001,7 @@ namespace System.Collections
                {
                        if (index < 0 || index >= _size) 
                        {
-                               throw new ArgumentOutOfRangeException("index", index,
+                               ThrowNewArgumentOutOfRangeException ("index", index,
                                        "Less than 0 or more than list count.");
                        }
 
@@ -3050,9 +3038,9 @@ namespace System.Collections
                        Array.Copy(_items, array, _size);
                }
 
-               public virtual void CopyTo(System.Array array, int index) 
+               public virtual void CopyTo(System.Array array, int arrayIndex) 
                {                       
-                       CopyTo(0, array, index, _size);
+                       CopyTo(0, array, arrayIndex, _size);
                }
 
                public virtual void CopyTo(int index, System.Array array, int arrayIndex, int count) 
@@ -3207,11 +3195,11 @@ namespace System.Collections
                        return retval;
                }
 
-               public virtual Array ToArray(Type elementType) 
+               public virtual Array ToArray(Type type) 
                {
                        Array retval;
                        
-                       retval = Array.CreateInstance(elementType, _size);
+                       retval = Array.CreateInstance(type, _size);
 
                        CopyTo(retval);
 
@@ -3238,12 +3226,12 @@ namespace System.Collections
                {
                        if (index < 0) 
                        {
-                               throw new ArgumentOutOfRangeException("index", index, "Can't be less than 0.");
+                               ThrowNewArgumentOutOfRangeException ("index", index, "Can't be less than 0.");
                        }
 
                        if (count < 0) 
                        {
-                               throw new ArgumentOutOfRangeException("count", count, "Can't be less than 0.");
+                               ThrowNewArgumentOutOfRangeException ("count", count, "Can't be less than 0.");
                        }
 
                        // re-ordered to avoid possible integer overflow
@@ -3253,6 +3241,17 @@ namespace System.Collections
                        }
                }
 
+               internal static void ThrowNewArgumentOutOfRangeException (string name, object actual, string message)
+               {
+                       throw new ArgumentOutOfRangeException (
+#if !INSIDE_CORLIB && NET_2_1
+                               name, message
+#else
+                               name, actual, message
+#endif
+                       );
+               }
+
                public static ArrayList Adapter(IList list) 
                {
                        // LAMESPEC: EWWW.  Other lists aren't *Array*Lists.
@@ -3262,29 +3261,31 @@ namespace System.Collections
                                throw new ArgumentNullException("list");
                        }
 
-                       if (list.IsSynchronized) 
-                       {
-                               return ArrayList.Synchronized(new ArrayListAdapter(list));
-                       }
+                       ArrayList arrayList = list as ArrayList;
+                       if (arrayList != null)
+                               return arrayList;
+                       else
+                               arrayList = new ArrayListAdapter(list);
+
+                       if (list.IsSynchronized)
+                               return ArrayList.Synchronized(arrayList);
                        else 
-                       {
-                               return new ArrayListAdapter(list);
-                       }
+                               return arrayList;
                }
 
-               public static ArrayList Synchronized(ArrayList arrayList) 
+               public static ArrayList Synchronized(ArrayList list) 
                {
-                       if (arrayList == null) 
+                       if (list == null) 
                        {
-                               throw new ArgumentNullException("arrayList");
+                               throw new ArgumentNullException("list");
                        }
 
-                       if (arrayList.IsSynchronized)
+                       if (list.IsSynchronized)
                        {
-                               return arrayList;
+                               return list;
                        }
 
-                       return new SynchronizedArrayListWrapper(arrayList);
+                       return new SynchronizedArrayListWrapper(list);
                }
 
                public static IList Synchronized(IList list) 
@@ -3302,19 +3303,19 @@ namespace System.Collections
                        return new SynchronizedListWrapper(list);
                }
 
-               public static ArrayList ReadOnly(ArrayList arrayList) 
+               public static ArrayList ReadOnly(ArrayList list) 
                {
-                       if (arrayList == null) 
+                       if (list == null) 
                        {
-                               throw new ArgumentNullException("arrayList");
+                               throw new ArgumentNullException("list");
                        }
 
-                       if (arrayList.IsReadOnly)
+                       if (list.IsReadOnly)
                        {
-                               return arrayList;
+                               return list;
                        }
 
-                       return new ReadOnlyArrayListWrapper(arrayList);
+                       return new ReadOnlyArrayListWrapper(list);
                }
 
                public static IList ReadOnly(IList list) 
@@ -3332,19 +3333,19 @@ namespace System.Collections
                        return new ReadOnlyListWrapper(list);
                }
 
-               public static ArrayList FixedSize(ArrayList arrayList) 
+               public static ArrayList FixedSize(ArrayList list) 
                {
-                       if (arrayList == null) 
+                       if (list == null) 
                        {
-                               throw new ArgumentNullException("arrayList");
+                               throw new ArgumentNullException("list");
                        }
 
-                       if (arrayList.IsFixedSize)
+                       if (list.IsFixedSize)
                        {
-                               return arrayList;
+                               return list;
                        }
 
-                       return new FixedSizeArrayListWrapper(arrayList);
+                       return new FixedSizeArrayListWrapper(list);
                }
 
                public static IList FixedSize(IList list)