improve: use SearchValues<char> in ShellQuoting.NeedsQuoting for SIMD scan

Replace per-character foreach+switch with System.Buffers.SearchValues<char>,
which uses SSE2/AVX2 vectorized IndexOfAny to detect shell metacharacters
in a single SIMD pass instead of a character-by-character loop.

- Add static SearchValues<char> s_shellMetachars (same 25-char set as former
- Replace NeedsQuoting foreach body with arg.AsSpan().IndexOfAny(s_shellMetachars) >= 0
- Remove private IsShellMetachar helper (no longer needed)
- Add using System.Buffers (SearchValues<T> namespace)

SearchValues<char> is available since .NET 8; this project targets net10.0.
All existing ShellQuotingTests pass unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
github-actions[bot] 2026-04-19 01:15:03 +00:00 committed by GitHub
parent e46dfe7830
commit 325a4089b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,3 +1,5 @@
using System.Buffers;
namespace OpenClaw.Shared;
/// <summary>
@ -7,18 +9,19 @@ namespace OpenClaw.Shared;
/// </summary>
internal static class ShellQuoting
{
// SearchValues<char> builds an optimized SIMD lookup structure once at startup,
// allowing IndexOfAny to scan multiple characters simultaneously (SSE2/AVX2 on x64).
// Equivalent set to the former IsShellMetachar switch — 25 shell metacharacters.
private static readonly SearchValues<char> s_shellMetachars =
SearchValues.Create(" \t\"'&|;<>()^%!$`*?[]{}~\n\r");
/// <summary>
/// Returns true when the argument contains characters that require quoting
/// to prevent shell splitting or metacharacter interpretation.
/// </summary>
internal static bool NeedsQuoting(string arg)
{
foreach (var c in arg)
{
if (IsShellMetachar(c))
return true;
}
return false;
return arg.AsSpan().IndexOfAny(s_shellMetachars) >= 0;
}
/// <summary>
@ -66,14 +69,4 @@ internal static class ShellQuoting
}
}
private static bool IsShellMetachar(char c) => c switch
{
' ' or '\t' or '"' or '\'' or
'&' or '|' or ';' or '<' or '>' or
'(' or ')' or '^' or '%' or '!' or
'$' or '`' or '*' or '?' or '[' or
']' or '{' or '}' or '~' or
'\n' or '\r' => true,
_ => false
};
}