Skip to content

Commit 061d354

Browse files
author
sridharn
committed
Merge remote-tracking branch 'upstream/master'
Conflicts: CSharpDriverSetup-2010.sln Installer/CSharpDriverInstaller.wixproj Installer/Product.wxs Installer/makeinstaller.bat
2 parents de971b0 + 6c270e2 commit 061d354

34 files changed

+2791
-474
lines changed

Bson/Bson.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
<Compile Include="IO\BsonDocumentReaderSettings.cs" />
8787
<Compile Include="IO\BsonDocumentWriterSettings.cs" />
8888
<Compile Include="IO\BsonReaderSettings.cs" />
89+
<Compile Include="IO\BsonTrie.cs" />
8990
<Compile Include="IO\BsonWriterSettings.cs" />
9091
<Compile Include="ObjectModel\GuidRepresentation.cs" />
9192
<Compile Include="ObjectModel\GuidConverter.cs" />

Bson/IO/BsonBinaryReader.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,15 @@ public override bool ReadBoolean()
160160
/// <summary>
161161
/// Reads a BsonType from the reader.
162162
/// </summary>
163+
/// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
164+
/// <param name="found">Set to true if a matching value was found in the trie.</param>
165+
/// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
163166
/// <returns>A BsonType.</returns>
164-
public override BsonType ReadBsonType()
167+
public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
165168
{
166169
if (Disposed) { ThrowObjectDisposedException(); }
170+
found = false;
171+
value = default(TValue);
167172
if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument)
168173
{
169174
// there is an implied type of Document for the top level and for scope documents
@@ -204,7 +209,7 @@ public override BsonType ReadBsonType()
204209
break;
205210
case ContextType.Document:
206211
case ContextType.ScopeDocument:
207-
CurrentName = _buffer.ReadCString();
212+
CurrentName = _buffer.ReadCString(bsonTrie, out found, out value);
208213
State = BsonReaderState.Name;
209214
break;
210215
default:

Bson/IO/BsonBuffer.cs

Lines changed: 93 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -533,31 +533,7 @@ public string ReadString()
533533
{
534534
throw new FileFormatException("String is missing null terminator.");
535535
}
536-
537-
switch (length)
538-
{
539-
// special case empty strings
540-
case 1:
541-
value = string.Empty;
542-
break;
543-
544-
// special case single character strings
545-
case 2:
546-
var c1 = _chunk[_chunkOffset];
547-
if (c1 < 128)
548-
{
549-
value = __asciiStringTable[c1];
550-
}
551-
else
552-
{
553-
value = __utf8Encoding.GetString(_chunk, _chunkOffset, 1); // let GetString throw a DecoderFallbackException
554-
}
555-
break;
556-
557-
default:
558-
value = __utf8Encoding.GetString(_chunk, _chunkOffset, length - 1); // don't decode the null terminator
559-
break;
560-
}
536+
value = DecodeUtf8String(_chunk, _chunkOffset, length - 1); // don't decode the null terminator
561537
Position += length;
562538
}
563539
else
@@ -577,10 +553,26 @@ public string ReadString()
577553
/// <summary>
578554
/// Reads a BSON CString from the reader (a null terminated string).
579555
/// </summary>
580-
/// <returns>A String.</returns>
556+
/// <returns>A string.</returns>
581557
public string ReadCString()
558+
{
559+
bool found;
560+
object value;
561+
return ReadCString(null, out found, out value);
562+
}
563+
564+
/// <summary>
565+
/// Reads a BSON CString from the reader (a null terminated string).
566+
/// </summary>
567+
/// <param name="bsonTrie">An optional BsonTrie to use during decoding.</param>
568+
/// <param name="found">Set to true if the string was found in the trie.</param>
569+
/// <param name="value">Set to the value found in the trie; otherwise, null.</param>
570+
/// <returns>A string.</returns>
571+
public string ReadCString<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
582572
{
583573
if (_disposed) { throw new ObjectDisposedException("BsonBuffer"); }
574+
found = false;
575+
value = default(TValue);
584576
// optimize for the case where the null terminator is on the same chunk
585577
int partialCount;
586578
if (_chunkIndex < _chunks.Count - 1)
@@ -592,44 +584,24 @@ public string ReadCString()
592584
partialCount = _length - _position; // populated part of last chunk
593585
}
594586

595-
if (partialCount > 0)
587+
var bsonTrieNode = bsonTrie != null ? bsonTrie.Root : null;
588+
var index = IndexOfNull(_chunk, _chunkOffset, partialCount, ref bsonTrieNode);
589+
if (index != -1)
596590
{
597-
var c1 = _chunk[_chunkOffset];
598-
599-
// special case empty strings
600-
if (c1 == 0)
591+
var stringLength = index - _chunkOffset;
592+
string cstring;
593+
if (bsonTrieNode != null && bsonTrieNode.HasValue)
601594
{
602-
Position += 1;
603-
return string.Empty;
595+
cstring = bsonTrieNode.ElementName;
596+
value = bsonTrieNode.Value;
597+
found = true;
604598
}
605-
606-
if (partialCount > 1)
599+
else
607600
{
608-
// special case single character strings
609-
if (_chunk[_chunkOffset + 1] == 0)
610-
{
611-
string value;
612-
if (c1 < 128)
613-
{
614-
value = __asciiStringTable[c1];
615-
}
616-
else
617-
{
618-
value = __utf8Encoding.GetString(_chunk, _chunkOffset, 1); // let GetString throw a DecoderFallbackException
619-
}
620-
Position += 2;
621-
return value;
622-
}
623-
624-
var index = Array.IndexOf<byte>(_chunk, 0, _chunkOffset + 2, partialCount - 2);
625-
if (index != -1)
626-
{
627-
var stringLength = index - _chunkOffset;
628-
var value = __utf8Encoding.GetString(_chunk, _chunkOffset, stringLength);
629-
Position += stringLength + 1;
630-
return value;
631-
}
601+
cstring = DecodeUtf8String(_chunk, _chunkOffset, stringLength);
632602
}
603+
Position += stringLength + 1;
604+
return cstring;
633605
}
634606

