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