From: Vadim Zeitlin Date: Sat, 18 Sep 2004 14:21:56 +0000 (+0000) Subject: use 4K buffer instead of reading characters one by one in ReadLine() X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/db7c5931ed25a56f4eaef1076b158ca5d30b9a37 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 --- diff --git a/src/common/protocol.cpp b/src/common/protocol.cpp index 8d83bc6dbb..64c385528f 100644 --- a/src/common/protocol.cpp +++ b/src/common/protocol.cpp @@ -90,40 +90,71 @@ bool wxProtocol::Reconnect() // Read a line from socket // ---------------------------------------------------------------------------- -// TODO ReadLine() should use buffers private to wxProtocol for efficiency! - -// static +/* static */ wxProtocolError wxProtocol::ReadLine(wxSocketBase *socket, wxString& result) { - result.Empty(); - char ch, chLast = '\0'; - while ( !socket->Read(&ch, sizeof(ch)).Error() ) + static const int LINE_BUF = 4095; + + result.clear(); + + wxCharBuffer buf(LINE_BUF); + while ( sock->WaitForRead() ) { - switch ( ch ) + // 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 ) { - case '\r': - // remember it, if the following is '\n', we're done - chLast = '\r'; - break; - - case '\n': - // only ends line if the previous character was '\r' - if ( chLast == '\r' ) + if ( eol == buf.data() ) + { + // check for case of "\r\n" being split + if ( result.empty() || result.Last() != _T('\r') ) { - // EOL found - return wxPROTO_NOERR; + // ignore the stray '\n' + eol = NULL; } - //else: fall through + //else: ok, got real EOL - default: - // normal char - if ( chLast ) + // 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' ) { - result += wxString::FromAscii( chLast ); - chLast = '\0'; + // 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); - result += wxString::FromAscii( ch ); + return wxPROTO_NOERR; } }