diff --git a/BeefLibs/corlib/src/Collections/HashSet.bf b/BeefLibs/corlib/src/Collections/HashSet.bf index 3255166f..08c80602 100644 --- a/BeefLibs/corlib/src/Collections/HashSet.bf +++ b/BeefLibs/corlib/src/Collections/HashSet.bf @@ -196,7 +196,13 @@ namespace System.Collections return false; } + [Obsolete("Method renamed to ContainsAlt", false)] public bool ContainsWith(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey + { + return ContainsAlt(item); + } + + public bool ContainsAlt(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey { if (mBuckets != null) { @@ -346,6 +352,11 @@ namespace System.Collections return Add(item, out entryPtr); } + public bool TryAddAlt(TAltKey item, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey + { + return AddAlt(item, out entryPtr); + } + public void CopyTo(T[] array) { CopyTo(array, 0, mCount); } public void CopyTo(T[] array, int32 arrayIndex, int32 count) @@ -632,6 +643,71 @@ namespace System.Collections mVersion++; #endif +#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE + if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) { + m_comparer = (IEqualityComparer) HashHelpers.GetRandomizedEqualityComparer(m_comparer); + SetCapacity(m_buckets.Length, true); + } +#endif // FEATURE_RANDOMIZED_STRING_HASHING + + entryPtr = &mSlots[index].mValue; + return true; + } + + /// Adds value to HashSet if not contained already + /// @return true if added and false if already present + /// @param value value to find + /// @param entryPtr ponter to entry + public bool AddAlt(TAltKey value, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey + { + if (mBuckets == null) + { + Initialize(0); + } + + int32 hashCode = (int32)InternalGetHashCodeAlt(value); + int32 bucket = hashCode % (int32)mBuckets.Count; +#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE + int collisionCount = 0; +#endif + for (int32 i = mBuckets[hashCode % mBuckets.Count] - 1; i >= 0; i = mSlots[i].mNext) + { + if (mSlots[i].mHashCode == hashCode && /*m_comparer.Equals*/(mSlots[i].mValue == value)) + { + entryPtr = &mSlots[i].mValue; + return false; + } +#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE + collisionCount++; +#endif + } + + int32 index; + if (mFreeList >= 0) + { + index = mFreeList; + mFreeList = mSlots[index].mNext; + } + else + { + if (mLastIndex == mSlots.Count) + { + IncreaseCapacity(); + // this will change during resize + bucket = hashCode % (int32)mBuckets.Count; + } + index = mLastIndex; + mLastIndex++; + } + mSlots[index].mHashCode = hashCode; + //mSlots[index].mValue = value; + mSlots[index].mNext = mBuckets[bucket] - 1; + mBuckets[bucket] = index + 1; + mCount++; +#if VERSION_HASHSET + mVersion++; +#endif + #if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) { m_comparer = (IEqualityComparer) HashHelpers.GetRandomizedEqualityComparer(m_comparer); @@ -1071,6 +1147,15 @@ namespace System.Collections return item.GetHashCode() & Lower31BitMask; } + private int InternalGetHashCodeAlt(TAltKey item) where TAltKey : IHashable + { + if (item == null) + { + return 0; + } + return item.GetHashCode() & Lower31BitMask; + } + #endregion // used for set checking operations (using enumerables) that rely on counting