/// <summary> /// Reads a BsonType from the reader. /// </summary> /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam> /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param> /// <param name="found">Set to true if a matching value was found in the trie.</param> /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param> /// <returns>A BsonType.</returns> public override BsonType ReadBsonType <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value) { if (Disposed) { ThrowObjectDisposedException(); } found = false; value = default(TValue); if (State == BsonReaderState.Initial || State == BsonReaderState.ScopeDocument) { // there is an implied type of Document for the top level and for scope documents CurrentBsonType = BsonType.Document; State = BsonReaderState.Value; return(CurrentBsonType); } if (State != BsonReaderState.Type) { ThrowInvalidState("ReadBsonType", BsonReaderState.Type); } switch (_context.ContextType) { case ContextType.Array: _currentValue = _context.GetNextValue(); if (_currentValue == null) { State = BsonReaderState.EndOfArray; return(BsonType.EndOfDocument); } State = BsonReaderState.Value; break; case ContextType.Document: var currentElement = _context.GetNextElement(); if (currentElement == null) { State = BsonReaderState.EndOfDocument; return(BsonType.EndOfDocument); } if (bsonTrie != null) { found = bsonTrie.TryGetValue(currentElement.Name, out value); } CurrentName = currentElement.Name; _currentValue = currentElement.Value; State = BsonReaderState.Name; break; default: throw new BsonInternalException("Invalid ContextType."); } CurrentBsonType = _currentValue.BsonType; return(CurrentBsonType); }
/// <summary> /// Reads an element name. /// </summary> /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam> /// <param name="bsonTrie">An optional BsonTrie to use during decoding.</param> /// <param name="found">Set to true if the string was found in the trie.</param> /// <param name="value">Set to the value found in the trie; otherwise, null.</param> /// <returns>A string.</returns> public string ReadName <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value) { ThrowIfDisposed(); found = false; value = default(TValue); if (bsonTrie == null) { return(ReadCString(Utf8Encodings.Strict)); // always use strict encoding for names } var savedPosition = _byteBuffer.Position; var bsonTrieNode = bsonTrie.Root; while (true) { var keyByte = _byteBuffer.ReadByte(); if (keyByte == 0) { if (bsonTrieNode.HasValue) { found = true; value = bsonTrieNode.Value; return(bsonTrieNode.ElementName); } else { var nullPosition = _byteBuffer.Position - 1; _byteBuffer.Position = savedPosition; return(ReadCString(Utf8Encodings.Strict, nullPosition)); // always use strict encoding for names } } bsonTrieNode = bsonTrieNode.GetChild(keyByte); if (bsonTrieNode == null) { var nullPosition = _byteBuffer.FindNullByte(); // starting from where we got so far _byteBuffer.Position = savedPosition; return(ReadCString(Utf8Encodings.Strict, nullPosition)); // always use strict encoding for names } } }
/// <summary> /// Reads a BsonType from the reader. /// </summary> /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam> /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param> /// <param name="found">Set to true if a matching value was found in the trie.</param> /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param> /// <returns>A BsonType.</returns> public override BsonType ReadBsonType <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value) { if (Disposed) { ThrowObjectDisposedException(); } found = false; value = default(TValue); if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument) { // there is an implied type of Document for the top level and for scope documents CurrentBsonType = BsonType.Document; State = BsonReaderState.Value; return(CurrentBsonType); } if (State != BsonReaderState.Type) { ThrowInvalidState("ReadBsonType", BsonReaderState.Type); } CurrentBsonType = _buffer.ReadBsonType(); if (CurrentBsonType == BsonType.EndOfDocument) { switch (_context.ContextType) { case ContextType.Array: State = BsonReaderState.EndOfArray; return(BsonType.EndOfDocument); case ContextType.Document: case ContextType.ScopeDocument: State = BsonReaderState.EndOfDocument; return(BsonType.EndOfDocument); default: var message = string.Format("BsonType EndOfDocument is not valid when ContextType is {0}.", _context.ContextType); throw new FileFormatException(message); } } else { switch (_context.ContextType) { case ContextType.Array: _buffer.SkipCString(); // ignore array element names State = BsonReaderState.Value; break; case ContextType.Document: case ContextType.ScopeDocument: CurrentName = _buffer.ReadCString(bsonTrie, out found, out value); State = BsonReaderState.Name; break; default: throw new BsonInternalException("Unexpected ContextType."); } return(CurrentBsonType); } }
/// <summary> /// Reads a BSON CString from the reader (a null terminated string). /// </summary> /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam> /// <param name="bsonTrie">An optional BsonTrie to use during decoding.</param> /// <param name="found">Set to true if the string was found in the trie.</param> /// <param name="value">Set to the value found in the trie; otherwise, null.</param> /// <returns>A string.</returns> public string ReadCString <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value) { if (_disposed) { throw new ObjectDisposedException("BsonBuffer"); } found = false; value = default(TValue); // optimize for the case where the null terminator is on the same chunk int partialCount; if (_chunkIndex < _chunks.Count - 1) { partialCount = __chunkSize - _chunkOffset; // remaining part of any chunk but the last } else { partialCount = _length - _position; // populated part of last chunk } var bsonTrieNode = bsonTrie != null ? bsonTrie.Root : null; var index = IndexOfNull(_chunk, _chunkOffset, partialCount, ref bsonTrieNode); if (index != -1) { var stringLength = index - _chunkOffset; string cstring; if (bsonTrieNode != null && bsonTrieNode.HasValue) { cstring = bsonTrieNode.ElementName; value = bsonTrieNode.Value; found = true; } else { cstring = DecodeUtf8String(_chunk, _chunkOffset, stringLength); } Position += stringLength + 1; return(cstring); } // the null terminator is not on the same chunk so keep looking starting with the next chunk var localChunkIndex = _chunkIndex + 1; var localPosition = localChunkIndex * __chunkSize; while (localPosition < _length) { var localChunk = _chunks[localChunkIndex]; if (localChunkIndex < _chunks.Count - 1) { partialCount = __chunkSize; // all of any chunk but the last } else { partialCount = _length - localPosition; // populated part of last chunk } index = IndexOfNull(localChunk, 0, partialCount, ref bsonTrieNode); if (index != -1) { localPosition += index; var stringLength = localPosition - _position; string cstring; if (bsonTrieNode != null && bsonTrieNode.HasValue) { cstring = bsonTrieNode.ElementName; value = bsonTrieNode.Value; found = true; Position += stringLength + 1; } else { cstring = __utf8Encoding.GetString(ReadBytes(stringLength)); // ReadBytes advances over string Position += 1; // skip over null byte at end } return(cstring); } localChunkIndex++; localPosition += __chunkSize; } throw new FileFormatException("String is missing null terminator."); }
/// <summary> /// Reads a BsonType from the reader. /// </summary> /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam> /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param> /// <param name="found">Set to true if a matching value was found in the trie.</param> /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param> /// <returns>A BsonType.</returns> public abstract BsonType ReadBsonType <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value);