From 009f01107fd062c1cd478fc9dbf20d927ff9c459 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 16 Nov 2009 18:23:28 +0100 Subject: configure.exe: fix when configured with -openssl-linked before, when configured with -openssl-linked, configure.exe hang, because of the following: We were checking for XQMAKESPEC via something like 'dictionary["XQMAKESPEC"] == "someValue"' , which added the XQMAKESPEC value to the dictionary. Later (line 3030), we checked whether XQMAKESPEC was set (which was now true), and we used the value although it was empty. Reviewed-by: Thiago Macieira Reviewed-by: Denis Dzyubenko --- configure.exe | Bin 1173504 -> 1174528 bytes tools/configure/configureapp.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.exe b/configure.exe index 7fe4a93..2c126df 100755 Binary files a/configure.exe and b/configure.exe differ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 735e030..3cd25ae 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2595,7 +2595,7 @@ void Configure::generateOutputVars() if (!opensslLibs.isEmpty()) qmakeVars += opensslLibs; else if (dictionary[ "OPENSSL" ] == "linked") { - if(dictionary[ "XQMAKESPEC" ].startsWith("symbian") ) + if(dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("symbian") ) qmakeVars += QString("OPENSSL_LIBS = -llibssl -llibcrypto"); else qmakeVars += QString("OPENSSL_LIBS = -lssleay32 -llibeay32"); -- cgit v0.12 From 1e6180c1de906864d2d6d73a9e18ed67574d4ed8 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 17 Nov 2009 12:56:00 +0100 Subject: qttracerelay: Handle wrong command line parameters Task-number: QTBUG-5550 Reviewed-by: TrustMe --- tools/qttracereplay/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp index 1d21a21..e62cf2c 100644 --- a/tools/qttracereplay/main.cpp +++ b/tools/qttracereplay/main.cpp @@ -162,6 +162,12 @@ int main(int argc, char **argv) return 1; } + QFile file(argv[1]); + if (!file.exists()) { + printf("%s does not exist\n", argv[1]); + return 1; + } + ReplayWidget *widget = new ReplayWidget(argv[1]); widget->show(); -- cgit v0.12 From 6f5fb0be85b1d7cc9f93b615b5034c882e946301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 12:36:48 +0100 Subject: There should only be one write buffer at a time in QFile To be sure, we should explicitly use the size of that buffer and not the whole QRingBuffer when flushing the data. With this change, we make violations of the one-buffer-rule explicitly fail on flush(), but we avoid corrupting data and reading past the buffer's end. Reviewed-by: Markus Goetz --- src/corelib/io/qfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index c9b2603..d4077bc 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1339,7 +1339,7 @@ QFile::setPermissions(const QString &fileName, Permissions permissions) static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer) { - qint64 ret = engine->write(buffer->readPointer(), buffer->size()); + qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize()); if (ret > 0) buffer->free(ret); return ret; -- cgit v0.12 From d5eb850f8c2524aa5573bb4e672b195724e5b5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 12:48:06 +0100 Subject: Remove needless loop in QIODevice::seek Either the buffer has more data than is being skipped and it can be cleared or it doesn't and we must skip it. If the total size of QRingBuffer exceeds INT_MAX there'll be bigger problems (e.g., QRingBuffer::size() will overflow) that can only be handled there and there's no point trying to work around them here. Reviewed-by: Markus Goetz --- src/corelib/io/qiodevice.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 4494d2a..856d737 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -619,7 +619,8 @@ qint64 QIODevice::size() const */ bool QIODevice::seek(qint64 pos) { - if (d_func()->openMode == NotOpen) { + Q_D(QIODevice); + if (d->openMode == NotOpen) { qWarning("QIODevice::seek: The device is not open"); return false; } @@ -628,7 +629,6 @@ bool QIODevice::seek(qint64 pos) return false; } - Q_D(QIODevice); #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()); @@ -640,21 +640,16 @@ bool QIODevice::seek(qint64 pos) d->devicePos = pos; } - if (offset > 0 && !d->buffer.isEmpty()) { - // When seeking forwards, we need to pop bytes off the front of the - // buffer. - do { - int bytesToSkip = int(qMin(offset, INT_MAX)); - d->buffer.skip(bytesToSkip); - offset -= bytesToSkip; - } while (offset > 0); - } else if (offset < 0) { + if (offset < 0 + || offset >= qint64(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)); + #if defined QIODEVICE_DEBUG printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos), d->buffer.size()); -- cgit v0.12 From 98a05681851db9d88b1364af52be543715fbe306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 13:07:53 +0100 Subject: Fix QIODevice::getChar optimization In Text mode there would be a huge penalty on each '\r' found even if the internal buffer was not exhausted, because we would repeatedly remove the '\r' from the buffer and put it back it. Before following through to the unoptimized code, anyway. Instead, we now loop over the internal buffer until we find a suitable character. Reduced code duplication by having QIODevice::getChar directly call QIODevice::read and letting compilers do their job. Reviewed-by: Markus Goetz --- src/corelib/io/qiodevice.cpp | 58 +++++++++----------------------------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 856d737..7ee65e1 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -757,22 +757,20 @@ qint64 QIODevice::read(char *data, qint64 maxSize) // Short circuit for getChar() if (maxSize == 1) { - int chint = d->buffer.getChar(); - if (chint != -1) { + int chint; + while ((chint = d->buffer.getChar()) != -1) { + if (!sequential) + ++d->pos; + char c = char(uchar(chint)); - if (c == '\r' && (d->openMode & Text)) { - d->buffer.ungetChar(c); - } else { - if (data) - *data = c; - if (!sequential) - ++d->pos; + if (c == '\r' && (d->openMode & Text)) + continue; + *data = c; #if defined QIODEVICE_DEBUG - printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this, - int(c), isprint(c) ? c : '?'); + printf("%p \tread 0x%hhx (%c) returning 1 (shortcut)\n", this, + int(c), isprint(c) ? c : '?'); #endif - return qint64(1); - } + return qint64(1); } } @@ -1379,40 +1377,8 @@ bool QIODevicePrivate::putCharHelper(char c) */ bool QIODevice::getChar(char *c) { - Q_D(QIODevice); - const OpenMode openMode = d->openMode; - if (!(openMode & ReadOnly)) { - if (openMode == NotOpen) - qWarning("QIODevice::getChar: Closed device"); - else - qWarning("QIODevice::getChar: WriteOnly device"); - return false; - } - - // Shortcut for QIODevice::read(c, 1) - QRingBuffer *buffer = &d->buffer; - const int chint = buffer->getChar(); - if (chint != -1) { - char ch = char(uchar(chint)); - if ((openMode & Text) && ch == '\r') { - buffer->ungetChar(ch); - } else { - if (c) - *c = ch; - if (!d->isSequential()) - ++d->pos; - return true; - } - } - - // Fall back to read(). char ch; - if (read(&ch, 1) == 1) { - if (c) - *c = ch; - return true; - } - return false; + return (1 == read(c ? c : &ch, 1)); } /*! -- cgit v0.12 From 72ee915bb0465549b7ca8e62d2af146cc44fdeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 16:11:09 +0100 Subject: Fix regression introduced in c08e708037d33271825ce6a6a1ac640e96b70c36 When writing nothing to a file, not actually writing anything is not an error. Also, from a change introduced in the same commit, there is no point in checking for EOF when writing. Task-number: QTBUG-5847 Reviewed-by: Olivier Goffart --- src/corelib/io/qfsfileengine.cpp | 6 ++---- tests/auto/qfile/tst_qfile.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 9ab831f..3cf9b7e 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -762,12 +762,10 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) // Buffered stdlib mode. size_t result; - bool eof; do { result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); writtenBytes += result; - eof = feof(fh); - } while (!eof && (result == 0 ? errno == EINTR : writtenBytes < len)); + } while (result == 0 ? errno == EINTR : writtenBytes < len); } else if (fd != -1) { // Unbuffered stdio mode. @@ -783,7 +781,7 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) || (result > 0 && (writtenBytes += result) < len)); } - if (writtenBytes == 0) { + if (len && writtenBytes == 0) { writtenBytes = -1; q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno)); } diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index b3d6fd9..d545909 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -210,6 +210,7 @@ private slots: void task167217(); void openDirectory(); + void writeNothing(); public: // disabled this test for the moment... it hangs @@ -2840,5 +2841,16 @@ void tst_QFile::openStandardStreams() } } +void tst_QFile::writeNothing() +{ + for (int i = 0; i < 3; ++i) { + QFile file("file.txt"); + QVERIFY( openFile(file, QIODevice::WriteOnly | QIODevice::Unbuffered, FileType(i)) ); + QVERIFY( 0 == file.write((char *)0, 0) ); + QCOMPARE( file.error(), QFile::NoError ); + closeFile(file); + } +} + QTEST_MAIN(tst_QFile) #include "tst_qfile.moc" -- cgit v0.12 From 0626fc90d79d114402a7cf8727c63d489f13d8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 17:06:27 +0100 Subject: Improve reliability of QFile test readAllStdin ... by catching failure to launch separate process earlier. --- tests/auto/qfile/tst_qfile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index d545909..e4e63ff 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -751,6 +751,7 @@ void tst_QFile::readAllStdin() QProcess process; process.start("stdinprocess/stdinprocess all"); + QVERIFY( process.waitForStarted() ); for (int i = 0; i < 5; ++i) { QTest::qWait(1000); process.write(lotsOfData); -- cgit v0.12 From 1e6b424b692b20dcfec920f8d3563e520ec1ff05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Mon, 16 Nov 2009 17:38:18 +0100 Subject: Removing unnecessary chunking and stat'ing when reading QIODevice Chunk size increased to QIODEVICE_BUFFERSIZE (currently 16k) where chunking is still needed. Namely, on sequential devices and when QByteArray is unable to allocate a large enough buffer. This is necessary for backward compatibility Improved validation and prevention of overflow in maxSize argument. Updated autotest that relied on a null QByteArray when no data was available and no errors were found. The only guarantee we should be providing in this case is an empty result -- even though that behavior is preserved for the time being. Affected functions: * QIODevice::read(qint64 maxSize) Chunking will still happen for large maxSize (i.e., QByteArray resize fails), where it could be used as a synonym for QIODevice::readAll(). No stat'ing performed. Read from device continues for as long as it is successful. Stops if an error occurs or if we get less data than requested. * QIODevice::readAll() Chunking is performed for sequential devices where total size wouldn't be known beforehand. For sequential devices, reading continues as long as data is returned, even if less than requested. Non-sequential devices will be stat'ed once. If QIODevice::size returns 0, this is taken to mean unknown size and chunking is performed. Otherwise, a single read request is made for the specified size. On failure to resize QByteArray, nothing is returned. * QIODevice::readLine(qint64 maxSize) Chunking is performed for maxSize == 0, or if we can't allocate a large enough buffer. No stat'ing performed at this level. Read from device continues until EOL is found, as long as we get all requested data. Task-number: QT-2347 Reviewed-by: Thiago Macieira Reviewed-by: Miikka Heikkinen --- src/corelib/io/qiodevice.cpp | 135 ++++++++++++++++++++++++----------------- tests/auto/qfile/tst_qfile.cpp | 4 +- 2 files changed, 83 insertions(+), 56 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 7ee65e1..e4e6a15 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -904,10 +904,10 @@ qint64 QIODevice::read(char *data, qint64 maxSize) QByteArray QIODevice::read(qint64 maxSize) { Q_D(QIODevice); - CHECK_MAXLEN(read, QByteArray()); - QByteArray tmp; - qint64 readSoFar = 0; - char buffer[4096]; + QByteArray result; + + 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())); @@ -915,16 +915,34 @@ QByteArray QIODevice::read(qint64 maxSize) Q_UNUSED(d); #endif - do { - qint64 bytesToRead = qMin(int(maxSize - readSoFar), int(sizeof(buffer))); - qint64 readBytes = read(buffer, bytesToRead); - if (readBytes <= 0) - break; - tmp.append(buffer, (int) readBytes); - readSoFar += readBytes; - } while (readSoFar < maxSize && bytesAvailable() > 0); + if (maxSize != qint64(int(maxSize))) { + qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); + maxSize = INT_MAX; + } - return tmp; + qint64 readBytes = 0; + if (maxSize) { + result.resize(int(maxSize)); + if (!result.size()) { + // If resize fails, read incrementally. + qint64 readResult; + do { + result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE))); + readResult = read(result.data() + readBytes, result.size() - readBytes); + if (readResult > 0 || readBytes == 0) + readBytes += readResult; + } while (readResult == QIODEVICE_BUFFERSIZE); + } else { + readBytes = read(result.data(), result.size()); + } + } + + if (readBytes <= 0) + result.clear(); + else + result.resize(int(readBytes)); + + return result; } /*! @@ -945,28 +963,30 @@ QByteArray QIODevice::readAll() this, int(d->pos), int(d->buffer.size())); #endif - QByteArray tmp; - if (d->isSequential() || size() == 0) { - // Read it in chunks. Use bytesAvailable() as an unreliable hint for - // sequential devices, but try to read 4K as a minimum. - int chunkSize = qMax(qint64(4096), bytesAvailable()); - qint64 totalRead = 0; - forever { - tmp.resize(tmp.size() + chunkSize); - qint64 readBytes = read(tmp.data() + totalRead, chunkSize); - tmp.chop(chunkSize - (readBytes < 0 ? 0 : readBytes)); - if (readBytes <= 0) - return tmp; - totalRead += readBytes; - chunkSize = qMax(qint64(4096), bytesAvailable()); - } + QByteArray result; + qint64 readBytes = 0; + if (d->isSequential() || (readBytes = 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 (readResult > 0 || readBytes == 0) + readBytes += readResult; + } while (readResult > 0); } else { // Read it all in one go. - tmp.resize(int(bytesAvailable())); - qint64 readBytes = read(tmp.data(), tmp.size()); - tmp.resize(readBytes < 0 ? 0 : int(readBytes)); + // If resize fails, don't read anything. + result.resize(int(readBytes - d->pos)); + readBytes = read(result.data(), result.size()); } - return tmp; + + if (readBytes <= 0) + result.clear(); + else + result.resize(int(readBytes)); + + return result; } /*! @@ -1115,11 +1135,9 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) QByteArray QIODevice::readLine(qint64 maxSize) { Q_D(QIODevice); - CHECK_MAXLEN(readLine, QByteArray()); - QByteArray tmp; - const int BufferGrowth = 4096; - qint64 readSoFar = 0; - qint64 readBytes = 0; + QByteArray result; + + CHECK_MAXLEN(readLine, result); #if defined QIODEVICE_DEBUG printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n", @@ -1128,25 +1146,34 @@ QByteArray QIODevice::readLine(qint64 maxSize) Q_UNUSED(d); #endif - do { - if (maxSize != 0) - tmp.resize(int(readSoFar + qMin(int(maxSize), BufferGrowth))); - else - tmp.resize(int(readSoFar + BufferGrowth)); - readBytes = readLine(tmp.data() + readSoFar, tmp.size() - readSoFar); - if (readBytes <= 0) - break; - - readSoFar += readBytes; - } while ((!maxSize || readSoFar < maxSize) && - readSoFar + 1 == tmp.size() && // +1 due to the ending null - tmp.at(readSoFar - 1) != '\n'); + if (maxSize > INT_MAX) { + qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit"); + maxSize = INT_MAX; + } - if (readSoFar == 0 && readBytes == -1) - tmp.clear(); // return Null if we found an error + result.resize(int(maxSize)); + qint64 readBytes = 0; + if (!result.size()) { + // If resize fails or maxSize == 0, read incrementally + if (maxSize == 0) + maxSize = INT_MAX; + qint64 readResult; + do { + result.resize(int(qMin(maxSize, result.size() + QIODEVICE_BUFFERSIZE))); + readResult = readLine(result.data() + readBytes, result.size() - readBytes); + if (readResult > 0 || readBytes == 0) + readBytes += readResult; + } while (readResult == QIODEVICE_BUFFERSIZE + && result[int(readBytes)] != '\n'); + } else + readBytes = readLine(result.data(), result.size()); + + if (readBytes <= 0) + result.clear(); else - tmp.resize(int(readSoFar)); - return tmp; + result.resize(readBytes); + + return result; } /*! diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index e4e63ff..cf46ce1 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -2491,13 +2491,13 @@ void tst_QFile::readEof() } QByteArray ret = file.read(10); - QVERIFY(ret.isNull()); + QVERIFY(ret.isEmpty()); QVERIFY(file.error() == QFile::NoError); QVERIFY(file.atEnd()); // Do it again to ensure that we get the same result ret = file.read(10); - QVERIFY(ret.isNull()); + QVERIFY(ret.isEmpty()); QVERIFY(file.error() == QFile::NoError); QVERIFY(file.atEnd()); } -- cgit v0.12 From 798ff84b2bd26da5ba2d01bf44e4a4d40dfcacac Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 17 Nov 2009 15:08:29 +0100 Subject: doc: Clarified function of setLayoutDirection() Task-number: QTBUG-5432 --- src/gui/kernel/qwidget.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 0d8da0c..754e7f5 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4677,8 +4677,10 @@ void QWidgetPrivate::resolveLayoutDirection() By default, this property is set to Qt::LeftToRight. When the layout direction is set on a widget, it will propagate to - the widget's children. Children added after the call to \c - setLayoutDirection() will not inherit the parent's layout + the widget's children, but not to a child that is a window and not + to a child for which setLayoutDirection() has been explicitly + called. Also, child widgets added \e after setLayoutDirection() + has been called for the parent do not inherit the parent's layout direction. \sa QApplication::layoutDirection -- cgit v0.12