Skip to content

Commit f42fb8d

Browse files
optimiz3rstam
authored andcommitted
Simplifying changes; inline the helper functions as they were only used once and eliminated all special cases except 0 and 1 byte string lengths.
1 parent 21753cf commit f42fb8d

File tree

1 file changed

+64
-109
lines changed

1 file changed

+64
-109
lines changed

Bson/IO/BsonBuffer.cs

Lines changed: 64 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.Linq;
2020
using System.Text;
2121
using System.Threading;
22+
using System.Reflection;
2223

2324
namespace MongoDB.Bson.IO
2425
{
@@ -509,16 +510,40 @@ public string ReadString()
509510
if (_disposed) { throw new ObjectDisposedException("BsonBuffer"); }
510511
var length = ReadInt32();
511512
EnsureDataAvailable(length);
513+
--length;
512514
string value;
513-
if (__chunkSize - _chunkOffset >= length - 1)
515+
if (__chunkSize - _chunkOffset >= length)
514516
{
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+
}
517541
}
518542
else
519543
{
520544
// straddles chunk boundary
521-
value = __utf8Encoding.GetString(ReadBytes(length - 1));
545+
var bytes = ReadBytes(length);
546+
value = __utf8Encoding.GetString(bytes, 0, length);
522547
}
523548
byte terminator = ReadByte();
524549
if (terminator != 0)
@@ -546,12 +571,40 @@ public string ReadCString()
546571
partialCount = _length - _position; // populated part of last chunk
547572
}
548573

549-
string value;
550-
var stringLength = TryParseCString(_chunk, _chunkOffset, partialCount, out value);
551-
if (stringLength >= 0)
574+
if (partialCount > 0)
552575
{
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+
}
555608
}
556609

557610
// the null terminator is not on the same chunk so keep looking starting with the next chunk
@@ -572,8 +625,8 @@ public string ReadCString()
572625
if (index != -1)
573626
{
574627
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
577630
Position += 1; // skip over null byte at end
578631
return value;
579632
}
@@ -912,104 +965,6 @@ private static string[] BuildAsciiStringTable()
912965
return asciiStringTable;
913966
}
914967

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-
1013968
// private methods
1014969
private void EnsureDataAvailable(int needed)
1015970
{

0 commit comments

Comments
 (0)