Created
March 17, 2025 02:58
-
-
Save otuncelli/85ceed657e7efe2623cac43893420f9a to your computer and use it in GitHub Desktop.
The string.Trim() implementation but removes both white-space and the provided characters in one pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
namespace BestProgram; | |
internal static class StringTrimExtensions | |
{ | |
#region TrimStartWhiteSpaceAnd | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimStartWhiteSpaceAnd(this string s, char trimChar) | |
{ | |
return s.TrimWhiteSpaceAnd(trimChar, TrimType.Head); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimStartWhiteSpaceAnd(this string s, params HashSet<char> trimChars) | |
{ | |
return s.TrimWhiteSpaceAnd(TrimType.Head, trimChars); | |
} | |
#endregion | |
#region TrimEndWhiteSpaceAnd | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimEndWhiteSpaceAnd(this string s, char trimChar) | |
{ | |
return s.TrimWhiteSpaceAnd(trimChar, TrimType.Tail); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimEndWhiteSpaceAnd(this string s, params HashSet<char> trimChars) | |
{ | |
return s.TrimWhiteSpaceAnd(TrimType.Tail, trimChars); | |
} | |
#endregion | |
#region TrimWhiteSpaceAnd | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimWhiteSpaceAnd(this string s, char trimChar) | |
{ | |
return s.TrimWhiteSpaceAnd(trimChar, TrimType.Both); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static string TrimWhiteSpaceAnd(this string s, params HashSet<char> trimChars) | |
{ | |
return s.TrimWhiteSpaceAnd(TrimType.Both, trimChars); | |
} | |
#endregion | |
#region Private | |
private static string TrimWhiteSpaceAnd(this string s, char trimChar, TrimType trimType) | |
{ | |
ArgumentNullException.ThrowIfNull(s); | |
if (s.Length == 0) | |
{ | |
return string.Empty.Trim(); | |
} | |
ReadOnlySpan<char> span = s.AsSpan(); | |
int start = 0; | |
int end = span.Length - 1; | |
char ch; | |
if (trimType.HasFlag(TrimType.Head)) | |
{ | |
while (start < span.Length) | |
{ | |
ch = span[start]; | |
if (!char.IsWhiteSpace(ch) && ch != trimChar) | |
{ | |
break; | |
} | |
start++; | |
} | |
} | |
if (trimType.HasFlag(TrimType.Tail)) | |
{ | |
while (end >= start) | |
{ | |
ch = span[end]; | |
if (!char.IsWhiteSpace(ch) && ch != trimChar) | |
{ | |
break; | |
} | |
end--; | |
} | |
} | |
int length = end - start + 1; | |
return length == span.Length ? s : CreateTrimmedString(span, start, length); | |
} | |
private static string TrimWhiteSpaceAnd(this string s, TrimType trimType, params HashSet<char> chars) | |
{ | |
ArgumentNullException.ThrowIfNull(s); | |
if (s.Length == 0 || chars.Count <= 0) | |
{ | |
return s.Trim(); | |
} | |
ReadOnlySpan<char> span = s.AsSpan(); | |
int start = 0; | |
int end = span.Length - 1; | |
char ch; | |
if (trimType.HasFlag(TrimType.Head)) | |
{ | |
while (start < span.Length) | |
{ | |
ch = span[start]; | |
if (!char.IsWhiteSpace(ch) && !chars.Contains(ch)) | |
{ | |
break; | |
} | |
start++; | |
} | |
} | |
if (trimType.HasFlag(TrimType.Tail)) | |
{ | |
while (end >= start) | |
{ | |
ch = span[end]; | |
if (!char.IsWhiteSpace(ch) && !chars.Contains(ch)) | |
{ | |
break; | |
} | |
end--; | |
} | |
} | |
int length = end - start + 1; | |
return length == span.Length ? s : CreateTrimmedString(span, start, length); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
private static string CreateTrimmedString(ReadOnlySpan<char> span, int start, int length) | |
{ | |
return length <= 0 ? string.Empty : new string(span.Slice(start, length)); | |
} | |
[Flags] | |
private enum TrimType | |
{ | |
Head = 1, | |
Tail = 2, | |
Both = 3 | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment