2 // System.Web.UI.WebControls.OrderedDictionary.cs
\r
5 // Lluis Sanchez Gual (lluis@novell.com)
\r
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
\r
9 // Permission is hereby granted, free of charge, to any person obtaining
\r
10 // a copy of this software and associated documentation files (the
\r
11 // "Software"), to deal in the Software without restriction, including
\r
12 // without limitation the rights to use, copy, modify, merge, publish,
\r
13 // distribute, sublicense, and/or sell copies of the Software, and to
\r
14 // permit persons to whom the Software is furnished to do so, subject to
\r
15 // the following conditions:
\r
17 // The above copyright notice and this permission notice shall be
\r
18 // included in all copies or substantial portions of the Software.
\r
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
31 using System.Runtime.Serialization;
\r
33 namespace System.Collections.Specialized
\r
36 public class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback
\r
41 int initialCapacity;
\r
42 SerializationInfo serializationInfo;
\r
43 IEqualityComparer comparer;
\r
45 public OrderedDictionary ()
\r
47 list = new ArrayList ();
\r
48 hash = new Hashtable ();
\r
51 public OrderedDictionary (int capacity)
\r
53 initialCapacity = (capacity < 0) ? 0 : capacity;
\r
54 list = new ArrayList (initialCapacity);
\r
55 hash = new Hashtable (initialCapacity);
\r
58 public OrderedDictionary (IEqualityComparer equalityComparer)
\r
60 list = new ArrayList ();
\r
61 hash = new Hashtable (equalityComparer);
\r
62 comparer = equalityComparer;
\r
65 public OrderedDictionary (int capacity, IEqualityComparer equalityComparer)
\r
67 initialCapacity = (capacity < 0) ? 0 : capacity;
\r
68 list = new ArrayList (initialCapacity);
\r
69 hash = new Hashtable (initialCapacity, equalityComparer);
\r
70 comparer = equalityComparer;
\r
73 protected OrderedDictionary (SerializationInfo info, StreamingContext context)
\r
75 serializationInfo = info;
\r
78 protected virtual void OnDeserialization (object sender)
\r
80 ((IDeserializationCallback) this).OnDeserialization (sender);
\r
83 void IDeserializationCallback.OnDeserialization (object sender)
\r
85 if (serializationInfo == null)
\r
88 comparer = (IEqualityComparer) serializationInfo.GetValue ("KeyComparer", typeof (IEqualityComparer));
\r
89 readOnly = serializationInfo.GetBoolean ("ReadOnly");
\r
90 initialCapacity = serializationInfo.GetInt32 ("InitialCapacity");
\r
93 list = new ArrayList ();
\r
97 hash = new Hashtable (comparer);
\r
98 object[] array = (object[]) serializationInfo.GetValue ("ArrayList", typeof(object[]));
\r
99 foreach (DictionaryEntry de in array) {
\r
100 hash.Add (de.Key, de.Value);
\r
105 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
\r
108 throw new ArgumentNullException ("info");
\r
110 info.AddValue ("KeyComparer", comparer, typeof (IEqualityComparer));
\r
111 info.AddValue ("ReadOnly", readOnly);
\r
112 info.AddValue ("InitialCapacity", initialCapacity);
\r
114 object[] array = new object [hash.Count];
\r
115 hash.CopyTo (array, 0);
\r
116 info.AddValue ("ArrayList", array);
\r
119 IEnumerator IEnumerable.GetEnumerator()
\r
121 return list.GetEnumerator ();
\r
130 bool ICollection.IsSynchronized {
\r
132 return list.IsSynchronized;
\r
136 object ICollection.SyncRoot {
\r
138 return list.SyncRoot;
\r
142 public void CopyTo (Array array, int index)
\r
144 list.CopyTo (array, index);
\r
147 bool IDictionary.IsFixedSize {
\r
153 public bool IsReadOnly
\r
160 public object this [object key]
\r
162 get { return hash [key]; }
\r
165 if (hash.Contains (key)) {
\r
166 int i = FindListEntry (key);
\r
167 list [i] = new DictionaryEntry (key, value);
\r
169 list.Add (new DictionaryEntry (key, value));
\r
171 hash [key] = value;
\r
175 public object this [int index]
\r
177 get { return ((DictionaryEntry) list [index]).Value; }
\r
180 DictionaryEntry de = (DictionaryEntry) list [index];
\r
182 // update (even on the list) isn't automatic
\r
184 hash [de.Key] = value;
\r
188 public ICollection Keys
\r
191 return new OrderedCollection (list, true);
\r
195 public ICollection Values
\r
198 return new OrderedCollection (list, false);
\r
202 public void Add (object key, object value)
\r
205 hash.Add (key, value);
\r
206 list.Add (new DictionaryEntry (key, value));
\r
209 public void Clear()
\r
216 public bool Contains (object key)
\r
218 return hash.Contains (key);
\r
221 public virtual IDictionaryEnumerator GetEnumerator()
\r
223 return new OrderedEntryCollectionEnumerator (list.GetEnumerator ());
\r
226 public void Remove (object key)
\r
230 if (hash.Contains (key)) {
\r
232 int i = FindListEntry (key);
\r
237 int FindListEntry (object key)
\r
239 for (int n=0; n<list.Count; n++) {
\r
240 DictionaryEntry de = (DictionaryEntry) list [n];
\r
241 if (comparer != null ? comparer.Equals(de.Key, key) : de.Key.Equals(key))
\r
250 throw new NotSupportedException ("Collection is read only");
\r
253 public OrderedDictionary AsReadOnly ()
\r
255 OrderedDictionary od = new OrderedDictionary ();
\r
258 od.comparer = comparer;
\r
259 od.readOnly = true;
\r
263 public void Insert (int index, object key, object value)
\r
266 hash.Add (key, value);
\r
267 list.Insert (index, new DictionaryEntry (key, value));
\r
270 public void RemoveAt (int index)
\r
273 DictionaryEntry entry = (DictionaryEntry) list [index];
\r
274 list.RemoveAt (index);
\r
275 hash.Remove (entry.Key);
\r
278 private class OrderedEntryCollectionEnumerator : IEnumerator, IDictionaryEnumerator
\r
280 IEnumerator listEnumerator;
\r
282 public OrderedEntryCollectionEnumerator (IEnumerator listEnumerator)
\r
284 this.listEnumerator = listEnumerator;
\r
287 public bool MoveNext()
\r
289 return listEnumerator.MoveNext ();
\r
292 public void Reset()
\r
294 listEnumerator.Reset ();
\r
297 public object Current
\r
299 get { return listEnumerator.Current; }
\r
302 public DictionaryEntry Entry
\r
304 get { return (DictionaryEntry) listEnumerator.Current; }
\r
309 get { return Entry.Key; }
\r
312 public object Value
\r
314 get { return Entry.Value; }
\r
318 private class OrderedCollection : ICollection
\r
320 private ArrayList list;
\r
321 private bool isKeyList;
\r
323 public OrderedCollection (ArrayList list, bool isKeyList)
\r
326 this.isKeyList = isKeyList;
\r
335 public bool IsSynchronized
\r
342 public object SyncRoot
\r
345 return list.SyncRoot;
\r
349 public void CopyTo (Array array, int index)
\r
351 for (int n=0; n<list.Count; n++) {
\r
352 DictionaryEntry de = (DictionaryEntry) list [n];
\r
353 if (isKeyList) array.SetValue (de.Key, index + n);
\r
354 else array.SetValue (de.Value, index + n);
\r
358 public IEnumerator GetEnumerator()
\r
360 return new OrderedCollectionEnumerator (list.GetEnumerator (), isKeyList);
\r
363 private class OrderedCollectionEnumerator : IEnumerator
\r
365 private bool isKeyList;
\r
366 IEnumerator listEnumerator;
\r
368 public OrderedCollectionEnumerator (IEnumerator listEnumerator, bool isKeyList)
\r
370 this.listEnumerator = listEnumerator;
\r
371 this.isKeyList = isKeyList;
\r
374 public object Current
\r
377 DictionaryEntry entry = (DictionaryEntry) listEnumerator.Current;
\r
378 return isKeyList ? entry.Key : entry.Value;
\r
382 public bool MoveNext()
\r
384 return listEnumerator.MoveNext ();
\r
387 public void Reset()
\r
389 listEnumerator.Reset ();
\r