///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
/*
using JetBrains.DataStructures;
namespace System.Collections.Generic
{
///
/// Mimics the Netfx35 HashSet class.
///
///
public class HashSet : ICollection
{
#region Data
protected internal Bucket[] _buckets;
protected internal uint _count;
protected internal uint _firstFree;
protected internal uint[] _hashTable;
protected internal uint _initialSize;
protected internal uint _size;
protected internal int _version;
#endregion
#region Init
public HashSet()
: this(0)
{
}
public HashSet(int initialSize)
{
_count = 0;
ReHash(_initialSize = HashtableParams.AdjustHashtableSize((uint)initialSize));
}
public HashSet(IEnumerable collection)
: this(0)
{
foreach(TKey item in collection)
Add(item);
}
#endregion
#region Attributes
public int Count
{
get
{
return (int)_count;
}
}
#endregion
#region Operations
public virtual void Add(TKey key)
{
uint tableIndex, prevIndex;
uint index = SearchCollisions(key, out tableIndex, out prevIndex);
if(index == 0)
{
uint i = _firstFree;
if(i != 0)
_firstFree = _buckets[i].Next;
else
{
i = _count + 1;
if(i == _buckets.Length)
{
ReHash(((_size * 13) - 7) >> 3);
tableIndex = ((uint)key.GetHashCode()) % _size;
}
}
_buckets[i].Key = key;
_buckets[i].Next = _hashTable[tableIndex];
_hashTable[tableIndex] = i;
++_count;
#if DEBUG
++_version;
#endif
}
}
public void Clear()
{
if(_initialSize != _size)
{
_count = 0;
ReHash(0);
}
else
{
if(_count > 0)
{
_count = 0;
_firstFree = 0;
Array.Clear(_hashTable, 0, _hashTable.Length);
Array.Clear(_buckets, 0, _buckets.Length);
}
}
}
public bool Contains(TKey key)
{
if(_count == 0)
return false;
if(key == null)
throw new ArgumentNullException("key");
uint tableIndex, prevIndex;
return SearchCollisions(key, out tableIndex, out prevIndex) != 0;
}
public IEnumerator GetEnumerator()
{
return new HashSetEnumerator(this);
}
public object GetKey(object key)
{
if(key == null)
throw new ArgumentNullException("key");
if(_count == 0)
return null;
uint tableIndex, prevIndex;
uint bucketIndex = SearchCollisions(key, out tableIndex, out prevIndex);
return (bucketIndex == 0) ? null : _buckets[bucketIndex].Key;
}
public void Remove(object key)
{
if(key == null)
throw new ArgumentNullException("key");
if(_count == 0)
return;
uint tableIndex, prevIndex;
uint index = SearchCollisions(key, out tableIndex, out prevIndex);
if(index != 0)
{
if(prevIndex != 0)
_buckets[prevIndex].Next = _buckets[index].Next;
else
_hashTable[tableIndex] = _buckets[index].Next;
_buckets[index].Key = null;
_buckets[index].Next = _firstFree;
_firstFree = index;
if(--_count == 0)
Clear();
#if DEBUG
++_version;
#endif
}
}
#endregion
#region Implementation
protected internal void ReHash(uint desiredSize)
{
if(desiredSize < _initialSize)
desiredSize = _initialSize;
uint size = HashtableParams.AdjustHashtableSize(desiredSize);
if(size != _size)
{
_firstFree = 0;
Bucket[] oldBuckets = _buckets;
_hashTable = new uint[size];
_buckets = new Bucket[size * HashtableParams.maxBucketsPerIndex];
if(_count > 0)
{
for(uint i = 1, j = 0; i < oldBuckets.Length; ++i)
{
object key = oldBuckets[i].Key;
if(key != null)
{
++j;
_buckets[j].Key = key;
uint hashValue = ((uint)key.GetHashCode()) % size;
_buckets[j].Next = _hashTable[hashValue];
_hashTable[hashValue] = j;
}
}
}
#if DEBUG
++_version;
#endif
_size = size;
}
}
///
/// Returns index of bucket where key is found or zero if not found.
///
protected internal uint SearchCollisions(TKey key, out uint tableIndex, out uint prevIndex)
{
prevIndex = 0;
uint bucketIndex = _hashTable[tableIndex = ((uint)key.GetHashCode()) % _size];
if(bucketIndex > 0 && !key.Equals(_buckets[bucketIndex].Key))
{
#if DEBUG
int savedVersion = _version;
#endif
_buckets[0].Key = key;
do
{
#if DEBUG
if(savedVersion != _version || !key.Equals(_buckets[0].Key))
throw new InvalidOperationException("Non-serialized usage detected!");
#endif
bucketIndex = _buckets[(prevIndex = bucketIndex)].Next;
} while(!key.Equals(_buckets[bucketIndex].Key));
_buckets[0].Key = null;
}
return bucketIndex;
}
#endregion
#region bucket Type
protected internal struct Bucket
{
#region Data
public TKey Key;
public uint Next;
#endregion
}
#endregion
#region Entry Type
///
/// Proxy object around a bucket representing key-value pair.
///
public class Entry
{
#region Data
internal Bucket[] _buckets;
internal uint _index;
#endregion
#region Init
internal Entry(Bucket[] buckets, uint index)
{
_buckets = buckets;
_index = index;
}
#endregion
#region Attributes
public object Key
{
get
{
return _buckets[_index].Key;
}
set
{
_buckets[_index].Key = value;
}
}
#endregion
}
#endregion
#region HashSetEnumerator Type
protected internal class HashSetEnumerator : IEnumerator
{
#region Data
private readonly uint _count;
private uint _counted;
private readonly Entry _entry;
#if DEBUG
private int _savedVersion;
private readonly HashSet _theSet;
#endregion
#region Init
public HashSetEnumerator(HashSet set)
{
_entry = new Entry(set._buckets, 0);
_count = set._count;
_theSet = set;
Reset();
}
#endregion
#region IEnumerator Members
public virtual bool MoveNext()
{
if(_counted == _count)
return false;
while(_entry._buckets[++_entry._index].Key == null)
;
++_counted;
return true;
}
public void Reset()
{
_entry._index = _counted = 0;
#if DEBUG
_savedVersion = _theSet._version;
#endif
}
public object Current
{
get
{
#if DEBUG
if(_counted == 0)
throw new InvalidOperationException("Enumerator.Current called without calling MoveNext().");
if(_savedVersion != _theSet._version)
throw new InvalidOperationException("Collection modified while enumeration.");
#endif
return _entry;
}
}
#endregion
#endif
}
#endregion
#endif
#region ICollection Members
///
///Determines whether the contains a specific value.
///
///
///
///true if is found in the ; otherwise, false.
///
///
///The object to locate in the .
bool ICollection.Contains(TKey item)
{
throw new NotImplementedException();
}
///
///Copies the elements of the to an , starting at a particular index.
///
///
///The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
///The zero-based index in at which copying begins.
/// is null.
/// is less than 0.
/// is multidimensional.-or- is equal to or greater than the length of .-or-The number of elements in the source is greater than the available space from to the end of the destination .-or-Type cannot be cast automatically to the type of the destination .
void ICollection.CopyTo(TKey[] array, int arrayIndex)
{
throw new NotImplementedException();
}
///
///Removes the first occurrence of a specific object from the .
///
///
///
///true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
///
///
///The object to remove from the .
///The is read-only.
bool ICollection.Remove(TKey item)
{
throw new NotImplementedException();
}
///
///Gets a value indicating whether the is read-only.
///
///
///
///true if the is read-only; otherwise, false.
///
///
bool ICollection.IsReadOnly
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region IEnumerable Members
///
///Returns an enumerator that iterates through the collection.
///
///
///
///A that can be used to iterate through the collection.
///
///1
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
}
}
*/