@@ -1456,9 +1456,9 @@ private string ReplaceHelper(int oldValueLength, string newValue, ReadOnlySpan<i
14561456 /// </returns>
14571457 public unsafe string Replace ( Rune oldRune , Rune newRune )
14581458 {
1459- if ( Length == 0 )
1459+ if ( oldRune . IsBmp && newRune . IsBmp )
14601460 {
1461- return this ;
1461+ return Replace ( ( char ) oldRune . Value , ( char ) newRune . Value ) ;
14621462 }
14631463
14641464 ReadOnlySpan < char > oldChars = oldRune . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
@@ -1684,19 +1684,23 @@ public string[] Split(Rune separator, StringSplitOptions options = StringSplitOp
16841684 /// <returns>An array whose elements contain the substrings from this instance that are delimited by <paramref name="separator"/>.</returns>
16851685 public unsafe string [ ] Split ( Rune separator , int count , StringSplitOptions options = StringSplitOptions . None )
16861686 {
1687- ReadOnlySpan < char > separatorSpan = separator . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
1688-
1689- if ( separatorSpan . Length == 1 )
1687+ if ( separator . IsBmp )
16901688 {
1691- return Split ( separatorSpan [ 0 ] , count , options ) ;
1689+ return Split ( ( char ) separator . Value , count , options ) ;
16921690 }
16931691
16941692 ArgumentOutOfRangeException . ThrowIfNegative ( count ) ;
16951693
16961694 CheckStringSplitOptions ( options ) ;
16971695
16981696 // Ensure matching the string separator overload.
1699- return ( count <= 1 || Length == 0 ) ? CreateSplitArrayOfThisAsSoleValue ( options , count ) : Split ( separatorSpan , count , options ) ;
1697+ if ( count <= 1 || Length == 0 )
1698+ {
1699+ return CreateSplitArrayOfThisAsSoleValue ( options , count ) ;
1700+ }
1701+
1702+ ReadOnlySpan < char > separatorSpan = separator . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
1703+ return Split ( separatorSpan , count , options ) ;
17001704 }
17011705
17021706 // Creates an array of strings by splitting this string at each
@@ -2413,39 +2417,28 @@ public unsafe string Trim(char trimChar)
24132417 /// </returns>
24142418 public unsafe string Trim ( Rune trimRune )
24152419 {
2416- if ( Length == 0 )
2420+ if ( trimRune . IsBmp )
24172421 {
2418- return this ;
2422+ return Trim ( ( char ) trimRune . Value ) ;
24192423 }
24202424
2421- // Convert trimRune to span
2422- ReadOnlySpan < char > trimChars = trimRune . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
2425+ UnicodeUtility . GetUtf16SurrogatesFromSupplementaryPlaneScalar ( ( uint ) trimRune . Value , out char highSurrogate , out char lowSurrogate ) ;
24232426
24242427 // Trim start
24252428 int index = 0 ;
2426- while ( index < Length && this . AsSpan ( index ) . StartsWith ( trimChars ) )
2429+ while ( ( uint ) ( index + 1 ) < ( uint ) Length && this [ index ] == highSurrogate && this [ index + 1 ] == lowSurrogate )
24272430 {
2428- index += trimChars . Length ;
2429- }
2430-
2431- if ( index >= Length )
2432- {
2433- return Empty ;
2431+ index += 2 ;
24342432 }
24352433
24362434 // Trim end
2437- int endIndex = Length - 1 ;
2438- while ( endIndex >= index && this . AsSpan ( index ..( endIndex + 1 ) ) . EndsWith ( trimChars ) )
2439- {
2440- endIndex -= trimChars . Length ;
2441- }
2442-
2443- if ( endIndex < index )
2435+ int endIndex = Length - 2 ;
2436+ while ( endIndex > index && this [ endIndex ] == highSurrogate && this [ endIndex + 1 ] == lowSurrogate )
24442437 {
2445- return Empty ;
2438+ endIndex -= 2 ;
24462439 }
24472440
2448- return this [ index ..( endIndex + 1 ) ] ;
2441+ return this [ index ..( endIndex + 2 ) ] ;
24492442 }
24502443
24512444 // Removes a set of characters from the beginning and end of this string.
@@ -2499,24 +2492,17 @@ public unsafe string Trim(params ReadOnlySpan<char> trimChars)
24992492 /// </returns>
25002493 public unsafe string TrimStart ( Rune trimRune )
25012494 {
2502- if ( Length == 0 )
2495+ if ( trimRune . IsBmp )
25032496 {
2504- return this ;
2497+ return TrimStart ( ( char ) trimRune . Value ) ;
25052498 }
25062499
2507- // Convert trimRune to span
2508- ReadOnlySpan < char > trimChars = trimRune . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
2500+ UnicodeUtility . GetUtf16SurrogatesFromSupplementaryPlaneScalar ( ( uint ) trimRune . Value , out char highSurrogate , out char lowSurrogate ) ;
25092501
2510- // Trim start
25112502 int index = 0 ;
2512- while ( index < Length && this . AsSpan ( index ) . StartsWith ( trimChars ) )
2503+ while ( ( uint ) ( index + 1 ) < ( uint ) Length && this [ index ] == highSurrogate && this [ index + 1 ] == lowSurrogate )
25132504 {
2514- index += trimChars . Length ;
2515- }
2516-
2517- if ( index >= Length )
2518- {
2519- return Empty ;
2505+ index += 2 ;
25202506 }
25212507
25222508 return this [ index ..] ;
@@ -2573,27 +2559,20 @@ public unsafe string TrimStart(params ReadOnlySpan<char> trimChars)
25732559 /// </returns>
25742560 public unsafe string TrimEnd ( Rune trimRune )
25752561 {
2576- if ( Length == 0 )
2562+ if ( trimRune . IsBmp )
25772563 {
2578- return this ;
2564+ return TrimEnd ( ( char ) trimRune . Value ) ;
25792565 }
25802566
2581- // Convert trimRune to span
2582- ReadOnlySpan < char > trimChars = trimRune . AsSpan ( stackalloc char [ Rune . MaxUtf16CharsPerRune ] ) ;
2567+ UnicodeUtility . GetUtf16SurrogatesFromSupplementaryPlaneScalar ( ( uint ) trimRune . Value , out char highSurrogate , out char lowSurrogate ) ;
25832568
2584- // Trim end
2585- int endIndex = Length - 1 ;
2586- while ( endIndex >= 0 && this . AsSpan ( ..( endIndex + 1 ) ) . EndsWith ( trimChars ) )
2569+ int endIndex = Length - 2 ;
2570+ while ( ( uint ) endIndex < ( uint ) Length && this [ endIndex ] == highSurrogate && this [ endIndex + 1 ] == lowSurrogate )
25872571 {
2588- endIndex -= trimChars . Length ;
2589- }
2590-
2591- if ( endIndex < 0 )
2592- {
2593- return Empty ;
2572+ endIndex -= 2 ;
25942573 }
25952574
2596- return this [ ..( endIndex + 1 ) ] ;
2575+ return this [ ..( endIndex + 2 ) ] ;
25972576 }
25982577
25992578 // Removes a set of characters from the end of this string.
0 commit comments