@@ -636,68 +636,125 @@ public unsafe void CopyFrom(byte[] data, int offset, int count)
636
636
637
637
public unsafe void CopyFromAscii ( string data )
638
638
{
639
- Debug . Assert ( _block ! = null ) ;
640
- Debug . Assert ( _block . Pool ! = null ) ;
641
- Debug . Assert ( _block . Next = = null ) ;
642
- Debug . Assert ( _block . End = = _index ) ;
643
-
644
- var pool = _block. Pool;
645
639
var block = _block ;
646
640
var blockIndex = _index ;
647
- var length = data . Length ;
641
+ var count = data . Length ;
648
642
649
- var bytesLeftInBlock = block . BlockEndOffset - blockIndex ;
650
- var bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3 ;
643
+ if ( count > int . MaxValue - 12 )
644
+ {
645
+ // protect unrolled loop from using negative values in extremis
646
+ throw new ArgumentOutOfRangeException ( nameof ( data ) ) ;
647
+ }
648
+
649
+ var blockRemaining = block . BlockEndOffset - blockIndex ;
651
650
652
651
fixed ( char * pData = data )
653
652
{
654
- var input = pData ;
655
- var inputEnd = pData + length ;
656
- var inputEndMinusSpan = inputEnd - 3 ;
653
+ if ( blockRemaining > = count )
654
+ {
655
+ _index = blockIndex + count ;
656
+
657
+ fixed ( byte * output = block . Array )
658
+ {
659
+ CopyFromAscii ( pData , output + blockIndex , count ) ;
660
+ }
657
661
658
- while ( input < inputEnd )
662
+ block . End = _index ;
663
+ return ;
664
+ }
665
+
666
+ var input = pData ;
667
+ do
659
668
{
660
- if ( bytesLeftInBlock == 0 )
669
+ if ( blockRemaining = = 0 )
661
670
{
662
- var nextBlock = pool. Lease( ) ;
663
- block. End = blockIndex;
671
+ var nextBlock = block . Pool . Lease ( ) ;
672
+ blockIndex = nextBlock . Data . Offset ;
673
+ blockRemaining = nextBlock . Data . Count ;
664
674
block . Next = nextBlock ;
665
675
block = nextBlock ;
666
-
667
- blockIndex = block. Data. Offset;
668
- bytesLeftInBlock = block. Data. Count;
669
- bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3 ;
670
676
}
671
677
672
- fixed ( byte * pOutput = block . Data . Array )
678
+ if ( count > blockRemaining )
673
679
{
674
- var output = pOutput + block . End ;
680
+ count -= blockRemaining ;
675
681
676
- var copied = 0 ;
677
- for ( ; input < inputEndMinusSpan && copied < bytesLeftInBlockMinusSpan; copied += 4 )
682
+ fixed ( byte * output = block . Array )
678
683
{
679
- * ( output) = ( byte ) * ( input) ;
680
- * ( output + 1 ) = ( byte ) * ( input + 1 ) ;
681
- * ( output + 2 ) = ( byte ) * ( input + 2 ) ;
682
- * ( output + 3 ) = ( byte ) * ( input + 3 ) ;
683
- output += 4 ;
684
- input += 4 ;
684
+ CopyFromAscii ( input , output + blockIndex , blockRemaining ) ;
685
685
}
686
- for ( ; input < inputEnd && copied < bytesLeftInBlock; copied++ )
686
+
687
+ block . End = blockIndex + blockRemaining ;
688
+ input += blockRemaining ;
689
+ blockRemaining = 0 ;
690
+ continue ;
691
+ }
692
+ else
693
+ {
694
+ _index = blockIndex + count ;
695
+
696
+ fixed ( byte * output = block . Array )
687
697
{
688
- * ( output++ ) = ( byte ) * ( input ++ ) ;
698
+ CopyFromAscii ( input , output + blockIndex , count ) ;
689
699
}
690
700
691
- blockIndex += copied ;
692
- bytesLeftInBlockMinusSpan -= copied ;
693
- bytesLeftInBlock -= copied ;
701
+ block . End = _index ;
702
+ _block = block ;
703
+ return ;
694
704
}
695
- }
705
+ } while ( true ) ;
696
706
}
707
+ }
697
708
698
- block. End = blockIndex;
699
- _block = block;
700
- _index = blockIndex;
709
+ private unsafe static void CopyFromAscii ( char * input , byte * output , int count )
710
+ {
711
+ var i = 0 ;
712
+
713
+ while ( i + 11 < count )
714
+ {
715
+ i += 12 ;
716
+ * ( output) = ( byte ) * ( input ) ;
717
+ * ( output + 1 ) = ( byte ) * ( input + 1 ) ;
718
+ * ( output + 2 ) = ( byte ) * ( input + 2 ) ;
719
+ * ( output + 3 ) = ( byte ) * ( input + 3 ) ;
720
+ * ( output + 4 ) = ( byte ) * ( input + 4 ) ;
721
+ * ( output + 5 ) = ( byte ) * ( input + 5 ) ;
722
+ * ( output + 6 ) = ( byte ) * ( input + 6 ) ;
723
+ * ( output + 7 ) = ( byte ) * ( input + 7 ) ;
724
+ * ( output + 8 ) = ( byte ) * ( input + 8 ) ;
725
+ * ( output + 9 ) = ( byte ) * ( input + 9 ) ;
726
+ * ( output + 10 ) = ( byte ) * ( input + 10 ) ;
727
+ * ( output + 11 ) = ( byte ) * ( input + 11 ) ;
728
+ output += 12 ;
729
+ input += 12 ;
730
+ }
731
+ if ( i + 6 < count )
732
+ {
733
+ i += 6 ;
734
+ * ( output ) = ( byte ) * ( input ) ;
735
+ * ( output + 1 ) = ( byte ) * ( input + 1 ) ;
736
+ * ( output + 2 ) = ( byte ) * ( input + 2 ) ;
737
+ * ( output + 3 ) = ( byte ) * ( input + 3 ) ;
738
+ * ( output + 4 ) = ( byte ) * ( input + 4 ) ;
739
+ * ( output + 5 ) = ( byte ) * ( input + 5 ) ;
740
+ output += 6 ;
741
+ input += 6 ;
742
+ }
743
+ if ( i + 3 < count )
744
+ {
745
+ i += 4 ;
746
+ * ( output ) = ( byte ) * ( input ) ;
747
+ * ( output + 1 ) = ( byte ) * ( input + 1 ) ;
748
+ * ( output + 2 ) = ( byte ) * ( input + 2 ) ;
749
+ * ( output + 3 ) = ( byte ) * ( input + 3 ) ;
750
+ output += 4 ;
751
+ input += 4 ;
752
+ }
753
+ while ( i < count )
754
+ {
755
+ i++ ;
756
+ * ( output ++ ) = ( byte ) * ( input ++ ) ;
757
+ }
701
758
}
702
759
}
703
760
}
0 commit comments