@@ -572,39 +572,69 @@ public ValueTask<string> ReadNullTerminatedString(bool async, CancellationToken
572572 /// </summary>
573573 ValueTask < string > ReadNullTerminatedString ( Encoding encoding , bool async , CancellationToken cancellationToken = default )
574574 {
575- return ReadFromBuffer ( this , encoding , out var s )
576- ? new ValueTask < string > ( s )
577- : ReadLong ( this , async, encoding , s ) ;
578-
579- static bool ReadFromBuffer ( NpgsqlReadBuffer buffer , Encoding encoding , out string s )
575+ for ( var i = ReadPosition ; i < FilledBytes ; i ++ )
580576 {
581- var start = buffer . ReadPosition ;
582- while ( buffer . ReadPosition < buffer . FilledBytes )
577+ if ( Buffer [ i ] == 0 )
583578 {
584- if ( buffer . Buffer [ buffer . ReadPosition ++ ] == 0 )
585- {
586- s = encoding . GetString ( buffer . Buffer , start , buffer . ReadPosition - start - 1 ) ;
587- return true ;
588- }
579+ var byteLen = i - ReadPosition ;
580+ var result = new ValueTask < string > ( encoding . GetString ( Buffer , ReadPosition , byteLen ) ) ;
581+ ReadPosition += byteLen + 1 ;
582+ return result ;
589583 }
590-
591- s = encoding . GetString ( buffer . Buffer , start , buffer . ReadPosition - start ) ;
592- return false ;
593584 }
594585
595- static async ValueTask < string > ReadLong ( NpgsqlReadBuffer buffer , bool async , Encoding encoding , string s )
586+ return ReadLong ( async ) ;
587+
588+ async ValueTask < string > ReadLong ( bool async )
596589 {
597- var builder = new StringBuilder ( s ) ;
598- bool complete ;
599- do
590+ var chunkSize = FilledBytes - ReadPosition ;
591+ var tempBuf = ArrayPool < byte > . Shared . Rent ( chunkSize + 1024 ) ;
592+
593+ try
600594 {
601- await buffer . ReadMore ( async ) ;
602- complete = ReadFromBuffer ( buffer , encoding , out s ) ;
603- builder . Append ( s ) ;
604- }
605- while ( ! complete ) ;
595+ bool foundTerminator ;
596+ var byteLen = chunkSize ;
597+ Array . Copy ( Buffer , ReadPosition , tempBuf , 0 , chunkSize ) ;
598+ ReadPosition += chunkSize ;
599+
600+ do
601+ {
602+ await ReadMore ( async ) ;
603+ Debug . Assert ( ReadPosition == 0 ) ;
606604
607- return builder . ToString ( ) ;
605+ foundTerminator = false ;
606+ int i ;
607+ for ( i = 0 ; i < FilledBytes ; i ++ )
608+ {
609+ if ( Buffer [ i ] == 0 )
610+ {
611+ foundTerminator = true ;
612+ break ;
613+ }
614+ }
615+
616+ if ( byteLen + i > tempBuf . Length )
617+ {
618+ var newTempBuf = ArrayPool < byte > . Shared . Rent (
619+ foundTerminator ? byteLen + i : byteLen + i + 1024 ) ;
620+
621+ Array . Copy ( tempBuf , 0 , newTempBuf , 0 , byteLen ) ;
622+ ArrayPool < byte > . Shared . Return ( tempBuf ) ;
623+ tempBuf = newTempBuf ;
624+ }
625+
626+ Array . Copy ( Buffer , 0 , tempBuf , byteLen , i ) ;
627+ byteLen += i ;
628+ ReadPosition = i ;
629+ } while ( ! foundTerminator ) ;
630+
631+ ReadPosition ++ ;
632+ return encoding . GetString ( tempBuf , 0 , byteLen ) ;
633+ }
634+ finally
635+ {
636+ ArrayPool < byte > . Shared . Return ( tempBuf ) ;
637+ }
608638 }
609639 }
610640
0 commit comments