19
19
using System . Linq ;
20
20
using System . Text ;
21
21
using System . Threading ;
22
+ using System . Reflection ;
22
23
23
24
namespace MongoDB . Bson . IO
24
25
{
@@ -509,16 +510,40 @@ public string ReadString()
509
510
if ( _disposed ) { throw new ObjectDisposedException ( "BsonBuffer" ) ; }
510
511
var length = ReadInt32 ( ) ;
511
512
EnsureDataAvailable ( length ) ;
513
+ -- length ;
512
514
string value ;
513
- if ( __chunkSize - _chunkOffset >= length - 1 )
515
+ if ( __chunkSize - _chunkOffset >= length )
514
516
{
515
- value = ParseString ( _chunk , _chunkOffset , length - 1 ) ;
516
- Position += length - 1 ;
517
+ switch ( length )
518
+ {
519
+ // special case empty strings
520
+ case 0 :
521
+ value = string . Empty ;
522
+ break ;
523
+
524
+ // special case single character strings
525
+ case 1 :
526
+ var c = _chunk [ _chunkOffset ] ;
527
+ if ( c >= 128 )
528
+ {
529
+ // multiple bytes required
530
+ throw new DecoderFallbackException ( "[" + c . ToString ( "X2" ) + "] is an invalid character" ) ;
531
+ }
532
+ value = __asciiStringTable [ c ] ;
533
+ ++ Position ;
534
+ break ;
535
+
536
+ default :
537
+ value = __utf8Encoding . GetString ( _chunk , _chunkOffset , length ) ;
538
+ Position += length ;
539
+ break ;
540
+ }
517
541
}
518
542
else
519
543
{
520
544
// straddles chunk boundary
521
- value = __utf8Encoding . GetString ( ReadBytes ( length - 1 ) ) ;
545
+ var bytes = ReadBytes ( length ) ;
546
+ value = __utf8Encoding . GetString ( bytes , 0 , length ) ;
522
547
}
523
548
byte terminator = ReadByte ( ) ;
524
549
if ( terminator != 0 )
@@ -546,12 +571,40 @@ public string ReadCString()
546
571
partialCount = _length - _position ; // populated part of last chunk
547
572
}
548
573
549
- string value ;
550
- var stringLength = TryParseCString ( _chunk , _chunkOffset , partialCount , out value ) ;
551
- if ( stringLength >= 0 )
574
+ if ( partialCount > 0 )
552
575
{
553
- Position += stringLength + 1 ;
554
- return value ;
576
+ var c = _chunk [ _chunkOffset ] ;
577
+
578
+ // special case empty strings
579
+ if ( c == 0 )
580
+ {
581
+ ++ Position ;
582
+ return string . Empty ;
583
+ }
584
+
585
+ if ( partialCount > 1 )
586
+ {
587
+ // special case single character strings
588
+ if ( _chunk [ _chunkOffset + 1 ] == 0 )
589
+ {
590
+ if ( c >= 128 )
591
+ {
592
+ // multiple bytes required
593
+ throw new DecoderFallbackException ( "[" + c . ToString ( "X2" ) + "] is an invalid character" ) ;
594
+ }
595
+ Position += 2 ;
596
+ return __asciiStringTable [ c ] ;
597
+ }
598
+
599
+ var index = Array . IndexOf < byte > ( _chunk , 0 , _chunkOffset + 2 , partialCount - 2 ) ;
600
+ if ( index >= 0 )
601
+ {
602
+ var stringLength = index - _chunkOffset ;
603
+ var value = __utf8Encoding . GetString ( _chunk , _chunkOffset , stringLength ) ;
604
+ Position += stringLength + 1 ;
605
+ return value ;
606
+ }
607
+ }
555
608
}
556
609
557
610
// the null terminator is not on the same chunk so keep looking starting with the next chunk
@@ -572,8 +625,8 @@ public string ReadCString()
572
625
if ( index != - 1 )
573
626
{
574
627
localPosition += index ;
575
- stringLength = localPosition - _position ;
576
- value = __utf8Encoding . GetString ( ReadBytes ( stringLength ) ) ; // ReadBytes advances over string
628
+ var stringLength = localPosition - _position ;
629
+ var value = __utf8Encoding . GetString ( ReadBytes ( stringLength ) ) ; // ReadBytes advances over string
577
630
Position += 1 ; // skip over null byte at end
578
631
return value ;
579
632
}
@@ -912,104 +965,6 @@ private static string[] BuildAsciiStringTable()
912
965
return asciiStringTable ;
913
966
}
914
967
915
- private static string ParseString ( byte [ ] buffer , int startIndex , int stringLength )
916
- {
917
- switch ( stringLength )
918
- {
919
- // special case empty strings
920
- case 0 :
921
- return string . Empty ;
922
-
923
- // special case single character strings
924
- case 1 :
925
- var c = buffer [ startIndex ] ;
926
- if ( c >= 128 )
927
- {
928
- // multiple bytes required
929
- throw new DecoderFallbackException ( "[" + c . ToString ( "X2" ) + "] is an invalid character" ) ;
930
- }
931
- return __asciiStringTable [ c ] ;
932
- }
933
-
934
- return __utf8Encoding . GetString ( buffer , startIndex , stringLength ) ;
935
- }
936
-
937
- /// <returns>The number of bytes parsed excluding the null terminator; -1 otherwise.</returns>
938
- private static int TryParseCString ( byte [ ] buffer , int startIndex , int length , out string value )
939
- {
940
- if ( length < 1 )
941
- {
942
- value = null ;
943
- return - 1 ;
944
- }
945
-
946
- // special case empty strings
947
- var c1 = buffer [ startIndex ] ;
948
- if ( c1 == 0 )
949
- {
950
- value = string . Empty ;
951
- return 0 ;
952
- }
953
-
954
- if ( length < 2 )
955
- {
956
- value = null ;
957
- return - 1 ;
958
- }
959
-
960
- // special case single character strings
961
- var c2 = buffer [ startIndex + 1 ] ;
962
- if ( c2 == 0 )
963
- {
964
- if ( c1 >= 128 )
965
- {
966
- // multiple bytes required
967
- throw new DecoderFallbackException ( "[" + c1 . ToString ( "X2" ) + "] is an invalid character" ) ;
968
- }
969
- value = __asciiStringTable [ c1 ] ;
970
- return 1 ;
971
- }
972
-
973
- if ( length < 3 )
974
- {
975
- value = null ;
976
- return - 1 ;
977
- }
978
-
979
- var c3 = buffer [ startIndex + 2 ] ;
980
- if ( c3 == 0 )
981
- {
982
- value = __utf8Encoding . GetString ( buffer , startIndex , 2 ) ;
983
- return 2 ;
984
- }
985
-
986
- if ( length < 4 )
987
- {
988
- value = null ;
989
- return - 1 ;
990
- }
991
-
992
- if ( buffer [ startIndex + 3 ] == 0 )
993
- {
994
- // special case the _id string
995
- // '_id'; 0x5f == '_', 0x69 == 'i', 0x64 == 'd'
996
- value = ( ( c1 | c2 << 8 | c3 << 16 ) == 0x64695f ) ?
997
- "_id" : __utf8Encoding . GetString ( buffer , startIndex , 3 ) ;
998
- return 3 ;
999
- }
1000
-
1001
- var index = Array . IndexOf < byte > ( buffer , 0 , startIndex + 4 , length - 4 ) ;
1002
- if ( index != - 1 )
1003
- {
1004
- var stringLength = index - startIndex ;
1005
- value = __utf8Encoding . GetString ( buffer , startIndex , stringLength ) ;
1006
- return stringLength ;
1007
- }
1008
-
1009
- value = null ;
1010
- return - 1 ;
1011
- }
1012
-
1013
968
// private methods
1014
969
private void EnsureDataAvailable ( int needed )
1015
970
{
0 commit comments