diff --git a/src/libs/FastEnum.Core/FastEnum.cs b/src/libs/FastEnum.Core/FastEnum.cs index 17d2815..14209ae 100644 --- a/src/libs/FastEnum.Core/FastEnum.cs +++ b/src/libs/FastEnum.Core/FastEnum.cs @@ -238,7 +238,7 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out T return false; } - if (isNumeric(value.At(0))) + if (StringHelper.IsNumeric(value.At(0))) return UnderlyingOperation.TryParseValue(value, out result); if (ignoreCase) @@ -248,31 +248,6 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out T #region Local Functions - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool isNumeric(char x) - { - // note: - // - In this case, there is no change in speed with or without sequential numbering. - - return x switch - { - '+' => true, // 43 - '-' => true, // 45 - '0' => true, // 48 - '1' => true, - '2' => true, - '3' => true, - '4' => true, - '5' => true, - '6' => true, - '7' => true, - '8' => true, - '9' => true, - _ => false, - }; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool tryParseNameCaseSensitive(ReadOnlySpan name, out T result) { diff --git a/src/libs/FastEnum.Core/Internals/SpecializedDictionary.cs b/src/libs/FastEnum.Core/Internals/SpecializedDictionary.cs index df3547e..15637e6 100644 --- a/src/libs/FastEnum.Core/Internals/SpecializedDictionary.cs +++ b/src/libs/FastEnum.Core/Internals/SpecializedDictionary.cs @@ -222,7 +222,7 @@ static int calculateCapacity(int collectionSize, float loadFactor) static bool tryAdd(Entry[] buckets, Entry entry, int indexFor) { - var hash = CaseSensitiveStringHelper.GetHashCode(entry.Key); + var hash = StringHelper.CaseSensitive.GetHashCode(entry.Key); var index = hash & indexFor; var target = buckets.At(index); if (target is null) @@ -235,7 +235,7 @@ static bool tryAdd(Entry[] buckets, Entry entry, int indexFor) while (true) { //--- Check duplicate - if (CaseSensitiveStringHelper.Equals(target.Key, entry.Key)) + if (StringHelper.CaseSensitive.Equals(target.Key, entry.Key)) return false; //--- Append entry @@ -266,12 +266,12 @@ public bool ContainsKey(ReadOnlySpan key) [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetValue(ReadOnlySpan key, [MaybeNullWhen(false)] out TValue value) { - var hash = CaseSensitiveStringHelper.GetHashCode(key); + var hash = StringHelper.CaseSensitive.GetHashCode(key); var index = hash & this._indexFor; var entry = this._buckets.At(index); while (entry is not null) { - if (CaseSensitiveStringHelper.Equals(key, entry.Key)) + if (StringHelper.CaseSensitive.Equals(key, entry.Key)) { value = entry.Value; return true; @@ -362,7 +362,7 @@ static int calculateCapacity(int collectionSize, float loadFactor) static bool tryAdd(Entry[] buckets, Entry entry, int indexFor) { - var hash = CaseInsensitiveStringHelper.GetHashCode(entry.Key); + var hash = StringHelper.CaseInsensitive.GetHashCode(entry.Key); var index = hash & indexFor; var target = buckets.At(index); if (target is null) @@ -375,7 +375,7 @@ static bool tryAdd(Entry[] buckets, Entry entry, int indexFor) while (true) { //--- Check duplicate - if (CaseInsensitiveStringHelper.Equals(target.Key, entry.Key)) + if (StringHelper.CaseInsensitive.Equals(target.Key, entry.Key)) return false; //--- Append entry @@ -406,12 +406,12 @@ public bool ContainsKey(ReadOnlySpan key) [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetValue(ReadOnlySpan key, [MaybeNullWhen(false)] out TValue value) { - var hash = CaseInsensitiveStringHelper.GetHashCode(key); + var hash = StringHelper.CaseInsensitive.GetHashCode(key); var index = hash & this._indexFor; var entry = this._buckets.At(index); while (entry is not null) { - if (CaseInsensitiveStringHelper.Equals(entry.Key, key)) + if (StringHelper.CaseInsensitive.Equals(entry.Key, key)) { value = entry.Value; return true; diff --git a/src/libs/FastEnum.Core/Internals/StringHelper.cs b/src/libs/FastEnum.Core/Internals/StringHelper.cs index 68ff11e..a87822d 100644 --- a/src/libs/FastEnum.Core/Internals/StringHelper.cs +++ b/src/libs/FastEnum.Core/Internals/StringHelper.cs @@ -5,49 +5,79 @@ namespace FastEnumUtility.Internals; -internal static class CaseSensitiveStringHelper +internal static class StringHelper { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetHashCode(ReadOnlySpan value) + public static bool IsNumeric(char x) { // note: - // - Suppress CA1307 : Specify StringComparison for clarity - // - Overload that specify StringComparison is slow because of internal branching by switch statements. + // - In this case, there is no change in speed with or without sequential numbering. + + return x switch + { + '+' => true, // 43 + '-' => true, // 45 + '0' => true, // 48 + '1' => true, + '2' => true, + '3' => true, + '4' => true, + '5' => true, + '6' => true, + '7' => true, + '8' => true, + '9' => true, + _ => false, + }; + } + + + #region Nested Types + public static class CaseSensitive + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetHashCode(ReadOnlySpan value) + { + // note: + // - Suppress CA1307 : Specify StringComparison for clarity + // - Overload that specify StringComparison is slow because of internal branching by switch statements. #pragma warning disable CA1307 - return string.GetHashCode(value); + return string.GetHashCode(value); #pragma warning restore CA1307 - } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Equals(ReadOnlySpan x, ReadOnlySpan y) - => MemoryExtensions.SequenceEqual(x, y); -} + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Equals(ReadOnlySpan x, ReadOnlySpan y) + => MemoryExtensions.SequenceEqual(x, y); + } -internal static class CaseInsensitiveStringHelper -{ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetHashCode(ReadOnlySpan value) + public static class CaseInsensitive { - // note: - // - Overload that specify StringComparison is slow because of internal branching by switch statements. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetHashCode(ReadOnlySpan value) + { + // note: + // - Overload that specify StringComparison is slow because of internal branching by switch statements. - return string_GetHashCodeOrdinalIgnoreCase(self: null, value); + return string_GetHashCodeOrdinalIgnoreCase(self: null, value); - #region Local Functions - // note: - // - UnsafeAccessor can't be defined within a Generic type. - [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "GetHashCodeOrdinalIgnoreCase")] - static extern int string_GetHashCodeOrdinalIgnoreCase(string? self, ReadOnlySpan value); - #endregion - } + #region Local Functions + // note: + // - UnsafeAccessor can't be defined within a Generic type. + [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "GetHashCodeOrdinalIgnoreCase")] + static extern int string_GetHashCodeOrdinalIgnoreCase(string? self, ReadOnlySpan value); + #endregion + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Equals(ReadOnlySpan x, ReadOnlySpan y) - => MemoryExtensions.Equals(x, y, StringComparison.OrdinalIgnoreCase); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Equals(ReadOnlySpan x, ReadOnlySpan y) + => MemoryExtensions.Equals(x, y, StringComparison.OrdinalIgnoreCase); + } + #endregion }