[build] Prevent cyclic targets from being built in parallel
[mono.git] / mcs / class / System / System.Collections.Specialized / OrderedDictionary.cs
1 //\r
2 // System.Web.UI.WebControls.OrderedDictionary.cs\r
3 //\r
4 // Authors:\r
5 //      Lluis Sanchez Gual (lluis@novell.com)\r
6 //\r
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)\r
8 //\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
16 // \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
19 // \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
27 //\r
28 \r
29 using System.Runtime.Serialization;\r
30 \r
31 namespace System.Collections.Specialized\r
32 {\r
33         [Serializable]\r
34         public class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback\r
35         {\r
36                 ArrayList list;\r
37                 Hashtable hash;\r
38                 bool readOnly;\r
39                 int initialCapacity;\r
40                 SerializationInfo serializationInfo;\r
41                 IEqualityComparer comparer;\r
42                 \r
43                 public OrderedDictionary ()\r
44                 {\r
45                         list = new ArrayList ();\r
46                         hash = new Hashtable ();\r
47                 }\r
48                 \r
49                 public OrderedDictionary (int capacity)\r
50                 {\r
51                         initialCapacity = (capacity < 0) ? 0 : capacity;\r
52                         list = new ArrayList (initialCapacity);\r
53                         hash = new Hashtable (initialCapacity);\r
54                 }\r
55                 \r
56                 public OrderedDictionary (IEqualityComparer comparer)\r
57                 {\r
58                         list = new ArrayList ();\r
59                         hash = new Hashtable (comparer);\r
60                         this.comparer = comparer;\r
61                 }\r
62 \r
63                 public OrderedDictionary (int capacity, IEqualityComparer comparer)\r
64                 {\r
65                         initialCapacity = (capacity < 0) ? 0 : capacity;\r
66                         list = new ArrayList (initialCapacity);\r
67                         hash = new Hashtable (initialCapacity, comparer);\r
68                         this.comparer = comparer;\r
69                 }\r
70 \r
71                 protected OrderedDictionary (SerializationInfo info, StreamingContext context)\r
72                 {\r
73                         serializationInfo = info;\r
74                 }\r
75 \r
76                 protected virtual void OnDeserialization (object sender)\r
77                 {\r
78                         ((IDeserializationCallback) this).OnDeserialization (sender);\r
79                 }\r
80 \r
81                 void IDeserializationCallback.OnDeserialization (object sender)\r
82                 {\r
83                         if (serializationInfo == null)\r
84                                 return;\r
85 \r
86                         comparer = (IEqualityComparer) serializationInfo.GetValue ("KeyComparer", typeof (IEqualityComparer));\r
87                         readOnly = serializationInfo.GetBoolean ("ReadOnly");\r
88                         initialCapacity = serializationInfo.GetInt32 ("InitialCapacity");\r
89 \r
90                         if (list == null)\r
91                                 list = new ArrayList ();\r
92                         else\r
93                                 list.Clear ();\r
94 \r
95                         hash = new Hashtable (comparer);\r
96                         object[] array = (object[]) serializationInfo.GetValue ("ArrayList", typeof(object[]));\r
97                         foreach (DictionaryEntry de in array) {\r
98                                 hash.Add (de.Key, de.Value);\r
99                                 list.Add (de);\r
100                         }\r
101                 }\r
102                 \r
103                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)\r
104                 {\r
105                         if (info == null)\r
106                                 throw new ArgumentNullException ("info");\r
107 \r
108                         info.AddValue ("KeyComparer", comparer, typeof (IEqualityComparer));\r
109                         info.AddValue ("ReadOnly", readOnly);\r
110                         info.AddValue ("InitialCapacity", initialCapacity);\r
111 \r
112                         object[] array = new object [hash.Count];\r
113                         hash.CopyTo (array, 0);\r
114                         info.AddValue ("ArrayList", array);\r
115                 }\r
116 \r
117                 IEnumerator IEnumerable.GetEnumerator()\r
118                 {\r
119                         return list.GetEnumerator ();\r
120                 }\r
121                 \r
122                 public int Count {\r
123                         get {\r
124                                 return list.Count;\r
125                         }\r
126                 }\r
127 \r
128                 bool ICollection.IsSynchronized {\r
129                         get {\r
130                                 return list.IsSynchronized;\r
131                         }\r
132                 }\r
133 \r
134                 object ICollection.SyncRoot {\r
135                         get {\r
136                                 return list.SyncRoot;\r
137                         }\r
138                 }\r
139 \r
140                 public void CopyTo (Array array, int index)\r
141                 {\r
142                         list.CopyTo (array, index);\r
143                 }\r
144 \r
145                 bool IDictionary.IsFixedSize {\r
146                         get {\r
147                                 return false;\r
148                         }\r
149                 }\r
150                 \r
151                 public bool IsReadOnly\r
152                 {\r
153                         get {\r
154                                 return readOnly;\r
155                         }\r
156                 }\r
157                 \r
158                 public object this [object key]\r
159                 {\r
160                         get { return hash [key]; }\r
161                         set {\r
162                                 WriteCheck ();\r
163                                 if (hash.Contains (key)) {\r
164                                         int i = FindListEntry (key);\r
165                                         list [i] = new DictionaryEntry (key, value);\r
166                                 } else\r
167                                         list.Add (new DictionaryEntry (key, value));\r
168                                 \r
169                                 hash [key] = value;\r
170                         }\r
171                 }\r
172                 \r
173                 public object this [int index]\r
174                 {\r
175                         get { return ((DictionaryEntry) list [index]).Value; }\r
176                         set {\r
177                                 WriteCheck ();\r
178                                 DictionaryEntry de = (DictionaryEntry) list [index];\r
179                                 de.Value = value;\r
180                                 // update (even on the list) isn't automatic\r
181                                 list [index] = de;\r
182                                 hash [de.Key] = value;\r
183                         }\r
184                 }\r
185                 \r
186                 public ICollection Keys\r
187                 {\r
188                         get {\r
189                                 return new OrderedCollection (list, true);\r
190                         }\r
191                 }\r
192                 \r
193                 public ICollection Values\r
194                 {\r
195                         get {\r
196                                 return new OrderedCollection (list, false);\r
197                         }\r
198                 }\r
199 \r
200                 public void Add (object key, object value)\r
201                 {\r
202                         WriteCheck ();\r
203                         hash.Add (key, value);\r
204                         list.Add (new DictionaryEntry (key, value));\r
205                 }\r
206                 \r
207                 public void Clear()\r
208                 {\r
209                         WriteCheck ();\r
210                         hash.Clear ();\r
211                         list.Clear ();\r
212                 }\r
213                 \r
214                 public bool Contains (object key)\r
215                 {\r
216                         return hash.Contains (key);\r
217                 }\r
218                 \r
219                 public virtual IDictionaryEnumerator GetEnumerator()\r
220                 {\r
221                         return new OrderedEntryCollectionEnumerator (list.GetEnumerator ());\r
222                 }\r
223                 \r
224                 public void Remove (object key)\r
225                 {\r
226                         WriteCheck ();\r
227 \r
228                         if (hash.Contains (key)) {\r
229                                 hash.Remove (key);\r
230                                 int i = FindListEntry (key);\r
231                                 list.RemoveAt (i);\r
232                         }\r
233                 }\r
234                 \r
235                 int FindListEntry (object key)\r
236                 {\r
237                         for (int n=0; n<list.Count; n++) {\r
238                                 DictionaryEntry de = (DictionaryEntry) list [n];\r
239                                 if (comparer != null ? comparer.Equals(de.Key, key) : de.Key.Equals(key))\r
240                                         return n;\r
241                         }\r
242                         return -1;\r
243                 }\r
244                 \r
245                 void WriteCheck ()\r
246                 {\r
247                         if (readOnly)\r
248                                 throw new NotSupportedException ("Collection is read only");\r
249                 }\r
250                 \r
251                 public OrderedDictionary AsReadOnly ()\r
252                 {\r
253                         OrderedDictionary od = new OrderedDictionary ();\r
254                         od.list = list;\r
255                         od.hash = hash;\r
256                         od.comparer = comparer;\r
257                         od.readOnly = true;\r
258                         return od;\r
259                 }\r
260                 \r
261                 public void Insert (int index, object key, object value)\r
262                 {\r
263                         WriteCheck ();\r
264                         hash.Add (key, value);\r
265                         list.Insert (index, new DictionaryEntry (key, value));\r
266                 }\r
267                 \r
268                 public void RemoveAt (int index)\r
269                 {\r
270                         WriteCheck ();\r
271                         DictionaryEntry entry = (DictionaryEntry) list [index];\r
272                         list.RemoveAt (index);\r
273                         hash.Remove (entry.Key);\r
274                 }\r
275                 \r
276                 private class OrderedEntryCollectionEnumerator : IEnumerator, IDictionaryEnumerator\r
277                 {\r
278                         IEnumerator listEnumerator;\r
279                         \r
280                         public OrderedEntryCollectionEnumerator (IEnumerator listEnumerator)\r
281                         {\r
282                                 this.listEnumerator = listEnumerator;\r
283                         }\r
284 \r
285                         public bool MoveNext()\r
286                         {\r
287                                 return listEnumerator.MoveNext ();\r
288                         }\r
289                         \r
290                         public void Reset()\r
291                         {\r
292                                 listEnumerator.Reset ();\r
293                         }\r
294                         \r
295                         public object Current\r
296                         {\r
297                                 get { return listEnumerator.Current; }\r
298                         }\r
299                         \r
300                         public DictionaryEntry Entry\r
301                         {\r
302                                 get { return (DictionaryEntry) listEnumerator.Current; }\r
303                         }\r
304                         \r
305                         public object Key\r
306                         {\r
307                                 get { return Entry.Key; }\r
308                         }\r
309                         \r
310                         public object Value\r
311                         {\r
312                                 get { return Entry.Value; }\r
313                         }\r
314                 }\r
315                 \r
316                 private class OrderedCollection : ICollection\r
317                 {\r
318                         private ArrayList list;\r
319                         private bool isKeyList;\r
320                                 \r
321                         public OrderedCollection (ArrayList list, bool isKeyList)\r
322                         {\r
323                                 this.list = list;\r
324                                 this.isKeyList = isKeyList;\r
325                         }\r
326 \r
327                         public int Count {\r
328                                 get {\r
329                                         return list.Count;\r
330                                 }\r
331                         }\r
332                         \r
333                         public bool IsSynchronized\r
334                         {\r
335                                 get {\r
336                                         return false;\r
337                                 }\r
338                         }\r
339                         \r
340                         public object SyncRoot\r
341                         {\r
342                                 get {\r
343                                         return list.SyncRoot;\r
344                                 }\r
345                         }\r
346 \r
347                         public void CopyTo (Array array, int index)\r
348                         {\r
349                                 for (int n=0; n<list.Count; n++) {\r
350                                         DictionaryEntry de = (DictionaryEntry) list [n];\r
351                                         if (isKeyList) array.SetValue (de.Key, index + n);\r
352                                         else array.SetValue (de.Value, index + n);\r
353                                 }\r
354                         }\r
355                         \r
356                         public IEnumerator GetEnumerator()\r
357                         {\r
358                                 return new OrderedCollectionEnumerator (list.GetEnumerator (), isKeyList);\r
359                         }\r
360                         \r
361                         private class OrderedCollectionEnumerator : IEnumerator\r
362                         {\r
363                                 private bool isKeyList;\r
364                                 IEnumerator listEnumerator;\r
365                                         \r
366                                 public OrderedCollectionEnumerator (IEnumerator listEnumerator, bool isKeyList)\r
367                                 {\r
368                                         this.listEnumerator = listEnumerator;\r
369                                         this.isKeyList = isKeyList;\r
370                                 }\r
371 \r
372                                 public object Current\r
373                                 {\r
374                                         get {\r
375                                                 DictionaryEntry entry = (DictionaryEntry) listEnumerator.Current;\r
376                                                 return isKeyList ? entry.Key : entry.Value;\r
377                                         }\r
378                                 }\r
379                                 \r
380                                 public bool MoveNext()\r
381                                 {\r
382                                         return listEnumerator.MoveNext ();\r
383                                 }\r
384                                 \r
385                                 public void Reset()\r
386                                 {\r
387                                         listEnumerator.Reset ();\r
388                                 }\r
389                         }\r
390                 }\r
391         }\r
392 }\r
393 \r