feat: Optimizes HTML Escape (#2273)
### Summary Optimizes HTML escaping by using a vectorized search.
This commit is contained in:
parent
ee1a40bb51
commit
6f64cddd0b
2 changed files with 309 additions and 8 deletions
|
|
@ -14,9 +14,11 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Server.Buffers;
|
||||
using Server.Text;
|
||||
|
||||
namespace Server;
|
||||
|
||||
|
|
@ -237,13 +239,70 @@ public static class Html
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static RawInterpolatedStringHandler Right(this ReadOnlySpan<char> text) => text.Right(-1);
|
||||
|
||||
private static readonly SearchValues<char> _htmlSearchValues = SearchValues.Create('<', '>', '&', '"', '\'');
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string EscapeHtml(this string input) =>
|
||||
new StringBuilder(input.Length).Append(input)
|
||||
.Replace("<", "<")
|
||||
.Replace(">", ">")
|
||||
.Replace("&", "&")
|
||||
.Replace("\"", """)
|
||||
.Replace("'", "'")
|
||||
.ToString();
|
||||
public static string EscapeHtml(this string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return input ?? "";
|
||||
}
|
||||
|
||||
return EscapeHtml(input.AsSpan());
|
||||
}
|
||||
|
||||
public static string EscapeHtml(this ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.IsEmpty)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
int indexOfAny = input.IndexOfAny(_htmlSearchValues);
|
||||
if (indexOfAny < 0)
|
||||
{
|
||||
return input.ToString();
|
||||
}
|
||||
|
||||
using var builder = ValueStringBuilder.Create(input.Length * 2);
|
||||
int lastIndex = 0;
|
||||
|
||||
while (indexOfAny >= 0)
|
||||
{
|
||||
if (indexOfAny > lastIndex)
|
||||
{
|
||||
builder.Append(input[lastIndex..indexOfAny]);
|
||||
}
|
||||
|
||||
char c = input[indexOfAny];
|
||||
var replacement = c switch
|
||||
{
|
||||
'&' => "&",
|
||||
'<' => "<",
|
||||
'>' => ">",
|
||||
'"' => """,
|
||||
'\'' => "'"
|
||||
};
|
||||
builder.Append(replacement);
|
||||
|
||||
lastIndex = indexOfAny + 1;
|
||||
indexOfAny = input[lastIndex..].IndexOfAny(_htmlSearchValues);
|
||||
if (indexOfAny < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
indexOfAny += lastIndex;
|
||||
}
|
||||
|
||||
if (lastIndex < input.Length)
|
||||
{
|
||||
builder.Append(input[lastIndex..]);
|
||||
}
|
||||
|
||||
var result = builder.ToString();
|
||||
builder.Dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue