Add locking to EventWaitHandle.Set/Reset to avoid crashes when another thread dispose...
[mono.git] / mcs / class / corlib / System.Collections / ArrayList.cs
index 97fd259b566ed0ce0afa8f62905996fab466b4d0..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 
 {
-#if NET_2_0
+       [Serializable]
+#if INSIDE_CORLIB
        [ComVisible(true)]
+       [DebuggerDisplay ("Count={Count}")]
+       [DebuggerTypeProxy (typeof (CollectionDebuggerView))]
+       public class ArrayList : IList, ICloneable, ICollection, IEnumerable {
+#else
+       internal class ArrayList : IList {
 #endif
-       [Serializable]
-       public class ArrayList
-               : IList, ICloneable, ICollection, IEnumerable 
-       {
                #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)
@@ -133,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)
@@ -352,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.");
                                }
 
@@ -407,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) 
@@ -458,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.");
                                }
 
@@ -541,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.");
                                }
 
@@ -646,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]);
                                
@@ -740,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) 
                                {
@@ -1812,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.");
                                }
 
@@ -1857,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);
@@ -1883,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.");
                                }
 
@@ -1900,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.");
                                }
 
@@ -1931,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.");
                                }
 
@@ -1976,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.");
                                }
 
@@ -2512,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
@@ -2539,7 +2522,7 @@ namespace System.Collections
                /// </summary>
                public ArrayList()
                {
-                       _items = new object[DefaultInitialCapacity];
+                       _items = EmptyArray;
                }               
 
                /// <summary>
@@ -2588,7 +2571,7 @@ namespace System.Collections
                {
                        if (capacity < 0) 
                        {
-                               throw new ArgumentOutOfRangeException("capacity",
+                               ThrowNewArgumentOutOfRangeException ("capacity",
                                        capacity, "The initial capacity can't be smaller than zero.");
                        }
 
@@ -2651,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.");
                                }
 
@@ -2662,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.");
                                }
 
@@ -2706,7 +2689,7 @@ namespace System.Collections
                        {
                                if (value < _size) 
                                {
-                                       throw new ArgumentOutOfRangeException("Capacity", value,
+                                       ThrowNewArgumentOutOfRangeException ("Capacity", value,
                                                "Must be more than count.");
                                }
 
@@ -2843,6 +2826,7 @@ namespace System.Collections
                                int x = index - count ;
 
                                Array.Copy(_items, x, _items, index, _size - x);
+                               Array.Clear(_items, _size + count, - count);
                        }
                }
 
@@ -2872,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) 
@@ -2896,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.");
                        }
 
@@ -2938,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.");
                        }
 
@@ -2960,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.");
                        }
 
@@ -2999,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) 
                        {
@@ -3017,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.");
                        }
 
@@ -3054,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) 
@@ -3211,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);
 
@@ -3242,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
@@ -3257,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.
@@ -3266,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) 
@@ -3306,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) 
@@ -3336,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)