summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/qhooks.cpp2
-rw-r--r--src/corelib/io/qfiledevice.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp2
-rw-r--r--src/corelib/io/qiodevice.cpp244
-rw-r--r--src/corelib/io/qiodevice.h5
-rw-r--r--src/corelib/io/qiodevice_p.h143
-rw-r--r--src/corelib/io/qprocess.cpp18
-rw-r--r--src/corelib/kernel/qcfsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp5
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp4
-rw-r--r--src/corelib/kernel/qppsobject.cpp3
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp1
-rw-r--r--src/corelib/kernel/qtranslator.cpp10
-rw-r--r--src/corelib/tools/qlocale.cpp21
-rw-r--r--src/corelib/tools/qlocale.h22
-rw-r--r--src/corelib/tools/qringbuffer_p.h2
-rw-r--r--src/dbus/qdbusconnection_p.h1
-rw-r--r--src/dbus/qdbusmetaobject.cpp4
-rw-r--r--src/dbus/qdbusserver.cpp3
-rw-r--r--src/dbus/qdbusservicewatcher.cpp4
-rw-r--r--src/dbus/qdbusutil.cpp8
-rw-r--r--src/gui/painting/qcolor.cpp3
-rw-r--r--src/gui/text/qstatictext.cpp21
-rw-r--r--src/gui/text/qstatictext_p.h50
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp8
-rw-r--r--src/network/socket/qabstractsocket.cpp15
-rw-r--r--src/network/ssl/qsslsocket.cpp4
-rw-r--r--src/tools/moc/moc.cpp2
-rw-r--r--tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp189
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp6
-rw-r--r--tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp12
-rw-r--r--tests/auto/other/toolsupport/tst_toolsupport.cpp2
33 files changed, 466 insertions, 358 deletions
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
index 40a7c88f13..88df9c2be9 100644
--- a/src/corelib/global/qhooks.cpp
+++ b/src/corelib/global/qhooks.cpp
@@ -61,7 +61,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = {
// The required sizes and offsets are tested in tests/auto/other/toolsupport.
// When this fails and the change was intentional, adjust the test and
// adjust this value here.
- 0
+ 1
};
Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index 4c5ed0aef6..e94da6de64 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -355,7 +355,7 @@ bool QFileDevice::atEnd() const
Q_D(const QFileDevice);
// If there's buffered data left, we're not at the end.
- if (!d->buffer.isEmpty())
+ if (!d->isBufferEmpty())
return false;
if (!isOpen())
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 8f6d9911e8..2f066aa37a 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -113,7 +113,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
// Find if an application other than Finder claims to know how to handle the package
QCFType<CFURLRef> application;
LSGetApplicationForURL(url,
- kLSRolesEditor|kLSRolesViewer|kLSRolesViewer,
+ kLSRolesEditor|kLSRolesViewer,
NULL,
&application);
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 64078b5c54..00b50af5ca 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -143,7 +143,9 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
*/
QIODevicePrivate::QIODevicePrivate()
: openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE),
- pos(0), devicePos(0)
+ pos(0), devicePos(0),
+ transactionPos(0),
+ transactionStarted(false)
, baseReadLineDataCalled(false)
, accessMode(Unset)
#ifdef QT_NO_QOBJECT
@@ -264,6 +266,12 @@ QIODevicePrivate::~QIODevicePrivate()
subclassing QIODevice, remember to bypass any buffer you may use
when the device is open in Unbuffered mode.
+ Usually, the incoming data stream from an asynchronous device is
+ fragmented, and chunks of data can arrive at arbitrary points in time.
+ To handle incomplete reads of data structures, use the transaction
+ mechanism implemented by QIODevice. See startTransaction() and related
+ functions for more details.
+
\sa QBuffer, QFile, QTcpSocket
*/
@@ -588,6 +596,8 @@ void QIODevice::close()
d->openMode = NotOpen;
d->errorString.clear();
d->pos = 0;
+ d->transactionStarted = false;
+ d->transactionPos = 0;
d->buffer.clear();
}
@@ -660,18 +670,8 @@ bool QIODevice::seek(qint64 pos)
this, pos, d->pos, d->buffer.size());
#endif
- qint64 offset = pos - d->pos;
- d->pos = pos;
d->devicePos = pos;
-
- 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
- d->buffer.skip(offset);
+ d->seekBuffer(pos);
#if defined QIODEVICE_DEBUG
printf("%p \tafter: d->pos == %lld, d->buffer.size() == %lld\n", this, d->pos,
@@ -681,6 +681,24 @@ bool QIODevice::seek(qint64 pos)
}
/*!
+ \internal
+*/
+void QIODevicePrivate::seekBuffer(qint64 newPos)
+{
+ const qint64 offset = newPos - pos;
+ pos = newPos;
+
+ if (offset < 0 || offset >= 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.
+ buffer.clear();
+ } else {
+ buffer.free(offset);
+ }
+}
+
+/*!
Returns \c true if the current read and write position is at the end
of the device (i.e. there is no more data available for reading on
the device); otherwise returns \c false.
@@ -695,7 +713,7 @@ bool QIODevice::seek(qint64 pos)
bool QIODevice::atEnd() const
{
Q_D(const QIODevice);
- const bool result = (d->openMode == NotOpen || (d->buffer.isEmpty()
+ const bool result = (d->openMode == NotOpen || (d->isBufferEmpty()
&& bytesAvailable() == 0));
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %lld\n", this,
@@ -740,7 +758,7 @@ qint64 QIODevice::bytesAvailable() const
Q_D(const QIODevice);
if (!d->isSequential())
return qMax(size() - d->pos, qint64(0));
- return d->buffer.size();
+ return d->buffer.size() - d->transactionPos;
}
/*! For buffered devices, this function returns the number of bytes
@@ -777,9 +795,10 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
#endif
const bool sequential = d->isSequential();
+ const bool keepDataInBuffer = sequential && d->transactionStarted;
// Short circuit for getChar()
- if (maxSize == 1) {
+ if (maxSize == 1 && !keepDataInBuffer) {
int chint;
while ((chint = d->buffer.getChar()) != -1) {
if (!sequential)
@@ -806,9 +825,13 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
char *readPtr = data;
forever {
// Try reading from the buffer.
- qint64 bufferReadChunkSize = d->buffer.read(data, maxSize);
+ qint64 bufferReadChunkSize = keepDataInBuffer
+ ? d->buffer.peek(data, maxSize, d->transactionPos)
+ : d->buffer.read(data, maxSize);
if (bufferReadChunkSize > 0) {
- if (!sequential)
+ if (keepDataInBuffer)
+ d->transactionPos += bufferReadChunkSize;
+ else if (!sequential)
d->pos += bufferReadChunkSize;
readSoFar += bufferReadChunkSize;
data += bufferReadChunkSize;
@@ -826,7 +849,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
// 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)) {
+ if ((maxSize >= QIODEVICE_BUFFERSIZE || (d->openMode & Unbuffered))
+ && !keepDataInBuffer) {
// Read big chunk directly to output buffer
readFromDevice = readData(data, maxSize);
deviceAtEof = (readFromDevice != maxSize);
@@ -844,7 +868,9 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
}
} else {
- const qint64 bytesToBuffer = QIODEVICE_BUFFERSIZE;
+ // Do not read more than maxSize on unbuffered devices
+ const qint64 bytesToBuffer = (d->openMode & Unbuffered)
+ ? qMin(maxSize, QIODEVICE_BUFFERSIZE) : QIODEVICE_BUFFERSIZE;
// Try to fill QIODevice buffer by single read
readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer);
deviceAtEof = (readFromDevice != bytesToBuffer);
@@ -907,10 +933,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
debugBinaryString(data - readSoFar, readSoFar);
#endif
- if (madeBufferReadsOnly && d->buffer.isEmpty()) {
- d->buffer.clear();
+ if (madeBufferReadsOnly && d->isBufferEmpty())
readData(data, 0);
- }
return readSoFar;
}
@@ -992,7 +1016,9 @@ QByteArray QIODevice::readAll()
qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
if (readBytes == 0) {
// Size is unknown, read incrementally.
- qint64 readChunkSize = qMax(d->buffer.size(), QIODEVICE_BUFFERSIZE);
+ qint64 readChunkSize = qMax(QIODEVICE_BUFFERSIZE,
+ d->isSequential() ? (d->buffer.size() - d->transactionPos)
+ : d->buffer.size());
qint64 readResult;
do {
if (readBytes + readChunkSize >= MaxByteArraySize) {
@@ -1077,21 +1103,35 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
--maxSize;
const bool sequential = d->isSequential();
+ const bool keepDataInBuffer = sequential && d->transactionStarted;
qint64 readSoFar = 0;
- if (!d->buffer.isEmpty()) {
- readSoFar = d->buffer.readLine(data, maxSize);
+ if (keepDataInBuffer) {
+ if (d->transactionPos < d->buffer.size()) {
+ // Peek line from the specified position
+ const qint64 i = d->buffer.indexOf('\n', maxSize, d->transactionPos);
+ readSoFar = d->buffer.peek(data, i >= 0 ? (i - d->transactionPos + 1) : maxSize,
+ d->transactionPos);
+ d->transactionPos += readSoFar;
+ if (d->transactionPos == d->buffer.size())
+ readData(data, 0);
+ }
+ } else if (!d->buffer.isEmpty()) {
+ // QRingBuffer::readLine() terminates the line with '\0'
+ readSoFar = d->buffer.readLine(data, maxSize + 1);
if (d->buffer.isEmpty())
readData(data,0);
if (!sequential)
d->pos += readSoFar;
+ }
+
+ if (readSoFar) {
#if defined QIODEVICE_DEBUG
printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", this,
readSoFar, data[readSoFar - 1]);
- if (readSoFar)
- debugBinaryString(data, int(readSoFar));
+ debugBinaryString(data, int(readSoFar));
#endif
- if (readSoFar && data[readSoFar - 1] == '\n') {
+ if (data[readSoFar - 1] == '\n') {
if (d->openMode & Text) {
// QRingBuffer::readLine() isn't Text aware.
if (readSoFar > 1 && data[readSoFar - 2] == '\r') {
@@ -1107,7 +1147,11 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
if (d->pos != d->devicePos && !sequential && !seek(d->pos))
return qint64(-1);
d->baseReadLineDataCalled = false;
- qint64 readBytes = readLineData(data + readSoFar, maxSize - readSoFar);
+ // Force base implementation for transaction on sequential device
+ // as it stores the data in internal buffer automatically.
+ qint64 readBytes = keepDataInBuffer
+ ? QIODevice::readLineData(data + readSoFar, maxSize - readSoFar)
+ : readLineData(data + readSoFar, maxSize - readSoFar);
#if defined QIODEVICE_DEBUG
printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", this,
readBytes, readSoFar);
@@ -1262,7 +1306,95 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize)
*/
bool QIODevice::canReadLine() const
{
- return d_func()->buffer.canReadLine();
+ Q_D(const QIODevice);
+ return d->buffer.indexOf('\n', d->buffer.size(),
+ d->isSequential() ? d->transactionPos : Q_INT64_C(0)) >= 0;
+}
+
+/*!
+ \since 5.7
+
+ Starts a new read transaction on the device.
+
+ Defines a restorable point within the sequence of read operations. For
+ sequential devices, read data will be duplicated internally to allow
+ recovery in case of incomplete reads. For random-access devices,
+ this function saves the current position. Call commitTransaction() or
+ rollbackTransaction() to finish the transaction.
+
+ \note Nesting transactions is not supported.
+
+ \sa commitTransaction(), rollbackTransaction()
+*/
+void QIODevice::startTransaction()
+{
+ Q_D(QIODevice);
+ if (d->transactionStarted) {
+ checkWarnMessage(this, "startTransaction", "Called while transaction already in progress");
+ return;
+ }
+ d->transactionPos = d->pos;
+ d->transactionStarted = true;
+}
+
+/*!
+ \since 5.7
+
+ Completes a read transaction.
+
+ For sequential devices, all data recorded in the internal buffer during
+ the transaction will be discarded.
+
+ \sa startTransaction(), rollbackTransaction()
+*/
+void QIODevice::commitTransaction()
+{
+ Q_D(QIODevice);
+ if (!d->transactionStarted) {
+ checkWarnMessage(this, "commitTransaction", "Called while no transaction in progress");
+ return;
+ }
+ if (d->isSequential())
+ d->buffer.free(d->transactionPos);
+ d->transactionStarted = false;
+ d->transactionPos = 0;
+}
+
+/*!
+ \since 5.7
+
+ Rolls back a read transaction.
+
+ Restores the input stream to the point of the startTransaction() call.
+ This function is commonly used to rollback the transaction when an
+ incomplete read was detected prior to committing the transaction.
+
+ \sa startTransaction(), commitTransaction()
+*/
+void QIODevice::rollbackTransaction()
+{
+ Q_D(QIODevice);
+ if (!d->transactionStarted) {
+ checkWarnMessage(this, "rollbackTransaction", "Called while no transaction in progress");
+ return;
+ }
+ if (!d->isSequential())
+ d->seekBuffer(d->transactionPos);
+ d->transactionStarted = false;
+ d->transactionPos = 0;
+}
+
+/*!
+ \since 5.7
+
+ Returns \c true if a transaction is in progress on the device, otherwise
+ \c false.
+
+ \sa startTransaction()
+*/
+bool QIODevice::isTransactionStarted() const
+{
+ return d_func()->transactionStarted;
}
/*!
@@ -1386,12 +1518,19 @@ qint64 QIODevice::write(const char *data)
If \a c was not previously read from the device, the behavior is
undefined.
+
+ \note This function is not available while a transaction is in progress.
*/
void QIODevice::ungetChar(char c)
{
Q_D(QIODevice);
CHECK_READABLE(read, Q_VOID);
+ if (d->transactionStarted) {
+ checkWarnMessage(this, "ungetChar", "Called while transaction is in progress");
+ return;
+ }
+
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::ungetChar(0x%hhx '%c')\n", this, c, isprint(c) ? c : '?');
#endif
@@ -1426,13 +1565,26 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
{
- qint64 readBytes = q_func()->read(data, maxSize);
- if (readBytes <= 0)
+ Q_Q(QIODevice);
+
+ if (transactionStarted) {
+ const qint64 savedTransactionPos = transactionPos;
+ const qint64 savedPos = pos;
+
+ qint64 readBytes = q->read(data, maxSize);
+
+ // Restore initial position
+ if (isSequential())
+ transactionPos = savedTransactionPos;
+ else
+ seekBuffer(savedPos);
return readBytes;
+ }
+
+ q->startTransaction();
+ qint64 readBytes = q->read(data, maxSize);
+ q->rollbackTransaction();
- buffer.ungetBlock(data, readBytes);
- if (!isSequential())
- pos -= readBytes;
return readBytes;
}
@@ -1441,14 +1593,26 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevicePrivate::peek(qint64 maxSize)
{
- QByteArray result = q_func()->read(maxSize);
+ Q_Q(QIODevice);
+
+ if (transactionStarted) {
+ const qint64 savedTransactionPos = transactionPos;
+ const qint64 savedPos = pos;
+
+ QByteArray result = q->read(maxSize);
- if (result.isEmpty())
+ // Restore initial position
+ if (isSequential())
+ transactionPos = savedTransactionPos;
+ else
+ seekBuffer(savedPos);
return result;
+ }
+
+ q->startTransaction();
+ QByteArray result = q->read(maxSize);
+ q->rollbackTransaction();
- buffer.ungetBlock(result.constData(), result.size());
- if (!isSequential())
- pos -= result.size();
return result;
}
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
index b62c8d266c..49f6848540 100644
--- a/src/corelib/io/qiodevice.h
+++ b/src/corelib/io/qiodevice.h
@@ -111,6 +111,11 @@ public:
QByteArray readLine(qint64 maxlen = 0);
virtual bool canReadLine() const;
+ void startTransaction();
+ void commitTransaction();
+ void rollbackTransaction();
+ bool isTransactionStarted() const;
+
qint64 write(const char *data, qint64 len);
qint64 write(const char *data);
inline qint64 write(const QByteArray &data)
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 56a89ab680..45f5219240 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -62,138 +62,6 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT int qt_subtract_from_timeout(int timeout, int elapsed);
-// This is QIODevice's read buffer, optimized for read(), isEmpty() and getChar()
-class QIODevicePrivateLinearBuffer
-{
-public:
- QIODevicePrivateLinearBuffer(int) : len(0), first(0), buf(0), capacity(0) {
- }
- ~QIODevicePrivateLinearBuffer() {
- delete [] buf;
- }
- void clear() {
- len = 0;
- delete [] buf;
- buf = 0;
- first = buf;
- capacity = 0;
- }
- qint64 size() const {
- return len;
- }
- bool isEmpty() const {
- return len == 0;
- }
- void skip(qint64 n) {
- if (n >= len) {
- clear();
- } else {
- len -= n;
- first += n;
- }
- }
- int getChar() {
- if (len == 0)
- return -1;
- int ch = uchar(*first);
- len--;
- first++;
- return ch;
- }
- qint64 read(char* target, qint64 size) {
- qint64 r = qMin(size, len);
- memcpy(target, first, r);
- len -= r;
- first += r;
- return r;
- }
- qint64 peek(char* target, qint64 size) {
- qint64 r = qMin(size, len);
- memcpy(target, first, r);
- return r;
- }
- char* reserve(qint64 size) {
- makeSpace(size + len, freeSpaceAtEnd);
- char* writePtr = first + len;
- len += size;
- return writePtr;
- }
- void chop(qint64 size) {
- if (size >= len) {
- clear();
- } else {
- len -= size;
- }
- }
- QByteArray readAll() {
- QByteArray retVal(first, len);
- clear();
- return retVal;
- }
- 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 r;
- }
- bool canReadLine() const {
- return memchr(first, '\n', len);
- }
- void ungetChar(char c) {
- if (first == buf) {
- // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
- makeSpace(len+1, freeSpaceAtStart);
- }
- first--;
- len++;
- *first = c;
- }
- 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);
- }
- first -= size;
- len += size;
- memcpy(first, block, size);
- }
-
-private:
- enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd};
- void makeSpace(size_t required, FreeSpacePos where) {
- size_t newCapacity = qMax(capacity, size_t(QIODEVICE_BUFFERSIZE));
- while (newCapacity < required)
- newCapacity *= 2;
- const size_t moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - size_t(len);
- if (newCapacity > capacity) {
- // allocate more space
- char* newBuf = new char[newCapacity];
- memmove(newBuf + moveOffset, first, len);
- delete [] buf;
- buf = newBuf;
- capacity = newCapacity;
- } else {
- // shift any existing data to make space
- memmove(buf + moveOffset, first, len);
- }
- first = buf + moveOffset;
- }
-
-private:
- // length of the unread data
- qint64 len;
- // start of the unread data
- char* first;
- // the allocated buffer
- char* buf;
- // allocated buffer size
- size_t capacity;
-};
-
class Q_CORE_EXPORT QIODevicePrivate
#ifndef QT_NO_QOBJECT
: public QObjectPrivate
@@ -208,9 +76,11 @@ public:
QIODevice::OpenMode openMode;
QString errorString;
- QIODevicePrivateLinearBuffer buffer;
+ QRingBuffer buffer;
qint64 pos;
qint64 devicePos;
+ qint64 transactionPos;
+ bool transactionStarted;
bool baseReadLineDataCalled;
virtual bool putCharHelper(char c);
@@ -228,6 +98,13 @@ public:
return accessMode == Sequential;
}
+ inline bool isBufferEmpty() const
+ {
+ return buffer.isEmpty() || (transactionStarted && isSequential()
+ && transactionPos == buffer.size());
+ }
+ void seekBuffer(qint64 newPos);
+
virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize);
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 823dc4c144..2392f7cbfd 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1395,15 +1395,17 @@ QProcess::ProcessChannel QProcess::readChannel() const
void QProcess::setReadChannel(ProcessChannel channel)
{
Q_D(QProcess);
+
+ if (d->transactionStarted) {
+ qWarning("QProcess::setReadChannel: Failed due to the active read transaction");
+ return;
+ }
+
if (d->processChannel != channel) {
- QByteArray buf = d->buffer.readAll();
- if (d->processChannel == QProcess::StandardOutput) {
- for (int i = buf.size() - 1; i >= 0; --i)
- d->stdoutChannel.buffer.ungetChar(buf.at(i));
- } else {
- for (int i = buf.size() - 1; i >= 0; --i)
- d->stderrChannel.buffer.ungetChar(buf.at(i));
- }
+ QRingBuffer *buffer = (d->processChannel == QProcess::StandardOutput)
+ ? &d->stdoutChannel.buffer
+ : &d->stderrChannel.buffer;
+ d->buffer.read(buffer->reserveFront(d->buffer.size()), d->buffer.size());
}
d->processChannel = channel;
}
diff --git a/src/corelib/kernel/qcfsocketnotifier.cpp b/src/corelib/kernel/qcfsocketnotifier.cpp
index 7f4c26d978..62272c1bca 100644
--- a/src/corelib/kernel/qcfsocketnotifier.cpp
+++ b/src/corelib/kernel/qcfsocketnotifier.cpp
@@ -235,7 +235,7 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier)
void QCFSocketNotifier::removeSocketNotifiers()
{
// Remove CFSockets from the runloop.
- foreach (MacSocketInfo *socketInfo, macSockets) {
+ for (MacSocketInfo *socketInfo : qAsConst(macSockets)) {
unregisterSocketInfo(socketInfo);
delete socketInfo;
}
@@ -272,9 +272,9 @@ void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoo
Q_UNUSED(ref);
Q_UNUSED(activity);
- QCFSocketNotifier *that = static_cast<QCFSocketNotifier *>(info);
+ const QCFSocketNotifier *that = static_cast<QCFSocketNotifier *>(info);
- foreach (MacSocketInfo *socketInfo, that->macSockets) {
+ for (MacSocketInfo *socketInfo : that->macSockets) {
if (!CFSocketIsValid(socketInfo->socket))
continue;
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 324b664a1a..f427f6d062 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -154,7 +154,7 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
const QStringList wArgv = qWinCmdArgs(QString::fromLocal8Bit(cmdParam));
argv.clear();
argc = wArgv.size();
- foreach (const QString &wArg, wArgv)
+ for (const QString &wArg : wArgv)
argv.append(_strdup(wArg.toLocal8Bit().constData()));
}
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index df070dd1ae..37738198e2 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -376,7 +376,8 @@ bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
}
Q_D(QEventDispatcherWinRT);
- foreach (int id, d->timerIdToObject.keys()) {
+ const auto timerIds = d->timerIdToObject.keys(); // ### FIXME: iterate over hash directly? But unregisterTimer() modifies the hash!
+ for (int id : timerIds) {
if (d->timerIdToObject.value(id) == object)
unregisterTimer(id);
}
@@ -395,7 +396,7 @@ QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTime
Q_D(const QEventDispatcherWinRT);
QList<TimerInfo> timerInfos;
- foreach (const WinRTTimerInfo &info, d->timerInfos) {
+ for (const WinRTTimerInfo &info : d->timerInfos) {
if (info.object == object && info.timerId != INVALID_TIMER_ID)
timerInfos.append(info);
}
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index 0a5a5dffb9..f372230ff6 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -69,7 +69,7 @@ static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
{
jboolean ret = JNI_FALSE;
QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
- foreach (auto listener, g_genericMotionEventListeners()->listeners)
+ for (auto *listener : qAsConst(g_genericMotionEventListeners()->listeners))
ret |= listener->handleGenericMotionEvent(event);
return ret;
}
@@ -86,7 +86,7 @@ static jboolean dispatchKeyEvent(JNIEnv *, jclass, jobject event)
{
jboolean ret = JNI_FALSE;
QMutexLocker locker(&g_keyEventListeners()->mutex);
- foreach (auto listener, g_keyEventListeners()->listeners)
+ for (auto *listener : qAsConst(g_keyEventListeners()->listeners))
ret |= listener->handleKeyEvent(event);
return ret;
}
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
index 76508f12c5..065a053bec 100644
--- a/src/corelib/kernel/qppsobject.cpp
+++ b/src/corelib/kernel/qppsobject.cpp
@@ -349,7 +349,8 @@ QVariant QPpsObjectPrivate::variantFromPpsAttribute(const QPpsAttribute &attribu
return attribute.toString();
case QPpsAttribute::Array: {
QVariantList variantList;
- Q_FOREACH (const QPpsAttribute &attr, attribute.toList()) {
+ const auto attrs = attribute.toList();
+ for (const QPpsAttribute &attr : attrs) {
QVariant variant = variantFromPpsAttribute(attr);
if (!variant.isValid())
return QVariantList();
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index 0dd0e64977..1447d7033c 100644
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -136,7 +136,6 @@ static QString qt_eval_string()
break;
default:
return QString();
- msg = 0;
}
return QString::fromLatin1(msg)
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index dad471c1b0..f8523eaded 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -652,7 +652,7 @@ static QString find_translation(const QLocale & locale,
#endif
// try explicit locales names first
- foreach (QString localeName, languages) {
+ for (QString localeName : qAsConst(languages)) {
localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
realname += localeName + suffixOrDotQM;
@@ -668,7 +668,8 @@ static QString find_translation(const QLocale & locale,
}
// start guessing
- foreach (QString localeName, fuzzyLocales) {
+ for (const QString &fuzzyLocale : qAsConst(fuzzyLocales)) {
+ QStringRef localeName(&fuzzyLocale);
for (;;) {
int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
// no truncations? fail
@@ -708,7 +709,8 @@ static QString find_translation(const QLocale & locale,
if (is_readable_file(realname))
return realname;
- return QString();
+ realname.truncate(0);
+ return realname;
}
/*!
@@ -1046,7 +1048,7 @@ QString QTranslatorPrivate::do_translate(const char *context, const char *source
}
searchDependencies:
- foreach (QTranslator *translator, subTranslators) {
+ for (QTranslator *translator : subTranslators) {
QString tn = translator->translate(context, sourceText, comment, n);
if (!tn.isNull())
return tn;
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 1f4d0c88c5..af2522acc3 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -869,6 +869,14 @@ bool QLocale::operator!=(const QLocale &other) const
}
/*!
+ \fn void QLocale::swap(QLocale &other)
+ \since 5.6
+
+ Swaps locale \a other with this locale. This operation is very fast and
+ never fails.
+*/
+
+/*!
\since 5.6
\relates QLocale
@@ -3452,12 +3460,23 @@ QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const
return format.arg(str, sym);
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
/*!
\since 4.8
\overload
*/
QString QLocale::toCurrencyString(double value, const QString &symbol) const
{
+ return toCurrencyString(value, symbol, d->m_data->m_currency_digits);
+}
+#endif
+
+/*!
+ \since 5.7
+ \overload
+ */
+QString QLocale::toCurrencyString(double value, const QString &symbol, int precision) const
+{
#ifndef QT_NO_SYSTEMLOCALE
if (d->m_data == systemData()) {
QSystemLocale::CurrencyToStringArgument arg(value, symbol);
@@ -3474,7 +3493,7 @@ QString QLocale::toCurrencyString(double value, const QString &symbol) const
size = data->m_currency_negative_format_size;
value = -value;
}
- QString str = toString(value, 'f', d->m_data->m_currency_digits);
+ QString str = toString(value, 'f', precision == -1 ? d->m_data->m_currency_digits : precision);
QString sym = symbol.isNull() ? currencySymbol() : symbol;
if (sym.isEmpty())
sym = currencySymbol(QLocale::CurrencyIsoCode);
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index e90354138c..1f4083950c 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -866,9 +866,13 @@ public:
QLocale(Language language, Country country = AnyCountry);
QLocale(Language language, Script script, Country country);
QLocale(const QLocale &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QLocale &operator=(QLocale &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+#endif
+ QLocale &operator=(const QLocale &other);
~QLocale();
- QLocale &operator=(const QLocale &other);
+ void swap(QLocale &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
Language language() const;
Script script() const;
@@ -959,8 +963,18 @@ public:
inline QString toCurrencyString(ushort, const QString &symbol = QString()) const;
inline QString toCurrencyString(int, const QString &symbol = QString()) const;
inline QString toCurrencyString(uint, const QString &symbol = QString()) const;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ QString toCurrencyString(double, const QString &symbol = QString(), int precision = -1) const;
+ inline QString toCurrencyString(float i, const QString &symbol = QString(), int precision = -1) const
+ { return toCurrencyString(double(i), symbol, precision); }
+#else
QString toCurrencyString(double, const QString &symbol = QString()) const;
- inline QString toCurrencyString(float, const QString &symbol = QString()) const;
+ QString toCurrencyString(double, const QString &symbol, int precision) const;
+ inline QString toCurrencyString(float i, const QString &symbol = QString()) const
+ { return toCurrencyString(double(i), symbol); }
+ inline QString toCurrencyString(float i, const QString &symbol, int precision) const
+ { return toCurrencyString(double(i), symbol, precision); }
+#endif
QStringList uiLanguages() const;
@@ -994,7 +1008,7 @@ private:
QSharedDataPointer<QLocalePrivate> d;
};
-Q_DECLARE_TYPEINFO(QLocale, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QLocale)
Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::NumberOptions)
inline QString QLocale::toString(short i) const
@@ -1016,8 +1030,6 @@ inline QString QLocale::toCurrencyString(int i, const QString &symbol) const
{ return toCurrencyString(qlonglong(i), symbol); }
inline QString QLocale::toCurrencyString(uint i, const QString &symbol) const
{ return toCurrencyString(qulonglong(i), symbol); }
-inline QString QLocale::toCurrencyString(float i, const QString &symbol) const
-{ return toCurrencyString(double(i), symbol); }
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLocale &);
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 96c4f9acb6..a03007f606 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -135,7 +135,7 @@ private:
QList<QByteArray> buffers;
int head, tail;
int tailBuffer; // always buffers.size() - 1
- const int basicBlockSize;
+ int basicBlockSize;
qint64 bufferSize;
};
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index f030a3ff8c..c126e3636e 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -138,7 +138,6 @@ public:
inline ObjectTreeNode() : obj(0), flags(0) { }
inline ObjectTreeNode(const QString &n) // intentionally implicit
: name(n), obj(0), flags(0) { }
- inline ~ObjectTreeNode() { }
inline bool operator<(const QString &other) const
{ return name < other; }
inline bool operator<(const QStringRef &other) const
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index 678ce2a97c..bae1c04054 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -427,9 +427,9 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
int data_size = idata.size() +
(header->methodCount * (5+intsPerMethod)) + methodParametersDataSize +
(header->propertyCount * (3+intsPerProperty));
- foreach (const Method &mm, signals_)
+ for (const Method &mm : qAsConst(signals_))
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
- foreach (const Method &mm, methods)
+ for (const Method &mm : qAsConst(methods))
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
idata.resize(data_size + 1);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index babb270da0..6b5166508f 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -99,9 +99,8 @@ QDBusServer::~QDBusServer()
{
if (QDBusConnectionManager::instance()) {
QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
- Q_FOREACH (const QString &name, d->serverConnectionNames) {
+ for (const QString &name : qAsConst(d->serverConnectionNames))
QDBusConnectionManager::instance()->removeConnection(name);
- }
d->serverConnectionNames.clear();
}
d->ref.store(0);
diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp
index 72c1a12f2c..eb90b149c8 100644
--- a/src/dbus/qdbusservicewatcher.cpp
+++ b/src/dbus/qdbusservicewatcher.cpp
@@ -78,7 +78,7 @@ void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBus
{
if (connection.isConnected()) {
// remove older rules
- foreach (const QString &s, servicesWatched)
+ for (const QString &s : qAsConst(servicesWatched))
removeService(s);
}
@@ -88,7 +88,7 @@ void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBus
if (connection.isConnected()) {
// add new rules
- foreach (const QString &s, servicesWatched)
+ for (const QString &s : qAsConst(servicesWatched))
addService(s);
}
}
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index 371b7b184e..04e805d173 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -77,8 +77,8 @@ static bool variantToString(const QVariant &arg, QString &out)
if (argType == QVariant::StringList) {
out += QLatin1Char('{');
- QStringList list = arg.toStringList();
- foreach (const QString &item, list)
+ const QStringList list = arg.toStringList();
+ for (const QString &item : list)
out += QLatin1Char('\"') + item + QLatin1String("\", ");
if (!list.isEmpty())
out.chop(2);
@@ -95,8 +95,8 @@ static bool variantToString(const QVariant &arg, QString &out)
out += QLatin1Char('}');
} else if (argType == QVariant::List) {
out += QLatin1Char('{');
- QList<QVariant> list = arg.toList();
- foreach (const QVariant &item, list) {
+ const QList<QVariant> list = arg.toList();
+ for (const QVariant &item : list) {
if (!variantToString(item, out))
return false;
out += QLatin1String(", ");
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 3f30c061dc..1f92c8b145 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -2415,8 +2415,7 @@ bool QColor::operator==(const QColor &color) const
{
if (cspec == Hsl && cspec == color.cspec) {
return (ct.argb.alpha == color.ct.argb.alpha
- && ((((ct.ahsl.hue % 36000) == (color.ct.ahsl.hue % 36000)))
- || (ct.ahsl.hue == color.ct.ahsl.hue))
+ && ct.ahsl.hue % 36000 == color.ct.ahsl.hue % 36000
&& (qAbs(ct.ahsl.saturation - color.ct.ahsl.saturation) < 50
|| ct.ahsl.lightness == 0
|| color.ct.ahsl.lightness == 0
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index 74f4b10305..62c24797dc 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -700,25 +700,4 @@ void QStaticTextPrivate::init()
needsRelayout = false;
}
-QStaticTextItem::~QStaticTextItem()
-{
- if (m_userData != 0 && !m_userData->ref.deref())
- delete m_userData;
- setFontEngine(0);
-}
-
-void QStaticTextItem::setFontEngine(QFontEngine *fe)
-{
- if (m_fontEngine == fe)
- return;
-
- if (m_fontEngine != 0 && !m_fontEngine->ref.deref())
- delete m_fontEngine;
-
- m_fontEngine = fe;
-
- if (m_fontEngine != 0)
- m_fontEngine->ref.ref();
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 49ca24d51c..e654b8329d 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -75,46 +75,18 @@ public:
userDataNeedsUpdate(0), usesRawFont(0),
m_fontEngine(0), m_userData(0) {}
- QStaticTextItem(const QStaticTextItem &other)
- {
- operator=(other);
- }
-
- void operator=(const QStaticTextItem &other)
+ void setUserData(QStaticTextUserData *newUserData)
{
- glyphPositions = other.glyphPositions;
- glyphs = other.glyphs;
- numGlyphs = other.numGlyphs;
- font = other.font;
- color = other.color;
- useBackendOptimizations = other.useBackendOptimizations;
- userDataNeedsUpdate = other.userDataNeedsUpdate;
- usesRawFont = other.usesRawFont;
-
- m_fontEngine = 0;
- m_userData = 0;
- setUserData(other.userData());
- setFontEngine(other.fontEngine());
+ m_userData = newUserData;
}
+ QStaticTextUserData *userData() const { return m_userData.data(); }
- ~QStaticTextItem();
-
- void setUserData(QStaticTextUserData *newUserData)
+ void setFontEngine(QFontEngine *fe)
{
- if (m_userData == newUserData)
- return;
-
- if (m_userData != 0 && !m_userData->ref.deref())
- delete m_userData;
-
- m_userData = newUserData;
- if (m_userData != 0)
- m_userData->ref.ref();
+ m_fontEngine = fe;
}
- QStaticTextUserData *userData() const { return m_userData; }
- void setFontEngine(QFontEngine *fe);
- QFontEngine *fontEngine() const { return m_fontEngine; }
+ QFontEngine *fontEngine() const { return m_fontEngine.data(); }
union {
QFixedPoint *glyphPositions; // 8 bytes per glyph
@@ -135,11 +107,11 @@ public:
char userDataNeedsUpdate : 1; //
char usesRawFont : 1; //
-private: // Needs special handling in setters, so private to avoid abuse
- QFontEngine *m_fontEngine; // 4 bytes per item
- QStaticTextUserData *m_userData; // 8 bytes per item
- // ================
- // 43 bytes per item
+private: // private to avoid abuse
+ QExplicitlySharedDataPointer<QFontEngine> m_fontEngine; // 4 bytes per item
+ QExplicitlySharedDataPointer<QStaticTextUserData> m_userData; // 8 bytes per item
+ // ================
+ // 43 bytes per item
};
class QStaticText;
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 9c761f9479..4e74595909 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -51,11 +51,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_LIBRARY
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QBearerEngineFactoryInterface_iid, QLatin1String("/bearer")))
-#endif
-
QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
: QObject(), pollTimer(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
{
@@ -382,7 +377,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
bool envOK = false;
const int skipGeneric = qEnvironmentVariableIntValue("QT_EXCLUDE_GENERIC_BEARER", &envOK);
QBearerEngine *generic = 0;
- QFactoryLoader *l = loader();
+ static QFactoryLoader loader(QBearerEngineFactoryInterface_iid, QLatin1String("/bearer"));
+ QFactoryLoader *l = &loader;
const PluginKeyMap keyMap = l->keyMap();
const PluginKeyMapConstIterator cend = keyMap.constEnd();
QStringList addedEngines;
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 6110131484..7b42f3eb14 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -2479,22 +2479,25 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size)
qint64 written = d->socketEngine->write(data, size);
if (written < 0) {
d->setError(d->socketEngine->error(), d->socketEngine->errorString());
- return written;
} else if (written < size) {
// Buffer what was not written yet
char *ptr = d->writeBuffer.reserve(size - written);
memcpy(ptr, data + written, size - written);
+ written = size;
d->socketEngine->setWriteNotificationEnabled(true);
}
- return size; // size=actually written + what has been buffered
+
+#if defined (QABSTRACTSOCKET_DEBUG)
+ qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
+ qt_prettyDebug(data, qMin((int)size, 32), size).data(),
+ size, written);
+#endif
+ return written; // written = actually written + what has been buffered
} else if (!d->isBuffered && d->socketType != TcpSocket) {
// This is for a QUdpSocket that was connect()ed
qint64 written = d->socketEngine->write(data, size);
- if (written < 0) {
+ if (written < 0)
d->setError(d->socketEngine->error(), d->socketEngine->errorString());
- } else if (!d->writeBuffer.isEmpty()) {
- d->socketEngine->setWriteNotificationEnabled(true);
- }
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::writeData(%p \"%s\", %lli) == %lli", data,
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 1dfd87a0f8..6f3ed58e18 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -2531,7 +2531,7 @@ qint64 QSslSocketPrivate::peek(char *data, qint64 maxSize)
if (mode == QSslSocket::UnencryptedMode && !autoStartHandshake) {
//unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
//peek at data already in the QIODevice buffer (from a previous read)
- qint64 r = buffer.peek(data, maxSize);
+ qint64 r = buffer.peek(data, maxSize, transactionPos);
if (r == maxSize)
return r;
data += r;
@@ -2560,7 +2560,7 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
//peek at data already in the QIODevice buffer (from a previous read)
QByteArray ret;
ret.reserve(maxSize);
- ret.resize(buffer.peek(ret.data(), maxSize));
+ ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
if (ret.length() == maxSize)
return ret;
//peek at data in the plain socket
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 726d1972f1..0cdf9918ab 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1444,7 +1444,7 @@ bool Moc::until(Token target) {
case LPAREN: ++parenCount; break;
case RPAREN: --parenCount; break;
case LANGLE:
- if (parenCount == 0 && braceCount == 0 && parenCount == 0)
+ if (parenCount == 0 && braceCount == 0)
++angleCount;
break;
case RANGLE:
diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index 334f5aba05..9271630b32 100644
--- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -57,9 +57,11 @@ private slots:
void readLine2_data();
void readLine2();
- void peekBug();
void readAllKeepPosition();
void writeInTextMode();
+
+ void transaction_data();
+ void transaction();
};
void tst_QIODevice::initTestCase()
@@ -528,77 +530,23 @@ void tst_QIODevice::readLine2()
}
}
-
-class PeekBug : public QIODevice {
- Q_OBJECT
-public:
- char alphabet[27];
- qint64 counter;
- PeekBug() : QIODevice(), counter(0) {
- memcpy(alphabet,"abcdefghijklmnopqrstuvqxyz",27);
- };
- qint64 readData(char *data, qint64 maxlen) {
- qint64 pos = 0;
- while (pos < maxlen) {
- *(data + pos) = alphabet[counter];
- pos++;
- counter++;
- if (counter == 26)
- counter = 0;
- }
- return maxlen;
- }
- qint64 writeData(const char * /* data */, qint64 /* maxlen */) {
- return -1;
- }
-
-};
-
-// This is a regression test for an old bug where peeking at
-// more than one character failed to put them back.
-void tst_QIODevice::peekBug()
-{
- PeekBug peekBug;
- peekBug.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
-
- char onetwo[2];
- peekBug.peek(onetwo, 2);
- QCOMPARE(onetwo[0], 'a');
- QCOMPARE(onetwo[1], 'b');
-
- peekBug.read(onetwo, 1);
- QCOMPARE(onetwo[0], 'a');
-
- peekBug.peek(onetwo, 2);
- QCOMPARE(onetwo[0], 'b');
- QCOMPARE(onetwo[1], 'c');
-
- peekBug.read(onetwo, 1);
- QCOMPARE(onetwo[0], 'b');
- peekBug.read(onetwo, 1);
- QCOMPARE(onetwo[0], 'c');
- peekBug.read(onetwo, 1);
- QCOMPARE(onetwo[0], 'd');
-
- peekBug.peek(onetwo, 2);
- QCOMPARE(onetwo[0], 'e');
- QCOMPARE(onetwo[1], 'f');
-
-}
-
class SequentialReadBuffer : public QIODevice
{
public:
- SequentialReadBuffer(const char *data) : QIODevice(), buf(data), offset(0) { }
+ SequentialReadBuffer(const char *data)
+ : QIODevice(), buf(new QByteArray(data)), offset(0), ownbuf(true) { }
+ SequentialReadBuffer(QByteArray *byteArray)
+ : QIODevice(), buf(byteArray), offset(0), ownbuf(false) { }
+ virtual ~SequentialReadBuffer() { if (ownbuf) delete buf; }
bool isSequential() const Q_DECL_OVERRIDE { return true; }
- const QByteArray &buffer() const { return buf; }
+ const QByteArray &buffer() const { return *buf; }
protected:
qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE
{
- maxSize = qMin(maxSize, qint64(buf.size() - offset));
- memcpy(data, buf.constData() + offset, maxSize);
+ maxSize = qMin(maxSize, qint64(buf->size() - offset));
+ memcpy(data, buf->constData() + offset, maxSize);
offset += maxSize;
return maxSize;
}
@@ -608,8 +556,9 @@ protected:
}
private:
- QByteArray buf;
+ QByteArray *buf;
int offset;
+ bool ownbuf;
};
// Test readAll() on position change for sequential device
@@ -669,5 +618,117 @@ void tst_QIODevice::writeInTextMode()
#endif
}
+void tst_QIODevice::transaction_data()
+{
+ QTest::addColumn<bool>("sequential");
+ QTest::addColumn<qint8>("i8Data");
+ QTest::addColumn<qint16>("i16Data");
+ QTest::addColumn<qint32>("i32Data");
+ QTest::addColumn<qint64>("i64Data");
+ QTest::addColumn<bool>("bData");
+ QTest::addColumn<float>("fData");
+ QTest::addColumn<double>("dData");
+ QTest::addColumn<QByteArray>("strData");
+
+ bool sequential = true;
+ do {
+ QByteArray devName(sequential ? "sequential" : "random-access");
+
+ QTest::newRow(qPrintable(devName + '1')) << sequential << qint8(1) << qint16(2)
+ << qint32(3) << qint64(4) << true
+ << 5.0f << double(6.0)
+ << QByteArray("Hello world!");
+ QTest::newRow(qPrintable(devName + '2')) << sequential << qint8(1 << 6) << qint16(1 << 14)
+ << qint32(1 << 30) << (qint64(1) << 62) << false
+ << 123.0f << double(234.0)
+ << QByteArray("abcdefghijklmnopqrstuvwxyz");
+ QTest::newRow(qPrintable(devName + '3')) << sequential << qint8(-1) << qint16(-2)
+ << qint32(-3) << qint64(-4) << true
+ << -123.0f << double(-234.0)
+ << QByteArray("Qt rocks!");
+ sequential = !sequential;
+ } while (!sequential);
+}
+
+// Test transaction integrity
+void tst_QIODevice::transaction()
+{
+ QByteArray testBuffer;
+
+ QFETCH(bool, sequential);
+ QFETCH(qint8, i8Data);
+ QFETCH(qint16, i16Data);
+ QFETCH(qint32, i32Data);
+ QFETCH(qint64, i64Data);
+ QFETCH(bool, bData);
+ QFETCH(float, fData);
+ QFETCH(double, dData);
+ QFETCH(QByteArray, strData);
+
+ {
+ QDataStream stream(&testBuffer, QIODevice::WriteOnly);
+
+ stream << i8Data << i16Data << i32Data << i64Data
+ << bData << fData << dData << strData.constData();
+ }
+
+ for (int splitPos = 0; splitPos <= testBuffer.size(); ++splitPos) {
+ QByteArray readBuffer(testBuffer.left(splitPos));
+ QIODevice *dev = sequential ? (QIODevice *) new SequentialReadBuffer(&readBuffer)
+ : (QIODevice *) new QBuffer(&readBuffer);
+ dev->open(QIODevice::ReadOnly);
+ QDataStream stream(dev);
+
+ qint8 i8;
+ qint16 i16;
+ qint32 i32;
+ qint64 i64;
+ bool b;
+ float f;
+ double d;
+ char *str;
+
+ forever {
+ QVERIFY(!dev->isTransactionStarted());
+ dev->startTransaction();
+ QVERIFY(dev->isTransactionStarted());
+
+ // Try to read all data in one go. If the status of the data stream
+ // indicates an unsuccessful operation, restart a read transaction
+ // on the completed buffer.
+ stream >> i8 >> i16 >> i32 >> i64 >> b >> f >> d >> str;
+
+ QVERIFY(stream.atEnd());
+ if (stream.status() == QDataStream::Ok) {
+ dev->commitTransaction();
+ break;
+ }
+
+ dev->rollbackTransaction();
+ QVERIFY(splitPos == 0 || !stream.atEnd());
+ QCOMPARE(dev->pos(), Q_INT64_C(0));
+ QCOMPARE(dev->bytesAvailable(), qint64(readBuffer.size()));
+ QVERIFY(readBuffer.size() < testBuffer.size());
+ delete [] str;
+ readBuffer.append(testBuffer.right(testBuffer.size() - splitPos));
+ stream.resetStatus();
+ }
+
+ QVERIFY(!dev->isTransactionStarted());
+ QVERIFY(stream.atEnd());
+ QCOMPARE(i8, i8Data);
+ QCOMPARE(i16, i16Data);
+ QCOMPARE(i32, i32Data);
+ QCOMPARE(i64, i64Data);
+ QCOMPARE(b, bData);
+ QCOMPARE(f, fData);
+ QCOMPARE(d, dData);
+ QVERIFY(strData == str);
+ delete [] str;
+ stream.setDevice(0);
+ delete dev;
+ }
+}
+
QTEST_MAIN(tst_QIODevice)
#include "tst_qiodevice.moc"
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index 51f691b1a4..f8058f2240 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -2187,12 +2187,18 @@ void tst_QLocale::currency()
QCOMPARE(c.toCurrencyString(qlonglong(-1234)), QString("-1234"));
QCOMPARE(c.toCurrencyString(double(1234.56)), QString("1234.56"));
QCOMPARE(c.toCurrencyString(double(-1234.56)), QString("-1234.56"));
+ QCOMPARE(c.toCurrencyString(double(-1234.5678)), QString("-1234.57"));
+ QCOMPARE(c.toCurrencyString(double(-1234.5678), NULL, 4), QString("-1234.5678"));
+ QCOMPARE(c.toCurrencyString(double(-1234.56), NULL, 4), QString("-1234.5600"));
const QLocale en_US("en_US");
QCOMPARE(en_US.toCurrencyString(qulonglong(1234)), QString("$1,234"));
QCOMPARE(en_US.toCurrencyString(qlonglong(-1234)), QString("$-1,234"));
QCOMPARE(en_US.toCurrencyString(double(1234.56)), QString("$1,234.56"));
QCOMPARE(en_US.toCurrencyString(double(-1234.56)), QString("$-1,234.56"));
+ QCOMPARE(en_US.toCurrencyString(double(-1234.5678)), QString("$-1,234.57"));
+ QCOMPARE(en_US.toCurrencyString(double(-1234.5678), NULL, 4), QString("$-1,234.5678"));
+ QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("$-1,234.5600"));
const QLocale ru_RU("ru_RU");
QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1."));
diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
index b77fe23bd6..9cc66cd5e2 100644
--- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
+++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
@@ -34,12 +34,14 @@
#include <QtTest/QtTest>
#include <private/qringbuffer_p.h>
+#include <qvector.h>
class tst_QRingBuffer : public QObject
{
Q_OBJECT
private slots:
void constructing();
+ void usingInVector();
void readPointerAtPositionWriteRead();
void readPointerAtPositionEmptyRead();
void readPointerAtPositionWithHead();
@@ -74,6 +76,16 @@ void tst_QRingBuffer::constructing()
QCOMPARE(ringBuffer.peek(buf, sizeof(buf)), Q_INT64_C(0));
}
+void tst_QRingBuffer::usingInVector()
+{
+ QRingBuffer ringBuffer;
+ QVector<QRingBuffer> buffers;
+
+ ringBuffer.reserve(5);
+ buffers.append(ringBuffer);
+ QCOMPARE(buffers[0].size(), Q_INT64_C(5));
+}
+
void tst_QRingBuffer::sizeWhenReserved()
{
QRingBuffer ringBuffer;
diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp
index 7942a84615..93cbb2809d 100644
--- a/tests/auto/other/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp
@@ -124,7 +124,7 @@ void tst_toolsupport::offsets_data()
{
QTestData &data = QTest::newRow("QFilePrivate::fileName")
<< pmm_to_offsetof(&QFilePrivate::fileName);
- data << 168 << 248;
+ data << 184 << 256;
}
#endif