From 229502e1b324c721186884c0c3961aa98583a948 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 21 Jun 2022 00:39:55 -0400 Subject: [PATCH] Avoid unnecessary allocations in SanitizeEntryFilePath (#71034) --- .../src/System/IO/Archiving.Utils.Windows.cs | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs b/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs index d8ee462..88f7ffb 100644 --- a/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs +++ b/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs @@ -9,19 +9,38 @@ namespace System.IO { internal static string SanitizeEntryFilePath(string entryPath) { - StringBuilder builder = new StringBuilder(entryPath); + // Find the first illegal character in the entry path. for (int i = 0; i < entryPath.Length; i++) { - if (((int)builder[i] >= 0 && (int)builder[i] < 32) || - builder[i] == '?' || builder[i] == ':' || - builder[i] == '*' || builder[i] == '"' || - builder[i] == '<' || builder[i] == '>' || - builder[i] == '|') + switch (entryPath[i]) { - builder[i] = '_'; + // We found at least one character that needs to be replaced. + case < (char)32 or '?' or ':' or '*' or '"' or '<' or '>' or '|': + return string.Create(entryPath.Length, (i, entryPath), (dest, state) => + { + string entryPath = state.entryPath; + + // Copy over to the new string everything until the character, then + // substitute for the found character. + entryPath.AsSpan(0, state.i).CopyTo(dest); + dest[state.i] = '_'; + + // Continue looking for and replacing any more illegal characters. + for (int i = state.i + 1; i < entryPath.Length; i++) + { + char c = entryPath[i]; + dest[i] = c switch + { + < (char)32 or '?' or ':' or '*' or '"' or '<' or '>' or '|' => '_', + _ => c, + }; + } + }); } } - return builder.ToString(); + + // There weren't any characters to sanitize. Just return the original string. + return entryPath; } } } -- 2.7.4