OrdinalStringFrozenSet
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Collections.Frozen
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
internal abstract class OrdinalStringFrozenSet : FrozenSetInternalBase<string, OrdinalStringFrozenSet.GSW>
{
[System.Runtime.CompilerServices.Nullable(0)]
internal struct GSW : IGenericSpecializedWrapper
{
private OrdinalStringFrozenSet _set;
public int Count => _set.Count;
public IEqualityComparer<string> Comparer => _set.Comparer;
public void Store(FrozenSet<string> set)
{
_set = (OrdinalStringFrozenSet)set;
}
public int FindItemIndex(string item)
{
return _set.FindItemIndex(item);
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public Enumerator GetEnumerator()
{
return _set.GetEnumerator();
}
}
private readonly FrozenHashTable _hashTable;
private readonly string[] _items;
private readonly int _minimumLength;
private readonly int _maximumLengthDiff;
private protected int HashIndex { get; }
private protected int HashCount { get; }
private protected override string[] ItemsCore => _items;
private protected override int CountCore => _hashTable.Count;
internal OrdinalStringFrozenSet(string[] entries, IEqualityComparer<string> comparer, int minimumLength, int maximumLengthDiff, int hashIndex = -1, int hashCount = -1)
: base(comparer)
{
_items = new string[entries.Length];
_minimumLength = minimumLength;
_maximumLengthDiff = maximumLengthDiff;
HashIndex = hashIndex;
HashCount = hashCount;
int[] array = ArrayPool<int>.Shared.Rent(entries.Length);
Span<int> hashCodes = array.AsSpan(0, entries.Length);
for (int i = 0; i < entries.Length; i++) {
hashCodes[i] = GetHashCode(entries[i]);
}
_hashTable = FrozenHashTable.Create(hashCodes, false);
for (int j = 0; j < hashCodes.Length; j++) {
int num = hashCodes[j];
_items[num] = entries[j];
}
ArrayPool<int>.Shared.Return(array, false);
}
[System.Runtime.CompilerServices.NullableContext(2)]
private protected virtual bool Equals(string x, string y)
{
return string.Equals(x, y);
}
[System.Runtime.CompilerServices.NullableContext(0)]
private protected virtual bool Equals(ReadOnlySpan<char> x, [System.Runtime.CompilerServices.Nullable(2)] string y)
{
return EqualsOrdinal(x, y);
}
private protected abstract int GetHashCode(string s);
[System.Runtime.CompilerServices.NullableContext(0)]
private protected abstract int GetHashCode(ReadOnlySpan<char> s);
private protected virtual bool CheckLengthQuick(uint length)
{
return true;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
private protected override Enumerator GetEnumeratorCore()
{
return new Enumerator(_items);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private protected override int FindItemIndex(string item)
{
if (item != null && (uint)(item.Length - _minimumLength) <= (uint)_maximumLengthDiff && CheckLengthQuick((uint)item.Length)) {
int hashCode = GetHashCode(item);
_hashTable.FindMatchingEntries(hashCode, out int i, out int endIndex);
for (; i <= endIndex; i++) {
if (hashCode == _hashTable.HashCodes[i] && Equals(item, _items[i]))
return i;
}
}
return -1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(0)]
private protected static bool EqualsOrdinal(ReadOnlySpan<char> x, [System.Runtime.CompilerServices.Nullable(2)] string y)
{
if (!x.IsEmpty || y != null)
return x.SequenceEqual(y.AsSpan());
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(0)]
private protected static bool EqualsOrdinalIgnoreCase(ReadOnlySpan<char> x, [System.Runtime.CompilerServices.Nullable(2)] string y)
{
if (!x.IsEmpty || y != null)
return MemoryExtensions.Equals(x, y.AsSpan(), StringComparison.OrdinalIgnoreCase);
return false;
}
}
}