summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-02-14 11:33:02 +0100
committerLiang Qi <liang.qi@qt.io>2017-02-14 11:33:02 +0100
commit27432d40f2500b11780398f6c7d67719050dae6c (patch)
tree97f9a60af2d520d66fa7ff802ccddad56e0cadaf /src/corelib/io
parent071a120400b17eaa0b414a0ed262b0a090908679 (diff)
parent10ecbc4041cb7db004f4ed4d40ce082553d75844 (diff)
Merge remote-tracking branch 'origin/5.8' into 5.9
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qiodevice.cpp159
-rw-r--r--src/corelib/io/qiodevice_p.h1
-rw-r--r--src/corelib/io/qresource.cpp22
3 files changed, 103 insertions, 79 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 52a78ad1c4..41a4d7a1ba 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1007,10 +1007,9 @@ 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 && !keepDataInBuffer) {
+ // Short-cut for getChar(), unless we need to keep the data in the buffer.
+ if (maxSize == 1 && !(sequential && d->transactionStarted)) {
int chint;
while ((chint = d->buffer.getChar()) != -1) {
if (!sequential)
@@ -1031,43 +1030,67 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
CHECK_MAXLEN(read, qint64(-1));
+ CHECK_READABLE(read, qint64(-1));
+
+ const qint64 readBytes = d->read(data, maxSize);
+
+#if defined QIODEVICE_DEBUG
+ printf("%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n", this,
+ readBytes, d->pos, d->buffer.size());
+ if (readBytes > 0)
+ debugBinaryString(data - readBytes, readBytes);
+#endif
+
+ return readBytes;
+}
+
+/*!
+ \internal
+*/
+qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
+{
+ Q_Q(QIODevice);
+
+ const bool buffered = (openMode & QIODevice::Unbuffered) == 0;
+ const bool sequential = isSequential();
+ const bool keepDataInBuffer = sequential
+ ? peeking || transactionStarted
+ : peeking && buffered;
+ const qint64 savedPos = pos;
qint64 readSoFar = 0;
bool madeBufferReadsOnly = true;
bool deviceAtEof = false;
char *readPtr = data;
+ qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
forever {
// Try reading from the buffer.
qint64 bufferReadChunkSize = keepDataInBuffer
- ? d->buffer.peek(data, maxSize, d->transactionPos)
- : d->buffer.read(data, maxSize);
+ ? buffer.peek(data, maxSize, bufferPos)
+ : buffer.read(data, maxSize);
if (bufferReadChunkSize > 0) {
- if (keepDataInBuffer)
- d->transactionPos += bufferReadChunkSize;
- else if (!sequential)
- d->pos += bufferReadChunkSize;
+ bufferPos += bufferReadChunkSize;
+ if (!sequential)
+ pos += bufferReadChunkSize;
+#if defined QIODEVICE_DEBUG
+ printf("%p \treading %lld bytes from buffer into position %lld\n", q,
+ bufferReadChunkSize, readSoFar);
+#endif
readSoFar += bufferReadChunkSize;
data += bufferReadChunkSize;
maxSize -= bufferReadChunkSize;
-#if defined QIODEVICE_DEBUG
- printf("%p \treading %lld bytes from buffer into position %lld\n", this,
- bufferReadChunkSize, readSoFar - bufferReadChunkSize);
-#endif
- } else {
- CHECK_READABLE(read, qint64(-1));
}
if (maxSize > 0 && !deviceAtEof) {
qint64 readFromDevice = 0;
// Make sure the device is positioned correctly.
- if (sequential || d->pos == d->devicePos || seek(d->pos)) {
+ if (sequential || pos == devicePos || q->seek(pos)) {
madeBufferReadsOnly = false; // fix readData attempt
- if ((maxSize >= d->readBufferChunkSize || (d->openMode & Unbuffered))
- && !keepDataInBuffer) {
+ if ((!buffered || maxSize >= readBufferChunkSize) && !keepDataInBuffer) {
// Read big chunk directly to output buffer
- readFromDevice = readData(data, maxSize);
+ readFromDevice = q->readData(data, maxSize);
deviceAtEof = (readFromDevice != maxSize);
#if defined QIODEVICE_DEBUG
- printf("%p \treading %lld bytes from device (total %lld)\n", this,
+ printf("%p \treading %lld bytes from device (total %lld)\n", q,
readFromDevice, readSoFar);
#endif
if (readFromDevice > 0) {
@@ -1075,24 +1098,24 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
data += readFromDevice;
maxSize -= readFromDevice;
if (!sequential) {
- d->pos += readFromDevice;
- d->devicePos += readFromDevice;
+ pos += readFromDevice;
+ devicePos += readFromDevice;
}
}
} else {
// Do not read more than maxSize on unbuffered devices
- const qint64 bytesToBuffer = (d->openMode & Unbuffered)
- ? qMin(maxSize, qint64(d->readBufferChunkSize))
- : qint64(d->readBufferChunkSize);
+ const qint64 bytesToBuffer = (buffered || readBufferChunkSize < maxSize)
+ ? qint64(readBufferChunkSize)
+ : maxSize;
// Try to fill QIODevice buffer by single read
- readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer);
+ readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer);
deviceAtEof = (readFromDevice != bytesToBuffer);
- d->buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
+ buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice));
if (readFromDevice > 0) {
if (!sequential)
- d->devicePos += readFromDevice;
+ devicePos += readFromDevice;
#if defined QIODEVICE_DEBUG
- printf("%p \treading %lld from device into buffer\n", this,
+ printf("%p \treading %lld from device into buffer\n", q,
readFromDevice);
#endif
continue;
@@ -1108,7 +1131,7 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
}
- if ((d->openMode & Text) && readPtr < data) {
+ if ((openMode & QIODevice::Text) && readPtr < data) {
const char *endPtr = data;
// optimization to avoid initial self-assignment
@@ -1140,14 +1163,18 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
break;
}
-#if defined QIODEVICE_DEBUG
- printf("%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n", this,
- readSoFar, d->pos, d->buffer.size());
- debugBinaryString(data - readSoFar, readSoFar);
-#endif
+ // Restore positions after reading
+ if (keepDataInBuffer) {
+ if (peeking)
+ pos = savedPos; // does nothing on sequential devices
+ else
+ transactionPos = bufferPos;
+ } else if (peeking) {
+ seekBuffer(savedPos); // unbuffered random-access device
+ }
- if (madeBufferReadsOnly && d->isBufferEmpty())
- readData(data, 0);
+ if (madeBufferReadsOnly && isBufferEmpty())
+ q->readData(data, 0);
return readSoFar;
}
@@ -1759,27 +1786,7 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
{
- 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();
-
- return readBytes;
+ return read(data, maxSize, true);
}
/*!
@@ -1787,26 +1794,17 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevicePrivate::peek(qint64 maxSize)
{
- Q_Q(QIODevice);
-
- if (transactionStarted) {
- const qint64 savedTransactionPos = transactionPos;
- const qint64 savedPos = pos;
+ QByteArray result(maxSize, Qt::Uninitialized);
- QByteArray result = q->read(maxSize);
+ const qint64 readBytes = read(result.data(), maxSize, true);
- // Restore initial position
- if (isSequential())
- transactionPos = savedTransactionPos;
+ if (readBytes < maxSize) {
+ if (readBytes <= 0)
+ result.clear();
else
- seekBuffer(savedPos);
- return result;
+ result.resize(readBytes);
}
- q->startTransaction();
- QByteArray result = q->read(maxSize);
- q->rollbackTransaction();
-
return result;
}
@@ -1844,7 +1842,12 @@ bool QIODevice::getChar(char *c)
*/
qint64 QIODevice::peek(char *data, qint64 maxSize)
{
- return d_func()->peek(data, maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, qint64(-1));
+ CHECK_READABLE(peek, qint64(-1));
+
+ return d->peek(data, maxSize);
}
/*!
@@ -1866,7 +1869,13 @@ qint64 QIODevice::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevice::peek(qint64 maxSize)
{
- return d_func()->peek(maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, QByteArray());
+ CHECK_MAXBYTEARRAYSIZE(peek);
+ CHECK_READABLE(peek, QByteArray());
+
+ return d->peek(maxSize);
}
/*!
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 76bec89ef2..71a326dd53 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -171,6 +171,7 @@ public:
void setReadChannelCount(int count);
void setWriteChannelCount(int count);
+ qint64 read(char *data, qint64 maxSize, bool peeking = false);
virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize);
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index febf22639c..32639759e4 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -149,12 +149,23 @@ static QString cleanPath(const QString &_path)
Q_DECLARE_TYPEINFO(QResourceRoot, Q_MOVABLE_TYPE);
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, resourceMutex, (QMutex::Recursive))
-
typedef QList<QResourceRoot*> ResourceList;
-Q_GLOBAL_STATIC(ResourceList, resourceList)
+struct QResourceGlobalData
+{
+ QMutex resourceMutex{QMutex::Recursive};
+ ResourceList resourceList;
+ QStringList resourceSearchPaths;
+};
+Q_GLOBAL_STATIC(QResourceGlobalData, resourceGlobalData)
+
+static inline QMutex *resourceMutex()
+{ return &resourceGlobalData->resourceMutex; }
-Q_GLOBAL_STATIC(QStringList, resourceSearchPaths)
+static inline ResourceList *resourceList()
+{ return &resourceGlobalData->resourceList; }
+
+static inline QStringList *resourceSearchPaths()
+{ return &resourceGlobalData->resourceSearchPaths; }
/*!
\class QResource
@@ -870,6 +881,9 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tree,
const unsigned char *name, const unsigned char *data)
{
+ if (resourceGlobalData.isDestroyed())
+ return false;
+
QMutexLocker lock(resourceMutex());
if ((version == 0x01 || version == 0x02) && resourceList()) {
QResourceRoot res(version, tree, name, data);