Home | History | Annotate | Download | only in Antlr.Runtime.Collections
      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 
     72 			internal HashListEnumerator()
     73 			{
     74 				_index = 0;
     75 				_key = null;
     76 				_value = null;
     77 			}
     78 
     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 
    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 
    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 
    190 			internal KeyCollection()
    191 			{
    192 			}
    193 
    194 			internal KeyCollection(HashList hashList)
    195 			{
    196 				_hashList = hashList;
    197 			}
    198 
    199 			#endregion
    200 
    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 
    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 
    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 
    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 
    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 
    285 			internal ValueCollection()
    286 			{
    287 			}
    288 
    289 			internal ValueCollection(HashList hashList)
    290 			{
    291 				_hashList = hashList;
    292 			}
    293 
    294 			#endregion
    295 
    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 
    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 
    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 
    358 		public HashList() : this(-1)
    359 		{
    360 		}
    361 
    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 
    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 
    401 		public void Remove(object key)
    402 		{
    403 			_dictionary.Remove(key);
    404 			_insertionOrderList.Remove(key);
    405 			_version++;
    406 		}
    407 
    408 		public bool Contains(object key)
    409 		{
    410 			return _dictionary.Contains(key);
    411 		}
    412 
    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 
    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 
    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 
    475 		IEnumerator System.Collections.IEnumerable.GetEnumerator()
    476 		{
    477 			return new HashListEnumerator(this, HashListEnumerator.EnumerationMode.Entry);
    478 		}
    479 
    480 		#endregion
    481 
    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 
    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 }