diff options
author | Alex Trotsenko <[email protected]> | 2021-06-23 18:26:10 +0300 |
---|---|---|
committer | Alex Trotsenko <[email protected]> | 2021-07-06 17:52:58 +0300 |
commit | b3fbfcd3738a0ff864439499390513b95ca671aa (patch) | |
tree | ac274d4652ea3415e9b0ef302c3c6bd146e15e4d | |
parent | 46d2ba1ea4d0e5f1a2ae1d1801e416e487ea45b4 (diff) |
QLocalSocket: reimplement readLineData() function
The base implementation reads data using repeated calls to getChar(),
which is quite slow.
Change-Id: Ie46624df63791b2cdd3c8a28fe3327427d942505
Reviewed-by: Oswald Buddenhagen <[email protected]>
-rw-r--r-- | src/corelib/io/qwindowspipereader.cpp | 24 | ||||
-rw-r--r-- | src/corelib/io/qwindowspipereader_p.h | 1 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket.cpp | 5 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket.h | 1 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket_tcp.cpp | 10 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket_unix.cpp | 10 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket_win.cpp | 34 |
7 files changed, 76 insertions, 9 deletions
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 539902c2337..c3ac51df949 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -209,6 +209,30 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) } /*! + Reads a line from the internal buffer, but no more than \c{maxlen} + characters. A terminating '\0' byte is always appended to \c{data}, + so \c{maxlen} must be larger than 1. + */ +qint64 QWindowsPipeReader::readLine(char *data, qint64 maxlen) +{ + QMutexLocker locker(&mutex); + qint64 readSoFar = 0; + + if (actualReadBufferSize > 0) { + readSoFar = readBuffer.readLine(data, qMin(actualReadBufferSize + 1, maxlen)); + actualReadBufferSize -= readSoFar; + } + + if (!pipeBroken) { + startAsyncReadHelper(&locker); + if (readSoFar == 0) + return -2; // signal EWOULDBLOCK + } + + return readSoFar; +} + +/*! Returns \c true if a complete line of data can be read from the buffer. */ bool QWindowsPipeReader::canReadLine() const diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index 77c90645c6d..e2190d67d92 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -78,6 +78,7 @@ public: bool isPipeClosed() const { return pipeBroken; } qint64 bytesAvailable() const; qint64 read(char *data, qint64 maxlen); + qint64 readLine(char *data, qint64 maxlen); bool canReadLine() const; DWORD checkPipeState(); bool checkForReadyRead() { return consumePendingAndEmit(false); } diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp index 98c686de639..12b9f45a142 100644 --- a/src/network/socket/qlocalsocket.cpp +++ b/src/network/socket/qlocalsocket.cpp @@ -167,6 +167,11 @@ QT_BEGIN_NAMESPACE */ /*! + \fn qint64 QLocalSocket::readLineData(char *data, qint64 maxSize) + \reimp +*/ + +/*! \fn qint64 QLocalSocket::skipData(qint64 maxSize) \reimp */ diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index 2a578dd10ba..c74c36e9a79 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -139,6 +139,7 @@ Q_SIGNALS: protected: virtual qint64 readData(char*, qint64) override; + qint64 readLineData(char *data, qint64 maxSize) override; qint64 skipData(qint64 maxSize) override; virtual qint64 writeData(const char*, qint64) override; diff --git a/src/network/socket/qlocalsocket_tcp.cpp b/src/network/socket/qlocalsocket_tcp.cpp index 2f0179f40a7..1b6aa16c9ba 100644 --- a/src/network/socket/qlocalsocket_tcp.cpp +++ b/src/network/socket/qlocalsocket_tcp.cpp @@ -301,6 +301,16 @@ qint64 QLocalSocket::readData(char *data, qint64 c) return d->tcpSocket->read(data, c); } +qint64 QLocalSocket::readLineData(char *data, qint64 maxSize) +{ + if (!maxSize) + return 0; + + // QIODevice::readLine() reserves space for the trailing '\0' byte, + // so we must read 'maxSize + 1' bytes. + return d_func()->tcpSocket->readLine(data, maxSize + 1); +} + qint64 QLocalSocket::skipData(qint64 maxSize) { return d_func()->tcpSocket->skip(maxSize); diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 5e050ad3230..4dc542f2e34 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -483,6 +483,16 @@ qint64 QLocalSocket::readData(char *data, qint64 c) return d->unixSocket.read(data, c); } +qint64 QLocalSocket::readLineData(char *data, qint64 maxSize) +{ + if (!maxSize) + return 0; + + // QIODevice::readLine() reserves space for the trailing '\0' byte, + // so we must read 'maxSize + 1' bytes. + return d_func()->unixSocket.readLine(data, maxSize + 1); +} + qint64 QLocalSocket::skipData(qint64 maxSize) { return d_func()->unixSocket.skip(maxSize); diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index aa5c12b5b8a..efeb3cdf0ac 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -238,6 +238,20 @@ void QLocalSocket::connectToServer(OpenMode openMode) emit connected(); } +static qint64 tranformPipeReaderResult(qint64 res) +{ + // QWindowsPipeReader's reading functions return error codes + // that don't match what we need. + switch (res) { + case 0: // EOF -> transform to error + return -1; + case -2: // EWOULDBLOCK -> no error, just no bytes + return 0; + default: + return res; + } +} + // This is reading from the buffer qint64 QLocalSocket::readData(char *data, qint64 maxSize) { @@ -246,17 +260,19 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize) if (!maxSize) return 0; - qint64 ret = d->pipeReader->read(data, maxSize); + return tranformPipeReaderResult(d->pipeReader->read(data, maxSize)); +} + +qint64 QLocalSocket::readLineData(char *data, qint64 maxSize) +{ + Q_D(QLocalSocket); - // QWindowsPipeReader::read() returns error codes that don't match what we need - switch (ret) { - case 0: // EOF -> transform to error - return -1; - case -2: // EWOULDBLOCK -> no error, just no bytes + if (!maxSize) return 0; - default: - return ret; - } + + // QIODevice::readLine() reserves space for the trailing '\0' byte, + // so we must read 'maxSize + 1' bytes. + return tranformPipeReaderResult(d->pipeReader->readLine(data, maxSize + 1)); } qint64 QLocalSocket::skipData(qint64 maxSize) |