2005-12-07 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Collections / SortedList.cs
index e36500a28452bbdb4da4f78735f47cb32019e488..3fc8fe47b684ce83fab7dac9c55c78d3a8291fe9 100644 (file)
-// \r
-// System.Collections.SortedList\r
-// \r
-// Author:\r
-//   Sergey Chaban (serge@wildwestsoftware.com)\r
-// \r
-\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Globalization;\r
-\r
-namespace System.Collections {\r
-\r
-       /// <summary>\r
-       ///  Represents a collection of associated keys and values\r
-       ///  that are sorted by the keys and are accessible by key\r
-       ///  and by index.\r
-       /// </summary>\r
-       [Serializable]\r
-       public class SortedList : IDictionary, ICollection,\r
-                                 IEnumerable, ICloneable {\r
-\r
-\r
-               internal struct Slot {\r
-                       internal Object key;\r
-                       internal Object value;\r
-               }\r
-\r
-               private readonly static int INITIAL_SIZE = 16;\r
-\r
-               public enum EnumeratorMode : int {KEY_MODE = 0, VALUE_MODE}\r
-\r
-               private int inUse;\r
-               private int modificationCount;\r
-               private Slot[] table;\r
-               private IComparer comparer;\r
-\r
-               //\r
-               // Constructors\r
-               //\r
-               public SortedList () : this (INITIAL_SIZE)\r
-               {\r
-               }\r
-\r
-               public SortedList (int initialCapacity)\r
-                       : this (null, initialCapacity)\r
-               {\r
-               }\r
-\r
-               public SortedList (IComparer comparer, int initialCapacity)\r
-               {\r
-                       if (initialCapacity < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       this.comparer = comparer;\r
-                       InitTable (initialCapacity, true);\r
-               }\r
-\r
-               public SortedList (IComparer comparer)\r
-               {\r
-                       this.comparer = comparer;\r
-                       InitTable (INITIAL_SIZE, true);\r
-               }\r
-\r
-\r
-               public SortedList (IDictionary d) : this (d, null)\r
-               {\r
-               }\r
-\r
-               public SortedList (IDictionary d, IComparer comparer)\r
-               {\r
-                       if (d  ==  null)\r
-                               throw new ArgumentNullException ("dictionary");\r
-\r
-                       InitTable (d.Count, true);\r
-                       this.comparer = comparer;\r
-\r
-                       IDictionaryEnumerator it = d.GetEnumerator ();\r
-                       while (it.MoveNext ()) {\r
-                               if (it.Key is IComparable) {\r
-                                       Add (it.Key, it.Value);\r
-                               } else {\r
-                                       throw new InvalidCastException("!IComparable");\r
-                               }\r
-                       }\r
-               }\r
-\r
-               //\r
-               // Properties\r
-               //\r
-\r
-               // ICollection\r
-\r
-               public virtual int Count {\r
-                       get {\r
-                               return inUse;\r
-                       }\r
-               }\r
-\r
-               public virtual bool IsSynchronized {\r
-                       get {\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               public virtual Object SyncRoot {\r
-                       get {\r
-                               return this;\r
-                       }\r
-               }\r
-\r
-\r
-               // IDictionary\r
-\r
-               public virtual bool IsFixedSize {\r
-                       get {\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-\r
-               public virtual bool IsReadOnly {\r
-                       get {\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               public virtual ICollection Keys {\r
-                       get {\r
-                               return new ListKeys (this);\r
-                       }\r
-               }\r
-\r
-               public virtual ICollection Values {\r
-                       get {\r
-                               return new ListValues (this);\r
-                       }\r
-               }\r
-\r
-\r
-\r
-               public virtual Object this [Object key] {\r
-                       get {\r
-                               if (key == null)\r
-                                       throw new ArgumentNullException();\r
-                               return GetImpl (key);\r
-                       }\r
-                       set {\r
-                               if (key == null)\r
-                                       throw new ArgumentNullException();\r
-                               if (IsReadOnly)\r
-                                       throw new NotSupportedException("SortedList is Read Only.");\r
-                               if (Find(key) < 0 && IsFixedSize)\r
-                                       throw new NotSupportedException("Key not found and SortedList is fixed size.");\r
-\r
-                               PutImpl (key, value, true);\r
-                       }\r
-               }\r
-\r
-               public virtual int Capacity {\r
-                       get {\r
-                               return table.Length;\r
-                       }\r
-                       set {\r
-                               Slot [] table = this.table;\r
-                               int current = table.Length;\r
-\r
-                               if (inUse > value)\r
-                                       throw new ArgumentOutOfRangeException("capacity too small");\r
-\r
-                               if (value > current) {\r
-                                       Slot [] newTable = new Slot [value];\r
-                                       Array.Copy (table, newTable, current);\r
-                                       this.table = newTable;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               //\r
-               // Public instance methods.\r
-               //\r
-\r
-               // IEnumerable\r
-\r
-               IEnumerator IEnumerable.GetEnumerator ()\r
-               {\r
-                       return new Enumerator (this, EnumeratorMode.KEY_MODE);\r
-               }\r
-\r
-\r
-               // IDictionary\r
-\r
-               public virtual void Add (object key, object value)\r
-               {\r
-                       PutImpl (key, value, false);\r
-               }\r
-\r
-\r
-               public virtual void Clear () \r
-               {\r
-                       this.table = new Slot [INITIAL_SIZE];\r
-                       inUse = 0;\r
-                       modificationCount++;\r
-               }\r
-\r
-               public virtual bool Contains (object key)\r
-               {\r
-                       if (null == key)\r
-                               throw new ArgumentNullException();\r
-\r
-                       try {\r
-                               return (Find (key) >= 0);\r
-                       } catch (Exception) {\r
-                               throw new InvalidOperationException();\r
-                       }\r
-               }\r
-\r
-\r
-               public virtual IDictionaryEnumerator GetEnumerator ()\r
-               {\r
-                       return new Enumerator (this, EnumeratorMode.KEY_MODE);\r
-               }\r
-\r
-               public virtual void Remove (object key)\r
-               {\r
-                       int i = IndexOfKey (key);\r
-                       if (i >= 0) RemoveAt (i);\r
-               }\r
-\r
-\r
-               // ICollection\r
-\r
-               public virtual void CopyTo (Array array, int arrayIndex)\r
-               {\r
-                       if (null == array)\r
-                               throw new ArgumentNullException();\r
-\r
-                       if (arrayIndex < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-                       \r
-                       if (array.Rank > 1)\r
-                               throw new ArgumentException("array is multi-dimensional");\r
-                       if (arrayIndex >= array.Length)\r
-                               throw new ArgumentNullException("arrayIndex is greater than or equal to array.Length");\r
-                       if (Count > (array.Length - arrayIndex))\r
-                               throw new ArgumentNullException("Not enough space in array from arrayIndex to end of array");\r
-\r
-                       IDictionaryEnumerator it = GetEnumerator ();\r
-                       int i = arrayIndex;\r
-\r
-                       while (it.MoveNext ()) {\r
-                               array.SetValue (it.Entry, i++);\r
-                       }\r
-               }\r
-\r
-\r
-\r
-               // ICloneable\r
-\r
-               public virtual object Clone ()\r
-               {\r
-                       SortedList sl = new SortedList (this, comparer);\r
-                       sl.modificationCount = this.modificationCount;\r
-                       return sl;\r
-               }\r
-\r
-\r
-\r
-\r
-               //\r
-               // SortedList\r
-               //\r
-\r
-               public virtual IList GetKeyList ()\r
-               {\r
-                       return new ListKeys (this);\r
-               }\r
-\r
-\r
-               public virtual IList GetValueList ()\r
-               {\r
-                       return new ListValues (this);\r
-               }\r
-\r
-\r
-               public virtual void RemoveAt (int index)\r
-               {\r
-                       Slot [] table = this.table;\r
-                       int cnt = Count;\r
-                       if (index >= 0 && index < cnt) {\r
-                               if (index != cnt - 1) {\r
-                                       Array.Copy (table, index+1, table, index, cnt-1-index);\r
-                               } else {\r
-                                       table [index].key = null;\r
-                                       table [index].value = null;\r
-                               }\r
-                               --inUse;\r
-                               ++modificationCount;\r
-                       } else {\r
-                               throw new ArgumentOutOfRangeException("index out of range");\r
-                       }\r
-               }\r
-\r
-               public virtual int IndexOfKey (object key)\r
-               {\r
-                       if (null == key)\r
-                               throw new ArgumentNullException();\r
-\r
-                       int indx = 0;\r
-                       try {\r
-                               indx = Find (key);\r
-                       } catch (Exception) {\r
-                               throw new InvalidOperationException();\r
-                       }\r
-\r
-                       return (indx | (indx >> 31));\r
-               }\r
-\r
-\r
-               public virtual int IndexOfValue (object value)\r
-               {\r
-                       if (null == value)\r
-                               return -1;\r
-\r
-                       Slot [] table = this.table;\r
-                       int len = table.Length;\r
-\r
-                       for (int i=0; i < len; i++) {\r
-                               object trialValue = table[i].value;\r
-                               if ((null != trialValue) && (trialValue.Equals (value))) {\r
-                                       return i;\r
-                               }\r
-                       }\r
-\r
-                       return -1;\r
-               }\r
-\r
-\r
-               public virtual bool ContainsKey (object key)\r
-               {\r
-                       if (null == key)\r
-                               throw new ArgumentNullException();\r
-\r
-                       try {\r
-                               return Contains (key);   \r
-                       } catch (Exception) {\r
-                               throw new InvalidOperationException();\r
-                       }\r
-               }\r
-\r
-\r
-               public virtual bool ContainsValue (object value)\r
-               {\r
-                       return IndexOfValue (value) >= 0;\r
-               }\r
-\r
-\r
-               public virtual object GetByIndex (int index)\r
-               {\r
-                       if (index >= 0 && index < Count) {\r
-                               return table [index].value;\r
-                       } else {\r
-                               throw new ArgumentOutOfRangeException("index out of range");\r
-                       }\r
-               }\r
-\r
-\r
-               public virtual void SetByIndex (int index, object value)\r
-               {\r
-                       if (index >= 0 && index < Count) {\r
-                               table [index].value = value;\r
-                       } else {\r
-                               throw new ArgumentOutOfRangeException("index out of range");\r
-                       }\r
-               }\r
-\r
-\r
-               public virtual object GetKey (int index)\r
-               {\r
-                       if (index >= 0 && index < Count) {\r
-                               return table [index].key;\r
-                       } else {\r
-                               throw new ArgumentOutOfRangeException("index out of range");\r
-                       }\r
-               }\r
-\r
-               public static SortedList Synchronized (SortedList list)\r
-               {\r
-                       if (list == null)\r
-                               throw new ArgumentNullException (Locale.GetText ("Base list is null."));\r
-                       return new SynchedSortedList (list);\r
-               }\r
-\r
-               public virtual void TrimToSize ()\r
-               {\r
-                       // From Beta2:\r
-                       // Trimming an empty SortedList sets the capacity\r
-                       // of the SortedList to the default capacity,\r
-                       // not zero.\r
-                       if (Count == 0) Resize (INITIAL_SIZE, false);\r
-                       else Resize (Count, true);\r
-               }\r
-\r
-\r
-               //\r
-               // Private methods\r
-               //\r
-\r
-\r
-               private void Resize (int n, bool copy)\r
-               {\r
-                       Slot [] table = this.table;\r
-                       Slot [] newTable = new Slot [n];\r
-                       if (copy) Array.Copy (table, 0, newTable, 0, n);\r
-                       this.table = newTable;\r
-               }\r
-\r
-\r
-               private void EnsureCapacity (int n, int free)\r
-               {\r
-                       Slot [] table = this.table;\r
-                       Slot [] newTable = null;\r
-                       int cap = Capacity;\r
-                       bool gap = (free >=0 && free < Count);\r
-\r
-                       if (n > cap) {\r
-                               newTable = new Slot [n << 1];\r
-                       }\r
-\r
-                       if (newTable != null) {\r
-                               if (gap) {\r
-                                       int copyLen = free;\r
-                                       if (copyLen > 0) {\r
-                                               Array.Copy (table, 0, newTable, 0, copyLen);\r
-                                       }\r
-                                       copyLen = Count - free;\r
-                                       if (copyLen > 0) {\r
-                                               Array.Copy (table, free, newTable, free+1, copyLen);\r
-                                       }\r
-                               } else {\r
-                                       // Just a resizing, copy the entire table.\r
-                                       Array.Copy (table, newTable, Count);\r
-                               }\r
-                               this.table = newTable;\r
-                       } else if (gap) {\r
-                               Array.Copy (table, free, table, free+1, Count - free);\r
-                       }\r
-               }\r
-\r
-\r
-               private void PutImpl (object key, object value, bool overwrite)\r
-               {\r
-                       if (key == null)\r
-                               throw new ArgumentNullException ("null key");\r
-\r
-                       Slot [] table = this.table;\r
-\r
-                       int freeIndx = -1;\r
-\r
-                       try {\r
-                               freeIndx = Find (key);\r
-                       } catch (Exception) {\r
-                               throw new InvalidOperationException();\r
-                       }\r
-\r
-                       if (freeIndx >= 0) {\r
-                               if (!overwrite)\r
-                                       throw new ArgumentException("element already exists");\r
-\r
-                               table [freeIndx].value = value;\r
-                               return;\r
-                       }\r
-\r
-                       freeIndx = ~freeIndx;\r
-\r
-                       if (freeIndx > Capacity + 1)\r
-                               throw new Exception ("SortedList::internal error ("+key+", "+value+") at ["+freeIndx+"]");\r
-\r
-\r
-                       EnsureCapacity (Count+1, freeIndx);\r
-\r
-                       table = this.table;\r
-                       table [freeIndx].key = key;\r
-                       table [freeIndx].value = value;\r
-\r
-                       ++inUse;\r
-                       ++modificationCount;\r
-\r
-               }\r
-\r
-\r
-               private object GetImpl (object key)\r
-               {\r
-                       int i = Find (key);\r
-\r
-                       if (i >= 0)\r
-                               return table [i].value;\r
-                       else\r
-                               return null;\r
-               }\r
-\r
-               private void InitTable (int capacity)\r
-               {\r
-                       InitTable (capacity, false);\r
-               }\r
-\r
-               private void InitTable (int capacity, bool forceSize) {\r
-                       if (!forceSize && (capacity < INITIAL_SIZE)) capacity = INITIAL_SIZE;\r
-                       this.table = new Slot [capacity];\r
-                       this.inUse = 0;\r
-                       this.modificationCount = 0;\r
-               }\r
-\r
-               private void  CopyToArray (Array arr, int i, \r
-                                          EnumeratorMode mode)\r
-               {\r
-                       IEnumerator it = new Enumerator (this, mode);\r
-\r
-                       while (it.MoveNext ()) {\r
-                               arr.SetValue (it.Current, i++);\r
-                       }\r
-               }\r
-\r
-\r
-               private int Find (object key)\r
-               {\r
-                       Slot [] table = this.table;\r
-                       int len = Count;\r
-\r
-                       if (len == 0) return ~0;\r
-\r
-                       IComparer comparer = (this.comparer == null)\r
-                                             ? Comparer.Default\r
-                                             : this.comparer;\r
-\r
-                       int left = 0;\r
-                       int right = len-1;\r
-\r
-                       while (left <= right) {\r
-                               int guess = (left + right) >> 1;\r
-\r
-                               int cmp = comparer.Compare (key, table[guess].key);\r
-                               if (cmp == 0) return guess;\r
-\r
-                               if (cmp >  0) left = guess+1;\r
-                               else right = guess-1;\r
-                       }\r
-\r
-                       return ~left;\r
-               }\r
-\r
-\r
-\r
-               //\r
-               // Inner classes\r
-               //\r
-\r
-\r
-               protected sealed class Enumerator : IDictionaryEnumerator,\r
-                                                   IEnumerator {\r
-\r
-                       private SortedList host;\r
-                       private int stamp;\r
-                       private int pos;\r
-                       private int size;\r
-                       private EnumeratorMode mode;\r
-\r
-                       private object currentKey;\r
-                       private object currentValue;\r
-\r
-                       private readonly static string xstr = "SortedList.Enumerator: snapshot out of sync.";\r
-\r
-                       public Enumerator (SortedList host, EnumeratorMode mode)\r
-                       {\r
-                               this.host = host;\r
-                               stamp = host.modificationCount;\r
-                               size = host.Count;\r
-                               this.mode = mode;\r
-                               Reset ();\r
-                       }\r
-\r
-                       public Enumerator (SortedList host)\r
-                       : this (host, EnumeratorMode.KEY_MODE)\r
-                       {\r
-                       }\r
-\r
-\r
-                       private void FailFast ()\r
-                       {\r
-                               if (host.modificationCount != stamp) {\r
-                                       throw new InvalidOperationException (xstr);\r
-                               }\r
-                       }\r
-\r
-                       public void Reset ()\r
-                       {\r
-                               FailFast ();\r
-\r
-                               pos = -1;\r
-                               currentKey = null;\r
-                               currentValue = null;\r
-                       }\r
-\r
-                       public bool MoveNext ()\r
-                       {\r
-                               FailFast ();\r
-\r
-                               Slot [] table = host.table;\r
-\r
-                               if (++pos < size) {\r
-                                       Slot entry = table [pos];\r
-\r
-                                       currentKey = entry.key;\r
-                                       currentValue = entry.value;\r
-                                       return true;\r
-                               }\r
-\r
-                               currentKey = null;\r
-                               currentValue = null;\r
-                               return false;\r
-                       }\r
-\r
-                       public DictionaryEntry Entry\r
-                       {\r
-                               get {\r
-                                       FailFast ();\r
-                                       return new DictionaryEntry (currentKey,\r
-                                                                   currentValue);\r
-                               }\r
-                       }\r
-\r
-                       public Object Key {\r
-                               get {\r
-                                       FailFast ();\r
-                                       return currentKey;\r
-                               }\r
-                       }\r
-\r
-                       public Object Value {\r
-                               get {\r
-                                       FailFast ();\r
-                                       return currentValue;\r
-                               }\r
-                       }\r
-\r
-                       public Object Current {\r
-                               get {\r
-                                       FailFast ();\r
-                                       return (mode == EnumeratorMode.KEY_MODE)\r
-                                               ? currentKey\r
-                                               : currentValue;\r
-                               }\r
-                       }\r
-               }\r
-\r
-\r
-               protected class ListKeys : IList, IEnumerable {\r
-\r
-                       private SortedList host;\r
-\r
-\r
-                       public ListKeys (SortedList host)\r
-                       {\r
-                               if (host == null)\r
-                                       throw new ArgumentNullException ();\r
-\r
-                               this.host = host;\r
-                       }\r
-\r
-                       //\r
-                       // ICollection\r
-                       //\r
-\r
-                       public virtual int Count {\r
-                               get {\r
-                                       return host.Count;\r
-                               }\r
-                       }\r
-\r
-                       public virtual bool IsSynchronized {\r
-                               get {\r
-                                       return host.IsSynchronized;\r
-                               }\r
-                       }\r
-\r
-                       public virtual Object SyncRoot {\r
-                               get {\r
-                                       return host.SyncRoot;\r
-                               }\r
-                       }\r
-\r
-                       public virtual void CopyTo (Array array, int arrayIndex)\r
-                       {\r
-                               host.CopyToArray (array, arrayIndex, EnumeratorMode.KEY_MODE);\r
-                       }\r
-\r
-\r
-                       //\r
-                       // IList\r
-                       //\r
-\r
-                       public virtual bool IsFixedSize {\r
-                               get {\r
-                                       return true;\r
-                               }\r
-                       }\r
-\r
-                       public virtual bool IsReadOnly {\r
-                               get {\r
-                                       return true;\r
-                               }\r
-                       }\r
-\r
-\r
-                       public virtual object this [int index] {\r
-                               get {\r
-                                       return host.GetKey (index);\r
-                               }\r
-                               set {\r
-                                       throw new NotSupportedException("attempt to modify a key");\r
-                               }\r
-                       }\r
-\r
-                       public virtual int Add (object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Add not supported");\r
-                       }\r
-\r
-                       public virtual void Clear ()\r
-                       {\r
-                               throw new NotSupportedException("IList::Clear not supported");\r
-                       }\r
-\r
-                       public virtual bool Contains (object key)\r
-                       {\r
-                               return host.Contains (key);\r
-                       }\r
-\r
-\r
-                       public virtual int IndexOf (object key)\r
-                       {\r
-                               return host.IndexOfKey (key);\r
-                       }\r
-\r
-\r
-                       public virtual void Insert (int index, object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Insert not supported");\r
-                       }\r
-\r
-\r
-                       public virtual void Remove (object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Remove not supported");\r
-                       }\r
-\r
-\r
-                       public virtual void RemoveAt (int index)\r
-                       {\r
-                               throw new NotSupportedException("IList::RemoveAt not supported");\r
-                       }\r
-\r
-\r
-                       //\r
-                       // IEnumerable\r
-                       //\r
-\r
-                       public virtual IEnumerator GetEnumerator ()\r
-                       {\r
-                               return new SortedList.Enumerator (host, EnumeratorMode.KEY_MODE);\r
-                       }\r
-\r
-\r
-               }\r
-\r
-\r
-               protected class ListValues : IList, IEnumerable {\r
-\r
-                       private SortedList host;\r
-\r
-\r
-                       public ListValues (SortedList host)\r
-                       {\r
-                               if (host == null)\r
-                                       throw new ArgumentNullException ();\r
-\r
-                               this.host = host;\r
-                       }\r
-\r
-                       //\r
-                       // ICollection\r
-                       //\r
-\r
-                       public virtual int Count {\r
-                               get {\r
-                                       return host.Count;\r
-                               }\r
-                       }\r
-\r
-                       public virtual bool IsSynchronized {\r
-                               get {\r
-                                       return host.IsSynchronized;\r
-                               }\r
-                       }\r
-\r
-                       public virtual Object SyncRoot {\r
-                               get {\r
-                                       return host.SyncRoot;\r
-                               }\r
-                       }\r
-\r
-                       public virtual void CopyTo (Array array, int arrayIndex)\r
-                       {\r
-                               host.CopyToArray (array, arrayIndex, EnumeratorMode.VALUE_MODE);\r
-                       }\r
-\r
-\r
-                       //\r
-                       // IList\r
-                       //\r
-\r
-                       public virtual bool IsFixedSize {\r
-                               get {\r
-                                       return true;\r
-                               }\r
-                       }\r
-\r
-                       public virtual bool IsReadOnly {\r
-                               get {\r
-                                       return true;\r
-                               }\r
-                       }\r
-\r
-\r
-                       [MonoTODO]\r
-                       public virtual object this [int index] {\r
-                               get {\r
-                                       return host.GetByIndex (index);\r
-                               }\r
-                               set {\r
-                                       // FIXME: It seems (according to tests)\r
-                                       // that modifications are allowed\r
-                                       // in Beta2.\r
-                                       // ? host.SetByIndex (index, value);\r
-                                       throw new NotSupportedException("attempt to modify a value");\r
-                               }\r
-                       }\r
-\r
-                       public virtual int Add (object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Add not supported");\r
-                       }\r
-\r
-                       public virtual void Clear ()\r
-                       {\r
-                               throw new NotSupportedException("IList::Clear not supported");\r
-                       }\r
-\r
-                       public virtual bool Contains (object value)\r
-                       {\r
-                               return host.ContainsValue (value);\r
-                       }\r
-\r
-\r
-                       public virtual int IndexOf (object value)\r
-                       {\r
-                               return host.IndexOfValue (value);\r
-                       }\r
-\r
-\r
-                       public virtual void Insert (int index, object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Insert not supported");\r
-                       }\r
-\r
-\r
-                       public virtual void Remove (object value)\r
-                       {\r
-                               throw new NotSupportedException("IList::Remove not supported");\r
-                       }\r
-\r
-\r
-                       public virtual void RemoveAt (int index)\r
-                       {\r
-                               throw new NotSupportedException("IList::RemoveAt not supported");\r
-                       }\r
-\r
-\r
-                       //\r
-                       // IEnumerable\r
-                       //\r
-\r
-                       public virtual IEnumerator GetEnumerator ()\r
-                       {\r
-                               return new SortedList.Enumerator (host, EnumeratorMode.VALUE_MODE);\r
-                       }\r
-\r
-               }\r
-\r
-               protected class SynchedSortedList : SortedList {\r
-\r
-                       private SortedList host;\r
-\r
-                       public SynchedSortedList (SortedList host)\r
-                       {\r
-                               if (host == null)\r
-                                       throw new ArgumentNullException ();\r
-                               this.host = host;\r
-                       }\r
-\r
-                       // ICollection\r
-\r
-                       public override int Count {\r
-                               get {\r
-                                       return host.Count;\r
-                               }\r
-                       }\r
-\r
-                       public override bool IsSynchronized {\r
-                               get {\r
-                                       return true;\r
-                               }\r
-                       }\r
-\r
-                       public override Object SyncRoot {\r
-                               get {\r
-                                       return host.SyncRoot;\r
-                               }\r
-                       }\r
-\r
-\r
-\r
-                       // IDictionary\r
-\r
-                       public override bool IsFixedSize {\r
-                               get {\r
-                                       return host.IsFixedSize;\r
-                               }     \r
-                       }\r
-\r
-\r
-                       public override bool IsReadOnly {\r
-                               get {\r
-                                       return host.IsReadOnly;\r
-                               }\r
-                       }\r
-\r
-                       public override ICollection Keys {\r
-                               get {\r
-                                       ICollection keys = null;\r
-                                       lock (host.SyncRoot) {\r
-                                               keys = host.Keys;\r
-                                       }\r
-                                       return keys;\r
-                               }\r
-                       }\r
-\r
-                       public override ICollection Values {\r
-                               get {\r
-                                       ICollection vals = null;\r
-                                       lock (host.SyncRoot) {\r
-                                               vals = host.Values;\r
-                                       }\r
-                                       return vals;\r
-                               }\r
-                       }\r
-\r
-\r
-\r
-                       public override Object this [object key] {\r
-                               get {\r
-                                       lock (host.SyncRoot) {\r
-                                               return host.GetImpl (key);\r
-                                       }\r
-                               }\r
-                               set {\r
-                                       lock (host.SyncRoot) {\r
-                                               host.PutImpl (key, value, true);\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-\r
-\r
-                       // ICollection\r
-\r
-                       public override void CopyTo (Array array, int arrayIndex)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.CopyTo (array, arrayIndex);\r
-                               }\r
-                       }\r
-\r
-\r
-                       // IDictionary\r
-\r
-                       public override void Add (object key, object value)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.PutImpl (key, value, false);\r
-                               }\r
-                       }\r
-\r
-                       public override void Clear () \r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.Clear ();\r
-                               }\r
-                       }\r
-\r
-                       public override bool Contains (object key)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return (host.Find (key) >= 0);\r
-                               }\r
-                       }\r
-\r
-                       public override IDictionaryEnumerator GetEnumerator ()\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.GetEnumerator();\r
-                               }\r
-                       }\r
-\r
-                       public override void Remove (object key)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.Remove (key);\r
-                               }\r
-                       }\r
-\r
-\r
-\r
-                       public override bool ContainsKey (object key)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.Contains (key);\r
-                               }\r
-                       }\r
-\r
-                       public override bool ContainsValue (object value)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.ContainsValue (value);\r
-                               }\r
-                       }\r
-\r
-\r
-                       // ICloneable\r
-\r
-                       public override object Clone ()\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return (host.Clone () as SortedList);\r
-                               }\r
-                       }\r
-\r
-\r
-\r
-                       //\r
-                       // SortedList overrides\r
-                       //\r
-\r
-                       public override Object GetByIndex (int index)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.GetByIndex (index);\r
-                               }\r
-                       }\r
-\r
-                       public override Object GetKey (int index)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.GetKey (index);\r
-                               }\r
-                       }\r
-\r
-                       public override IList GetKeyList ()\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return new ListKeys (host);\r
-                               }\r
-                       }\r
-\r
-\r
-                       public override IList GetValueList ()\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return new ListValues (host);\r
-                               }\r
-                       }\r
-\r
-                       public override void RemoveAt (int index)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.RemoveAt (index);\r
-                               }\r
-                       }\r
-\r
-                       public override int IndexOfKey (object key)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.IndexOfKey (key);\r
-                               }\r
-                       }\r
-\r
-                       public override int IndexOfValue (Object val)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       return host.IndexOfValue (val);\r
-                               }\r
-                       }\r
-\r
-                       public override void SetByIndex (int index, object value)\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.SetByIndex (index, value);\r
-                               }\r
-                       }\r
-\r
-                       public override void TrimToSize()\r
-                       {\r
-                               lock (host.SyncRoot) {\r
-                                       host.TrimToSize();\r
-                               }\r
-                       }\r
-\r
-\r
-               } // SynchedSortedList\r
-\r
-       } // SortedList\r
-\r
-} // System.Collections\r
+// 
+// System.Collections.SortedList.cs
+// 
+// Author:
+//   Sergey Chaban (serge@wildwestsoftware.com)
+//   Duncan Mak (duncan@ximian.com)
+//   Herve Poussineau (hpoussineau@fr.st
+// 
+
+//
+// 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
+// "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.
+//
+
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+namespace System.Collections {
+
+       /// <summary>
+       ///  Represents a collection of associated keys and values
+       ///  that are sorted by the keys and are accessible by key
+       ///  and by index.
+       /// </summary>
+       [Serializable]
+#if NET_2_0
+       [ComVisible(true)]
+#endif
+       public class SortedList : IDictionary, ICollection,
+                                 IEnumerable, ICloneable {
+
+
+               [Serializable]
+               internal struct Slot {
+                       internal Object key;
+                       internal Object value;
+               }
+
+               private readonly static int INITIAL_SIZE = 16;
+
+               private enum EnumeratorMode : int { KEY_MODE = 0, VALUE_MODE, ENTRY_MODE }
+
+               private int inUse;
+               private int modificationCount;
+               private Slot[] table;
+               private IComparer comparer;
+               private int defaultCapacity;
+
+               //
+               // Constructors
+               //
+               public SortedList () 
+                       : this (null, INITIAL_SIZE)
+               {
+               }
+
+               public SortedList (int initialCapacity)
+                       : this (null, initialCapacity)
+               {
+               }
+
+               public SortedList (IComparer comparer, int initialCapacity)
+               {
+                       if (initialCapacity < 0)
+                               throw new ArgumentOutOfRangeException ("initialCapacity");
+
+                       if (initialCapacity == 0)
+                               defaultCapacity = 0;
+                       else
+                               defaultCapacity = INITIAL_SIZE;
+
+                       this.comparer = comparer;
+                       InitTable (initialCapacity, true);
+               }
+
+               public SortedList (IComparer comparer)
+               {
+                       this.comparer = comparer;
+                       InitTable (INITIAL_SIZE, true);
+               }
+
+
+               public SortedList (IDictionary d) : this (d, null)
+               {
+               }
+
+               // LAMESPEC: MSDN docs talk about an InvalidCastException but 
+               // I wasn't able to duplicate such a case in the unit tests.
+               public SortedList (IDictionary d, IComparer comparer)
+               {
+                       if (d  ==  null)
+                               throw new ArgumentNullException ("dictionary");
+
+                       InitTable (d.Count, true);
+                       this.comparer = comparer;
+
+                       IDictionaryEnumerator it = d.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               Add (it.Key, it.Value);
+                       }
+               }
+
+               //
+               // Properties
+               //
+
+               // ICollection
+
+               public virtual int Count {
+                       get {
+                               return inUse;
+                       }
+               }
+
+               public virtual bool IsSynchronized {
+                       get {
+                               return false;
+                       }
+               }
+
+               public virtual Object SyncRoot {
+                       get {
+                               return this;
+                       }
+               }
+
+
+               // IDictionary
+
+               public virtual bool IsFixedSize {
+                       get {
+                               return false;
+                       }
+               }
+
+
+               public virtual bool IsReadOnly {
+                       get {
+                               return false;
+                       }
+               }
+
+               public virtual ICollection Keys {
+                       get {
+                               return new ListKeys (this);
+                       }
+               }
+
+               public virtual ICollection Values {
+                       get {
+                               return new ListValues (this);
+                       }
+               }
+
+
+
+               public virtual Object this [Object key] {
+                       get {
+                               if (key == null)
+                                       throw new ArgumentNullException();
+                               return GetImpl (key);
+                       }
+                       set {
+                               if (key == null)
+                                       throw new ArgumentNullException();
+                               if (IsReadOnly)
+                                       throw new NotSupportedException("SortedList is Read Only.");
+                               if (Find(key) < 0 && IsFixedSize)
+                                       throw new NotSupportedException("Key not found and SortedList is fixed size.");
+
+                               PutImpl (key, value, true);
+                       }
+               }
+
+               public virtual int Capacity {
+                       get {
+                               return table.Length;
+                       }
+
+                       set {
+                               int current = this.table.Length;
+
+                               if (inUse > value) {
+                                       throw new ArgumentOutOfRangeException("capacity too small");
+                               }
+                               else if (value == 0) {
+                                       // return to default size
+                                        Slot [] newTable = new Slot [defaultCapacity];
+                                        Array.Copy (table, newTable, inUse);
+                                        this.table = newTable;
+                               }
+#if NET_1_0
+                               else if (current > defaultCapacity && value < current) {
+                                        Slot [] newTable = new Slot [defaultCapacity];
+                                        Array.Copy (table, newTable, inUse);
+                                        this.table = newTable;
+                                }
+#endif
+                               else if (value > inUse) {
+                                        Slot [] newTable = new Slot [value];
+                                        Array.Copy (table, newTable, inUse);
+                                        this.table = newTable;
+                                }
+                               else if (value > current) {
+                                       Slot [] newTable = new Slot [value];
+                                       Array.Copy (table, newTable, current);
+                                       this.table = newTable;
+                               }
+                       }
+               }
+
+               //
+               // Public instance methods.
+               //
+
+               // IEnumerable
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return new Enumerator (this, EnumeratorMode.ENTRY_MODE);
+               }
+
+
+               // IDictionary
+
+               public virtual void Add (object key, object value)
+               {
+                       PutImpl (key, value, false);
+               }
+
+
+               public virtual void Clear () 
+               {
+                       defaultCapacity = INITIAL_SIZE;
+                       this.table = new Slot [defaultCapacity];
+                       inUse = 0;
+                       modificationCount++;
+               }
+
+               public virtual bool Contains (object key)
+               {
+                       if (null == key)
+                               throw new ArgumentNullException();
+
+                       try {
+                               return (Find (key) >= 0);
+                       } catch (Exception) {
+                               throw new InvalidOperationException();
+                       }
+               }
+
+
+               public virtual IDictionaryEnumerator GetEnumerator ()
+               {
+                       return new Enumerator (this, EnumeratorMode.ENTRY_MODE);
+               }
+
+               public virtual void Remove (object key)
+               {
+                       int i = IndexOfKey (key);
+                       if (i >= 0) RemoveAt (i);
+               }
+
+
+               // ICollection
+
+               public virtual void CopyTo (Array array, int arrayIndex)
+               {
+                       if (null == array)
+                               throw new ArgumentNullException();
+
+                       if (arrayIndex < 0)
+                               throw new ArgumentOutOfRangeException();
+                       
+                       if (array.Rank > 1)
+                               throw new ArgumentException("array is multi-dimensional");
+                       if (arrayIndex >= array.Length)
+                               throw new ArgumentNullException("arrayIndex is greater than or equal to array.Length");
+                       if (Count > (array.Length - arrayIndex))
+                               throw new ArgumentNullException("Not enough space in array from arrayIndex to end of array");
+
+                       IDictionaryEnumerator it = GetEnumerator ();
+                       int i = arrayIndex;
+
+                       while (it.MoveNext ()) {
+                               array.SetValue (it.Entry, i++);
+                       }
+               }
+
+
+
+               // ICloneable
+
+               public virtual object Clone ()
+               {
+                       SortedList sl = new SortedList (this, comparer);
+                       sl.modificationCount = this.modificationCount;
+                       return sl;
+               }
+
+
+
+
+               //
+               // SortedList
+               //
+
+               public virtual IList GetKeyList ()
+               {
+                       return new ListKeys (this);
+               }
+
+
+               public virtual IList GetValueList ()
+               {
+                       return new ListValues (this);
+               }
+
+
+               public virtual void RemoveAt (int index)
+               {
+                       Slot [] table = this.table;
+                       int cnt = Count;
+                       if (index >= 0 && index < cnt) {
+                               if (index != cnt - 1) {
+                                       Array.Copy (table, index+1, table, index, cnt-1-index);
+                               } else {
+                                       table [index].key = null;
+                                       table [index].value = null;
+                               }
+                               --inUse;
+                               ++modificationCount;
+                       } else {
+                               throw new ArgumentOutOfRangeException("index out of range");
+                       }
+               }
+
+               public virtual int IndexOfKey (object key)
+               {
+                       if (null == key)
+                               throw new ArgumentNullException();
+
+                       int indx = 0;
+                       try {
+                               indx = Find (key);
+                       } catch (Exception) {
+                               throw new InvalidOperationException();
+                       }
+
+                       return (indx | (indx >> 31));
+               }
+
+
+               public virtual int IndexOfValue (object value)
+               {
+                       if (inUse == 0)
+                               return -1;
+
+                       for (int i = 0; i < inUse; i ++) {
+                               Slot current = this.table [i];
+
+                               if (Equals (value, current.value))
+                                       return i;
+                       }
+
+                       return -1;
+               }
+
+
+               public virtual bool ContainsKey (object key)
+               {
+                       if (null == key)
+                               throw new ArgumentNullException();
+
+                       try {
+                               return Contains (key);   
+                       } catch (Exception) {
+                               throw new InvalidOperationException();
+                       }
+               }
+
+
+               public virtual bool ContainsValue (object value)
+               {
+                       return IndexOfValue (value) >= 0;
+               }
+
+
+               public virtual object GetByIndex (int index)
+               {
+                       if (index >= 0 && index < Count)
+                               return table [index].value;
+
+                       else 
+                               throw new ArgumentOutOfRangeException("index out of range");
+               }
+
+
+               public virtual void SetByIndex (int index, object value)
+               {
+                       if (index >= 0 && index < Count)
+                               table [index].value = value;
+
+                       else
+                               throw new ArgumentOutOfRangeException("index out of range");
+               }
+
+
+               public virtual object GetKey (int index)
+               {
+                       if (index >= 0 && index < Count)
+                               return table [index].key;
+
+                       else
+                               throw new ArgumentOutOfRangeException("index out of range");
+               }
+
+               public static SortedList Synchronized (SortedList list)
+               {
+                       if (list == null)
+                               throw new ArgumentNullException (Locale.GetText ("Base list is null."));
+
+                       return new SynchedSortedList (list);
+               }
+
+               public virtual void TrimToSize ()
+               {
+                       // From Beta2:
+                       // Trimming an empty SortedList sets the capacity
+                       // of the SortedList to the default capacity,
+                       // not zero.
+                       if (Count == 0)
+                                Resize (defaultCapacity, false);
+                       else
+                                Resize (Count, true);
+               }
+
+
+               //
+               // Private methods
+               //
+
+
+               private void Resize (int n, bool copy)
+               {
+                       Slot [] table = this.table;
+                       Slot [] newTable = new Slot [n];
+                       if (copy) Array.Copy (table, 0, newTable, 0, n);
+                       this.table = newTable;
+               }
+
+
+               private void EnsureCapacity (int n, int free)
+               {
+                       Slot [] table = this.table;
+                       Slot [] newTable = null;
+                       int cap = Capacity;
+                       bool gap = (free >=0 && free < Count);
+
+                       if (n > cap) {
+                               newTable = new Slot [n << 1];
+                       }
+
+                       if (newTable != null) {
+                               if (gap) {
+                                       int copyLen = free;
+                                       if (copyLen > 0) {
+                                               Array.Copy (table, 0, newTable, 0, copyLen);
+                                       }
+                                       copyLen = Count - free;
+                                       if (copyLen > 0) {
+                                               Array.Copy (table, free, newTable, free+1, copyLen);
+                                       }
+                               } else {
+                                       // Just a resizing, copy the entire table.
+                                       Array.Copy (table, newTable, Count);
+                               }
+                               this.table = newTable;
+                       } else if (gap) {
+                               Array.Copy (table, free, table, free+1, Count - free);
+                       }
+               }
+
+
+               private void PutImpl (object key, object value, bool overwrite)
+               {
+                       if (key == null)
+                               throw new ArgumentNullException ("null key");
+
+                       Slot [] table = this.table;
+
+                       int freeIndx = -1;
+
+                       try {
+                               freeIndx = Find (key);
+                       } catch (Exception) {
+                               throw new InvalidOperationException();
+                       }
+
+                       if (freeIndx >= 0) {
+                               if (!overwrite) {
+                                       string msg = Locale.GetText ("Key '{0}' already exists in list.", key);
+                                       throw new ArgumentException (msg);
+                               }
+
+                               table [freeIndx].value = value;
+                               ++modificationCount;
+                               return;
+                       }
+
+                       freeIndx = ~freeIndx;
+
+                       if (freeIndx > Capacity + 1)
+                               throw new Exception ("SortedList::internal error ("+key+", "+value+") at ["+freeIndx+"]");
+
+
+                       EnsureCapacity (Count+1, freeIndx);
+
+                       table = this.table;
+                       table [freeIndx].key = key;
+                       table [freeIndx].value = value;
+
+                       ++inUse;
+                       ++modificationCount;
+
+               }
+
+
+               private object GetImpl (object key)
+               {
+                       int i = Find (key);
+
+                       if (i >= 0)
+                               return table [i].value;
+                       else
+                               return null;
+               }
+
+               private void InitTable (int capacity, bool forceSize) 
+               {
+                       if (!forceSize && (capacity < defaultCapacity))
+                               capacity = defaultCapacity;
+                       this.table = new Slot [capacity];
+                       this.inUse = 0;
+                       this.modificationCount = 0;
+               }
+
+               private void  CopyToArray (Array arr, int i, 
+                                          EnumeratorMode mode)
+               {
+                       if (arr == null)
+                               throw new ArgumentNullException ("arr");
+
+                       if (i < 0 || i + this.Count > arr.Length)
+                               throw new ArgumentOutOfRangeException ("i");
+                       
+                       IEnumerator it = new Enumerator (this, mode);
+
+                       while (it.MoveNext ()) {
+                               arr.SetValue (it.Current, i++);
+                       }
+               }
+
+
+               private int Find (object key)
+               {
+                       Slot [] table = this.table;
+                       int len = Count;
+
+                       if (len == 0) return ~0;
+
+                       IComparer comparer = (this.comparer == null)
+                                             ? Comparer.Default
+                                             : this.comparer;
+
+                       int left = 0;
+                       int right = len-1;
+
+                       while (left <= right) {
+                               int guess = (left + right) >> 1;
+
+                               int cmp = comparer.Compare (key, table[guess].key);
+                               if (cmp == 0) return guess;
+
+                               if (cmp >  0) left = guess+1;
+                               else right = guess-1;
+                       }
+
+                       return ~left;
+               }
+
+
+
+               //
+               // Inner classes
+               //
+
+
+               private sealed class Enumerator : ICloneable, IDictionaryEnumerator, IEnumerator {
+
+                       private SortedList host;
+                       private int stamp;
+                       private int pos;
+                       private int size;
+                       private EnumeratorMode mode;
+
+                       private object currentKey;
+                       private object currentValue;
+
+                       bool invalid = false;
+
+                       private readonly static string xstr = "SortedList.Enumerator: snapshot out of sync.";
+
+                       public Enumerator (SortedList host, EnumeratorMode mode)
+                       {
+                               this.host = host;
+                               stamp = host.modificationCount;
+                               size = host.Count;
+                               this.mode = mode;
+                               Reset ();
+                       }
+
+                       public Enumerator (SortedList host)
+                       : this (host, EnumeratorMode.ENTRY_MODE)
+                       {
+                       }
+
+                       public void Reset ()
+                       {
+                               if (host.modificationCount != stamp || invalid)
+                                       throw new InvalidOperationException (xstr);
+
+                               pos = -1;
+                               currentKey = null;
+                               currentValue = null;
+                       }
+
+                       public bool MoveNext ()
+                       {
+                               if (host.modificationCount != stamp || invalid)
+                                       throw new InvalidOperationException (xstr);
+
+                               Slot [] table = host.table;
+
+                               if (++pos < size) {
+                                       Slot entry = table [pos];
+
+                                       currentKey = entry.key;
+                                       currentValue = entry.value;
+                                       return true;
+                               }
+
+                               currentKey = null;
+                               currentValue = null;
+                               return false;
+                       }
+
+                       public DictionaryEntry Entry
+                       {
+                               get {
+                                       if (invalid || pos >= size || pos == -1)
+                                               throw new InvalidOperationException (xstr);
+                                       
+                                       return new DictionaryEntry (currentKey,
+                                                                   currentValue);
+                               }
+                       }
+
+                       public Object Key {
+                               get {
+                                       if (invalid || pos >= size || pos == -1)
+                                               throw new InvalidOperationException (xstr);
+                                       return currentKey;
+                               }
+                       }
+
+                       public Object Value {
+                               get {
+                                       if (invalid || pos >= size || pos == -1)
+                                               throw new InvalidOperationException (xstr);
+                                       return currentValue;
+                               }
+                       }
+
+                       public Object Current {
+                               get {
+                                       if (invalid || pos >= size || pos == -1)
+                                               throw new InvalidOperationException (xstr);
+
+                                       switch (mode) {
+                                        case EnumeratorMode.KEY_MODE:
+                                                return currentKey;
+                                        case EnumeratorMode.VALUE_MODE:
+                                                return currentValue;
+                                        case EnumeratorMode.ENTRY_MODE:
+                                                return this.Entry;
+
+                                        default:
+                                                throw new NotSupportedException (mode + " is not a supported mode.");
+                                        }
+                               }
+                       }
+
+                       // ICloneable
+
+                       public object Clone ()
+                       {
+                               Enumerator e = new Enumerator (host, mode);
+                               e.stamp = stamp;
+                               e.pos = pos;
+                               e.size = size;
+                               e.currentKey = currentKey;
+                               e.currentValue = currentValue;
+                               e.invalid = invalid;
+                               return e;
+                       }
+               }
+
+
+               private class ListKeys : IList, IEnumerable {
+
+                       private SortedList host;
+
+
+                       public ListKeys (SortedList host)
+                       {
+                               if (host == null)
+                                       throw new ArgumentNullException ();
+
+                               this.host = host;
+                       }
+
+                       //
+                       // ICollection
+                       //
+
+                       public virtual int Count {
+                               get {
+                                       return host.Count;
+                               }
+                       }
+
+                       public virtual bool IsSynchronized {
+                               get {
+                                       return host.IsSynchronized;
+                               }
+                       }
+
+                       public virtual Object SyncRoot {
+                               get {
+                                       return host.SyncRoot;
+                               }
+                       }
+
+                       public virtual void CopyTo (Array array, int arrayIndex)
+                       {
+                               host.CopyToArray (array, arrayIndex, EnumeratorMode.KEY_MODE);
+                       }
+
+
+                       //
+                       // IList
+                       //
+
+                       public virtual bool IsFixedSize {
+                               get {
+                                       return true;
+                               }
+                       }
+
+                       public virtual bool IsReadOnly {
+                               get {
+                                       return true;
+                               }
+                       }
+
+
+                       public virtual object this [int index] {
+                               get {
+                                       return host.GetKey (index);
+                               }
+                               set {
+                                       throw new NotSupportedException("attempt to modify a key");
+                               }
+                       }
+
+                       public virtual int Add (object value)
+                       {
+                               throw new NotSupportedException("IList::Add not supported");
+                       }
+
+                       public virtual void Clear ()
+                       {
+                               throw new NotSupportedException("IList::Clear not supported");
+                       }
+
+                       public virtual bool Contains (object key)
+                       {
+                               return host.Contains (key);
+                       }
+
+
+                       public virtual int IndexOf (object key)
+                       {
+                               return host.IndexOfKey (key);
+                       }
+
+
+                       public virtual void Insert (int index, object value)
+                       {
+                               throw new NotSupportedException("IList::Insert not supported");
+                       }
+
+
+                       public virtual void Remove (object value)
+                       {
+                               throw new NotSupportedException("IList::Remove not supported");
+                       }
+
+
+                       public virtual void RemoveAt (int index)
+                       {
+                               throw new NotSupportedException("IList::RemoveAt not supported");
+                       }
+
+
+                       //
+                       // IEnumerable
+                       //
+
+                       public virtual IEnumerator GetEnumerator ()
+                       {
+                               return new SortedList.Enumerator (host, EnumeratorMode.KEY_MODE);
+                       }
+
+
+               }
+
+
+               private class ListValues : IList, IEnumerable {
+
+                       private SortedList host;
+
+
+                       public ListValues (SortedList host)
+                       {
+                               if (host == null)
+                                       throw new ArgumentNullException ();
+
+                               this.host = host;
+                       }
+
+                       //
+                       // ICollection
+                       //
+
+                       public virtual int Count {
+                               get {
+                                       return host.Count;
+                               }
+                       }
+
+                       public virtual bool IsSynchronized {
+                               get {
+                                       return host.IsSynchronized;
+                               }
+                       }
+
+                       public virtual Object SyncRoot {
+                               get {
+                                       return host.SyncRoot;
+                               }
+                       }
+
+                       public virtual void CopyTo (Array array, int arrayIndex)
+                       {
+                               host.CopyToArray (array, arrayIndex, EnumeratorMode.VALUE_MODE);
+                       }
+
+
+                       //
+                       // IList
+                       //
+
+                       public virtual bool IsFixedSize {
+                               get {
+                                       return true;
+                               }
+                       }
+
+                       public virtual bool IsReadOnly {
+                               get {
+                                       return true;
+                               }
+                       }
+
+
+                       [MonoTODO]
+                       public virtual object this [int index] {
+                               get {
+                                       return host.GetByIndex (index);
+                               }
+                               set {
+                                       // FIXME: It seems (according to tests)
+                                       // that modifications are allowed
+                                       // in Beta2.
+                                       // ? host.SetByIndex (index, value);
+                                       throw new NotSupportedException("attempt to modify a value");
+                               }
+                       }
+
+                       public virtual int Add (object value)
+                       {
+                               throw new NotSupportedException("IList::Add not supported");
+                       }
+
+                       public virtual void Clear ()
+                       {
+                               throw new NotSupportedException("IList::Clear not supported");
+                       }
+
+                       public virtual bool Contains (object value)
+                       {
+                               return host.ContainsValue (value);
+                       }
+
+
+                       public virtual int IndexOf (object value)
+                       {
+                               return host.IndexOfValue (value);
+                       }
+
+
+                       public virtual void Insert (int index, object value)
+                       {
+                               throw new NotSupportedException("IList::Insert not supported");
+                       }
+
+
+                       public virtual void Remove (object value)
+                       {
+                               throw new NotSupportedException("IList::Remove not supported");
+                       }
+
+
+                       public virtual void RemoveAt (int index)
+                       {
+                               throw new NotSupportedException("IList::RemoveAt not supported");
+                       }
+
+
+                       //
+                       // IEnumerable
+                       //
+
+                       public virtual IEnumerator GetEnumerator ()
+                       {
+                               return new SortedList.Enumerator (host, EnumeratorMode.VALUE_MODE);
+                       }
+
+               }
+
+               private class SynchedSortedList : SortedList {
+
+                       private SortedList host;
+
+                       public SynchedSortedList (SortedList host)
+                       {
+                               if (host == null)
+                                       throw new ArgumentNullException ();
+                               this.host = host;
+                       }
+
+                       public override int Capacity {
+                               get {
+                                       lock (host.SyncRoot) {
+                                               return host.Capacity;
+                                       }
+                               }
+                               set {
+                                       lock (host.SyncRoot) {
+                                               host.Capacity = value;
+                                       }
+                               }
+                       }
+
+                       // ICollection
+
+                       public override int Count {
+                               get {
+                                       return host.Count;
+                               }
+                       }
+
+                       public override bool IsSynchronized {
+                               get {
+                                       return true;
+                               }
+                       }
+
+                       public override Object SyncRoot {
+                               get {
+                                       return host.SyncRoot;
+                               }
+                       }
+
+
+
+                       // IDictionary
+
+                       public override bool IsFixedSize {
+                               get {
+                                       return host.IsFixedSize;
+                               }     
+                       }
+
+
+                       public override bool IsReadOnly {
+                               get {
+                                       return host.IsReadOnly;
+                               }
+                       }
+
+                       public override ICollection Keys {
+                               get {
+                                       ICollection keys = null;
+                                       lock (host.SyncRoot) {
+                                               keys = host.Keys;
+                                       }
+                                       return keys;
+                               }
+                       }
+
+                       public override ICollection Values {
+                               get {
+                                       ICollection vals = null;
+                                       lock (host.SyncRoot) {
+                                               vals = host.Values;
+                                       }
+                                       return vals;
+                               }
+                       }
+
+
+
+                       public override Object this [object key] {
+                               get {
+                                       lock (host.SyncRoot) {
+                                               return host.GetImpl (key);
+                                       }
+                               }
+                               set {
+                                       lock (host.SyncRoot) {
+                                               host.PutImpl (key, value, true);
+                                       }
+                               }
+                       }
+
+
+
+                       // ICollection
+
+                       public override void CopyTo (Array array, int arrayIndex)
+                       {
+                               lock (host.SyncRoot) {
+                                       host.CopyTo (array, arrayIndex);
+                               }
+                       }
+
+
+                       // IDictionary
+
+                       public override void Add (object key, object value)
+                       {
+                               lock (host.SyncRoot) {
+                                       host.PutImpl (key, value, false);
+                               }
+                       }
+
+                       public override void Clear () 
+                       {
+                               lock (host.SyncRoot) {
+                                       host.Clear ();
+                               }
+                       }
+
+                       public override bool Contains (object key)
+                       {
+                               lock (host.SyncRoot) {
+                                       return (host.Find (key) >= 0);
+                               }
+                       }
+
+                       public override IDictionaryEnumerator GetEnumerator ()
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.GetEnumerator();
+                               }
+                       }
+
+                       public override void Remove (object key)
+                       {
+                               lock (host.SyncRoot) {
+                                       host.Remove (key);
+                               }
+                       }
+
+
+
+                       public override bool ContainsKey (object key)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.Contains (key);
+                               }
+                       }
+
+                       public override bool ContainsValue (object value)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.ContainsValue (value);
+                               }
+                       }
+
+
+                       // ICloneable
+
+                       public override object Clone ()
+                       {
+                               lock (host.SyncRoot) {
+                                       return (host.Clone () as SortedList);
+                               }
+                       }
+
+
+
+                       //
+                       // SortedList overrides
+                       //
+
+                       public override Object GetByIndex (int index)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.GetByIndex (index);
+                               }
+                       }
+
+                       public override Object GetKey (int index)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.GetKey (index);
+                               }
+                       }
+
+                       public override IList GetKeyList ()
+                       {
+                               lock (host.SyncRoot) {
+                                       return new ListKeys (host);
+                               }
+                       }
+
+
+                       public override IList GetValueList ()
+                       {
+                               lock (host.SyncRoot) {
+                                       return new ListValues (host);
+                               }
+                       }
+
+                       public override void RemoveAt (int index)
+                       {
+                               lock (host.SyncRoot) {
+                                       host.RemoveAt (index);
+                               }
+                       }
+
+                       public override int IndexOfKey (object key)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.IndexOfKey (key);
+                               }
+                       }
+
+                       public override int IndexOfValue (Object val)
+                       {
+                               lock (host.SyncRoot) {
+                                       return host.IndexOfValue (val);
+                               }
+                       }
+
+                       public override void SetByIndex (int index, object value)
+                       {
+                               lock (host.SyncRoot) {
+                                       host.SetByIndex (index, value);
+                               }
+                       }
+
+                       public override void TrimToSize()
+                       {
+                               lock (host.SyncRoot) {
+                                       host.TrimToSize();
+                               }
+                       }
+
+
+               } // SynchedSortedList
+
+       } // SortedList
+
+} // System.Collections