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; }
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; }
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); }
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); }
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); }
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); }
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(); } }
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(); } }