System.Collections.Immutable by Microsoft

<PackageReference Include="System.Collections.Immutable" Version="9.0.0-preview.1.24080.9" />

.NET API 253,616 bytes

 KeyAnalyzer

static class KeyAnalyzer
using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Collections.Frozen { internal static class KeyAnalyzer { private delegate ReadOnlySpan<char> GetSpan (string s, int index, int count); internal readonly struct AnalysisResults { public bool IgnoreCase { get; } public bool AllAsciiIfIgnoreCase { get; } public int HashIndex { get; } public int HashCount { get; } public int MinimumLength { get; } public int MaximumLengthDiff { get; } public bool SubstringHashing => HashCount != 0; public bool RightJustifiedSubstring => HashIndex < 0; public AnalysisResults(bool ignoreCase, bool allAsciiIfIgnoreCase, int hashIndex, int hashCount, int minLength, int maxLength) { IgnoreCase = ignoreCase; AllAsciiIfIgnoreCase = allAsciiIfIgnoreCase; HashIndex = hashIndex; HashCount = hashCount; MinimumLength = minLength; MaximumLengthDiff = maxLength - minLength; } } private abstract class SubstringComparer : IEqualityComparer<string> { public int Index; public int Count; public bool IsLeft; public abstract bool Equals(string x, string y); public abstract int GetHashCode(string s); } private sealed class JustifiedSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return x.AsSpan(IsLeft ? Index : (x.Length + Index), Count).SequenceEqual(y.AsSpan(IsLeft ? Index : (y.Length + Index), Count)); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinal(s.AsSpan(IsLeft ? Index : (s.Length + Index), Count)); } } private sealed class JustifiedCaseInsensitiveSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return MemoryExtensions.Equals(x.AsSpan(IsLeft ? Index : (x.Length + Index), Count), y.AsSpan(IsLeft ? Index : (y.Length + Index), Count), StringComparison.OrdinalIgnoreCase); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinalIgnoreCase(s.AsSpan(IsLeft ? Index : (s.Length + Index), Count)); } } public static AnalysisResults Analyze([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<string> uniqueStrings, bool ignoreCase, int minLength, int maxLength) { if (minLength != 0 && TryUseSubstring(uniqueStrings, ignoreCase, minLength, maxLength, out AnalysisResults results)) return results; results = CreateAnalysisResults(uniqueStrings, ignoreCase, minLength, maxLength, 0, 0, false, (string s, int _, int _) => s.AsSpan()); return results; } private static bool TryUseSubstring(ReadOnlySpan<string> uniqueStrings, bool ignoreCase, int minLength, int maxLength, out AnalysisResults results) { int length = uniqueStrings.Length; int acceptableNonUniqueCount = length / 20; SubstringComparer substringComparer = ignoreCase ? ((SubstringComparer)new JustifiedCaseInsensitiveSubstringComparer()) : ((SubstringComparer)new JustifiedSubstringComparer()); HashSet<string> set = new HashSet<string>(substringComparer); int num = Math.Min(minLength, 8); for (int i = 1; i <= num; i++) { substringComparer.IsLeft = true; substringComparer.Count = i; for (int j = 0; j <= minLength - i; j++) { substringComparer.Index = j; if (HasSufficientUniquenessFactor(set, uniqueStrings, acceptableNonUniqueCount)) { results = CreateAnalysisResults(uniqueStrings, ignoreCase, minLength, maxLength, j, i, true, (string s, int index, int count) => s.AsSpan(index, count)); return true; } } if (minLength != maxLength) { substringComparer.IsLeft = false; for (int k = 0; k <= minLength - i; k++) { substringComparer.Index = -k - i; if (HasSufficientUniquenessFactor(set, uniqueStrings, acceptableNonUniqueCount)) { results = CreateAnalysisResults(uniqueStrings, ignoreCase, minLength, maxLength, substringComparer.Index, i, true, (string s, int index, int count) => s.AsSpan(s.Length + index, count)); return true; } } } } results = default(AnalysisResults); return false; } private static AnalysisResults CreateAnalysisResults(ReadOnlySpan<string> uniqueStrings, bool ignoreCase, int minLength, int maxLength, int index, int count, bool isSubstring, GetSpan getSubstringSpan) { bool allAsciiIfIgnoreCase = true; if (ignoreCase) { bool flag = !isSubstring; ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string s in readOnlySpan) { ReadOnlySpan<char> s2 = getSubstringSpan(s, index, count); if (!IsAllAscii(s2)) { allAsciiIfIgnoreCase = false; flag = false; break; } if (flag && ContainsAnyLetters(s2)) flag = false; } if (flag) ignoreCase = false; } return new AnalysisResults(ignoreCase, allAsciiIfIgnoreCase, index, count, minLength, maxLength); } internal unsafe static bool IsAllAscii(ReadOnlySpan<char> s) { fixed (char* ptr = &s.GetPinnableReference()) { uint* ptr2 = (uint*)ptr; int num; for (num = s.Length; num >= 4; num -= 4) { if (!<IsAllAscii>g__AllCharsInUInt32AreAscii|4_0(*ptr2 | ptr2[1])) return false; ptr2 += 2; } char* ptr3 = (char*)ptr2; while (num-- > 0) { char* intPtr = ptr3; ptr3 = intPtr + 1; char c = *intPtr; if (c >= '€') return false; } } return true; } internal static bool ContainsAnyLetters(ReadOnlySpan<char> s) { ReadOnlySpan<char> readOnlySpan = s; foreach (char c in readOnlySpan) { if ((uint)((c | 32) - 97) <= 25) return true; } return false; } [System.Runtime.CompilerServices.NullableContext(1)] internal static bool HasSufficientUniquenessFactor(HashSet<string> set, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<string> uniqueStrings, int acceptableNonUniqueCount) { set.Clear(); ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string item in readOnlySpan) { if (!set.Add(item) && --acceptableNonUniqueCount < 0) return false; } return true; } } }