use 4K buffer instead of reading characters one by one in ReadLine()
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29202 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -90,41 +90,72 @@ bool wxProtocol::Reconnect()
|
|||||||
// Read a line from socket
|
// Read a line from socket
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO ReadLine() should use buffers private to wxProtocol for efficiency!
|
/* static */
|
||||||
|
|
||||||
// static
|
|
||||||
wxProtocolError wxProtocol::ReadLine(wxSocketBase *socket, wxString& result)
|
wxProtocolError wxProtocol::ReadLine(wxSocketBase *socket, wxString& result)
|
||||||
{
|
{
|
||||||
result.Empty();
|
static const int LINE_BUF = 4095;
|
||||||
char ch, chLast = '\0';
|
|
||||||
while ( !socket->Read(&ch, sizeof(ch)).Error() )
|
|
||||||
{
|
|
||||||
switch ( ch )
|
|
||||||
{
|
|
||||||
case '\r':
|
|
||||||
// remember it, if the following is '\n', we're done
|
|
||||||
chLast = '\r';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
result.clear();
|
||||||
// only ends line if the previous character was '\r'
|
|
||||||
if ( chLast == '\r' )
|
wxCharBuffer buf(LINE_BUF);
|
||||||
|
while ( sock->WaitForRead() )
|
||||||
{
|
{
|
||||||
// EOL found
|
// peek at the socket to see if there is a CRLF
|
||||||
|
sock->Peek(buf.data(), LINE_BUF);
|
||||||
|
|
||||||
|
size_t nRead = sock->LastCount();
|
||||||
|
if ( !nRead && sock->Error() )
|
||||||
|
return wxPROTO_NETERR;
|
||||||
|
|
||||||
|
// look for "\r\n" paying attention to a special case: "\r\n" could
|
||||||
|
// have been split by buffer boundary, so check also for \r at the end
|
||||||
|
// of the last chunk and \n at the beginning of this one
|
||||||
|
buf.data()[nRead] = '\0';
|
||||||
|
const char *eol = strchr(buf, '\n');
|
||||||
|
|
||||||
|
// if we found '\n', is there a '\r' as well?
|
||||||
|
if ( eol )
|
||||||
|
{
|
||||||
|
if ( eol == buf.data() )
|
||||||
|
{
|
||||||
|
// check for case of "\r\n" being split
|
||||||
|
if ( result.empty() || result.Last() != _T('\r') )
|
||||||
|
{
|
||||||
|
// ignore the stray '\n'
|
||||||
|
eol = NULL;
|
||||||
|
}
|
||||||
|
//else: ok, got real EOL
|
||||||
|
|
||||||
|
// read just this '\n' and restart
|
||||||
|
nRead = 1;
|
||||||
|
}
|
||||||
|
else // '\n' in the middle of the buffer
|
||||||
|
{
|
||||||
|
// in any case, read everything up to and including '\n'
|
||||||
|
nRead = eol - buf + 1;
|
||||||
|
|
||||||
|
if ( eol[-1] != '\r' )
|
||||||
|
{
|
||||||
|
// as above, simply ignore stray '\n'
|
||||||
|
eol = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock->Read(buf.data(), nRead);
|
||||||
|
if ( sock->LastCount() != nRead )
|
||||||
|
return wxPROTO_NETERR;
|
||||||
|
|
||||||
|
buf.data()[nRead] = '\0';
|
||||||
|
result += wxString::FromAscii(buf);
|
||||||
|
|
||||||
|
if ( eol )
|
||||||
|
{
|
||||||
|
// remove trailing "\r\n"
|
||||||
|
result.RemoveLast(2);
|
||||||
|
|
||||||
return wxPROTO_NOERR;
|
return wxPROTO_NOERR;
|
||||||
}
|
}
|
||||||
//else: fall through
|
|
||||||
|
|
||||||
default:
|
|
||||||
// normal char
|
|
||||||
if ( chLast )
|
|
||||||
{
|
|
||||||
result += wxString::FromAscii( chLast );
|
|
||||||
chLast = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
result += wxString::FromAscii( ch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxPROTO_NETERR;
|
return wxPROTO_NETERR;
|
||||||
|
Reference in New Issue
Block a user