diff --git a/src/widgets/accessmanagerreply_p.h b/src/widgets/accessmanagerreply_p.h --- a/src/widgets/accessmanagerreply_p.h +++ b/src/widgets/accessmanagerreply_p.h @@ -96,6 +96,7 @@ private: QByteArray m_data; + qint64 m_offset; bool m_metaDataRead; bool m_ignoreContentDisposition; bool m_emitReadyReadOnMetaDataChange; diff --git a/src/widgets/accessmanagerreply_p.cpp b/src/widgets/accessmanagerreply_p.cpp --- a/src/widgets/accessmanagerreply_p.cpp +++ b/src/widgets/accessmanagerreply_p.cpp @@ -46,6 +46,7 @@ bool emitReadyReadOnMetaDataChange, QObject *parent) : QNetworkReply(parent), + m_offset(0), m_metaDataRead(false), m_ignoreContentDisposition(false), m_emitReadyReadOnMetaDataChange(emitReadyReadOnMetaDataChange), @@ -84,6 +85,7 @@ QObject *parent) : QNetworkReply(parent), m_data(data), + m_offset(0), m_ignoreContentDisposition(false), m_emitReadyReadOnMetaDataChange(false) { @@ -106,7 +108,8 @@ QNetworkReply::NetworkError errorCode, const QString &errorMessage, QObject *parent) - : QNetworkReply(parent) + : QNetworkReply(parent), + m_offset(0) { setRequest(request); setOpenMode(QIODevice::ReadOnly); @@ -131,21 +134,31 @@ } m_kioJob.clear(); m_data.clear(); + m_offset = 0; m_metaDataRead = false; } qint64 AccessManagerReply::bytesAvailable() const { - return (QNetworkReply::bytesAvailable() + m_data.length()); + return (QNetworkReply::bytesAvailable() + m_data.length() - m_offset); } qint64 AccessManagerReply::readData(char *data, qint64 maxSize) { - const qint64 length = qMin(qint64(m_data.length()), maxSize); + const qint64 length = qMin(qint64(m_data.length() - m_offset), maxSize); + + if (length <= 0) + return 0; + + memcpy(data, m_data.constData() + m_offset, length); + m_offset += length; - if (length) { - memcpy(data, m_data.constData(), length); - m_data.remove(0, length); + // Remove the stale data before m_offset only if it grows to half + // of the total size, to avoid calling the expensive .remove function. + // If there's no data left, it's a trivial remove. + if (m_data.length() == m_offset || m_offset * 2 >= m_data.length()) { + m_data.remove(0, m_offset); + m_offset = 0; } return length;