diff --git a/README b/README index ca79c7489..8470d9fad 100644 --- a/README +++ b/README @@ -61,7 +61,7 @@ QTBUG-21548, QTBUG-6133, QTBUG-18188, QTBUG-36767, QTBUG-35387, QTBUG-37035, QTBUG-28321, QTBUG-21993, QTBUG-26590, QTBUG-2124, QTBUG-20482, QTBUG-41361, QTBUG-40153, QTBUG-35479, QTBUG-1628, QTBUG-42989, QTBUG-34861, QTBUG-46767, QTBUG-25114, QTBUG-24672, QTBUG-23524 (WIP), QTBUG-56088, QTBUG-42189, -QTBUG-39285 +QTBUG-39285, QTBUG-18173, QTBUG-28968, QTBUG-34336, QTBUG-40974, QTBUG-44286 Unless you use QMake and QDoc porting to Katie or even supporting it along with Qt4 in the same codebase is trivial and requires only minor changes because diff --git a/src/core/io/qfsfileengine.cpp b/src/core/io/qfsfileengine.cpp index ca9dca1ef..e25c51d08 100644 --- a/src/core/io/qfsfileengine.cpp +++ b/src/core/io/qfsfileengine.cpp @@ -45,12 +45,12 @@ #include "qdatetime.h" #include "qdiriterator.h" #include "qset.h" -#include +#include "qdebug.h" +#include "qcore_unix_p.h" #ifndef QT_NO_FSFILEENGINE #include -#include "qcore_unix_p.h" #include #include diff --git a/src/core/io/qiodevice.cpp b/src/core/io/qiodevice.cpp index 70313b270..16afd5465 100644 --- a/src/core/io/qiodevice.cpp +++ b/src/core/io/qiodevice.cpp @@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE +#define QBYTEARRAY_MAX INT_MAX + #ifdef QIODEVICE_DEBUG void debugBinaryString(const QByteArray &input) { @@ -97,8 +99,10 @@ inline void debugBinaryString(const char *data, qint64 maxlen) #define CHECK_WRITABLE(function, returnType) \ do { \ if ((d->openMode & WriteOnly) == 0) { \ - if (d->openMode == NotOpen) \ + if (d->openMode == NotOpen) { \ + qWarning("QIODevice::"#function": device not open"); \ return returnType; \ + } \ qWarning("QIODevice::"#function": ReadOnly device"); \ return returnType; \ } \ @@ -107,8 +111,10 @@ inline void debugBinaryString(const char *data, qint64 maxlen) #define CHECK_READABLE(function, returnType) \ do { \ if ((d->openMode & ReadOnly) == 0) { \ - if (d->openMode == NotOpen) \ + if (d->openMode == NotOpen) { \ + qWarning("QIODevice::"#function": device not open"); \ return returnType; \ + } \ qWarning("QIODevice::"#function": WriteOnly device"); \ return returnType; \ } \ @@ -118,8 +124,7 @@ inline void debugBinaryString(const char *data, qint64 maxlen) */ QIODevicePrivate::QIODevicePrivate() : openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE), - pos(0), devicePos(0), seqDumpPos(0) - , pPos(&pos), pDevicePos(&devicePos) + pos(0), devicePos(0) , baseReadLineDataCalled(false) , firstRead(true) , accessMode(Unset) @@ -265,9 +270,10 @@ QIODevicePrivate::~QIODevicePrivate() \value NotOpen The device is not open. \value ReadOnly The device is open for reading. - \value WriteOnly The device is open for writing. + \value WriteOnly The device is open for writing. Note that this mode implies + Truncate. \value ReadWrite The device is open for reading and writing. - \value Append The device is opened in append mode, so that all data is + \value Append The device is opened in append mode so that all data is written to the end of the file. \value Truncate If possible, the device is truncated before it is opened. All earlier contents of the device are lost. @@ -582,7 +588,6 @@ void QIODevice::close() d->openMode = NotOpen; d->errorString.clear(); d->pos = 0; - d->seqDumpPos = 0; d->buffer.clear(); d->firstRead = true; } @@ -604,7 +609,7 @@ qint64 QIODevice::pos() const { Q_D(const QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::pos() == %d\n", this, int(d->pos)); + printf("%p QIODevice::pos() == %lld\n", this, d->pos); #endif return d->pos; } @@ -626,30 +631,34 @@ qint64 QIODevice::size() const /*! For random-access devices, this function sets the current position to \a pos, returning true on success, or false if an error occurred. - For sequential devices, the default behavior is to do nothing and - return false. + For sequential devices, the default behavior is to produce a warning + and return false. When subclassing QIODevice, you must call QIODevice::seek() at the start of your function to ensure integrity with QIODevice's - built-in buffer. The base implementation always returns true. + built-in buffer. \sa pos(), isSequential() */ bool QIODevice::seek(qint64 pos) { Q_D(QIODevice); + if (d->isSequential()) { + qWarning("QIODevice::seek: Cannot call seek on a sequential device"); + return false; + } if (d->openMode == NotOpen) { qWarning("QIODevice::seek: The device is not open"); return false; } if (pos < 0) { - qWarning("QIODevice::seek: Invalid pos: %d", int(pos)); + qWarning("QIODevice::seek: Invalid pos: %lld", pos); return false; } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n", - this, int(pos), int(d->pos), d->buffer.size()); + printf("%p QIODevice::seek(%lld), before: d->pos = %lld, d->buffer.size() = %lld\n", + this, pos, d->pos, d->buffer.size()); #endif qint64 offset = pos - d->pos; @@ -658,18 +667,17 @@ bool QIODevice::seek(qint64 pos) d->devicePos = pos; } - if (offset < 0 - || offset >= qint64(d->buffer.size())) + if (offset < 0 || offset >= d->buffer.size()) // When seeking backwards, an operation that is only allowed for // random-access devices, the buffer is cleared. The next read // operation will then refill the buffer. We can optimize this, if we // find that seeking backwards becomes a significant performance hit. d->buffer.clear(); else if (!d->buffer.isEmpty()) - d->buffer.skip(int(offset)); + d->buffer.skip(offset); #if defined QIODEVICE_DEBUG - printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos), + printf("%p \tafter: d->pos == %lld, d->buffer.size() == %lld\n", this, d->pos, d->buffer.size()); #endif return true; @@ -691,8 +699,9 @@ bool QIODevice::atEnd() const { Q_D(const QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %d\n", this, (d->openMode == NotOpen || d->pos == size()) ? "true" : "false", - int(d->openMode), int(d->pos)); + printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %lld\n", this, + (d->openMode == NotOpen || d->pos == size()) ? "true" : "false", int(d->openMode), + d->pos); #endif return d->openMode == NotOpen || (d->buffer.isEmpty() && bytesAvailable() == 0); } @@ -766,15 +775,18 @@ qint64 QIODevice::read(char *data, qint64 maxSize) Q_D(QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, data, maxSize, d->pos, d->buffer.size()); #endif + const bool sequential = d->isSequential(); + // Short circuit for getChar() if (maxSize == 1) { int chint; while ((chint = d->buffer.getChar()) != -1) { - ++(*d->pPos); + if (!sequential) + ++d->pos; char c = char(uchar(chint)); if (c == '\r' && (d->openMode & Text)) @@ -784,28 +796,29 @@ qint64 QIODevice::read(char *data, qint64 maxSize) printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this, int(c), isprint(c) ? c : '?'); #endif + if (d->buffer.isEmpty()) + readData(data, 0); return qint64(1); } } CHECK_MAXLEN(read, qint64(-1)); qint64 readSoFar = 0; - bool moreToRead = true; - do { + bool madeBufferReadsOnly = true; + bool deviceAtEof = false; + char *readPtr = data; + forever { // Try reading from the buffer. - int lastReadChunkSize = d->buffer.read(data, maxSize); - if (lastReadChunkSize > 0) { - *d->pPos += lastReadChunkSize; - readSoFar += lastReadChunkSize; - // fast exit when satisfied by buffer - if (lastReadChunkSize == maxSize && !(d->openMode & Text)) - return readSoFar; - - data += lastReadChunkSize; - maxSize -= lastReadChunkSize; + qint64 bufferReadChunkSize = d->buffer.read(data, maxSize); + if (bufferReadChunkSize > 0) { + if (!sequential) + d->pos += bufferReadChunkSize; + readSoFar += bufferReadChunkSize; + data += bufferReadChunkSize; + maxSize -= bufferReadChunkSize; #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize, - int(readSoFar) - lastReadChunkSize); + printf("%p \treading %lld bytes from buffer into position %lld\n", this, + bufferReadChunkSize, readSoFar - bufferReadChunkSize); #endif } else { if (d->firstRead) { @@ -813,111 +826,99 @@ qint64 QIODevice::read(char *data, qint64 maxSize) // for fast pos updates. CHECK_READABLE(read, qint64(-1)); d->firstRead = false; - if (d->isSequential()) { - d->pPos = &d->seqDumpPos; - d->pDevicePos = &d->seqDumpPos; - } } + } - if (!maxSize) - return readSoFar; - - if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) { - // In buffered mode, we try to fill up the QIODevice buffer before - // we do anything else. - // buffer is empty at this point, try to fill it - int bytesToBuffer = QIODEVICE_BUFFERSIZE; - char *writePointer = d->buffer.reserve(bytesToBuffer); - - // Make sure the device is positioned correctly. - if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos)) - return readSoFar ? readSoFar : qint64(-1); - qint64 readFromDevice = readData(writePointer, bytesToBuffer); - d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice))); - - if (readFromDevice > 0) { - *d->pDevicePos += readFromDevice; + if (maxSize > 0 && !deviceAtEof) { + qint64 readFromDevice = 0; + // Make sure the device is positioned correctly. + if (sequential || d->pos == d->devicePos || seek(d->pos)) { + madeBufferReadsOnly = false; // fix readData attempt + if (maxSize >= QIODEVICE_BUFFERSIZE || (d->openMode & Unbuffered)) { + // Read big chunk directly to output buffer + readFromDevice = readData(data, maxSize); + deviceAtEof = (readFromDevice != maxSize); #if defined QIODEVICE_DEBUG - printf("%p \treading %d from device into buffer\n", this, int(readFromDevice)); + printf("%p \treading %lld bytes from device (total %lld)\n", this, + readFromDevice, readSoFar); #endif - - if (!d->buffer.isEmpty()) { - lastReadChunkSize = d->buffer.read(data, maxSize); - readSoFar += lastReadChunkSize; - data += lastReadChunkSize; - maxSize -= lastReadChunkSize; - *d->pPos += lastReadChunkSize; + if (readFromDevice > 0) { + readSoFar += readFromDevice; + data += readFromDevice; + maxSize -= readFromDevice; + if (!sequential) { + d->pos += readFromDevice; + d->devicePos += readFromDevice; + } + } + } else { + const qint64 bytesToBuffer = QIODEVICE_BUFFERSIZE; + // Try to fill QIODevice buffer by single read + readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer); + deviceAtEof = (readFromDevice != bytesToBuffer); + d->buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice)); + if (readFromDevice > 0) { + if (!sequential) + d->devicePos += readFromDevice; #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from buffer at position %d\n", this, - lastReadChunkSize, int(readSoFar)); + printf("%p \treading %lld from device into buffer\n", this, + readFromDevice); #endif + continue; } } + } else { + readFromDevice = -1; } - } - // If we need more, try reading from the device. - if (maxSize > 0) { - // Make sure the device is positioned correctly. - if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos)) - return readSoFar ? readSoFar : qint64(-1); - qint64 readFromDevice = readData(data, maxSize); -#if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar)); -#endif - if (readFromDevice == -1 && readSoFar == 0) { + if (readFromDevice < 0 && readSoFar == 0) { // error and we haven't read anything: return immediately - return -1; - } - if (readFromDevice > 0) { - lastReadChunkSize += int(readFromDevice); - readSoFar += readFromDevice; - data += readFromDevice; - maxSize -= readFromDevice; - *d->pPos += readFromDevice; - *d->pDevicePos += readFromDevice; + return qint64(-1); } } - // Best attempt has been made to read data, don't try again except for text mode adjustment below - moreToRead = false; - if (readSoFar && d->openMode & Text) { - char *readPtr = data - lastReadChunkSize; + if ((d->openMode & Text) && readPtr < data) { const char *endPtr = data; - if (readPtr < endPtr) { - // optimization to avoid initial self-assignment - while (*readPtr != '\r') { - if (++readPtr == endPtr) - return readSoFar; - } - - char *writePtr = readPtr; - - while (readPtr < endPtr) { - char ch = *readPtr++; - if (ch != '\r') - *writePtr++ = ch; - else { - --readSoFar; - --data; - ++maxSize; - } - } - - // Make sure we get more data if there is room for more. This - // is very important for when someone seeks to the start of a - // '\r\n' and reads one character - they should get the '\n'. - moreToRead = (readPtr != writePtr); + // optimization to avoid initial self-assignment + while (*readPtr != '\r') { + if (++readPtr == endPtr) + break; } + + char *writePtr = readPtr; + + while (readPtr < endPtr) { + char ch = *readPtr++; + if (ch != '\r') + *writePtr++ = ch; + else { + --readSoFar; + --data; + ++maxSize; + } + } + + // Make sure we get more data if there is room for more. This + // is very important for when someone seeks to the start of a + // '\r\n' and reads one character - they should get the '\n'. + readPtr = data; + continue; } - } while (moreToRead); + + break; + } #if defined QIODEVICE_DEBUG - printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this, - int(readSoFar), int(d->pos), d->buffer.size()); + printf("%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n", this, + readSoFar, d->pos, d->buffer.size()); debugBinaryString(data - readSoFar, readSoFar); #endif + if (madeBufferReadsOnly && d->buffer.isEmpty()) { + d->buffer.clear(); + readData(data, 0); + } + return readSoFar; } @@ -939,15 +940,15 @@ QByteArray QIODevice::read(qint64 maxSize) CHECK_MAXLEN(read, result); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n", - this, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, maxSize, d->pos, d->buffer.size()); #else Q_UNUSED(d); #endif - if (maxSize != qint64(int(maxSize))) { + if (quint64(maxSize) >= QBYTEARRAY_MAX) { qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); - maxSize = INT_MAX; + maxSize = QBYTEARRAY_MAX - 1; } qint64 readBytes = 0; @@ -989,33 +990,43 @@ QByteArray QIODevice::readAll() { Q_D(QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n", - this, int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n", + this, d->pos, d->buffer.size()); #endif QByteArray result; qint64 readBytes = 0; + const bool sequential = d->isSequential(); // flush internal read buffer if (!(d->openMode & Text) && !d->buffer.isEmpty()) { + if (quint64(d->buffer.size()) >= QBYTEARRAY_MAX) + return QByteArray(); result = d->buffer.readAll(); readBytes = result.size(); - d->pos += readBytes; + if (!sequential) + d->pos += readBytes; } qint64 theSize; - if (d->isSequential() || (theSize = size()) == 0) { + if (sequential || (theSize = size()) == 0) { // Size is unknown, read incrementally. qint64 readResult; do { - result.resize(result.size() + QIODEVICE_BUFFERSIZE); - readResult = read(result.data() + readBytes, result.size() - readBytes); + if (quint64(readBytes) + QIODEVICE_BUFFERSIZE >= QBYTEARRAY_MAX) { + // If resize would fail, don't read more, return what we have. + break; + } + result.resize(readBytes + QIODEVICE_BUFFERSIZE); + readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE); if (readResult > 0 || readBytes == 0) readBytes += readResult; } while (readResult > 0); } else { // Read it all in one go. // If resize fails, don't read anything. + if (quint64(readBytes + theSize - d->pos) >= QBYTEARRAY_MAX) + return QByteArray(); result.resize(int(readBytes + theSize - d->pos)); readBytes += read(result.data() + readBytes, result.size() - readBytes); } @@ -1073,8 +1084,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLine(%p, %d), d->pos = %d, d->buffer.size() = %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, data, maxSize, d->pos, d->buffer.size()); #endif // Leave room for a '\0' @@ -1085,11 +1096,13 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) qint64 readSoFar = 0; if (!d->buffer.isEmpty()) { readSoFar = d->buffer.readLine(data, maxSize); + if (d->buffer.isEmpty()) + readData(data, 0); if (!sequential) d->pos += readSoFar; #if defined QIODEVICE_DEBUG - printf("%p \tread from buffer: %d bytes, last character read: %hhx\n", this, - int(readSoFar), data[int(readSoFar) - 1]); + printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", this, + readSoFar, data[readSoFar - 1]); if (readSoFar) debugBinaryString(data, int(readSoFar)); #endif @@ -1111,8 +1124,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) d->baseReadLineDataCalled = false; qint64 readBytes = readLineData(data + readSoFar, maxSize - readSoFar); #if defined QIODEVICE_DEBUG - printf("%p \tread from readLineData: %d bytes, readSoFar = %d bytes\n", this, - int(readBytes), int(readSoFar)); + printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", this, + readBytes, readSoFar); if (readBytes > 0) { debugBinaryString(data, int(readSoFar + readBytes)); } @@ -1139,8 +1152,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p \treturning %d, d->pos = %d, d->buffer.size() = %d, size() = %d\n", - this, int(readSoFar), int(d->pos), d->buffer.size(), int(size())); + printf("%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n", + this, readSoFar, d->pos, d->buffer.size(), size()); debugBinaryString(data, int(readSoFar)); #endif return readSoFar; @@ -1164,15 +1177,15 @@ QByteArray QIODevice::readLine(qint64 maxSize) CHECK_MAXLEN(readLine, result); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n", - this, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readLine(%lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, maxSize, d->pos, d->buffer.size()); #else Q_UNUSED(d); #endif - if (maxSize > INT_MAX) { + if (quint64(maxSize) >= QBYTEARRAY_MAX) { qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); - maxSize = INT_MAX; + maxSize = QBYTEARRAY_MAX - 1; } result.resize(int(maxSize)); @@ -1180,7 +1193,7 @@ QByteArray QIODevice::readLine(qint64 maxSize) if (!result.size()) { // If resize fails or maxSize == 0, read incrementally if (maxSize == 0) - maxSize = INT_MAX; + maxSize = QBYTEARRAY_MAX - 1; // The first iteration needs to leave an extra byte for the terminating null result.resize(1); @@ -1237,8 +1250,8 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLineData(%p, %d), d->pos = %d, d->buffer.size() = %d, returns %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size()), int(readSoFar)); + printf("%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, " + "returns %lld\n", this, data, maxSize, d->pos, d->buffer.size(), readSoFar); #endif if (lastReadReturn != 1 && readSoFar == 0) return isSequential() ? lastReadReturn : -1; @@ -1381,7 +1394,8 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize) return readBytes; buffer.ungetBlock(data, readBytes); - *pPos -= readBytes; + if (!isSequential()) + pos -= readBytes; return readBytes; } @@ -1396,7 +1410,8 @@ QByteArray QIODevicePrivate::peek(qint64 maxSize) return result; buffer.ungetBlock(result.constData(), result.size()); - *pPos -= result.size(); + if (!isSequential()) + pos -= result.size(); return result; } @@ -1569,6 +1584,9 @@ QString QIODevice::errorString() const all the requested information was read and therefore does not retry reading if there was a problem. + This function might be called with a maxSize of 0, which can be used to + perform post-reading operations. + \sa read() readLine() writeData() */ diff --git a/src/core/io/qiodevice_p.h b/src/core/io/qiodevice_p.h index 643b0f8eb..199f87317 100644 --- a/src/core/io/qiodevice_p.h +++ b/src/core/io/qiodevice_p.h @@ -80,13 +80,13 @@ public: first = buf; len = 0; } - int size() const { + qint64 size() const { return len; } bool isEmpty() const { return len == 0; } - void skip(const int n) { + void skip(const qint64 n) { if (n >= len) { clear(); } else { @@ -102,25 +102,25 @@ public: first++; return ch; } - int read(char* target, const int size) { - const int r = qMin(size, len); + qint64 read(char* target, const qint64 size) { + const qint64 r = qMin(size, len); memcpy(target, first, r); len -= r; first += r; return r; } - int peek(char* target, const int size) { - const int r = qMin(size, len); + qint64 peek(char* target, const qint64 size) { + const qint64 r = qMin(size, len); memcpy(target, first, r); return r; } - char* reserve(const int size) { + char* reserve(const qint64 size) { makeSpace(size + len, freeSpaceAtEnd); char* writePtr = first + len; len += size; return writePtr; } - void chop(const int size) { + void chop(const qint64 size) { if (size >= len) { clear(); } else { @@ -133,15 +133,15 @@ public: clear(); return QByteArray(f, l); } - int readLine(char* target, int size) { - int r = qMin(size, len); + qint64 readLine(char* target, qint64 size) { + qint64 r = qMin(size, len); char* eol = static_cast(memchr(first, '\n', r)); if (eol) r = 1+(eol-first); memcpy(target, first, r); len -= r; first += r; - return int(r); + return r; } bool canReadLine() const { return memchr(first, '\n', len); @@ -155,7 +155,7 @@ public: len++; *first = c; } - void ungetBlock(const char* block, int size) { + void ungetBlock(const char* block, qint64 size) { if ((first - buf) < size) { // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer makeSpace(len + size, freeSpaceAtStart); @@ -187,7 +187,7 @@ private: } // length of the unread data - int len; + qint64 len; // start of the unread data char* first; // the allocated buffer @@ -213,10 +213,6 @@ public: QIODevicePrivateLinearBuffer buffer; qint64 pos; qint64 devicePos; - // these three are for fast position updates during read, avoiding isSequential test - qint64 seqDumpPos; - qint64 *pPos; - qint64 *pDevicePos; bool baseReadLineDataCalled; bool firstRead; diff --git a/src/core/io/qprocess.cpp b/src/core/io/qprocess.cpp index 400806d88..07a92c0bb 100644 --- a/src/core/io/qprocess.cpp +++ b/src/core/io/qprocess.cpp @@ -39,11 +39,22 @@ ** ****************************************************************************/ + +#include "qprocess.h" +#include "qprocess_p.h" +#include +#include +#include +#include +#include +#include +#include +#include + //#define QPROCESS_DEBUG #if defined QPROCESS_DEBUG -#include -#include + #include #include @@ -82,17 +93,7 @@ QT_END_NAMESPACE #endif -#include "qprocess.h" -#include "qprocess_p.h" - -#include -#include -#include -#include -#include - #ifndef QT_NO_PROCESS - extern char **environ; QT_BEGIN_NAMESPACE @@ -1566,8 +1567,7 @@ bool QProcess::waitForBytesWritten(int msecs) bool started = waitForStarted(msecs); if (!started) return false; - if (msecs != -1) - msecs -= stopWatch.elapsed(); + msecs = qt_timeout_value(msecs, stopWatch.elapsed()); } return d->waitForBytesWritten(msecs); @@ -1603,8 +1603,7 @@ bool QProcess::waitForFinished(int msecs) bool started = waitForStarted(msecs); if (!started) return false; - if (msecs != -1) - msecs -= stopWatch.elapsed(); + msecs = qt_timeout_value(msecs, stopWatch.elapsed()); } return d->waitForFinished(msecs); @@ -1646,6 +1645,8 @@ void QProcess::setupChildProcess() qint64 QProcess::readData(char *data, qint64 maxlen) { Q_D(QProcess); + if (!maxlen) + return 0; QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) ? &d->errorReadBuffer : &d->outputReadBuffer; diff --git a/src/core/io/qprocess_unix.cpp b/src/core/io/qprocess_unix.cpp index f32e4f458..1cbcb5127 100644 --- a/src/core/io/qprocess_unix.cpp +++ b/src/core/io/qprocess_unix.cpp @@ -862,19 +862,6 @@ static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); } -/* - Returns the difference between msecs and elapsed. If msecs is -1, - however, -1 is returned. -*/ -static int qt_timeout_value(int msecs, int elapsed) -{ - if (msecs == -1) - return -1; - - int timeout = msecs - elapsed; - return timeout < 0 ? 0 : timeout; -} - bool QProcessPrivate::waitForStarted(int msecs) { Q_Q(QProcess); diff --git a/src/core/kernel/qcore_unix_p.h b/src/core/kernel/qcore_unix_p.h index e1ec291b9..773edec4b 100644 --- a/src/core/kernel/qcore_unix_p.h +++ b/src/core/kernel/qcore_unix_p.h @@ -338,6 +338,21 @@ union qt_semun { unsigned short *array; /* array for GETALL, SETALL */ }; + +/* + Returns the difference between msecs and elapsed. If msecs is -1, + however, -1 is returned. +*/ +static int qt_timeout_value(int msecs, int elapsed) +{ + if (msecs == -1) + return -1; + + int timeout = msecs - elapsed; + return timeout < 0 ? 0 : timeout; +} + + QT_END_NAMESPACE #endif