Cosmos/Users/Orvid/Orvid.Concurrent/KeyComparer.cs

276 lines
9.9 KiB
C#

/*
Copyright 2008 The 'A Concurrent Hashtable' development team
(http://www.codeplex.com/CH/People/ProjectPeople.aspx)
This library is licensed under the GNU Library General Public License (LGPL). You should
have received a copy of the license along with the source code. If not, an online copy
of the license can be found at http://www.codeplex.com/CH/license.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orvid.Concurrent.Collections
{
internal interface IKeyComparer<T>
{
bool Equals(ref T x, bool xIsWeak, ref T y, bool yIsWeak);
int GetHashCode(ref T obj, bool objIsWeak);
}
#if !SILVERLIGHT
[Serializable]
#endif
internal struct WeakKeyComparer<E> : IKeyComparer<WeakKey<E>>
where E : class
{
public IEqualityComparer<E> _equalityComparer;
#region IKeyComparer<WeakKey<E>> Members
public bool Equals(ref WeakKey<E> key1, bool key1IsWeak, ref WeakKey<E> key2, bool key2IsWeak)
{
var obj1 = key1IsWeak ? ((WeakReference)key1._elementReference).Target : key1._elementReference;
var obj2 = key2IsWeak ? ((WeakReference)key2._elementReference).Target : key2._elementReference;
return
obj1 == null ? obj2 == null && object.ReferenceEquals(key1._elementReference, key2._elementReference) :
obj2 == null ? false :
object.ReferenceEquals(obj1, obj2) ? true :
_equalityComparer.Equals((E)obj1, (E)obj2);
}
public int GetHashCode(ref WeakKey<E> obj, bool objIsWeak)
{
return _equalityComparer.GetHashCode((E)(objIsWeak ? ((WeakReference)obj._elementReference).Target : obj._elementReference));
}
#endregion
}
[Serializable]
internal class StrongKeyComparer<E> : IKeyComparer<StrongKey<E>>
{
public IEqualityComparer<E> _equalityComparer = null;
public bool Equals(ref StrongKey<E> x, bool xIsWeak, ref StrongKey<E> y, bool yIsWeak)
{
return _equalityComparer.Equals(x._element, y._element);
}
public int GetHashCode(ref StrongKey<E> obj, bool objIsWeak)
{
return _equalityComparer.GetHashCode(obj._element);
}
}
[Serializable]
internal class KeySegmentComparer<E, T> : IKeyComparer<KeySegment<E, T>>
where E : class
where T : ITrashable
{
public WeakKeyComparer<E> _elementComparer;
public IKeyComparer<T> _tail;
#region IKeyComparer<WeakKeySegment<E,T>> Members
public bool Equals(ref KeySegment<E, T> x, bool xIsWeak, ref KeySegment<E, T> y, bool yIsWeak)
{
return
_elementComparer.Equals(ref x._elementReference, xIsWeak, ref y._elementReference, yIsWeak)
&& _tail.Equals(ref x._tail, xIsWeak, ref y._tail, yIsWeak)
;
}
public int GetHashCode(ref KeySegment<E, T> obj, bool objIsWeak)
{
return (int)Hasher.Rehash(_elementComparer.GetHashCode(ref obj._elementReference, objIsWeak)) ^ _tail.GetHashCode(ref obj._tail, objIsWeak);
}
#endregion
}
internal abstract class KeyComparerBase<K, V, S> : IEqualityComparer<K>
where K : KeyBase<V, S>
where V : ITrashable
{
public IKeyComparer<V> _comparers;
public IEqualityComparer<S> _strongValueComparer;
#region IEqualityComparer<Key<A,B,C,D>> Members
public bool Equals(K x, K y)
{ return _comparers.Equals(ref x._values, x.IsWeak, ref y._values, y.IsWeak) && _strongValueComparer.Equals(x._strongValue, y._strongValue); }
public int GetHashCode(K obj)
{ return obj._hash; }
public int CalculateHashCode(K obj)
{ return (int)Hasher.Rehash(_comparers.GetHashCode(ref obj._values, obj.IsWeak)) ^ _strongValueComparer.GetHashCode(obj._strongValue); }
#endregion
}
#if !SILVERLIGHT
[Serializable]
#endif
internal class KeyComparer<S> : IEqualityComparer<StrongKey<S>>
{
IEqualityComparer<S> _strongValueComparer;
public KeyComparer(IEqualityComparer<S> strongKeyComparer)
{
if (null == strongKeyComparer)
throw new ArgumentNullException("strongKeyComparer");
_strongValueComparer = strongKeyComparer;
}
#region IEqualityComparer<StrongKey<S>> Members
public bool Equals(StrongKey<S> x, StrongKey<S> y)
{ return _strongValueComparer.Equals(x._element, y._element); }
public int GetHashCode(StrongKey<S> obj)
{ return _strongValueComparer.GetHashCode(obj._element); }
#endregion
}
#if !SILVERLIGHT
[Serializable]
#endif
internal class KeyComparer<W1, S> : KeyComparerBase<Key<W1, S>, WeakKey<W1>, S>
where W1 : class
{
public KeyComparer(IEqualityComparer<W1> weakKeyComparer, IEqualityComparer<S> strongKeyComparer)
{
if (null == weakKeyComparer)
throw new ArgumentNullException("weakKeyComparer");
if (null == strongKeyComparer)
throw new ArgumentNullException("strongKeyComparer");
_comparers = new WeakKeyComparer<W1> { _equalityComparer = weakKeyComparer };
_strongValueComparer = strongKeyComparer;
}
}
#if !SILVERLIGHT
[Serializable]
#endif
internal class KeyComparer<W1, W2, S> : KeyComparerBase<Key<W1, W2, S>, KeySegment<W1, WeakKey<W2>>, S>
where W1 : class
where W2 : class
{
public KeyComparer(IEqualityComparer<W1> weakKey1Comparer, IEqualityComparer<W2> weakKey2Comparer, IEqualityComparer<S> strongKeyComparer)
{
if (null == weakKey1Comparer)
throw new ArgumentNullException("weakKey1Comparer");
if (null == weakKey2Comparer)
throw new ArgumentNullException("weakKey2Comparer");
if (null == strongKeyComparer)
throw new ArgumentNullException("strongKeyComparer");
_comparers =
new KeySegmentComparer<W1, WeakKey<W2>>
{
_elementComparer = new WeakKeyComparer<W1> { _equalityComparer = weakKey1Comparer },
_tail = new WeakKeyComparer<W2> { _equalityComparer = weakKey2Comparer }
}
;
_strongValueComparer = strongKeyComparer;
}
}
#if !SILVERLIGHT
[Serializable]
#endif
internal class KeyComparer<W1, W2, W3, S> : KeyComparerBase<Key<W1, W2, W3, S>, KeySegment<W1, KeySegment<W2, WeakKey<W3>>>, S>
where W1 : class
where W2 : class
where W3 : class
{
public KeyComparer(IEqualityComparer<W1> weakKey1Comparer, IEqualityComparer<W2> weakKey2Comparer, IEqualityComparer<W3> weakKey3Comparer, IEqualityComparer<S> strongKeyComparer)
{
if (null == weakKey1Comparer)
throw new ArgumentNullException("weakKey1Comparer");
if (null == weakKey2Comparer)
throw new ArgumentNullException("weakKey2Comparer");
if (null == weakKey3Comparer)
throw new ArgumentNullException("weakKey3Comparer");
if (null == strongKeyComparer)
throw new ArgumentNullException("strongKeyComparer");
_comparers =
new KeySegmentComparer<W1, KeySegment<W2, WeakKey<W3>>>
{
_elementComparer = new WeakKeyComparer<W1> { _equalityComparer = weakKey1Comparer },
_tail = new KeySegmentComparer<W2, WeakKey<W3>>
{
_elementComparer = new WeakKeyComparer<W2> { _equalityComparer = weakKey2Comparer },
_tail = new WeakKeyComparer<W3> { _equalityComparer = weakKey3Comparer }
}
}
;
_strongValueComparer = strongKeyComparer;
}
}
#if !SILVERLIGHT
[Serializable]
#endif
internal class KeyComparer<W1, W2, W3, W4, S> : KeyComparerBase<Key<W1, W2, W3, W4, S>, KeySegment<W1, KeySegment<W2, KeySegment<W3, WeakKey<W4>>>>, S>
where W1 : class
where W2 : class
where W3 : class
where W4 : class
{
public KeyComparer(IEqualityComparer<W1> weakKey1Comparer, IEqualityComparer<W2> weakKey2Comparer, IEqualityComparer<W3> weakKey3Comparer, IEqualityComparer<W4> weakKey4Comparer, IEqualityComparer<S> strongKeyComparer)
{
if (null == weakKey1Comparer)
throw new ArgumentNullException("weakKey1Comparer");
if (null == weakKey2Comparer)
throw new ArgumentNullException("weakKey2Comparer");
if (null == weakKey3Comparer)
throw new ArgumentNullException("weakKey3Comparer");
if (null == weakKey4Comparer)
throw new ArgumentNullException("weakKey4Comparer");
if (null == strongKeyComparer)
throw new ArgumentNullException("strongKeyComparer");
_comparers =
new KeySegmentComparer<W1, KeySegment<W2, KeySegment<W3, WeakKey<W4>>>>
{
_elementComparer = new WeakKeyComparer<W1> { _equalityComparer = weakKey1Comparer },
_tail = new KeySegmentComparer<W2, KeySegment<W3, WeakKey<W4>>>
{
_elementComparer = new WeakKeyComparer<W2> { _equalityComparer = weakKey2Comparer },
_tail = new KeySegmentComparer<W3, WeakKey<W4>>
{
_elementComparer = new WeakKeyComparer<W3> { _equalityComparer = weakKey3Comparer },
_tail = new WeakKeyComparer<W4> { _equalityComparer = weakKey4Comparer }
}
}
}
;
_strongValueComparer = strongKeyComparer;
}
}
}