/// <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);
        }
Esempio n. 2
0
        /// <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
                }
            }
        }
Esempio n. 3
0
        /// <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);
            }
        }
Esempio n. 4
0
        /// <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.");
        }
Esempio n. 5
0
 /// <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);