Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System / System.Collections.Specialized / NameObjectCollectionBase.cs
index 02944217bb2b6cd36ae658fd38131d14b3b06eb5..a1a377da08f34a0e6090892905d848c419d1ba71 100644 (file)
@@ -6,8 +6,7 @@
 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
-//
-
+// Copyright (C) 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
@@ -49,6 +48,12 @@ namespace System.Collections.Specialized
                private int m_defCapacity;
                private bool m_readonly;
                SerializationInfo infoCopy;
+               private KeysCollection keyscoll;
+               private IEqualityComparer equality_comparer;
+
+               internal IEqualityComparer EqualityComparer {
+                       get { return equality_comparer; }
+               }
 
                internal IComparer Comparer {
                        get {return m_comparer;}
@@ -76,7 +81,8 @@ namespace System.Collections.Specialized
                {
                        private NameObjectCollectionBase m_collection;
                        private int m_position;
-                       /*private*/internal _KeysEnumerator(NameObjectCollectionBase collection)
+
+                       internal _KeysEnumerator(NameObjectCollectionBase collection)
                        {
                                m_collection = collection;
                                Reset();
@@ -94,7 +100,7 @@ namespace System.Collections.Specialized
                        }
                        public bool MoveNext()
                        {
-                               return ((++m_position)<m_collection.Count)?true:false;
+                               return ((++m_position) < m_collection.Count);
                        }
                        public void Reset()
                        {
@@ -110,28 +116,38 @@ namespace System.Collections.Specialized
                {
                        private NameObjectCollectionBase m_collection;
 
-                       internal/*protected?*/ KeysCollection(NameObjectCollectionBase collection)
+                       internal KeysCollection (NameObjectCollectionBase collection)
                        {
                                this.m_collection = collection;
                        }
+
                        public virtual string Get( int index )
                        {
                                return m_collection.BaseGetKey(index);
-                               //throw new Exception("Not implemented yet");
                        }
                        
                        // ICollection methods -----------------------------------
-                       void ICollection.CopyTo(Array arr, int index)
+                       void ICollection.CopyTo (Array array, int arrayIndex)
                        {
-                               if (arr==null)
-                                       throw new ArgumentNullException("array can't be null");
-                               IEnumerator en = this.GetEnumerator();
-                               int i = index;
-                               while (en.MoveNext())
-                               {
-                                       arr.SetValue(en.Current,i);
-                                       i++;
-                               }                       
+                               ArrayList items = m_collection.m_ItemsArray;
+                               if (null == array)
+                                       throw new ArgumentNullException ("array");
+
+                               if (arrayIndex < 0)
+                                       throw new ArgumentOutOfRangeException ("arrayIndex");
+
+                               if ((array.Length > 0) && (arrayIndex >= array.Length))
+                                       throw new ArgumentException ("arrayIndex is equal to or greater than array.Length");
+
+                               if (arrayIndex + items.Count > array.Length)
+                                       throw new ArgumentException ("Not enough room from arrayIndex to end of array for this KeysCollection");
+
+                               if (array != null && array.Rank > 1)
+                                       throw new ArgumentException ("array is multidimensional");
+                               
+                               object[] objArray = (object[])array;
+                               for (int i = 0; i < items.Count; i++, arrayIndex++)
+                                       objArray [arrayIndex] = ((_Item)items [i]).key;
                        }
 
                        bool ICollection.IsSynchronized
@@ -153,7 +169,6 @@ namespace System.Collections.Specialized
                        {
                                get{
                                        return m_collection.Count;
-                                       //throw new Exception("Not implemented yet");
                                }
                        }
 
@@ -169,67 +184,54 @@ namespace System.Collections.Specialized
                        public IEnumerator GetEnumerator()
                        {
                                return new _KeysEnumerator(m_collection);
-//                             throw new Exception("Not implemented yet");
                        }
                }
 
-
-
                //--------------- Protected Instance Constructors --------------
                
                /// <summary>
                /// SDK: Initializes a new instance of the NameObjectCollectionBase class that is empty.
                /// </summary>
-               [MonoTODO]
-               protected NameObjectCollectionBase():base()
+               protected NameObjectCollectionBase ()
                {
                        m_readonly = false;
-
-#if NET_1_0
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
-                       m_comparer = CaseInsensitiveComparer.Default;
-#else
                        m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
                        m_comparer = CaseInsensitiveComparer.DefaultInvariant;
-#endif
                        m_defCapacity = 0;
                        Init();
-                       /*m_ItemsContainer = new Hashtable(m_hashprovider,m_comparer);
-                       m_ItemsArray = new ArrayList();
-                       m_NullKeyItem = null;*/
-                       //TODO: consider common Reset() method
                }
                
                protected NameObjectCollectionBase( int capacity )
                {
                        m_readonly = false;
-                       
-#if NET_1_0
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
-                       m_comparer = CaseInsensitiveComparer.Default;
-#else
                        m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
                        m_comparer = CaseInsensitiveComparer.DefaultInvariant;
-#endif
                        m_defCapacity = capacity;
                        Init();
-                       /*m_ItemsContainer = new Hashtable(m_defCapacity, m_hashprovider,m_comparer);
-                       m_ItemsArray = new ArrayList();
-                       m_NullKeyItem = null;                   */
-                       //throw new Exception("Not implemented yet");
-               }
-               protected NameObjectCollectionBase( IHashCodeProvider hashProvider, IComparer comparer )
+               }               
+
+               internal NameObjectCollectionBase (IEqualityComparer equalityComparer, IComparer comparer, IHashCodeProvider hcp)
                {
+                       equality_comparer = equalityComparer;
+                       m_comparer = comparer;
+                       m_hashprovider = hcp;
                        m_readonly = false;
-                       
-                       m_hashprovider = hashProvider;
+                       m_defCapacity = 0;
+                       Init ();
+               }
+
+               protected NameObjectCollectionBase (IEqualityComparer equalityComparer) : this( (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer), null, null)
+               {                       
+               }               
+
+               [Obsolete ("Use NameObjectCollectionBase(IEqualityComparer)")]
+               protected NameObjectCollectionBase( IHashCodeProvider hashProvider, IComparer comparer )
+               {                       
                        m_comparer = comparer;
+                       m_hashprovider = hashProvider;
+                       m_readonly = false;
                        m_defCapacity = 0;
-                       Init();
-                       /*m_ItemsContainer = new Hashtable(m_hashprovider,m_comparer);
-                       m_ItemsArray = new ArrayList();
-                       m_NullKeyItem = null;                   */
-                       //throw new Exception("Not implemented yet");
+                       Init ();
                }
 
                protected NameObjectCollectionBase (SerializationInfo info, StreamingContext context)
@@ -237,6 +239,15 @@ namespace System.Collections.Specialized
                        infoCopy = info;
                }
 
+               protected NameObjectCollectionBase (int capacity, IEqualityComparer equalityComparer)
+               {
+                       m_readonly = false;
+                       equality_comparer = (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer);
+                       m_defCapacity = capacity;
+                       Init();
+               }
+
+               [Obsolete ("Use NameObjectCollectionBase(int,IEqualityComparer)")]
                protected NameObjectCollectionBase( int capacity, IHashCodeProvider hashProvider, IComparer comparer )
                {
                        m_readonly = false;
@@ -245,25 +256,34 @@ namespace System.Collections.Specialized
                        m_comparer = comparer;
                        m_defCapacity = capacity;
                        Init();
-                       /*m_ItemsContainer = new Hashtable(m_defCapacity,m_hashprovider,m_comparer);
-                       m_ItemsArray = new ArrayList();
-                       m_NullKeyItem = null;   */
-
-                       //throw new Exception("Not implemented yet");
                }
                
-               private void Init(){
-                       m_ItemsContainer = new Hashtable(m_defCapacity,m_hashprovider,m_comparer);
+               private void Init ()
+               {
+                       if (m_ItemsContainer != null) {
+                               m_ItemsContainer.Clear ();
+                               m_ItemsContainer = null;
+                       }
+                       
+                       if (m_ItemsArray != null) {
+                               m_ItemsArray.Clear ();
+                               m_ItemsArray = null;
+                       }
+                       if (equality_comparer != null)
+                               m_ItemsContainer = new Hashtable (m_defCapacity, equality_comparer);
+                       else
+                               m_ItemsContainer = new Hashtable (m_defCapacity, m_hashprovider, m_comparer);
                        m_ItemsArray = new ArrayList();
                        m_NullKeyItem = null;   
                }
+
                //--------------- Public Instance Properties -------------------
-               public virtual NameObjectCollectionBase.KeysCollection Keys 
-               {
-                       get
-                       {
-                               return new KeysCollection(this);
-                               //throw new Exception("Not implemented yet");
+
+               public virtual NameObjectCollectionBase.KeysCollection Keys {
+                       get {
+                               if (keyscoll == null)
+                                       keyscoll = new KeysCollection (this);
+                               return keyscoll;
                        }
                }
                                
@@ -275,15 +295,10 @@ namespace System.Collections.Specialized
                /// <remark>This enumerator returns the keys of the collection as strings.</remark>
                /// </summary>
                /// <returns></returns>
-               public
-#if NET_2_0            
-               virtual
-#endif
-               IEnumerator GetEnumerator()
+               public virtual IEnumerator GetEnumerator()
                {
                        return new _KeysEnumerator(this);
                }
-               // GetHashCode
 
                // ISerializable
                public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
@@ -301,8 +316,14 @@ namespace System.Collections.Specialized
                                i++;
                        }
 
-                       info.AddValue("HashProvider", m_hashprovider, typeof(IHashCodeProvider));
-                       info.AddValue("Comparer", m_comparer, typeof(IComparer));
+                       if (equality_comparer != null) {
+                               info.AddValue ("KeyComparer", equality_comparer, typeof (IEqualityComparer));
+                               info.AddValue ("Version", 4, typeof (int));
+                       } else {
+                               info.AddValue ("HashProvider", m_hashprovider, typeof (IHashCodeProvider));
+                               info.AddValue ("Comparer", m_comparer, typeof (IComparer));
+                               info.AddValue ("Version", 2, typeof (int));
+                       }
                        info.AddValue("ReadOnly", m_readonly);
                        info.AddValue("Count", count);
                        info.AddValue("Keys", keys, typeof(string[]));
@@ -314,13 +335,14 @@ namespace System.Collections.Specialized
                {
                        get{
                                return m_ItemsArray.Count;
-                               //throw new Exception("Not implemented yet");
                        }
                }
+
                bool ICollection.IsSynchronized
                {
                        get { return false; }
                }
+
                object ICollection.SyncRoot
                {
                        get { return this; }
@@ -328,10 +350,9 @@ namespace System.Collections.Specialized
 
                void ICollection.CopyTo (Array array, int index)
                {
-                       throw new NotImplementedException ();
+                       ((ICollection)Keys).CopyTo (array, index);
                }
 
-
                // IDeserializationCallback
                public virtual void OnDeserialization (object sender)
                {
@@ -346,14 +367,13 @@ namespace System.Collections.Specialized
                        infoCopy = null;
                        m_hashprovider = (IHashCodeProvider) info.GetValue ("HashProvider",
                                                                            typeof (IHashCodeProvider));
-
-                       if (m_hashprovider == null)
-                               throw new SerializationException ("The hash provider is null");
-
-                       m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));
-                       if (m_comparer == null)
-                               throw new SerializationException ("The comparer is null");
-
+                       if (m_hashprovider == null) {
+                               equality_comparer = (IEqualityComparer) info.GetValue ("KeyComparer", typeof (IEqualityComparer));
+                       } else {
+                               m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));
+                               if (m_comparer == null)
+                                       throw new SerializationException ("The comparer is null");
+                       }
                        m_readonly = info.GetBoolean ("ReadOnly");
                        string [] keys = (string []) info.GetValue ("Keys", typeof (string []));
                        if (keys == null)
@@ -368,6 +388,7 @@ namespace System.Collections.Specialized
                        for (int i = 0; i < count; i++)
                                BaseAdd (keys [i], values [i]);
                }
