예제 #1
0
        internal override bool Write(WriteBuffer buf)
        {
            if (_charPos == -1)
            {
                // Start new query
                if (buf.WriteSpaceLeft < 1 + 4)
                    return false;
                _charPos = 0;
                var queryByteLen = _encoding.GetByteCount(_query);
                _queryChars = _query.ToCharArray();
                buf.WriteByte(Code);
                buf.WriteInt32(4 +            // Message length (including self excluding code)
                               queryByteLen + // Query byte length
                               1);            // Null terminator
            }

            if (_charPos < _queryChars.Length)
            {
                int charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                _charPos += charsUsed;
                if (!completed)
                    return false;
            }

            if (buf.WriteSpaceLeft < 1)
                return false;
            buf.WriteByte(0);

            _charPos = -1;
            return true;
        }
예제 #2
0
        internal override bool Write(WriteBuffer buf)
        {
            if (_charPos == -1)
            {
                // Start new query
                if (buf.WriteSpaceLeft < 1 + 4)
                    return false;
                _charPos = 0;
                var queryByteLen = PGUtil.UTF8Encoding.GetByteCount(_query);
                _queryChars = _query.ToCharArray();
                buf.WriteByte(Code);
                buf.WriteInt32(4 +            // Message length (including self excluding code)
                               queryByteLen + // Query byte length
                               1);            // Null terminator
            }

            if (_charPos < _queryChars.Length)
            {
                int charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                _charPos += charsUsed;
                if (!completed)
                    return false;
            }

            if (buf.WriteSpaceLeft < 1)
                return false;
            buf.WriteByte(0);

            _charPos = -1;
            return true;
        }
예제 #3
0
        public void ChunkedByteArrayEncodingFits()
        {
            WriteBuffer.WriteBytes(new byte[WriteBuffer.Size - 1], 0, WriteBuffer.Size - 1);
            Assert.That(WriteBuffer.WriteSpaceLeft, Is.EqualTo(1));

            var charsUsed = 1;
            var completed = true;

            // This unicode character is three bytes when encoded in UTF8
            Assert.That(() => WriteBuffer.WriteStringChunked("\uD55C".ToCharArray(), 0, 1, true, out charsUsed, out completed), Throws.Nothing);
            Assert.That(charsUsed, Is.EqualTo(0));
            Assert.That(completed, Is.False);
        }
예제 #4
0
        public void WriteZeroChars()
        {
            // Fill up the buffer entirely
            WriteBuffer.WriteBytes(new byte[WriteBuffer.Size], 0, WriteBuffer.Size);
            Assert.That(WriteBuffer.WriteSpaceLeft, Is.Zero);

            int  charsUsed;
            bool completed;

            WriteBuffer.WriteStringChunked("hello".ToCharArray(), 0, 5, true, out charsUsed, out completed);
            Assert.That(charsUsed, Is.Zero);
            Assert.That(completed, Is.False);
        }
예제 #5
0
        public void Chunked_char_array_encoding_fits_with_surrogates()
        {
            WriteBuffer.WriteBytes(new byte[WriteBuffer.Size - 1]);
            Assert.That(WriteBuffer.WriteSpaceLeft, Is.EqualTo(1));

            var charsUsed = 1;
            var completed = true;
            var cyclone   = "🌀";

            Assert.That(() => WriteBuffer.WriteStringChunked(cyclone.ToCharArray(), 0, cyclone.Length, true, out charsUsed, out completed), Throws.Nothing);
            Assert.That(charsUsed, Is.EqualTo(0));
            Assert.That(completed, Is.False);
        }
예제 #6
0
        public override bool Write(ref DirectBuffer directBuf)
        {
            if (_charPos == -1)
            {
                if (_byteLen <= _writeBuf.WriteSpaceLeft)
                {
                    // Can simply write the string to the buffer
                    if (_str != null)
                    {
                        _writeBuf.WriteString(_str, _charLen);
                        _str = null;
                    }
                    else
                    {
                        Contract.Assert(_chars != null);
                        _writeBuf.WriteChars(_chars, _charLen);
                        _str = null;
                    }
                    _writeBuf = null;
                    return(true);
                }

                if (_byteLen <= _writeBuf.UsableSize)
                {
                    // Buffer is currently too full, but the string can fit. Force a write to fill.
                    return(false);
                }

                // Bad case: the string doesn't fit in our buffer.
                _charPos = 0;

                // For strings, chunked/incremental conversion isn't supported
                // (see https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/6584398-add-system-text-encoder-convert-method-string-in)
                // So for now allocate a temporary byte buffer to hold the entire string and write it directly.
                if (_str != null)
                {
                    directBuf.Buffer = new byte[_byteLen];
                    _writeBuf.TextEncoding.GetBytes(_str, 0, _charLen, directBuf.Buffer, 0);
                    return(false);
                }
                Contract.Assert(_chars != null);

                // For char arrays, fall through to chunked writing below
            }

            if (_str != null)
            {
                // We did a direct buffer write above, and must now clean up
                _str      = null;
                _writeBuf = null;
                return(true);
            }

            int  charsUsed;
            bool completed;

            _writeBuf.WriteStringChunked(_chars, _charPos, _chars.Length - _charPos, false, out charsUsed, out completed);
            if (completed)
            {
                // Flush encoder
                _writeBuf.WriteStringChunked(_chars, _charPos, _chars.Length - _charPos, true, out charsUsed, out completed);
                _chars    = null;
                _writeBuf = null;
                return(true);
            }
            _charPos += charsUsed;
            return(false);
        }
