1 /* 2 [The "BSD licence"] 3 Copyright (c) 2005-2007 Kunle Odutola 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code MUST RETAIN the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form MUST REPRODUCE the above copyright 12 notice, this list of conditions and the following disclaimer in 13 the documentation and/or other materials provided with the 14 distribution. 15 3. The name of the author may not be used to endorse or promote products 16 derived from this software without specific prior WRITTEN permission. 17 4. Unless explicitly state otherwise, any contribution intentionally 18 submitted for inclusion in this work to the copyright owner or licensor 19 shall be under the terms and conditions of this license, without any 20 additional terms or conditions. 21 22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 35 namespace Antlr.Runtime.Collections 36 { 37 using System; 38 using IDictionary = System.Collections.IDictionary; 39 using IDictionaryEnumerator = System.Collections.IDictionaryEnumerator; 40 using ICollection = System.Collections.ICollection; 41 using IEnumerator = System.Collections.IEnumerator; 42 using Hashtable = System.Collections.Hashtable; 43 using ArrayList = System.Collections.ArrayList; 44 using DictionaryEntry = System.Collections.DictionaryEntry; 45 using StringBuilder = System.Text.StringBuilder; 46 47 /// <summary> 48 /// An Hashtable-backed dictionary that enumerates Keys and Values in 49 /// insertion order. 50 /// </summary> 51 public sealed class HashList : IDictionary 52 { 53 #region Helper classes 54 private sealed class HashListEnumerator : IDictionaryEnumerator 55 { 56 internal enum EnumerationMode 57 { 58 Key, 59 Value, 60 Entry 61 } 62 private HashList _hashList; 63 private ArrayList _orderList; 64 private EnumerationMode _mode; 65 private int _index; 66 private int _version; 67 private object _key; 68 private object _value; 69 70 #region Constructors 71 HashListEnumerator()72 internal HashListEnumerator() 73 { 74 _index = 0; 75 _key = null; 76 _value = null; 77 } 78 HashListEnumerator(HashList hashList, EnumerationMode mode)79 internal HashListEnumerator(HashList hashList, EnumerationMode mode) 80 { 81 _hashList = hashList; 82 _mode = mode; 83 _version = hashList._version; 84 _orderList = hashList._insertionOrderList; 85 _index = 0; 86 _key = null; 87 _value = null; 88 } 89 90 #endregion 91 92 #region IDictionaryEnumerator Members 93 94 public object Key 95 { 96 get 97 { 98 if (_key == null) 99 { 100 throw new InvalidOperationException("Enumeration has either not started or has already finished."); 101 } 102 return _key; 103 } 104 } 105 106 public object Value 107 { 108 get 109 { 110 if (_key == null) 111 { 112 throw new InvalidOperationException("Enumeration has either not started or has already finished."); 113 } 114 return _value; 115 } 116 } 117 118 public DictionaryEntry Entry 119 { 120 get 121 { 122 if (_key == null) 123 { 124 throw new InvalidOperationException("Enumeration has either not started or has already finished."); 125 } 126 return new DictionaryEntry(_key, _value); 127 } 128 } 129 130 #endregion 131 132 #region IEnumerator Members 133 Reset()134 public void Reset() 135 { 136 if (_version != _hashList._version) 137 { 138 throw new InvalidOperationException("Collection was modified; enumeration operation may not execute."); 139 } 140 _index = 0; 141 _key = null; 142 _value = null; 143 } 144 145 public object Current 146 { 147 get 148 { 149 if (_key == null) 150 { 151 throw new InvalidOperationException("Enumeration has either not started or has already finished."); 152 } 153 154 if (_mode == EnumerationMode.Key) 155 return _key; 156 else if (_mode == EnumerationMode.Value) 157 return _value; 158 159 return new DictionaryEntry(_key, _value); 160 } 161 } 162 MoveNext()163 public bool MoveNext() 164 { 165 if (_version != _hashList._version) 166 { 167 throw new InvalidOperationException("Collection was modified; enumeration operation may not execute."); 168 } 169 170 if (_index < _orderList.Count) 171 { 172 _key = _orderList[_index]; 173 _value = _hashList[_key]; 174 _index++; 175 return true; 176 } 177 _key = null; 178 return false; 179 } 180 181 #endregion 182 } 183 184 private sealed class KeyCollection : ICollection 185 { 186 private HashList _hashList; 187 188 #region Constructors 189 KeyCollection()190 internal KeyCollection() 191 { 192 } 193 KeyCollection(HashList hashList)194 internal KeyCollection(HashList hashList) 195 { 196 _hashList = hashList; 197 } 198 199 #endregion 200 ToString()201 public override string ToString() 202 { 203 StringBuilder result = new StringBuilder(); 204 205 result.Append("["); 206 ArrayList keys = _hashList._insertionOrderList; 207 for (int i = 0; i < keys.Count; i++) 208 { 209 if (i > 0) 210 { 211 result.Append(", "); 212 } 213 result.Append(keys[i]); 214 } 215 result.Append("]"); 216 217 return result.ToString(); 218 } 219 Equals(object o)220 public override bool Equals(object o) 221 { 222 if (o is KeyCollection) 223 { 224 KeyCollection other = (KeyCollection) o; 225 if ((Count == 0) && (other.Count == 0)) 226 return true; 227 else if (Count == other.Count) 228 { 229 for (int i = 0; i < Count; i++) 230 { 231 if ((_hashList._insertionOrderList[i] == other._hashList._insertionOrderList[i]) || 232 (_hashList._insertionOrderList[i].Equals(other._hashList._insertionOrderList[i]))) 233 return true; 234 } 235 } 236 } 237 return false; 238 } 239 GetHashCode()240 public override int GetHashCode() 241 { 242 return _hashList._insertionOrderList.GetHashCode(); 243 } 244 245 #region ICollection Members 246 247 public bool IsSynchronized 248 { 249 get { return _hashList.IsSynchronized; } 250 } 251 252 public int Count 253 { 254 get { return _hashList.Count; } 255 } 256 CopyTo(Array array, int index)257 public void CopyTo(Array array, int index) 258 { 259 _hashList.CopyKeysTo(array, index); 260 } 261 262 public object SyncRoot 263 { 264 get { return _hashList.SyncRoot; } 265 } 266 267 #endregion 268 269 #region IEnumerable Members 270 GetEnumerator()271 public IEnumerator GetEnumerator() 272 { 273 return new HashListEnumerator(_hashList, HashListEnumerator.EnumerationMode.Key); 274 } 275 276 #endregion 277 } 278 279 private sealed class ValueCollection : ICollection 280 { 281 private HashList _hashList; 282 283 #region Constructors 284 ValueCollection()285 internal ValueCollection() 286 { 287 } 288 ValueCollection(HashList hashList)289 internal ValueCollection(HashList hashList) 290 { 291 _hashList = hashList; 292 } 293 294 #endregion 295 ToString()296 public override string ToString() 297 { 298 StringBuilder result = new StringBuilder(); 299 300 result.Append("["); 301 IEnumerator iter = new HashListEnumerator(_hashList, HashListEnumerator.EnumerationMode.Value); 302 if (iter.MoveNext()) 303 { 304 result.Append((iter.Current == null) ? "null" : iter.Current); 305 while (iter.MoveNext()) 306 { 307 result.Append(", "); 308 result.Append((iter.Current == null) ? "null" : iter.Current); 309 } 310 } 311 result.Append("]"); 312 313 return result.ToString(); 314 } 315 316 #region ICollection Members 317 318 public bool IsSynchronized 319 { 320 get { return _hashList.IsSynchronized; } 321 } 322 323 public int Count 324 { 325 get { return _hashList.Count; } 326 } 327 CopyTo(Array array, int index)328 public void CopyTo(Array array, int index) 329 { 330 _hashList.CopyValuesTo(array, index); 331 } 332 333 public object SyncRoot 334 { 335 get { return _hashList.SyncRoot; } 336 } 337 338 #endregion 339 340 #region IEnumerable Members 341 GetEnumerator()342 public IEnumerator GetEnumerator() 343 { 344 return new HashListEnumerator(_hashList, HashListEnumerator.EnumerationMode.Value); 345 } 346 347 #endregion 348 } 349 350 #endregion 351 352 private Hashtable _dictionary = new Hashtable(); 353 private ArrayList _insertionOrderList = new ArrayList(); 354 private int _version; 355 356 #region Constructors 357 HashList()358 public HashList() : this(-1) 359 { 360 } 361 HashList(int capacity)362 public HashList(int capacity) 363 { 364 if (capacity < 0) 365 { 366 _dictionary = new Hashtable(); 367 _insertionOrderList = new ArrayList(); 368 } 369 else 370 { 371 _dictionary = new Hashtable(capacity); 372 _insertionOrderList = new ArrayList(capacity); 373 } 374 _version = 0; 375 } 376 377 #endregion 378 379 #region IDictionary Members 380 381 public bool IsReadOnly { get { return _dictionary.IsReadOnly; } } 382 GetEnumerator()383 public IDictionaryEnumerator GetEnumerator() 384 { 385 return new HashListEnumerator(this, HashListEnumerator.EnumerationMode.Entry); 386 } 387 388 public object this[object key] 389 { 390 get { return _dictionary[key]; } 391 set 392 { 393 bool isNewEntry = !_dictionary.Contains(key); 394 _dictionary[key] = value; 395 if (isNewEntry) 396 _insertionOrderList.Add(key); 397 _version++; 398 } 399 } 400 Remove(object key)401 public void Remove(object key) 402 { 403 _dictionary.Remove(key); 404 _insertionOrderList.Remove(key); 405 _version++; 406 } 407 Contains(object key)408 public bool Contains(object key) 409 { 410 return _dictionary.Contains(key); 411 } 412 Clear()413 public void Clear() 414 { 415 _dictionary.Clear(); 416 _insertionOrderList.Clear(); 417 _version++; 418 } 419 420 public ICollection Values 421 { 422 get { return new ValueCollection(this); } 423 } 424 Add(object key, object value)425 public void Add(object key, object value) 426 { 427 _dictionary.Add(key, value); 428 _insertionOrderList.Add(key); 429 _version++; 430 } 431 432 public ICollection Keys 433 { 434 get { return new KeyCollection(this); } 435 } 436 437 public bool IsFixedSize 438 { 439 get { return _dictionary.IsFixedSize; } 440 } 441 442 #endregion 443 444 #region ICollection Members 445 446 public bool IsSynchronized 447 { 448 get { return _dictionary.IsSynchronized; } 449 } 450 451 public int Count 452 { 453 get { return _dictionary.Count; } 454 } 455 CopyTo(Array array, int index)456 public void CopyTo(Array array, int index) 457 { 458 int len = _insertionOrderList.Count; 459 for (int i = 0; i < len; i++) 460 { 461 DictionaryEntry e = new DictionaryEntry(_insertionOrderList[i], _dictionary[_insertionOrderList[i]]); 462 array.SetValue(e, index++); 463 } 464 } 465 466 public object SyncRoot 467 { 468 get { return _dictionary.SyncRoot; } 469 } 470 471 #endregion 472 473 #region IEnumerable Members 474 System.Collections.IEnumerable.GetEnumerator()475 IEnumerator System.Collections.IEnumerable.GetEnumerator() 476 { 477 return new HashListEnumerator(this, HashListEnumerator.EnumerationMode.Entry); 478 } 479 480 #endregion 481 CopyKeysTo(Array array, int index)482 private void CopyKeysTo(Array array, int index) 483 { 484 int len = _insertionOrderList.Count; 485 for (int i = 0; i < len; i++) 486 { 487 array.SetValue(_insertionOrderList[i], index++); 488 } 489 } 490 CopyValuesTo(Array array, int index)491 private void CopyValuesTo(Array array, int index) 492 { 493 int len = _insertionOrderList.Count; 494 for (int i = 0; i < len; i++) 495 { 496 array.SetValue(_dictionary[_insertionOrderList[i]], index++); 497 } 498 } 499 500 } 501 }