+/* static */
+wxProtocolError wxProtocol::ReadLine(wxSocketBase *sock, wxString& result)
+{
+ static const int LINE_BUF = 4095;
+
+ result.clear();
+
+ wxCharBuffer buf(LINE_BUF);
+ char *pBuf = buf.data();
+ while ( sock->WaitForRead() )
+ {
+ // peek at the socket to see if there is a CRLF
+ sock->Peek(pBuf, 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
+ pBuf[nRead] = '\0';
+ const char *eol = strchr(pBuf, '\n');
+
+ // if we found '\n', is there a '\r' as well?
+ if ( eol )
+ {
+ if ( eol == pBuf )
+ {
+ // 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 - pBuf + 1;
+
+ if ( eol[-1] != '\r' )
+ {
+ // as above, simply ignore stray '\n'
+ eol = NULL;
+ }
+ }
+ }
+
+ sock->Read(pBuf, nRead);
+ if ( sock->LastCount() != nRead )
+ return wxPROTO_NETERR;
+
+ pBuf[nRead] = '\0';
+ result += wxString::FromAscii(pBuf);
+
+ if ( eol )
+ {
+ // remove trailing "\r\n"
+ result.RemoveLast(2);
+
+ return wxPROTO_NOERR;
+ }
+ }
+
+ return wxPROTO_NETERR;