System.Collections.Immutable by Microsoft

<PackageReference Include="System.Collections.Immutable" Version="8.0.0-preview.2.23128.3" />

.NET API 250,032 bytes

 KeyAnalyzer

static class KeyAnalyzer
using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Collections.Frozen { internal static class KeyAnalyzer { internal struct AnalysisResults { public bool AllAscii { [System.Runtime.CompilerServices.IsReadOnly] get; } public bool IgnoreCase { [System.Runtime.CompilerServices.IsReadOnly] get; } public int MinimumLength { [System.Runtime.CompilerServices.IsReadOnly] get; set; } public int MaximumLengthDiff { [System.Runtime.CompilerServices.IsReadOnly] get; set; } public int HashIndex { [System.Runtime.CompilerServices.IsReadOnly] get; } public int HashCount { [System.Runtime.CompilerServices.IsReadOnly] get; } public bool SubstringHashing => HashCount != 0; public bool RightJustifiedSubstring => HashIndex < 0; public AnalysisResults(bool allAscii, bool ignoreCase, int minimumLength, int maximumLengthDiff, int hashIndex, int hashCount) { AllAscii = allAscii; IgnoreCase = ignoreCase; MinimumLength = minimumLength; MaximumLengthDiff = maximumLengthDiff; HashIndex = hashIndex; HashCount = hashCount; } } private abstract class SubstringComparer : IEqualityComparer<string> { public int Index; public int Count; public abstract bool Equals(string x, string y); public abstract int GetHashCode(string s); } private sealed class LeftJustifiedSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return MemoryExtensions.AsSpan(x, Index, Count).SequenceEqual(MemoryExtensions.AsSpan(y, Index, Count)); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinal(MemoryExtensions.AsSpan(s, Index, Count)); } } private sealed class LeftJustifiedCaseInsensitiveSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return MemoryExtensions.Equals(MemoryExtensions.AsSpan(x, Index, Count), MemoryExtensions.AsSpan(y, Index, Count), StringComparison.OrdinalIgnoreCase); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinalIgnoreCase(MemoryExtensions.AsSpan(s, Index, Count)); } } private sealed class RightJustifiedSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return MemoryExtensions.AsSpan(x, x.Length + Index, Count).SequenceEqual(MemoryExtensions.AsSpan(y, y.Length + Index, Count)); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinal(MemoryExtensions.AsSpan(s, s.Length + Index, Count)); } } private sealed class RightJustifiedCaseInsensitiveSubstringComparer : SubstringComparer { public override bool Equals(string x, string y) { return MemoryExtensions.Equals(MemoryExtensions.AsSpan(x, x.Length + Index, Count), MemoryExtensions.AsSpan(y, y.Length + Index, Count), StringComparison.OrdinalIgnoreCase); } public override int GetHashCode(string s) { return Hashing.GetHashCodeOrdinalIgnoreCase(MemoryExtensions.AsSpan(s, s.Length + Index, Count)); } } public static void Analyze([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<string> uniqueStrings, bool ignoreCase, out AnalysisResults results) { if (!UseSubstring(uniqueStrings, ignoreCase, out results)) UseFullString(uniqueStrings, ignoreCase, out results); int num = 2147483647; int num2 = 0; ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string text in readOnlySpan) { if (text.Length < num) num = text.Length; if (text.Length > num2) num2 = text.Length; } results.MinimumLength = num; results.MaximumLengthDiff = num2 - num; } private static bool UseSubstring(ReadOnlySpan<string> uniqueStrings, bool ignoreCase, out AnalysisResults results) { int num = 2147483647; ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string text in readOnlySpan) { if (text.Length < num) num = text.Length; } SubstringComparer substringComparer = ignoreCase ? ((SubstringComparer)new LeftJustifiedCaseInsensitiveSubstringComparer()) : ((SubstringComparer)new LeftJustifiedSubstringComparer()); SubstringComparer substringComparer2 = ignoreCase ? ((SubstringComparer)new RightJustifiedCaseInsensitiveSubstringComparer()) : ((SubstringComparer)new RightJustifiedSubstringComparer()); HashSet<string> set = new HashSet<string>(substringComparer); HashSet<string> set2 = new HashSet<string>(substringComparer2); for (int j = 1; j <= num; j++) { for (int k = 0; k <= num - j; k++) { substringComparer.Index = k; substringComparer.Count = j; double uniquenessFactor = GetUniquenessFactor(set, uniqueStrings); if (uniquenessFactor >= 0.95) { bool allAscii = true; ReadOnlySpan<string> readOnlySpan2 = uniqueStrings; foreach (string text2 in readOnlySpan2) { if (!IsAllAscii(MemoryExtensions.AsSpan(text2, substringComparer.Index, substringComparer.Count))) { allAscii = false; break; } } results = new AnalysisResults(allAscii, ignoreCase, 0, 0, substringComparer.Index, substringComparer.Count); return true; } substringComparer2.Index = -k - j; substringComparer2.Count = j; uniquenessFactor = GetUniquenessFactor(set2, uniqueStrings); if (uniquenessFactor >= 0.95) { bool allAscii2 = true; ReadOnlySpan<string> readOnlySpan3 = uniqueStrings; foreach (string text3 in readOnlySpan3) { if (!IsAllAscii(MemoryExtensions.AsSpan(text3, text3.Length + substringComparer2.Index, substringComparer2.Count))) { allAscii2 = false; break; } } results = new AnalysisResults(allAscii2, ignoreCase, 0, 0, substringComparer2.Index, substringComparer2.Count); return true; } } } results = default(AnalysisResults); return false; } private static void UseFullString(ReadOnlySpan<string> uniqueStrings, bool ignoreCase, out AnalysisResults results) { bool allAscii = true; ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string text in readOnlySpan) { if (!IsAllAscii(MemoryExtensions.AsSpan(text))) { allAscii = false; break; } } results = new AnalysisResults(allAscii, ignoreCase, 0, 0, 0, 0); } internal unsafe static bool IsAllAscii(ReadOnlySpan<char> s) { fixed (char* ptr = &s.GetPinnableReference()) { uint* ptr2 = (uint*)ptr; int num; for (num = s.Length; num > 3; num -= 4) { if (!<IsAllAscii>g__AllCharsInUInt32AreAscii|3_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; } private static double GetUniquenessFactor(HashSet<string> set, ReadOnlySpan<string> uniqueStrings) { set.Clear(); ReadOnlySpan<string> readOnlySpan = uniqueStrings; foreach (string item in readOnlySpan) { set.Add(item); } return (double)set.Count / (double)uniqueStrings.Length; } } }