635607
// the null terminator is not on the same chunk so keep looking starting with the next chunk
@@ -646,14 +618,25 @@ public string ReadCString()
646618
{
647619
partialCount = _length - localPosition; // populated part of last chunk
648620
}
649-
var index = Array.IndexOf<byte>(localChunk, 0, 0, partialCount);
621+
index = IndexOfNull(localChunk, 0, partialCount, ref bsonTrieNode);
650622
if (index != -1)
651623
{
652624
localPosition += index;
653625
var stringLength = localPosition - _position;
654-
var value = __utf8Encoding.GetString(ReadBytes(stringLength)); // ReadBytes advances over string
655-
Position += 1; // skip over null byte at end
656-
return value;
626+
string cstring;
627+
if (bsonTrieNode != null && bsonTrieNode.HasValue)
628+
{
629+
cstring = bsonTrieNode.ElementName;
630+
value = bsonTrieNode.Value;
631+
found = true;
632+
Position += stringLength + 1;
633+
}
634+
else
635+
{
636+
cstring = __utf8Encoding.GetString(ReadBytes(stringLength)); // ReadBytes advances over string
637+
Position += 1; // skip over null byte at end
638+
}
639+
return cstring;
657640
}
658641
localChunkIndex++;
659642
localPosition += __chunkSize;
@@ -978,6 +961,27 @@ public void WriteZero()
978961
}
979962

980963
// private methods
964+
private string DecodeUtf8String(byte[] buffer, int index, int count)
965+
{
966+
switch (count)
967+
{
968+
// special case empty strings
969+
case 0:
970+
return "";
971+
972+
// special case single character strings
973+
case 1:
974+
var byte1 = (int)buffer[index];
975+
if (byte1 < __asciiStringTable.Length)
976+
{
977+
return __asciiStringTable[byte1];
978+
}
979+
break;
980+
}
981+
982+
return __utf8Encoding.GetString(buffer, index, count);
983+
}
984+
981985
private void EnsureDataAvailable(int needed)
982986
{
983987
if (_length - _position < needed)
@@ -1009,5 +1013,31 @@ private void EnsureSpaceAvailable(int needed)
10091013
}
10101014
}
10111015
}
1016+
1017+
private static int IndexOfNull<TValue>(
1018+
byte[] buffer,
1019+
int index,
1020+
int count,
1021+
ref BsonTrieNode<TValue> bsonTrieNode)
1022+
{
1023+
for (; count > 0; index++, count--)
1024+
{
1025+
// bsonTrieNode might be null on entry or it might become null while navigating the trie
1026+
if (bsonTrieNode == null)
1027+
{
1028+
return Array.IndexOf<byte>(buffer, 0, index, count);
1029+
}
1030+
1031+
var keyByte = buffer[index];
1032+
if (keyByte == 0)
1033+
{
1034+
return index;
1035+
}
1036+
1037+
bsonTrieNode = bsonTrieNode.GetChild(keyByte); // might return null
1038+
}
1039+
1040+
return -1;
1041+
}
10121042
}
10131043
}

Bson/IO/BsonDocumentReader.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,15 @@ public override bool ReadBoolean()
103103
/// <summary>
104104
/// Reads a BsonType from the reader.
105105
/// </summary>
106+
/// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
107+
/// <param name="found">Set to true if a matching value was found in the trie.</param>
108+
/// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
106109
/// <returns>A BsonType.</returns>
107-
public override BsonType ReadBsonType()
110+
public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
108111
{
109112
if (Disposed) { ThrowObjectDisposedException(); }
113+
found = false;
114+
value = default(TValue);
110115
if (State == BsonReaderState.Initial || State == BsonReaderState.ScopeDocument)
111116
{
112117
// there is an implied type of Document for the top level and for scope documents
@@ -137,6 +142,10 @@ public override BsonType ReadBsonType()
137142
State = BsonReaderState.EndOfDocument;
138143
return BsonType.EndOfDocument;
139144
}
145+
if (bsonTrie != null)
146+
{
147+
found = bsonTrie.TryGetValue(currentElement.Name, out value);
148+
}
140149
CurrentName = currentElement.Name;
141150
_currentValue = currentElement.Value;
142151
State = BsonReaderState.Name;

Bson/IO/BsonReader.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,21 @@ public bool ReadBoolean(string name)
368368
/// Reads a BsonType from the reader.
369369
/// </summary>
370370
/// <returns>A BsonType.</returns>
371-
public abstract BsonType ReadBsonType();
371+
public BsonType ReadBsonType()
372+
{
373+
bool found;
374+
object value;
375+
return ReadBsonType(null, out found, out value);
376+
}
377+
378+
/// <summary>
379+
/// Reads a BsonType from the reader.
380+
/// </summary>
381+
/// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
382+
/// <param name="found">Set to true if a matching value was found in the trie.</param>
383+
/// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
384+
/// <returns>A BsonType.</returns>
385+
public abstract BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value);
372386

373387
/// <summary>
374388
/// Reads a BSON DateTime from the reader.

0 commit comments

Comments
 (0)