From b4130b1f2d2bfe482dbd4a16d7d2913e6c593709 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 27 Jan 2026 15:07:23 -0800 Subject: [PATCH] Revert "Reduce unsafe usage in TextInfo.cs (#122116)" This reverts commit bb5ea9b094032cd73066eb91ed14e0a8169e745c. --- .../src/System/Globalization/TextInfo.cs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs index 62c2892ddf5fe7..f9571bc811297c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs @@ -390,7 +390,7 @@ private static unsafe string ChangeCaseCommon(TextInfo? instance, s } } - internal static string ToLowerAsciiInvariant(string s) + internal static unsafe string ToLowerAsciiInvariant(string s) { if (s.Length == 0) { @@ -403,19 +403,25 @@ internal static string ToLowerAsciiInvariant(string s) return s; } - // Duplicate the source into the destination, then update the destination in-place, - // starting with the index where we know a change is required. This technically does - // more work than strictly necessary, but we don't anticipate this method being - // called in a perf-critical scenario. - - return string.Create(s.Length, (IdxOfFirstCharRequiringConversion: i, OriginalString: s), static (span, state) => + fixed (char* pSource = s) { - state.OriginalString.CopyTo(span); - foreach (ref char c in span.Slice(state.IdxOfFirstCharRequiringConversion)) + string result = string.FastAllocateString(s.Length); + fixed (char* pResult = result) { - c = ToLowerAsciiInvariant(c); + s.AsSpan(0, i).CopyTo(new Span(pResult, result.Length)); + + pResult[i] = (char)(pSource[i] | 0x20); + i++; + + while (i < s.Length) + { + pResult[i] = ToLowerAsciiInvariant(pSource[i]); + i++; + } } - }); + + return result; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)]