예제 #7
0
        internal override bool Write(WriteBuffer buf)
        {
            Contract.Requires(Statement != null);

            switch (_state)
            {
            case State.WroteNothing:
                _statementNameBytes = Statement.Length == 0 ? PGUtil.EmptyBuffer : _encoding.GetBytes(Statement);
                _queryLen           = _encoding.GetByteCount(Query);
                if (buf.WriteSpaceLeft < 1 + 4 + _statementNameBytes.Length + 1)
                {
                    return(false);
                }

                var messageLength =
                    1 +                             // Message code
                    4 +                             // Length
                    _statementNameBytes.Length +
                    1 +                             // Null terminator
                    _queryLen +
                    1 +                             // Null terminator
                    2 +                             // Number of parameters
                    ParameterTypeOIDs.Count * 4;

                buf.WriteByte(Code);
                buf.WriteInt32(messageLength - 1);
                buf.WriteBytesNullTerminated(_statementNameBytes);
                goto case State.WroteHeader;

            case State.WroteHeader:
                _state = State.WroteHeader;

                if (_queryLen <= buf.WriteSpaceLeft)
                {
                    buf.WriteString(Query);
                    goto case State.WroteQuery;
                }

                if (_queryLen <= buf.Size)
                {
                    // String can fit entirely in an empty buffer. Flush and retry rather than
                    // going into the partial writing flow below (which requires ToCharArray())
                    return(false);
                }

                _queryChars = Query.ToCharArray();
                _charPos    = 0;
                goto case State.WritingQuery;

            case State.WritingQuery:
                _state = State.WritingQuery;
                int  charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                if (!completed)
                {
                    _charPos += charsUsed;
                    return(false);
                }
                goto case State.WroteQuery;

            case State.WroteQuery:
                _state = State.WroteQuery;
                if (buf.WriteSpaceLeft < 1 + 2)
                {
                    return(false);
                }
                buf.WriteByte(0);     // Null terminator for the query
                buf.WriteInt16((short)ParameterTypeOIDs.Count);
                goto case State.WritingParameterTypes;

            case State.WritingParameterTypes:
                _state = State.WritingParameterTypes;
                for (; _parameterTypePos < ParameterTypeOIDs.Count; _parameterTypePos++)
                {
                    if (buf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    buf.WriteInt32((int)ParameterTypeOIDs[_parameterTypePos]);
                }

                _state = State.WroteAll;
                return(true);

            default:
                throw PGUtil.ThrowIfReached();
            }
        }
예제 #8
0
        internal override bool Write(WriteBuffer buf)
        {
            Contract.Requires(Statement != null);

            switch (_state)
            {
                case State.WroteNothing:
                    _statementNameBytes = Statement.Length == 0 ? PGUtil.EmptyBuffer : _encoding.GetBytes(Statement);
                    _queryLen = _encoding.GetByteCount(Query);
                    if (buf.WriteSpaceLeft < 1 + 4 + _statementNameBytes.Length + 1) {
                        return false;
                    }

                    var messageLength =
                        1 +                         // Message code
                        4 +                         // Length
                        _statementNameBytes.Length +
                        1 +                         // Null terminator
                        _queryLen +
                        1 +                         // Null terminator
                        2 +                         // Number of parameters
                        ParameterTypeOIDs.Count * 4;

                    buf.WriteByte(Code);
                    buf.WriteInt32(messageLength - 1);
                    buf.WriteBytesNullTerminated(_statementNameBytes);
                    goto case State.WroteHeader;

                case State.WroteHeader:
                    _state = State.WroteHeader;

                    if (_queryLen <= buf.WriteSpaceLeft) {
                        buf.WriteString(Query);
                        goto case State.WroteQuery;
                    }

                    if (_queryLen <= buf.Size) {
                        // String can fit entirely in an empty buffer. Flush and retry rather than
                        // going into the partial writing flow below (which requires ToCharArray())
                        return false;
                    }

                    _queryChars = Query.ToCharArray();
                    _charPos = 0;
                    goto case State.WritingQuery;

                case State.WritingQuery:
                    _state = State.WritingQuery;
                    int charsUsed;
                    bool completed;
                    buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                           out charsUsed, out completed);
                    if (!completed)
                    {
                        _charPos += charsUsed;
                        return false;
                    }
                    goto case State.WroteQuery;

                case State.WroteQuery:
                    _state = State.WroteQuery;
                    if (buf.WriteSpaceLeft < 1 + 2) {
                        return false;
                    }
                    buf.WriteByte(0); // Null terminator for the query
                    buf.WriteInt16((short)ParameterTypeOIDs.Count);
                    goto case State.WritingParameterTypes;

                case State.WritingParameterTypes:
                    _state = State.WritingParameterTypes;
                    for (; _parameterTypePos < ParameterTypeOIDs.Count; _parameterTypePos++)
                    {
                        if (buf.WriteSpaceLeft < 4)
                        {
                            return false;
                        }
                        buf.WriteInt32((int)ParameterTypeOIDs[_parameterTypePos]);
                    }

                    _state = State.WroteAll;
                    return true;

                default:
                    throw PGUtil.ThrowIfReached();
            }
        }