2009-08-20 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System / System.Collections.Specialized / OrderedDictionary.cs
index 1a18c2cd25065fc1dfa27f130a431ad4ba3b1de3..9aa976bf9b2a7b50febe74bda240f2ec216b4551 100644 (file)
@@ -4,9 +4,7 @@
 // Authors:\r
 //     Lluis Sanchez Gual (lluis@novell.com)\r
 //\r
-// (C) 2005 Novell, Inc (http://www.novell.com)\r
-//\r
-\r
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)\r
 //\r
 // Permission is hereby granted, free of charge, to any person obtaining\r
 // a copy of this software and associated documentation files (the\r
 \r
 #if NET_2_0\r
 \r
-using System;\r
 using System.Runtime.Serialization;\r
-
+\r
 namespace System.Collections.Specialized\r
 {\r
        [Serializable]\r
-       public class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection, IEnumerable, ISerializable\r
+       public class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback\r
        {\r
                ArrayList list;\r
                Hashtable hash;\r
-               IKeyComparer comparer;\r
                bool readOnly;\r
                int initialCapacity;\r
+               SerializationInfo serializationInfo;\r
+               IEqualityComparer comparer;\r
                \r
                public OrderedDictionary ()\r
                {\r
@@ -50,52 +48,74 @@ namespace System.Collections.Specialized
                        hash = new Hashtable ();\r
                }\r
                \r
-               [MonoTODO ("Use Hashtable's key comparer constructor")]\r
-               public OrderedDictionary (IKeyComparer comparer)\r
+               public OrderedDictionary (int capacity)\r
                {\r
-                       this.comparer = comparer;\r
-                       list = new ArrayList ();\r
-                       hash = new Hashtable ();\r
-//                     hash = new Hashtable (comparer);\r
+                       initialCapacity = (capacity < 0) ? 0 : capacity;\r
+                       list = new ArrayList (initialCapacity);\r
+                       hash = new Hashtable (initialCapacity);\r
                }\r
                \r
-               public OrderedDictionary (int capacity)\r
+               public OrderedDictionary (IEqualityComparer equalityComparer)\r
                {\r
-                       initialCapacity = capacity;\r
-                       list = new ArrayList (capacity);\r
-                       hash = new Hashtable (capacity);\r
+                       list = new ArrayList ();\r
+                       hash = new Hashtable (equalityComparer);\r
+                       comparer = equalityComparer;\r
                }\r
-               \r
-               [MonoTODO ("Use Hashtable's key comparer constructor")]\r
-               public OrderedDictionary (int capacity, IKeyComparer comparer)\r
+\r
+               public OrderedDictionary (int capacity, IEqualityComparer equalityComparer)\r
                {\r
-                       this.comparer = comparer;\r
-                       initialCapacity = capacity;\r
-                       list = new ArrayList (capacity);\r
-                       hash = new Hashtable (capacity);\r
-//                     hash = new Hashtable (capacity, comparer);\r
-                       \r
-                       this.comparer = comparer;\r
+                       initialCapacity = (capacity < 0) ? 0 : capacity;\r
+                       list = new ArrayList (initialCapacity);\r
+                       hash = new Hashtable (initialCapacity, equalityComparer);\r
+                       comparer = equalityComparer;\r
                }\r
-               \r
-               public OrderedDictionary (SerializationInfo info, StreamingContext context)\r
+\r
+               protected OrderedDictionary (SerializationInfo info, StreamingContext context)\r
+               {\r
+                       serializationInfo = info;\r
+               }\r
+\r
+               protected virtual void OnDeserialization (object sender)\r
                {\r
-                       comparer = (IKeyComparer) info.GetValue ("KeyComparer", typeof(IKeyComparer));\r
-                       readOnly = info.GetBoolean ("ReadOnly");\r
-                       initialCapacity = info.GetInt32 ("InitialCapacity");\r
-                       hash = (Hashtable) info.GetValue ("HashTable", typeof(Hashtable));\r
-                       list = (ArrayList) info.GetValue ("ArrayList", typeof(ArrayList));\r
+                       ((IDeserializationCallback) this).OnDeserialization (sender);\r
+               }\r
+\r
+               void IDeserializationCallback.OnDeserialization (object sender)\r
+               {\r
+                       if (serializationInfo == null)\r
+                               return;\r
+\r
+                       comparer = (IEqualityComparer) serializationInfo.GetValue ("KeyComparer", typeof (IEqualityComparer));\r
+                       readOnly = serializationInfo.GetBoolean ("ReadOnly");\r
+                       initialCapacity = serializationInfo.GetInt32 ("InitialCapacity");\r
+\r
+                       if (list == null)\r
+                               list = new ArrayList ();\r
+                       else\r
+                               list.Clear ();\r
+\r
+                       hash = new Hashtable (comparer);\r
+                       object[] array = (object[]) serializationInfo.GetValue ("ArrayList", typeof(object[]));\r
+                       foreach (DictionaryEntry de in array) {\r
+                               hash.Add (de.Key, de.Value);\r
+                               list.Add (de);\r
+                       }\r
                }\r
                \r
                public virtual void GetObjectData (SerializationInfo info, StreamingContext context)\r
                {\r
-                       info.AddValue ("KeyComparer", comparer, typeof(IKeyComparer));\r
+                       if (info == null)\r
+                               throw new ArgumentNullException ("info");\r
+\r
+                       info.AddValue ("KeyComparer", comparer, typeof (IEqualityComparer));\r
                        info.AddValue ("ReadOnly", readOnly);\r
                        info.AddValue ("InitialCapacity", initialCapacity);\r
-                       info.AddValue ("HashTable", hash);\r
-                       info.AddValue ("ArrayList", list);\r
+\r
+                       object[] array = new object [hash.Count];\r
+                       hash.CopyTo (array, 0);\r
+                       info.AddValue ("ArrayList", array);\r
                }\r
-               \r
+\r
                IEnumerator IEnumerable.GetEnumerator()\r
                {\r
                        return list.GetEnumerator ();\r
@@ -106,14 +126,14 @@ namespace System.Collections.Specialized
                                return list.Count;\r
                        }\r
                }\r
-               \r
-               public bool IsSynchronized {\r
+\r
+               bool ICollection.IsSynchronized {\r
                        get {\r
                                return list.IsSynchronized;\r
                        }\r
                }\r
-               \r
-               public object SyncRoot {\r
+\r
+               object ICollection.SyncRoot {\r
                        get {\r
                                return list.SyncRoot;\r
                        }\r
@@ -123,29 +143,28 @@ namespace System.Collections.Specialized
                {\r
                        list.CopyTo (array, index);\r
                }\r
-               \r
-               public bool IsFixedSize\r
-               {\r
+\r
+               bool IDictionary.IsFixedSize {\r
                        get {\r
                                return false;\r
                        }\r
                }\r
                \r
-               public virtual bool IsReadOnly\r
+               public bool IsReadOnly\r
                {\r
                        get {\r
                                return readOnly;\r
                        }\r
                }\r
                \r
-               public virtual object this [object key]\r
+               public object this [object key]\r
                {\r
                        get { return hash [key]; }\r
                        set {\r
                                WriteCheck ();\r
                                if (hash.Contains (key)) {\r
                                        int i = FindListEntry (key);\r
-                                       list [i] = value;\r
+                                       list [i] = new DictionaryEntry (key, value);\r
                                } else\r
                                        list.Add (new DictionaryEntry (key, value));\r
                                \r
@@ -153,24 +172,27 @@ namespace System.Collections.Specialized
                        }\r
                }\r
                \r
-               public virtual object this [int index]\r
+               public object this [int index]\r
                {\r
                        get { return ((DictionaryEntry) list [index]).Value; }\r
                        set {\r
                                WriteCheck ();\r
                                DictionaryEntry de = (DictionaryEntry) list [index];\r
                                de.Value = value;\r
+                               // update (even on the list) isn't automatic\r
+                               list [index] = de;\r
+                               hash [de.Key] = value;\r
                        }\r
                }\r
                \r
-               public virtual ICollection Keys\r
+               public ICollection Keys\r
                {\r
                        get {\r
                                return new OrderedCollection (list, true);\r
                        }\r
                }\r
                \r
-               public virtual ICollection Values\r
+               public ICollection Values\r
                {\r
                        get {\r
                                return new OrderedCollection (list, false);\r
@@ -205,25 +227,19 @@ namespace System.Collections.Specialized
                {\r
                        WriteCheck ();\r
 \r
-                       hash.Remove (key);\r
-                       int i = FindListEntry (key);\r
-                       list.RemoveAt (i);\r
+                       if (hash.Contains (key)) {\r
+                               hash.Remove (key);\r
+                               int i = FindListEntry (key);\r
+                               list.RemoveAt (i);\r
+                       }\r
                }\r
                \r
                int FindListEntry (object key)\r
                {\r
-                       if (comparer != null) {\r
-                               for (int n=0; n<list.Count; n++) {\r
-                                       DictionaryEntry de = (DictionaryEntry) list [n];\r
-                                       if (comparer.Equals (de.Key, key))\r
-                                               return n;\r
-                               }\r
-                       } else {\r
-                               for (int n=0; n<list.Count; n++) {\r
-                                       DictionaryEntry de = (DictionaryEntry) list [n];\r
-                                       if (de.Key.Equals (key))\r
-                                               return n;\r
-                               }\r
+                       for (int n=0; n<list.Count; n++) {\r
+                               DictionaryEntry de = (DictionaryEntry) list [n];\r
+                               if (comparer != null ? comparer.Equals(de.Key, key) : de.Key.Equals(key))\r
+                                       return n;\r
                        }\r
                        return -1;\r
                }\r
@@ -231,7 +247,7 @@ namespace System.Collections.Specialized
                void WriteCheck ()\r
                {\r
                        if (readOnly)\r
-                               throw new InvalidOperationException ("Collection is read only");\r
+                               throw new NotSupportedException ("Collection is read only");\r
                }\r
                \r
                public OrderedDictionary AsReadOnly ()\r