2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System / System.Collections.Specialized / HybridDictionary.cs
1 //\r
2 // System.Collections.Specialized.HybridDictionary.cs\r
3 //\r
4 // Author:\r
5 //   Lawrence Pit (loz@cable.a2000.nl)
6 //
7 // Copyright (C) 2004 Novell (http://www.novell.com)\r
8 //\r
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 \r
31 using System;\r
32 using System.Collections;\r
33 \r
34 namespace System.Collections.Specialized {\r
35         \r
36         [Serializable]\r
37         public class HybridDictionary : IDictionary, ICollection, IEnumerable {\r
38                 \r
39                 private const int switchAfter = 10;\r
40 \r
41                 private ListDictionary list;\r
42                 private Hashtable hashtable;\r
43                 private bool caseInsensitive = false;\r
44 \r
45                 // Constructors\r
46                 \r
47                 public HybridDictionary() : this (0, false) { }\r
48                 \r
49                 public HybridDictionary (bool caseInsensitive) : this (0, caseInsensitive) { }\r
50                 \r
51                 public HybridDictionary (int initialSize) : this (initialSize, false) { }\r
52                 \r
53                 public HybridDictionary(int initialSize, bool caseInsensitive) \r
54                 {\r
55                         this.caseInsensitive = caseInsensitive;\r
56                 \r
57                         if (initialSize <= switchAfter)\r
58                                 if (caseInsensitive)\r
59                                         list = new ListDictionary (CaseInsensitiveComparer.Default);\r
60                                 else\r
61                                         list = new ListDictionary ();\r
62                         else\r
63                                 if (caseInsensitive) \r
64                                         hashtable = new Hashtable (initialSize, \r
65                                                         CaseInsensitiveHashCodeProvider.Default, \r
66                                                         CaseInsensitiveComparer.Default);\r
67                                 else\r
68                                         hashtable = new Hashtable (initialSize);\r
69                 }               \r
70 \r
71                 \r
72                 // Properties\r
73                 \r
74                 public int Count {\r
75                         get {\r
76                                 if (list != null)\r
77                                         return list.Count;\r
78                                 return hashtable.Count;\r
79                         }\r
80                 }\r
81                 \r
82                 public bool IsFixedSize {\r
83                         get { return false; }\r
84                 }\r
85                 \r
86                 public bool IsReadOnly {\r
87                         get { return false; }\r
88                 }\r
89                 \r
90                 public bool IsSynchronized {\r
91                         get { return false; }\r
92                 }\r
93                 \r
94                 public object this [object key] {\r
95                         get { \r
96                                 if (key == null)\r
97                                         throw new ArgumentNullException("key");\r
98                                 if (list != null)\r
99                                         return list [key];\r
100                                 return hashtable [key];\r
101                         }\r
102                         set { \r
103                                 if (list != null)\r
104                                         if (list.Count >= switchAfter) \r
105                                                 Switch ();\r
106                                         else {\r
107                                                 list [key] = value;\r
108                                                 return;\r
109                                         }\r
110                                 hashtable [key] = value;\r
111                         }\r
112                 }\r
113                 \r
114                 public ICollection Keys {\r
115                         get {\r
116                                 if (list != null)\r
117                                         return list.Keys;\r
118                                 return hashtable.Keys;\r
119                         }\r
120                 }\r
121                 \r
122                 public object SyncRoot {\r
123                         get { return this; }\r
124                 }\r
125                 \r
126                 public ICollection Values {\r
127                         get { \r
128                                 if (list != null)\r
129                                         return list.Values;\r
130                                 return hashtable.Values;\r
131                         }\r
132                 }\r
133                 \r
134                 \r
135                 // Methods\r
136                 \r
137                 public void Add (object key, object value) \r
138                 {\r
139                         if (list != null)\r
140                                 if (list.Count >= switchAfter) \r
141                                         Switch ();\r
142                                 else {\r
143                                         list.Add (key, value);\r
144                                         return;\r
145                                 }\r
146                         hashtable.Add (key, value);\r
147                 }\r
148                 \r
149                 public void Clear ()\r
150                 {\r
151                         if (caseInsensitive)\r
152                                 list = new ListDictionary (CaseInsensitiveComparer.Default);\r
153                         else\r
154                                 list = new ListDictionary ();\r
155                         hashtable = null;\r
156                 }\r
157                 \r
158                 public bool Contains (object key)\r
159                 {
160                         if (key == null) {
161                                 if (this.Count == 0)
162                                         return false;
163                                 else
164                                         throw new ArgumentNullException ("key");\r
165                         }
166                         if (list != null)\r
167                                 return list.Contains (key);\r
168                         return hashtable.Contains (key);\r
169                 }\r
170                 \r
171                 public void CopyTo (Array array, int index)\r
172                 {\r
173                         if (list != null) \r
174                                 list.CopyTo (array, index);\r
175                         else\r
176                                 hashtable.CopyTo (array, index);\r
177                 }\r
178                 \r
179                 public IDictionaryEnumerator GetEnumerator ()\r
180                 {\r
181                         if (list != null)\r
182                                 return list.GetEnumerator ();\r
183                         return hashtable.GetEnumerator ();\r
184                 }\r
185 \r
186                 IEnumerator IEnumerable.GetEnumerator ()\r
187                 {\r
188                         return GetEnumerator ();\r
189                 }\r
190 \r
191                 public void Remove (object key)\r
192                 {\r
193                         if (list != null)\r
194                                 list.Remove (key);\r
195                         else    \r
196                                 hashtable.Remove (key);\r
197                 }\r
198                 \r
199                 private void Switch ()\r
200                 {\r
201                         if (caseInsensitive) \r
202                                 hashtable = new Hashtable (switchAfter + 1,\r
203                                                         CaseInsensitiveHashCodeProvider.Default, \r
204                                                         CaseInsensitiveComparer.Default);\r
205                         else\r
206                                 hashtable = new Hashtable (switchAfter + 1);\r
207                         IDictionaryEnumerator e = list.GetEnumerator ();\r
208                         while (e.MoveNext ())\r
209                                 hashtable.Add (e.Key, e.Value);\r
210                         list = null;\r
211                 }\r
212         }\r
213 }\r