+
                //--------------- Protected Instance Properties ----------------
                /// <summary>
                /// SDK: Gets or sets a value indicating whether the NameObjectCollectionBase instance is read-only.
@@ -412,8 +433,8 @@ namespace System.Collections.Specialized
                        if (this.IsReadOnly)
                                throw new NotSupportedException("Collection is read-only");
                        Init();
-                       //throw new Exception("Not implemented yet");
                }
+
                /// <summary>
                /// SDK: Gets the value of the entry at the specified index of the NameObjectCollectionBase instance.
                /// </summary>
@@ -422,8 +443,8 @@ namespace System.Collections.Specialized
                protected object BaseGet( int index )
                {
                        return ((_Item)m_ItemsArray[index]).value;
-                       //throw new Exception("Not implemented yet");
                }
+
                /// <summary>
                /// SDK: Gets the value of the first entry with the specified key from the NameObjectCollectionBase instance.
                /// </summary>
@@ -483,8 +504,8 @@ namespace System.Collections.Specialized
                protected string BaseGetKey( int index )
                {
                        return ((_Item)m_ItemsArray[index]).key;
-                       //throw new Exception("Not implemented yet");
                }
+
                /// <summary>
                /// Gets a value indicating whether the NameObjectCollectionBase instance contains entries whose keys are not a null reference 
                /// </summary>
