OSDN Git Service

QIODevice upstream fixes
authorIvailo Monev <xakepa10@laimg.moc>
Sun, 19 May 2019 02:06:26 +0000 (02:06 +0000)
committerIvailo Monev <xakepa10@laimg.moc>
Sun, 19 May 2019 02:06:26 +0000 (02:06 +0000)
this includes upstream commits:
https://github.com/qt/qtbase/commit/0c748fb7b109244c03eebbceb400db53af95974c
https://github.com/qt/qtbase/commit/06632928afbd44b13d333f390bc50403e63f87a4
https://github.com/qt/qtbase/commit/85da1625e47cadf0b41e24863e8988e771e50943
https://github.com/qt/qtbase/commit/c70658d301e274c3aaa1fb6cebe2a5e56db1277
https://github.com/qt/qtbase/commit/a373ffcda9b2e7b38509dcb2e772b86d67a72c80
https://github.com/qt/qtbase/commit/ed0c0070f9b05c647019270dfc42073d071c830a
https://github.com/qt/qtbase/commit/35ee5349f2f549d5fe9d9bd57cef7af0047ee2d4
https://github.com/qt/qtbase/commit/f40cf77b0fa1cd5353ca866a7a5799da9f303081
https://github.com/qt/qtbase/commit/7c149dd86944b3669420832b2b14fac00327d4b7
https://github.com/qt/qtbase/commit/84b739158d5fdc356e5c6c963ba740fd081db82e
https://github.com/qt/qtbase/commit/ada8f1985d1f04440fca97894192748d98e47441
https://github.com/qt/qtbase/commit/310b7ef010f524e8d3cde5605cd495a4ffed5862
https://github.com/qt/qtbase/commit/05d980664fd3958add575712faf2abbb12b20857
https://github.com/qt/qtbase/commit/1ce203d05a952f039105d30968daf2eacae66be8
https://github.com/qt/qtbase/commit/a9c398096bcb342e7d7b1cec6137b0ee8d05872e
https://github.com/qt/qtbase/commit/5221ae5f424f24000d877d2a4394e2d75a052cca
https://github.com/qt/qtbase/commit/fe1cbe9ca78619b54b08e4ec1155d7e6e4e0640a
https://github.com/qt/qtbase/commit/81e69ffdbac1e6f2066c2de3e5cfecbb923f2b15

Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
README
src/core/io/qfsfileengine.cpp
src/core/io/qiodevice.cpp
src/core/io/qiodevice_p.h
src/core/io/qprocess.cpp
src/core/io/qprocess_unix.cpp
src/core/kernel/qcore_unix_p.h

diff --git a/README b/README
index ca79c74..8470d9f 100644 (file)
--- 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
index ca9dca1..e25c51d 100644 (file)
 #include "qdatetime.h"
 #include "qdiriterator.h"
 #include "qset.h"
-#include <QtCore/qdebug.h>
+#include "qdebug.h"
+#include "qcore_unix_p.h"
 
 #ifndef QT_NO_FSFILEENGINE
 
 #include <errno.h>
-#include "qcore_unix_p.h"
 #include <stdio.h>
 #include <stdlib.h>
 
index 70313b2..16afd54 100644 (file)
@@ -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;
-                }
+            // optimization to avoid initial self-assignment
+            while (*readPtr != '\r') {
+                if (++readPtr == endPtr)
+                    break;
+            }
 
-                char *writePtr = readPtr;
+            char *writePtr = readPtr;
 
-                while (readPtr < endPtr) {
-                    char ch = *readPtr++;
-                    if (ch != '\r')
-                        *writePtr++ = ch;
-                    else {
-                        --readSoFar;
-                        --data;
-                        ++maxSize;
-                    }
+            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);
             }
+
+            // 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()
 */
 
index 643b0f8..199f873 100644 (file)
@@ -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<char*>(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;
 
index 400806d..07a92c0 100644 (file)
 **
 ****************************************************************************/
 
-//#define QPROCESS_DEBUG
 
-#if defined QPROCESS_DEBUG
+#include "qprocess.h"
+#include "qprocess_p.h"
 #include <qdebug.h>
 #include <qstring.h>
+#include <qbytearray.h>
+#include <qelapsedtimer.h>
+#include <qcoreapplication.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+#include <qcore_unix_p.h>
+
+//#define QPROCESS_DEBUG
+
+#if defined QPROCESS_DEBUG
+
 #include <ctype.h>
 #include <errno.h>
 
@@ -82,17 +93,7 @@ QT_END_NAMESPACE
 
 #endif
 
-#include "qprocess.h"
-#include "qprocess_p.h"
-
-#include <qbytearray.h>
-#include <qelapsedtimer.h>
-#include <qcoreapplication.h>
-#include <qsocketnotifier.h>
-#include <qtimer.h>
-
 #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;
index f32e4f4..1cbcb51 100644 (file)
@@ -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);
index e1ec291..773edec 100644 (file)
@@ -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