return hostname.ToLowerInvariant();
}
- string bidiStrippedHost;
- unsafe
- {
- fixed (char* hostnamePtr = hostname)
- {
- bidiStrippedHost = UriHelper.StripBidiControlCharacter(hostnamePtr, 0, hostname.Length);
- }
- }
+ string bidiStrippedHost = UriHelper.StripBidiControlCharacters(hostname, hostname);
try
{
if (end <= start)
return idn;
- string unescapedHostname = UriHelper.StripBidiControlCharacter(hostname, start, (end - start));
+ string unescapedHostname = UriHelper.StripBidiControlCharacters(new ReadOnlySpan<char>(hostname + start, end - start));
string? unicodeEqvlHost = null;
int curPos = 0;
if (hasUnicode)
{
- string temp = UriHelper.StripBidiControlCharacter(pString, start, end - start);
+ string temp = UriHelper.StripBidiControlCharacters(new ReadOnlySpan<char>(pString + start, end - start));
try
{
- newHost += ((temp != null) ? temp.Normalize(NormalizationForm.FormC) : null);
+ newHost += temp.Normalize(NormalizationForm.FormC);
}
catch (ArgumentException)
{
using System.Text;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
namespace System
{
//
// Strip Bidirectional control characters from this string
//
- internal static unsafe string StripBidiControlCharacter(char* strToClean, int start, int length)
+ internal static unsafe string StripBidiControlCharacters(ReadOnlySpan<char> strToClean, string? backingString = null)
{
- if (length <= 0) return "";
+ Debug.Assert(backingString is null || strToClean.Length == backingString.Length);
- char[] cleanStr = new char[length];
- int count = 0;
- for (int i = 0; i < length; ++i)
+ int charsToRemove = 0;
+ foreach (char c in strToClean)
{
- char c = strToClean[start + i];
- if (c < '\u200E' || c > '\u202E' || !IsBidiControlCharacter(c))
+ if ((uint)(c - '\u200E') <= ('\u202E' - '\u200E') && IsBidiControlCharacter(c))
{
- cleanStr[count++] = c;
+ charsToRemove++;
}
}
- return new string(cleanStr, 0, count);
+
+ if (charsToRemove == 0)
+ {
+ return backingString ?? new string(strToClean);
+ }
+
+ if (charsToRemove == strToClean.Length)
+ {
+ return string.Empty;
+ }
+
+ fixed (char* pStrToClean = &MemoryMarshal.GetReference(strToClean))
+ {
+ return string.Create(strToClean.Length - charsToRemove, (StrToClean: (IntPtr)pStrToClean, strToClean.Length), (buffer, state) =>
+ {
+ var strToClean = new ReadOnlySpan<char>((char*)state.StrToClean, state.Length);
+ int destIndex = 0;
+ foreach (char c in strToClean)
+ {
+ if ((uint)(c - '\u200E') > ('\u202E' - '\u200E') || !IsBidiControlCharacter(c))
+ {
+ buffer[destIndex++] = c;
+ }
+ }
+ Debug.Assert(buffer.Length == destIndex);
+ });
+ }
}
}
}