/* 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 { 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 : IKeyComparer> where E : class { public IEqualityComparer _equalityComparer; #region IKeyComparer> Members public bool Equals(ref WeakKey key1, bool key1IsWeak, ref WeakKey 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 obj, bool objIsWeak) { return _equalityComparer.GetHashCode((E)(objIsWeak ? ((WeakReference)obj._elementReference).Target : obj._elementReference)); } #endregion } [Serializable] internal class StrongKeyComparer : IKeyComparer> { public IEqualityComparer _equalityComparer = null; public bool Equals(ref StrongKey x, bool xIsWeak, ref StrongKey y, bool yIsWeak) { return _equalityComparer.Equals(x._element, y._element); } public int GetHashCode(ref StrongKey obj, bool objIsWeak) { return _equalityComparer.GetHashCode(obj._element); } } [Serializable] internal class KeySegmentComparer : IKeyComparer> where E : class where T : ITrashable { public WeakKeyComparer _elementComparer; public IKeyComparer _tail; #region IKeyComparer> Members public bool Equals(ref KeySegment x, bool xIsWeak, ref KeySegment 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 obj, bool objIsWeak) { return (int)Hasher.Rehash(_elementComparer.GetHashCode(ref obj._elementReference, objIsWeak)) ^ _tail.GetHashCode(ref obj._tail, objIsWeak); } #endregion } internal abstract class KeyComparerBase : IEqualityComparer where K : KeyBase where V : ITrashable { public IKeyComparer _comparers; public IEqualityComparer _strongValueComparer; #region IEqualityComparer> 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 : IEqualityComparer> { IEqualityComparer _strongValueComparer; public KeyComparer(IEqualityComparer strongKeyComparer) { if (null == strongKeyComparer) throw new ArgumentNullException("strongKeyComparer"); _strongValueComparer = strongKeyComparer; } #region IEqualityComparer> Members public bool Equals(StrongKey x, StrongKey y) { return _strongValueComparer.Equals(x._element, y._element); } public int GetHashCode(StrongKey obj) { return _strongValueComparer.GetHashCode(obj._element); } #endregion } #if !SILVERLIGHT [Serializable] #endif internal class KeyComparer : KeyComparerBase, WeakKey, S> where W1 : class { public KeyComparer(IEqualityComparer weakKeyComparer, IEqualityComparer strongKeyComparer) { if (null == weakKeyComparer) throw new ArgumentNullException("weakKeyComparer"); if (null == strongKeyComparer) throw new ArgumentNullException("strongKeyComparer"); _comparers = new WeakKeyComparer { _equalityComparer = weakKeyComparer }; _strongValueComparer = strongKeyComparer; } } #if !SILVERLIGHT [Serializable] #endif internal class KeyComparer : KeyComparerBase, KeySegment>, S> where W1 : class where W2 : class { public KeyComparer(IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer 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> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey1Comparer }, _tail = new WeakKeyComparer { _equalityComparer = weakKey2Comparer } } ; _strongValueComparer = strongKeyComparer; } } #if !SILVERLIGHT [Serializable] #endif internal class KeyComparer : KeyComparerBase, KeySegment>>, S> where W1 : class where W2 : class where W3 : class { public KeyComparer(IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer 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>> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey1Comparer }, _tail = new KeySegmentComparer> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey2Comparer }, _tail = new WeakKeyComparer { _equalityComparer = weakKey3Comparer } } } ; _strongValueComparer = strongKeyComparer; } } #if !SILVERLIGHT [Serializable] #endif internal class KeyComparer : KeyComparerBase, KeySegment>>>, S> where W1 : class where W2 : class where W3 : class where W4 : class { public KeyComparer(IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer weakKey4Comparer, IEqualityComparer 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>>> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey1Comparer }, _tail = new KeySegmentComparer>> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey2Comparer }, _tail = new KeySegmentComparer> { _elementComparer = new WeakKeyComparer { _equalityComparer = weakKey3Comparer }, _tail = new WeakKeyComparer { _equalityComparer = weakKey4Comparer } } } } ; _strongValueComparer = strongKeyComparer; } } }