@@ -423,53 +423,12 @@ public string ToString(int startIndex, int length)
423423 }
424424
425425 AssertInvariants ( ) ;
426-
427- StringBuilder chunk = this ;
428- int sourceEndIndex = startIndex + length ;
429-
430426 string result = string . FastAllocateString ( length ) ;
431- int curDestIndex = length ;
432427 unsafe
433428 {
434429 fixed ( char * destinationPtr = result )
435430 {
436- while ( curDestIndex > 0 )
437- {
438- int chunkEndIndex = sourceEndIndex - chunk . m_ChunkOffset ;
439- if ( chunkEndIndex >= 0 )
440- {
441- chunkEndIndex = Math . Min ( chunkEndIndex , chunk . m_ChunkLength ) ;
442-
443- int countLeft = curDestIndex ;
444- int chunkCount = countLeft ;
445- int chunkStartIndex = chunkEndIndex - countLeft ;
446- if ( chunkStartIndex < 0 )
447- {
448- chunkCount += chunkStartIndex ;
449- chunkStartIndex = 0 ;
450- }
451- curDestIndex -= chunkCount ;
452-
453- if ( chunkCount > 0 )
454- {
455- // Work off of local variables so that they are stable even in the presence of race conditions
456- char [ ] sourceArray = chunk . m_ChunkChars ;
457-
458- // Check that we will not overrun our boundaries.
459- if ( ( uint ) ( chunkCount + curDestIndex ) <= ( uint ) length && ( uint ) ( chunkCount + chunkStartIndex ) <= ( uint ) sourceArray . Length )
460- {
461- fixed ( char * sourcePtr = & sourceArray [ chunkStartIndex ] )
462- string . wstrcpy ( destinationPtr + curDestIndex , sourcePtr , chunkCount ) ;
463- }
464- else
465- {
466- throw new ArgumentOutOfRangeException ( nameof ( chunkCount ) , SR . ArgumentOutOfRange_Index ) ;
467- }
468- }
469- }
470- chunk = chunk . m_ChunkPrevious ;
471- }
472-
431+ this . CopyTo ( startIndex , new Span < char > ( destinationPtr , length ) , length ) ;
473432 return result ;
474433 }
475434 }
@@ -790,6 +749,79 @@ public StringBuilder Append(string value, int startIndex, int count)
790749 }
791750 }
792751
752+ public StringBuilder Append ( StringBuilder value )
753+ {
754+ if ( value != null && value . Length != 0 )
755+ {
756+ return AppendCore ( value , 0 , value . Length ) ;
757+ }
758+ return this ;
759+ }
760+
761+ public StringBuilder Append ( StringBuilder value , int startIndex , int count )
762+ {
763+ if ( startIndex < 0 )
764+ {
765+ throw new ArgumentOutOfRangeException ( nameof ( startIndex ) , SR . ArgumentOutOfRange_Index ) ;
766+ }
767+
768+ if ( count < 0 )
769+ {
770+ throw new ArgumentOutOfRangeException ( nameof ( count ) , SR . ArgumentOutOfRange_GenericPositive ) ;
771+ }
772+
773+ if ( value == null )
774+ {
775+ if ( startIndex == 0 && count == 0 )
776+ {
777+ return this ;
778+ }
779+ throw new ArgumentNullException ( nameof ( value ) ) ;
780+ }
781+
782+ if ( count == 0 )
783+ {
784+ return this ;
785+ }
786+
787+ if ( count > value . Length - startIndex )
788+ {
789+ throw new ArgumentOutOfRangeException ( nameof ( startIndex ) , SR . ArgumentOutOfRange_Index ) ;
790+ }
791+
792+ return AppendCore ( value , startIndex , count ) ;
793+ }
794+
795+ private StringBuilder AppendCore ( StringBuilder value , int startIndex , int count )
796+ {
797+ if ( value == this )
798+ return Append ( value . ToString ( startIndex , count ) ) ;
799+
800+ int newLength = Length + count ;
801+
802+ if ( ( uint ) newLength > ( uint ) m_MaxCapacity )
803+ {
804+ throw new ArgumentOutOfRangeException ( nameof ( Capacity ) , SR . ArgumentOutOfRange_Capacity ) ;
805+ }
806+
807+ while ( count > 0 )
808+ {
809+ int length = Math . Min ( m_ChunkChars . Length - m_ChunkLength , count ) ;
810+ if ( length == 0 )
811+ {
812+ ExpandByABlock ( count ) ;
813+ length = Math . Min ( m_ChunkChars . Length - m_ChunkLength , count ) ;
814+ }
815+ value . CopyTo ( startIndex , new Span < char > ( m_ChunkChars , m_ChunkLength , length ) , length ) ;
816+
817+ m_ChunkLength += length ;
818+ startIndex += length ;
819+ count -= length ;
820+ }
821+
822+ return this ;
823+ }
824+
793825 public StringBuilder AppendLine ( ) => Append ( Environment . NewLine ) ;
794826
795827 public StringBuilder AppendLine ( string value )
0 commit comments