@@ -492,7 +513,6 @@ namespace System.Collections.Specialized
                protected bool BaseHasKeys()
                {
                        return (m_ItemsContainer.Count>0);
-//                     throw new Exception("Not implemented yet");
                }
 
                protected void BaseRemove( string name )
@@ -512,13 +532,12 @@ namespace System.Collections.Specialized
                        cnt = m_ItemsArray.Count;
                        for (int i=0 ; i< cnt; ){
                                key=BaseGetKey(i);
-                               if (m_comparer.Compare (key, name) == 0) {
+                               if (Equals (key, name)) {
                                        m_ItemsArray.RemoveAt(i);
                                        cnt--;
                                }
                                else 
                                        i++;
-                               
                        }
                }
 
@@ -536,7 +555,6 @@ namespace System.Collections.Specialized
                /// It's ok only then the key is uniquely assosiated with the value
                /// To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added 
                /// </LAME>>
-               [MonoTODO]
                protected void BaseRemoveAt( int index )
                {
                        if (this.IsReadOnly)
@@ -549,8 +567,8 @@ namespace System.Collections.Specialized
                        else
                                m_NullKeyItem = null;
                        m_ItemsArray.RemoveAt(index);
-//                     throw new Exception("Not implemented yet");
                }
+
                /// <summary>
                /// SDK: Sets the value of the entry at the specified index of the NameObjectCollectionBase instance.
                /// </summary>
@@ -562,8 +580,8 @@ namespace System.Collections.Specialized
                                throw new NotSupportedException("Collection is read-only");
                        _Item item = (_Item)m_ItemsArray[index];
                        item.value = value;
-                       //throw new Exception("Not implemented yet");
                }
+
                /// <summary>
                /// Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance.
                /// </summary>
@@ -578,9 +596,8 @@ namespace System.Collections.Specialized
                                item.value=value;
                        else 
                                BaseAdd(name, value);
-
-                       //throw new Exception("Not implemented yet");
                }
+
                [MonoTODO]
                private _Item FindFirstMatchedItem(string name)
                {
@@ -589,11 +606,15 @@ namespace System.Collections.Specialized
                        else {
                                //TODO: consider null key case
                                return m_NullKeyItem;
-                               //throw new Exception("Not implemented yet");
                        }
+               }
 
+               internal bool Equals (string s1, string s2)
+               {
+                       if (m_comparer != null)
+                               return (m_comparer.Compare (s1, s2) == 0);
+                       else
+                               return equality_comparer.Equals (s1, s2);
                }
-               //~Object();
-               
        }
 }