Author: zoltan
Date: 2005-11-09 17:01:04 -0500 (Wed, 09 Nov 2005)
New Revision: 52800
Added:
trunk/mcs/class/System/System.Collections.Generic/SortedList.cs
Modified:
trunk/mcs/class/System/System.Collections.Generic/ChangeLog
Log:
2005-11-09 Zoltan Varga <[EMAIL PROTECTED]>
* SortedList.cs: New file.
Modified: trunk/mcs/class/System/System.Collections.Generic/ChangeLog
===================================================================
--- trunk/mcs/class/System/System.Collections.Generic/ChangeLog 2005-11-09
22:00:29 UTC (rev 52799)
+++ trunk/mcs/class/System/System.Collections.Generic/ChangeLog 2005-11-09
22:01:04 UTC (rev 52800)
@@ -1,3 +1,7 @@
+2005-11-09 Zoltan Varga <[EMAIL PROTECTED]>
+
+ * SortedList.cs: New file.
+
2005-09-04 David Waite <[EMAIL PROTECTED]>
* LinkedList.cs, LinkedListNode.cs: added implementation of
LinkedList<T>
Added: trunk/mcs/class/System/System.Collections.Generic/SortedList.cs
===================================================================
--- trunk/mcs/class/System/System.Collections.Generic/SortedList.cs
2005-11-09 22:00:29 UTC (rev 52799)
+++ trunk/mcs/class/System/System.Collections.Generic/SortedList.cs
2005-11-09 22:01:04 UTC (rev 52800)
@@ -0,0 +1,1053 @@
+//
+// System.Collections.Generic.SortedList.cs
+//
+// Author:
+// Sergey Chaban ([EMAIL PROTECTED])
+// Duncan Mak ([EMAIL PROTECTED])
+// Herve Poussineau ([EMAIL PROTECTED]
+// Zoltan Varga ([EMAIL PROTECTED])
+//
+
+//
+// Copyright (C) 2004 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.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+namespace System.Collections.Generic {
+
+ /// <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]
+ [ComVisible(false)]
+ public class SortedList<TKey, TValue> : IDictionary<TKey, TValue>,
+ IDictionary,
+ ICollection,
+ ICollection<KeyValuePair<TKey, TValue>>,
+ IEnumerable<KeyValuePair<TKey, TValue>>,
+ IEnumerable {
+
+ 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 KeyValuePair<TKey, TValue>[] table;
+ private IComparer<TKey> comparer;
+ private int defaultCapacity;
+
+ //
+ // Constructors
+ //
+ public SortedList ()
+ : this (null, INITIAL_SIZE)
+ {
+ }
+
+ public SortedList (int initialCapacity)
+ : this (null, initialCapacity)
+ {
+ }
+
+ public SortedList (IComparer<TKey> comparer, int
initialCapacity)
+ {
+ if (initialCapacity < 0)
+ throw new ArgumentOutOfRangeException
("initialCapacity");
+
+ if (initialCapacity == 0)
+ defaultCapacity = 0;
+ else
+ defaultCapacity = INITIAL_SIZE;
+ Init (comparer, initialCapacity, true);
+ }
+
+ public SortedList (IComparer<TKey> comparer) : this (comparer,
INITIAL_SIZE)
+ {
+ }
+
+ public SortedList (IDictionary<TKey, TValue> dictionary) : this
(dictionary, null)
+ {
+ }
+
+ public SortedList (IDictionary<TKey, TValue> dictionary,
IComparer<TKey> comparer)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException ("dictionary");
+
+ Init (comparer, dictionary.Count, true);
+
+ foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
+ Add (kvp.Key, kvp.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 TValue this [TKey key] {
+ get {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ int i = Find (key);
+
+ if (i >= 0)
+ return table [i].Value;
+ else
+ throw new KeyNotFoundException ();
+ }
+ set {
+ if (key == null)
+ throw new ArgumentNullException("key");
+ if (IsReadOnly)
+ throw new
NotSupportedException("SortedList<TKey, TValue>is Read Only.");
+ if (Find(key) < 0 && IsFixedSize)
+ throw new NotSupportedException("Key
not found and SortedList<TKey, TValue>is fixed size.");
+
+ PutImpl (key, value, true);
+ }
+ }
+
+ object IDictionary.this [object key] {
+ get {
+ if (!(key is TKey))
+ return null;
+ else
+ return this [(TKey)key];
+ }
+
+ set {
+ this [ToKey (key)] = ToValue (value);
+ }
+ }
+
+ 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
+ KeyValuePair<TKey, TValue> [] newTable
= new KeyValuePair<TKey, TValue> [defaultCapacity];
+ Array.Copy (table, newTable, inUse);
+ this.table = newTable;
+ }
+#if NET_1_0
+ else if (current > defaultCapacity && value <
current) {
+ KeyValuePair<TKey, TValue> [] newTable
= new KeyValuePair<TKey, TValue> [defaultCapacity];
+ Array.Copy (table, newTable, inUse);
+ this.table = newTable;
+ }
+#endif
+ else if (value > inUse) {
+ KeyValuePair<TKey, TValue> [] newTable
= new KeyValuePair<TKey, TValue> [value];
+ Array.Copy (table, newTable, inUse);
+ this.table = newTable;
+ }
+ else if (value > current) {
+ KeyValuePair<TKey, TValue> [] newTable
= new KeyValuePair<TKey, TValue> [value];
+ Array.Copy (table, newTable, current);
+ this.table = newTable;
+ }
+ }
+ }
+
+ public IList<TKey> Keys {
+ get {
+ return new ListKeys (this);
+ }
+ }
+
+ public IList<TValue> Values {
+ get {
+ return new ListValues (this);
+ }
+ }
+
+ ICollection IDictionary.Keys {
+ get {
+ return new ListKeys (this);
+ }
+ }
+
+ ICollection IDictionary.Values {
+ get {
+ return new ListValues (this);
+ }
+ }
+
+ ICollection<TKey> IDictionary<TKey, TValue>.Keys {
+ get {
+ return Keys;
+ }
+ }
+
+ ICollection<TValue> IDictionary<TKey, TValue>.Values {
+ get {
+ return Values;
+ }
+ }
+
+ //
+ // Public instance methods.
+ //
+
+ // IDictionary<TKey, TValue>
+
+ public virtual void Add (TKey key, TValue value)
+ {
+ if (key == null)
+ throw new ArgumentNullException ("key");
+
+ PutImpl (key, value, false);
+ }
+
+ public bool ContainsKey (TKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException ("key");
+
+ return (Find (key) >= 0);
+ }
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator ()
+ {
+ for (int i = 0; i < inUse; i ++) {
+ KeyValuePair<TKey, TValue> current = this.table
[i];
+
+ yield return new KeyValuePair<TKey, TValue>
(current.Key, current.Value);
+ }
+ }
+
+ public virtual bool Remove (TKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException ("key");
+
+ int i = IndexOfKey (key);
+ if (i >= 0) {
+ RemoveAt (i);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // ICollection<KeyValuePair<TKey, TValue>>
+
+ public virtual void Clear ()
+ {
+ defaultCapacity = INITIAL_SIZE;
+ this.table = new KeyValuePair<TKey, TValue>
[defaultCapacity];
+ inUse = 0;
+ modificationCount++;
+ }
+
+ 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");
+
+ IEnumerator<KeyValuePair<TKey,TValue>> it =
GetEnumerator ();
+ int i = arrayIndex;
+
+ while (it.MoveNext ()) {
+ array.SetValue (it.Current, i++);
+ }
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo
(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ {
+ if (null == array)
+ throw new ArgumentNullException();
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException();
+
+ 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");
+
+ int i = arrayIndex;
+ foreach (KeyValuePair<TKey, TValue> pair in this)
+ array [i++] = pair;
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add
(KeyValuePair<TKey, TValue> keyValuePair) {
+ Add (keyValuePair.Key, keyValuePair.Value);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains
(KeyValuePair<TKey, TValue> keyValuePair) {
+ int i = Find (keyValuePair.Key);
+
+ if (i >= 0)
+ return Comparer<KeyValuePair<TKey,
TValue>>.Default.Compare (table [i], keyValuePair) == 0;
+ else
+ return false;
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove
(KeyValuePair<TKey, TValue> keyValuePair) {
+ int i = Find (keyValuePair.Key);
+
+ if (i >= 0 && (Comparer<KeyValuePair<TKey,
TValue>>.Default.Compare (table [i], keyValuePair) == 0)) {
+ RemoveAt (i);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // IEnumerable<KeyValuePair<TKey, TValue>>
+
+ IEnumerator<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator ()
+ {
+ for (int i = 0; i < inUse; i ++) {
+ KeyValuePair<TKey, TValue> current = this.table
[i];
+
+ yield return new KeyValuePair<TKey, TValue>
(current.Key, current.Value);
+ }
+ }
+
+ // IEnumerable
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+
+ // IDictionary
+
+ void IDictionary.Add (object key, object value)
+ {
+ PutImpl (ToKey (key), ToValue (value), false);
+ }
+
+ bool IDictionary.Contains (object key)
+ {
+ if (null == key)
+ throw new ArgumentNullException();
+ if (!(key is TKey))
+ return false;
+
+ return (Find ((TKey)key) >= 0);
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator ()
+ {
+ return new Enumerator (this, EnumeratorMode.ENTRY_MODE);
+ }
+
+ void IDictionary.Remove (object key)
+ {
+ if (null == key)
+ throw new ArgumentNullException ("key");
+ if (!(key is TKey))
+ return;
+ int i = IndexOfKey ((TKey)key);
+ if (i >= 0) RemoveAt (i);
+ }
+
+ // ICollection
+
+ void ICollection.CopyTo (Array array, int arrayIndex)
+ {
+ CopyTo (array, arrayIndex);
+ }
+
+ //
+ // SortedList<TKey, TValue>
+ //
+
+ public virtual void RemoveAt (int index)
+ {
+ KeyValuePair<TKey, TValue> [] 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] = default (KeyValuePair
<TKey, TValue>);
+ }
+ --inUse;
+ ++modificationCount;
+ } else {
+ throw new ArgumentOutOfRangeException("index
out of range");
+ }
+ }
+
+ public int IndexOfKey (TKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException ("key");
+
+ int indx = 0;
+ try {
+ indx = Find (key);
+ } catch (Exception) {
+ throw new InvalidOperationException();
+ }
+
+ return (indx | (indx >> 31));
+ }
+
+ public int IndexOfValue (TValue value)
+ {
+ if (inUse == 0)
+ return -1;
+
+ for (int i = 0; i < inUse; i ++) {
+ KeyValuePair<TKey, TValue> current = this.table
[i];
+
+ if (Equals (value, current.Value))
+ return i;
+ }
+
+ return -1;
+ }
+
+ public bool ContainsValue (TValue value)
+ {
+ return IndexOfValue (value) >= 0;
+ }
+
+ [MonoTODO]
+ public void TrimExcess ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool TryGetValue (TKey key, out TValue value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ int i = Find (key);
+
+ if (i >= 0) {
+ value = table [i].Value;
+ return true;
+ }
+ else {
+ value = default (TValue);
+ return false;
+ }
+ }
+
+ //
+ // Private methods
+ //
+
+ private void Resize (int n, bool copy)
+ {
+ KeyValuePair<TKey, TValue> [] table = this.table;
+ KeyValuePair<TKey, TValue> [] newTable = new
KeyValuePair<TKey, TValue> [n];
+ if (copy) Array.Copy (table, 0, newTable, 0, n);
+ this.table = newTable;
+ }
+
+ private void EnsureCapacity (int n, int free)
+ {
+ KeyValuePair<TKey, TValue> [] table = this.table;
+ KeyValuePair<TKey, TValue> [] newTable = null;
+ int cap = Capacity;
+ bool gap = (free >=0 && free < Count);
+
+ if (n > cap) {
+ newTable = new KeyValuePair<TKey, TValue> [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 (TKey key, TValue value, bool overwrite)
+ {
+ if (key == null)
+ throw new ArgumentNullException ("null key");
+
+ KeyValuePair<TKey, TValue> [] table = this.table;
+
+ int freeIndx = -1;
+
+ try {
+ freeIndx = Find (key);
+ } catch (Exception) {
+ throw new InvalidOperationException();
+ }
+
+ if (freeIndx >= 0) {
+ if (!overwrite)
+ throw new ArgumentException("element
already exists");
+
+ table [freeIndx] = new KeyValuePair <TKey,
TValue> (key, 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] = new KeyValuePair <TKey, TValue>
(key, value);
+
+ ++inUse;
+ ++modificationCount;
+
+ }
+
+ private void Init (IComparer<TKey> comparer, int capacity, bool
forceSize)
+ {
+ if (comparer == null)
+ comparer = Comparer<TKey>.Default;
+ this.comparer = comparer;
+ if (!forceSize && (capacity < defaultCapacity))
+ capacity = defaultCapacity;
+ this.table = new KeyValuePair<TKey, TValue> [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 (TKey key)
+ {
+ KeyValuePair<TKey, TValue> [] table = this.table;
+ int len = Count;
+
+ if (len == 0) return ~0;
+
+ 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;
+ }
+
+ private TKey ToKey (object key) {
+ if (key == null)
+ throw new ArgumentNullException ("key");
+ if (!(key is TKey))
+ throw new ArgumentException ("The value \"" +
key + "\" isn't of type \"" + typeof (TKey) + "\" and can't be used in this
generic collection.", "key");
+ return (TKey)key;
+ }
+
+ private TValue ToValue (object value) {
+ if (!(value is TValue))
+ throw new ArgumentException ("The value \"" +
value + "\" isn't of type \"" + typeof (TValue) + "\" and can't be used in this
generic collection.", "value");
+ return (TValue)value;
+ }
+
+ internal TKey KeyAt (int index) {
+ if (index >= 0 && index < Count)
+ return table [index].Key;
+ else
+ throw new ArgumentOutOfRangeException("Index
out of range");
+ }
+
+ internal TValue ValueAt (int index) {
+ if (index >= 0 && index < Count)
+ return table [index].Value;
+ else
+ throw new ArgumentOutOfRangeException("Index
out of range");
+ }
+
+ //
+ // Inner classes
+ //
+
+
+ private sealed class Enumerator : ICloneable,
IDictionaryEnumerator, IEnumerator {
+
+ private SortedList<TKey, TValue>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<TKey, TValue>host,
EnumeratorMode mode)
+ {
+ this.host = host;
+ stamp = host.modificationCount;
+ size = host.Count;
+ this.mode = mode;
+ Reset ();
+ }
+
+ public Enumerator (SortedList<TKey, TValue>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);
+
+ KeyValuePair<TKey, TValue> [] table =
host.table;
+
+ if (++pos < size) {
+ KeyValuePair<TKey, TValue> 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<TKey>, ICollection, IEnumerable {
+
+ private SortedList<TKey, TValue> host;
+
+ public ListKeys (SortedList<TKey, TValue> host)
+ {
+ if (host == null)
+ throw new ArgumentNullException ();
+
+ this.host = host;
+ }
+
+ // ICollection<TKey>
+
+ public virtual void Add (TKey item) {
+ throw new NotSupportedException();
+ }
+
+ public virtual bool Remove (TKey key) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual void Clear () {
+ throw new NotSupportedException();
+ }
+
+ public virtual void CopyTo (TKey[] array, int
arrayIndex) {
+ if (array == null)
+ throw new ArgumentNullException
("array");
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException();
+ if (arrayIndex >= array.Length)
+ throw new ArgumentOutOfRangeException
("arrayIndex is greater than or equal to array.Length");
+ if (Count > (array.Length - arrayIndex))
+ throw new
ArgumentOutOfRangeException("Not enough space in array from arrayIndex to end
of array");
+
+ int j = arrayIndex;
+ for (int i = 0; i < Count; ++i)
+ array [j ++] = host.KeyAt (i);
+ }
+
+ public virtual bool Contains (TKey item) {
+ return host.IndexOfKey (item) > -1;
+ }
+
+ //
+ // IList<TKey>
+ //
+ public virtual int IndexOf (TKey item) {
+ return host.IndexOfKey (item);
+ }
+
+ public virtual void Insert (int index, TKey item) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual void RemoveAt (int index) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual TKey this [int index] {
+ get {
+ return host.KeyAt (index);
+ }
+ set {
+ throw new
NotSupportedException("attempt to modify a key");
+ }
+ }
+
+ //
+ // IEnumerable<TKey>
+ //
+
+ public virtual IEnumerator<TKey> GetEnumerator ()
+ {
+ for (int i = 0; i < host.Count; ++i)
+ yield return host.KeyAt (i);
+ }
+
+ //
+ // ICollection
+ //
+
+ public virtual int Count {
+ get {
+ return host.Count;
+ }
+ }
+
+ public virtual bool IsSynchronized {
+ get {
+ return host.IsSynchronized;
+ }
+ }
+
+ public virtual bool IsReadOnly {
+ get {
+ return true;
+ }
+ }
+
+ public virtual Object SyncRoot {
+ get {
+ return host.SyncRoot;
+ }
+ }
+
+ public virtual void CopyTo (Array array, int arrayIndex)
+ {
+ host.CopyToArray (array, arrayIndex,
EnumeratorMode.KEY_MODE);
+ }
+
+ //
+ // IEnumerable
+ //
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ for (int i = 0; i < host.Count; ++i)
+ yield return host.KeyAt (i);
+ }
+ }
+
+ private class ListValues : IList<TValue>, ICollection,
IEnumerable {
+
+ private SortedList<TKey, TValue>host;
+
+ public ListValues (SortedList<TKey, TValue>host)
+ {
+ if (host == null)
+ throw new ArgumentNullException ();
+
+ this.host = host;
+ }
+
+ // ICollection<TValue>
+
+ public virtual void Add (TValue item) {
+ throw new NotSupportedException();
+ }
+
+ public virtual bool Remove (TValue value) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual void Clear () {
+ throw new NotSupportedException();
+ }
+
+ public virtual void CopyTo (TValue[] array, int
arrayIndex) {
+ if (array == null)
+ throw new ArgumentNullException
("array");
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException();
+ if (arrayIndex >= array.Length)
+ throw new ArgumentOutOfRangeException
("arrayIndex is greater than or equal to array.Length");
+ if (Count > (array.Length - arrayIndex))
+ throw new
ArgumentOutOfRangeException("Not enough space in array from arrayIndex to end
of array");
+
+ int j = arrayIndex;
+ for (int i = 0; i < Count; ++i)
+ array [j ++] = host.ValueAt (i);
+ }
+
+ public virtual bool Contains (TValue item) {
+ return host.IndexOfValue (item) > -1;
+ }
+
+ //
+ // IList<TValue>
+ //
+ public virtual int IndexOf (TValue item) {
+ return host.IndexOfValue (item);
+ }
+
+ public virtual void Insert (int index, TValue item) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual void RemoveAt (int index) {
+ throw new NotSupportedException ();
+ }
+
+ public virtual TValue this [int index] {
+ get {
+ return host.ValueAt (index);
+ }
+ set {
+ throw new
NotSupportedException("attempt to modify a key");
+ }
+ }
+
+ //
+ // IEnumerable<TValue>
+ //
+
+ public virtual IEnumerator<TValue> GetEnumerator ()
+ {
+ for (int i = 0; i < host.Count; ++i)
+ yield return host.ValueAt (i);
+ }
+
+ //
+ // ICollection
+ //
+
+ public virtual int Count {
+ get {
+ return host.Count;
+ }
+ }
+
+ public virtual bool IsSynchronized {
+ get {
+ return host.IsSynchronized;
+ }
+ }
+
+ public virtual bool IsReadOnly {
+ get {
+ return true;
+ }
+ }
+
+ public virtual Object SyncRoot {
+ get {
+ return host.SyncRoot;
+ }
+ }
+
+ public virtual void CopyTo (Array array, int arrayIndex)
+ {
+ host.CopyToArray (array, arrayIndex,
EnumeratorMode.VALUE_MODE);
+ }
+
+ //
+ // IEnumerable
+ //
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ for (int i = 0; i < host.Count; ++i)
+ yield return host.ValueAt (i);
+ }
+ }
+
+ } // SortedList
+
+} // System.Collections.Generic
+
+#endif
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches