From ac84ea6e241ad2d2cde346144b2c4b3a5d64fa1d Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 17 Mar 2022 07:30:59 -0400 Subject: [PATCH] Replace StringBuilder with ValueStringBuilder in AssemblyName.FullName (#66750) --- ...alueStringBuilder.AppendSpanFormattable.cs | 2 +- .../Reflection/AssemblyNameFormatter.cs | 54 ++++++++++--------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs index 6ccde43ef6a50..04e9fcbdb5524 100644 --- a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs +++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs @@ -5,7 +5,7 @@ namespace System.Text { internal ref partial struct ValueStringBuilder { - internal void AppendSpanFormattable(T value, string? format, IFormatProvider? provider) where T : ISpanFormattable + internal void AppendSpanFormattable(T value, string? format = null, IFormatProvider? provider = null) where T : ISpanFormattable { if (value.TryFormat(_chars.Slice(_pos), out int charsWritten, format, provider)) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs index bdadec8d2c8af..bb13826d2c321 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs @@ -15,31 +15,31 @@ public static string ComputeDisplayName(string name, Version? version, string? c const int PUBLIC_KEY_TOKEN_LEN = 8; Debug.Assert(name.Length != 0); - StringBuilder sb = new StringBuilder(); - sb.AppendQuoted(name); + var vsb = new ValueStringBuilder(stackalloc char[256]); + vsb.AppendQuoted(name); if (version != null) { Version canonicalizedVersion = version.CanonicalizeVersion(); if (canonicalizedVersion.Major != ushort.MaxValue) { - sb.Append(", Version="); - sb.Append(canonicalizedVersion.Major); + vsb.Append(", Version="); + vsb.AppendSpanFormattable(canonicalizedVersion.Major); if (canonicalizedVersion.Minor != ushort.MaxValue) { - sb.Append('.'); - sb.Append(canonicalizedVersion.Minor); + vsb.Append('.'); + vsb.AppendSpanFormattable(canonicalizedVersion.Minor); if (canonicalizedVersion.Build != ushort.MaxValue) { - sb.Append('.'); - sb.Append(canonicalizedVersion.Build); + vsb.Append('.'); + vsb.AppendSpanFormattable(canonicalizedVersion.Build); if (canonicalizedVersion.Revision != ushort.MaxValue) { - sb.Append('.'); - sb.Append(canonicalizedVersion.Revision); + vsb.Append('.'); + vsb.AppendSpanFormattable(canonicalizedVersion.Revision); } } } @@ -50,8 +50,8 @@ public static string ComputeDisplayName(string name, Version? version, string? c { if (cultureName.Length == 0) cultureName = "neutral"; - sb.Append(", Culture="); - sb.AppendQuoted(cultureName); + vsb.Append(", Culture="); + vsb.AppendQuoted(cultureName); } if (pkt != null) @@ -59,27 +59,29 @@ public static string ComputeDisplayName(string name, Version? version, string? c if (pkt.Length > PUBLIC_KEY_TOKEN_LEN) throw new ArgumentException(); - sb.Append(", PublicKeyToken="); + vsb.Append(", PublicKeyToken="); if (pkt.Length == 0) - sb.Append("null"); + { + vsb.Append("null"); + } else { - sb.Append(HexConverter.ToString(pkt, HexConverter.Casing.Lower)); + HexConverter.EncodeToUtf16(pkt, vsb.AppendSpan(pkt.Length * 2), HexConverter.Casing.Lower); } } if (0 != (flags & AssemblyNameFlags.Retargetable)) - sb.Append(", Retargetable=Yes"); + vsb.Append(", Retargetable=Yes"); if (contentType == AssemblyContentType.WindowsRuntime) - sb.Append(", ContentType=WindowsRuntime"); + vsb.Append(", ContentType=WindowsRuntime"); // NOTE: By design (desktop compat) AssemblyName.FullName and ToString() do not include ProcessorArchitecture. - return sb.ToString(); + return vsb.ToString(); } - private static void AppendQuoted(this StringBuilder sb, string s) + private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) { bool needsQuoting = false; const char quoteChar = '\"'; @@ -90,7 +92,7 @@ private static void AppendQuoted(this StringBuilder sb, string s) needsQuoting = true; if (needsQuoting) - sb.Append(quoteChar); + vsb.Append(quoteChar); for (int i = 0; i < s.Length; i++) { @@ -101,24 +103,24 @@ private static void AppendQuoted(this StringBuilder sb, string s) case '=': case '\'': case '"': - sb.Append('\\'); + vsb.Append('\\'); break; case '\t': - sb.Append("\\t"); + vsb.Append("\\t"); continue; case '\r': - sb.Append("\\r"); + vsb.Append("\\r"); continue; case '\n': - sb.Append("\\n"); + vsb.Append("\\n"); continue; } - sb.Append(s[i]); + vsb.Append(s[i]); } if (needsQuoting) - sb.Append(quoteChar); + vsb.Append(quoteChar); } private static Version CanonicalizeVersion(this Version version)