/// <summary>
        /// Reads a keyword from the input stream.
        /// </summary>
        private object ReadKeyword()
        {
            JSonReaderTokenInfo topToken = PopTopToken();

            // top token contains the first letter of current keyword:
            StringBuilder buffer     = new StringBuilder(topToken.Text);
            int           lastLine   = _input.Line;
            int           lastOffset = _input.LineOffset;

            StringHelper.ReadKeywordChars(_input, buffer);

            // since keyword has no closing token (as arrays or strings), it might
            // happen that we read too many chars... so put that new char as a token on the
            // stack and instruct reader that token is already there...
            ReadNextToken(char.IsWhiteSpace(_input.CurrentChar));
            _getTokenFromStack = true;

            string keyword = buffer.ToString().ToLower();

            foreach (var k in AvailableKeywords)
            {
                if (k.Token == keyword)
                {
                    return(_factory.CreateKeyword(k));
                }
            }

            // token has not been found:
            throw new JSonReaderException("Unknown keyword", keyword, lastLine, lastOffset);
        }
        private object ReadItem(BSonItemType type, out string key)
        {
            int length;
            int dataOffset;

            key        = _input.ReadStringUTF8(int.MaxValue);
            dataOffset = _input.Offset;
            switch (type)
            {
            case BSonItemType.Double:
                return(_factory.CreateNumber(_input.ReadDouble()));

            case BSonItemType.String:
            case BSonItemType.JavaScript:
            case BSonItemType.Symbol:
                length = _input.ReadInt32();
                return(_factory.CreateString(_input.ReadStringUTF8(length)));

            case BSonItemType.Object:
                return(ReadDocument());

            case BSonItemType.Array:
                return(ReadArray());

            case BSonItemType.Binary:
                throw new FormatException("Unsupported 'binary' field at " + dataOffset);

            case BSonItemType.Undefined:
                throw new FormatException("Unsupported 'undefined' field at " + dataOffset);

            case BSonItemType.ObjectID:
                throw new FormatException("Unsupported 'object-id' field at " + dataOffset);

            case BSonItemType.Boolean:
                return(_factory.CreateKeyword(_input.ReadByte() > 0 ? JSonReader.TrueTokenData : JSonReader.FalseTokenData));

            case BSonItemType.DateTime:
                return(_factory.CreateNumber(_input.ReadUInt64()));

            case BSonItemType.Null:
                return(_factory.CreateKeyword(JSonReader.FalseTokenData));

            case BSonItemType.RegExp:
                return(ReadRegExp());

            case BSonItemType.DbPointer:
                throw new FormatException("Unsupported 'DbPointer' field at " + dataOffset);

            case BSonItemType.JavaScriptScoped:
                return(ReadJavaScriptScoped());

            case BSonItemType.Int32:
                return(_factory.CreateNumber(_input.ReadInt32()));

            case BSonItemType.Timestamp:
                return(_factory.CreateNumber(_input.ReadInt64()));

            case BSonItemType.Int64:
                return(_factory.CreateNumber(_input.ReadInt64()));

            default:
                throw new FormatException("Unsupported '" + type + "' field at " + dataOffset);
            }
        }