Merge remote-tracking branch 'origin/5.10' into dev

Conflicts:
	src/corelib/global/minimum-linux.S
	src/network/access/qhttpthreaddelegate.cpp
	src/widgets/kernel/qwidgetwindow.cpp

Change-Id: Id2e817e85f85c68f5482c9a12912d35590f9d5f8
bb10
Liang Qi 2017-11-05 17:58:48 +01:00
commit a7e4b645dc
50 changed files with 10328 additions and 6189 deletions

View File

@ -222,6 +222,7 @@ headersclean:!internal_module {
gcc_ver = $${QT_GCC_MAJOR_VERSION}.$${QT_GCC_MINOR_VERSION}
versionAtLeast(gcc_ver, 4.5): hcleanFLAGS += -Wdouble-promotion
versionAtLeast(gcc_ver, 4.9): hcleanFLAGS += -Wfloat-conversion
c++11 {
# only enabled for actual c++11 builds due to

View File

@ -1,15 +0,0 @@
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 7f5e75921f..f5c6180a03 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -165733,6 +165733,10 @@ static int getNodeSize(
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }else if( pRtree->iNodeSize<(512-64) ){
+ rc = SQLITE_CORRUPT;
+ *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
+ pRtree->zName);
}
}

View File

@ -6,7 +6,7 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "http://www.sqlite.org/",
"Version": "3.16.2",
"Version": "3.20.1",
"License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -333,11 +333,11 @@ void Widget::compareSensitiveFunction()
int z = QString::compare("auto", "Car", Qt::CaseInsensitive); // z < 0
//! [16]
//! [qCompareStrings-QSV-QSV]
int x = qCompareStrings(u"aUtO", u"AuTo", Qt::CaseInsensitive); // x == 0
int y = qCompareStrings(u"auto", u"Car", Qt::CaseSensitive); // y > 0
int z = qCompareStrings(u"auto", u"Car", Qt::CaseInsensitive); // z < 0
//! [qCompareStrings-QSV-QSV]
//! [QtPrivate::compareStrings-QSV-QSV]
int x = QtPrivate::compareStrings(u"aUtO", u"AuTo", Qt::CaseInsensitive); // x == 0
int y = QtPrivate::compareStrings(u"auto", u"Car", Qt::CaseSensitive); // y > 0
int z = QtPrivate::compareStrings(u"auto", u"Car", Qt::CaseInsensitive); // z < 0
//! [QtPrivate::compareStrings-QSV-QSV]
}
void Widget::containsFunction()

View File

@ -73,6 +73,7 @@ linux:!static {
} else {
SOURCES += global/minimum-linux.S
}
HEADERS += global/minimum-linux_p.h
}
qtConfig(slog2): \

View File

@ -37,7 +37,7 @@
**
****************************************************************************/
#include "private/qglobal_p.h"
#include "minimum-linux_p.h"
/* Copied from #include <elf.h>:
*/
@ -76,32 +76,6 @@
/* Operating systems: */
.long ELF_NOTE_OS_LINUX
/* Minimum Linux kernel version:
* We require the following features in Qt (unconditional, no fallback):
* Feature Added in version Macro
* - inotify_init1 before 2.6.12-rc12
* - futex(2) before 2.6.12-rc12
* - FUTEX_WAKE_OP 2.6.14 FUTEX_OP
* - linkat(2) 2.6.17 O_TMPFILE
* - FUTEX_PRIVATE_FLAG 2.6.22
* - O_CLOEXEC 2.6.23
* - eventfd 2.6.23
* - pipe2 & dup3 2.6.27
* - accept4 2.6.28
* - renameat2 3.16 QT_CONFIG(renameat2)
* - getrandom 3.17 QT_CONFIG(getentropy)
*/
#if QT_CONFIG(getentropy)
.long 3
.long 17
.long 0
#elif QT_CONFIG(renameat2)
.long 3
.long 16
.long 0
#else
.long 2
.long 6
.long 28
#endif
.long MINLINUX_MAJOR
.long MINLINUX_MINOR
.long MINLINUX_PATCH

View File

@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef MINIMUMLINUX_P_H
#define MINIMUMLINUX_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
// EXTRA WARNING
// -------------
//
// This file must also be valid assembler source.
//
#include "private/qglobal_p.h"
QT_BEGIN_NAMESPACE
/* Minimum Linux kernel version:
* We require the following features in Qt (unconditional, no fallback):
* Feature Added in version Macro
* - inotify_init1 before 2.6.12-rc12
* - futex(2) before 2.6.12-rc12
* - FUTEX_WAKE_OP 2.6.14 FUTEX_OP
* - linkat(2) 2.6.17 O_TMPFILE
* - FUTEX_PRIVATE_FLAG 2.6.22
* - O_CLOEXEC 2.6.23
* - eventfd 2.6.23
* - pipe2 & dup3 2.6.27
* - accept4 2.6.28
* - renameat2 3.16 QT_CONFIG(renameat2)
* - getrandom 3.17 QT_CONFIG(getentropy)
*/
#if QT_CONFIG(getentropy)
# define MINLINUX_MAJOR 3
# define MINLINUX_MINOR 17
# define MINLINUX_PATCH 0
#elif QT_CONFIG(renameat2)
# define MINLINUX_MAJOR 3
# define MINLINUX_MINOR 16
# define MINLINUX_PATCH 0
#else
# define MINLINUX_MAJOR 2
# define MINLINUX_MINOR 6
# define MINLINUX_PATCH 28
#endif
#define MINIMUM_LINUX_VERSION QT_VERSION_CHECK(MINLINUX_MAJOR, MINLINUX_MINOR, MINLINUX_PATCH)
QT_END_NAMESPACE
#endif // MINIMUMLINUX_P_H

View File

@ -167,7 +167,8 @@ inline qfloat16 operator/(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return qfloat
inline FP operator OP(qfloat16 lhs, FP rhs) Q_DECL_NOTHROW { return static_cast<FP>(lhs) OP rhs; } \
inline FP operator OP(FP lhs, qfloat16 rhs) Q_DECL_NOTHROW { return lhs OP static_cast<FP>(rhs); }
#define QF16_MAKE_ARITH_OP_EQ_FP(FP, OP_EQ, OP) \
inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) Q_DECL_NOTHROW { lhs = qfloat16(static_cast<FP>(lhs) OP rhs); return lhs; }
inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) Q_DECL_NOTHROW \
{ lhs = qfloat16(float(static_cast<FP>(lhs) OP rhs)); return lhs; }
#define QF16_MAKE_ARITH_OP(FP) \
QF16_MAKE_ARITH_OP_FP(FP, +) \
QF16_MAKE_ARITH_OP_FP(FP, -) \

View File

@ -51,9 +51,12 @@ class QRandomGenerator
template <typename UInt> using IfValidUInt =
typename std::enable_if<std::is_unsigned<UInt>::value && sizeof(UInt) >= sizeof(uint), bool>::type;
public:
static QRandomGenerator system() { return {}; }
static QRandomGenerator global() { return {}; }
QRandomGenerator() = default;
// ### REMOVE BEFORE 5.10
QRandomGenerator *operator->() { return this; }
static quint32 get32() { return generate(); }
static quint64 get64() { return generate64(); }
static qreal getReal() { return generateDouble(); }
@ -135,13 +138,14 @@ public:
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
private:
Q_DISABLE_COPY(QRandomGenerator)
static Q_CORE_EXPORT void fillRange_helper(void *buffer, void *bufferEnd);
};
class QRandomGenerator64
{
public:
static QRandomGenerator64 system() { return {}; }
static QRandomGenerator64 global() { return {}; }
QRandomGenerator64() = default;
static quint64 generate() { return QRandomGenerator::generate64(); }
@ -152,9 +156,6 @@ public:
double entropy() const Q_DECL_NOTHROW { return 0.0; }
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
private:
Q_DISABLE_COPY(QRandomGenerator64)
};

View File

@ -1261,7 +1261,8 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
// If we're using syscall(), check for ENOSYS;
// if renameat2 came from libc, we don't accept ENOSYS.
if (QT_CONFIG(renameat2) || errno != ENOSYS) {
// We can also get EINVAL for some non-local filesystems.
if ((QT_CONFIG(renameat2) || errno != ENOSYS) && errno != EINVAL) {
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
}

View File

@ -945,7 +945,7 @@ QUuid QUuid::createUuid()
QUuid result(Qt::Uninitialized);
uint *data = &(result.data1);
enum { AmountToRead = 4 };
QRandomGenerator::fillRange(data, AmountToRead);
QRandomGenerator::system()->fillRange(data, AmountToRead);
result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random

View File

@ -78,6 +78,13 @@ QThreadData::~QThreadData()
QThreadData::clearCurrentThreadData();
}
// ~QThread() sets thread to nullptr, so if it isn't null here, it's
// because we're being run before the main object itself. This can only
// happen for QAdoptedThread. Note that both ~QThreadPrivate() and
// ~QObjectPrivate() will deref this object again, but that is acceptable
// because this destructor is still running (the _ref sub-object has not
// been destroyed) and there's no reentrancy. The refcount will become
// negative, but that's acceptable.
QThread *t = thread;
thread = 0;
delete t;

View File

@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
return seed;
}
seed = QRandomGenerator::generate();
seed = QRandomGenerator::system()->generate();
#endif // QT_BOOTSTRAPPED
return seed;

View File

@ -160,7 +160,7 @@ static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::Ca
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW
qssize_t QtPrivate::qustrlen(const ushort *str) Q_DECL_NOTHROW
{
qssize_t result = 0;
@ -758,6 +758,7 @@ static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens
/*!
\relates QStringView
\internal
\since 5.10
Returns an integer that compares to 0 as \a lhs compares to \a rhs.
@ -771,13 +772,14 @@ static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens
\snippet qstring/main.cpp qCompareStrings-QSV-QSV
*/
int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_compare_strings(lhs, rhs, cs);
}
/*!
\relates QStringView
\internal
\since 5.10
\overload
@ -790,13 +792,14 @@ int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
int QtPrivate::compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_compare_strings(lhs, rhs, cs);
}
/*!
\relates QStringView
\internal
\since 5.10
\overload
@ -809,13 +812,14 @@ int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs)
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_compare_strings(lhs, rhs, cs);
}
/*!
\relates QStringView
\internal
\since 5.10
\overload
@ -828,7 +832,7 @@ int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs)
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
int qCompareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_compare_strings(lhs, rhs, cs);
}
@ -4732,15 +4736,17 @@ QByteArray QString::toLatin1_helper(const QChar *data, int length)
/*!
\since 5.10
\internal
\relates QStringView
Returns a Latin-1 representation of \a string as a QByteArray.
The behavior is undefined if \a string contains non-Latin1 characters.
\sa QString::toLatin1(), QStringView::toLatin1(), qConvertToUtf8(), qConvertToLocal8Bit(), qConvertToUcs4()
\sa QString::toLatin1(), QStringView::toLatin1(), QtPrivate::convertToUtf8(),
QtPrivate::convertToLocal8Bit(), QtPrivate::convertToUcs4()
*/
QByteArray qConvertToLatin1(QStringView string)
QByteArray QtPrivate::convertToLatin1(QStringView string)
{
return qt_convert_to_latin1(string);
}
@ -4853,6 +4859,7 @@ static QByteArray qt_convert_to_local_8bit(QStringView string)
/*!
\since 5.10
\internal
\relates QStringView
Returns a local 8-bit representation of \a string as a QByteArray.
@ -4864,9 +4871,10 @@ static QByteArray qt_convert_to_local_8bit(QStringView string)
The behavior is undefined if \a string contains characters not
supported by the locale's 8-bit encoding.
\sa QString::toLocal8Bit(), QStringView::toLocal8Bit(), qConvertToLatin1(), qConvertToUtf8(), qConvertToUcs4()
\sa QString::toLocal8Bit(), QStringView::toLocal8Bit(), QtPrivate::vonvertToLatin1(),
QtPrivate::convertToUtf8(), QtPrivate::convertToUcs4()
*/
QByteArray qConvertToLocal8Bit(QStringView string)
QByteArray QtPrivate::convertToLocal8Bit(QStringView string)
{
return qt_convert_to_local_8bit(string);
}
@ -4899,6 +4907,7 @@ static QByteArray qt_convert_to_utf8(QStringView str)
/*!
\since 5.10
\internal
\relates QStringView
Returns a UTF-8 representation of \a string as a QByteArray.
@ -4906,9 +4915,10 @@ static QByteArray qt_convert_to_utf8(QStringView str)
UTF-8 is a Unicode codec and can represent all characters in a Unicode
string like QStringView.
\sa QString::toUtf8(), QStringView::toUtf8(), qConvertToLatin1(), qConvertToLocal8Bit(), qConvertToUcs4()
\sa QString::toUtf8(), QStringView::toUtf8(), QtPrivate::convertToLatin1(),
QtPrivate::convertToLocal8Bit(), QtPrivate::convertToUcs4()
*/
QByteArray qConvertToUtf8(QStringView string)
QByteArray QtPrivate::convertToUtf8(QStringView string)
{
return qt_convert_to_utf8(string);
}
@ -4947,6 +4957,7 @@ static QVector<uint> qt_convert_to_ucs4(QStringView string)
/*!
\since 5.10
\internal
\relates QStringView
Returns a UCS-4/UTF-32 representation of \a string as a QVector<uint>.
@ -4958,9 +4969,10 @@ static QVector<uint> qt_convert_to_ucs4(QStringView string)
The returned vector is not NUL terminated.
\sa QString::toUcs4(), QStringView::toUcs4(), qConvertToLatin1(), qConvertToLocal8Bit(), qConvertToUtf8()
\sa QString::toUcs4(), QStringView::toUcs4(), QtPrivate::convertToLatin1(),
QtPrivate::convertToLocal8Bit(), QtPrivate::convertToUtf8()
*/
QVector<uint> qConvertToUcs4(QStringView string)
QVector<uint> QtPrivate::convertToUcs4(QStringView string)
{
return qt_convert_to_ucs4(string);
}
@ -5269,6 +5281,7 @@ namespace {
/*!
\fn QStringView qTrimmed(QStringView s)
\fn QLatin1String qTrimmed(QLatin1String s)
\internal
\relates QStringView
\since 5.10
@ -5280,12 +5293,12 @@ namespace {
\sa QString::trimmed(), QStringView::trimmed(), QLatin1String::trimmed()
*/
QStringView qTrimmed(QStringView s) Q_DECL_NOTHROW
QStringView QtPrivate::trimmed(QStringView s) Q_DECL_NOTHROW
{
return qt_trimmed(s);
}
QLatin1String qTrimmed(QLatin1String s) Q_DECL_NOTHROW
QLatin1String QtPrivate::trimmed(QLatin1String s) Q_DECL_NOTHROW
{
return qt_trimmed(s);
}
@ -5646,8 +5659,6 @@ QString& QString::fill(QChar ch, int size)
Note that no string is equal to \a s1 being 0.
Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}.
\sa qCompareStrings()
*/
/*!
@ -5659,8 +5670,6 @@ QString& QString::fill(QChar ch, int size)
For \a s1 != 0, this is equivalent to \c {compare(} \a s1, \a s2
\c {) != 0}. Note that no string is equal to \a s1 being 0.
\sa qCompareStrings()
*/
/*!
@ -5675,8 +5684,6 @@ QString& QString::fill(QChar ch, int size)
of the characters and is very fast, but is not what a human would
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
\sa qCompareStrings()
*/
/*!
@ -5691,8 +5698,6 @@ QString& QString::fill(QChar ch, int size)
of the characters and is very fast, but is not what a human would
expect. Consider sorting user-interface strings with
QString::localeAwareCompare().
\sa qCompareStrings()
*/
/*!
@ -5706,8 +5711,6 @@ QString& QString::fill(QChar ch, int size)
of the characters and is very fast, but is not what a human would
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
\sa qCompareStrings()
*/
/*!
@ -5788,7 +5791,7 @@ QString& QString::fill(QChar ch, int size)
\snippet qstring/main.cpp 16
\sa qCompareStrings(), operator==(), operator<(), operator>()
\sa operator==(), operator<(), operator>()
*/
/*!
@ -5798,8 +5801,6 @@ QString& QString::fill(QChar ch, int size)
Performs a comparison of \a s1 and \a s2, using the case
sensitivity setting \a cs.
\sa qCompareStrings()
*/
/*!
@ -5810,8 +5811,6 @@ QString& QString::fill(QChar ch, int size)
Performs a comparison of \a s1 and \a s2, using the case
sensitivity setting \a cs.
\sa qCompareStrings()
*/
@ -5825,8 +5824,6 @@ QString& QString::fill(QChar ch, int size)
string.
Same as compare(*this, \a other, \a cs).
\sa qCompareStrings()
*/
int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{
@ -5852,8 +5849,6 @@ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2,
\since 4.2
Same as compare(*this, \a other, \a cs).
\sa qCompareStrings()
*/
int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{
@ -5867,8 +5862,6 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N
Compares the string reference, \a ref, with the string and returns
an integer less than, equal to, or greater than zero if the string
is less than, equal to, or greater than \a ref.
\sa qCompareStrings()
*/
/*!
@ -5894,8 +5887,6 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2,
/*!
\fn int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
\overload compare()
\sa qCompareStrings()
*/
/*!
@ -10218,8 +10209,6 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
\sa qCompareStrings()
*/
/*!
@ -10233,8 +10222,6 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
\sa qCompareStrings()
*/
/*!
@ -10248,8 +10235,6 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
\sa qCompareStrings()
*/
/*!
@ -10265,8 +10250,6 @@ QStringRef QStringRef::appendTo(QString *string) const
otherwise the comparison is case insensitive.
Equivalent to \c {compare(*this, other, cs)}.
\sa qCompareStrings()
*/
/*!
@ -10282,8 +10265,6 @@ QStringRef QStringRef::appendTo(QString *string) const
otherwise the comparison is case insensitive.
Equivalent to \c {compare(*this, other, cs)}.
\sa qCompareStrings()
*/
/*!
@ -10299,8 +10280,6 @@ QStringRef QStringRef::appendTo(QString *string) const
otherwise the comparison is case insensitive.
Equivalent to \c {compare(*this, other, cs)}.
\sa qCompareStrings()
*/
/*!
@ -10317,8 +10296,6 @@ QStringRef QStringRef::appendTo(QString *string) const
otherwise the comparison is case insensitive.
Equivalent to \c {compare(*this, other, cs)}.
\sa qCompareStrings()
*/
/*!
@ -11107,14 +11084,15 @@ static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSe
}
/*!
\fn bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qStartsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::startsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\since 5.10
\internal
\relates QStringView
Returns \c true if \a haystack starts with \a needle,
@ -11123,25 +11101,25 @@ static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSe
If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
otherwise the search is case-insensitive.
\sa qEndsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
\sa QtPrivate::endsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
*/
bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_starts_with_impl(haystack, needle, cs);
}
bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_starts_with_impl(haystack, needle, cs);
}
bool qStartsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_starts_with_impl(haystack, needle, cs);
}
bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_starts_with_impl(haystack, needle, cs);
}
@ -11179,14 +11157,15 @@ static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSens
}
/*!
\fn bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qEndsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::endsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
\since 5.10
\fn bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\fn bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
\since 5.10
\internal
\relates QStringView
Returns \c true if \a haystack ends with \a needle,
@ -11195,25 +11174,25 @@ static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSens
If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
otherwise the search is case-insensitive.
\sa qEndsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
\sa QtPrivate::startsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
*/
bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_ends_with_impl(haystack, needle, cs);
}
bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_ends_with_impl(haystack, needle, cs);
}
bool qEndsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_ends_with_impl(haystack, needle, cs);
}
bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
return qt_ends_with_impl(haystack, needle, cs);
}

View File

@ -113,22 +113,22 @@ public:
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); }
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool startsWith(QChar c) const Q_DECL_NOTHROW
{ return !isEmpty() && front() == c; }
Q_REQUIRED_RESULT inline bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qStartsWith(*this, QStringView(&c, 1), cs); }
{ return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
Q_REQUIRED_RESULT bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool endsWith(QChar c) const Q_DECL_NOTHROW
{ return !isEmpty() && back() == c; }
Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qEndsWith(*this, QStringView(&c, 1), cs); }
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
using value_type = const char;
using reference = value_type&;
@ -167,7 +167,7 @@ public:
Q_DECL_RELAXED_CONSTEXPR void truncate(int n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
Q_REQUIRED_RESULT QLatin1String trimmed() const Q_DECL_NOTHROW { return qTrimmed(*this); }
Q_REQUIRED_RESULT QLatin1String trimmed() const Q_DECL_NOTHROW { return QtPrivate::trimmed(*this); }
inline bool operator==(const QString &s) const Q_DECL_NOTHROW;
inline bool operator!=(const QString &s) const Q_DECL_NOTHROW;
@ -205,9 +205,9 @@ typedef QLatin1String QLatin1Literal;
// QStringView members that require QLatin1String:
//
bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
class Q_CORE_EXPORT QString
{
@ -390,7 +390,7 @@ public:
bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#endif
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@ -399,7 +399,7 @@ public:
bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#endif
Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@ -1485,7 +1485,7 @@ public:
bool isRightToLeft() const;
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#if QT_STRINGVIEW_LEVEL < 2
@ -1494,7 +1494,7 @@ public:
#endif
Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#if QT_STRINGVIEW_LEVEL < 2
@ -1715,12 +1715,12 @@ inline bool operator<=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(r
inline bool operator>=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); }
// QStringView <> QStringView
inline bool operator==(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
inline bool operator==(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
inline bool operator!=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
inline bool operator< (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
inline bool operator<=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
inline bool operator> (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
inline bool operator>=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
inline bool operator< (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
inline bool operator<=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
inline bool operator> (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
inline bool operator>=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
// QStringView <> QChar
inline bool operator==(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs == QStringView(&rhs, 1); }
@ -1738,19 +1738,19 @@ inline bool operator> (QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStri
inline bool operator>=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) >= rhs; }
// QStringView <> QLatin1String
inline bool operator==(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
inline bool operator==(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
inline bool operator!=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
inline bool operator< (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
inline bool operator<=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
inline bool operator> (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
inline bool operator>=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
inline bool operator< (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
inline bool operator<=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
inline bool operator> (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
inline bool operator>=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
inline bool operator==(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
inline bool operator==(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
inline bool operator!=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
inline bool operator< (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
inline bool operator<=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
inline bool operator> (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
inline bool operator>=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
inline bool operator< (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
inline bool operator<=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
inline bool operator> (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
inline bool operator>=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
// QStringRef <> QByteArray

View File

@ -53,31 +53,35 @@ class QLatin1String;
class QStringView;
template <typename T> class QVector;
namespace QtPrivate {
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView qTrimmed(QStringView s) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String qTrimmed(QLatin1String s) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToLatin1(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToUtf8(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToLocal8Bit(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> qConvertToUcs4(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> convertToUcs4(QStringView str);
} // namespace QtPRivate
QT_END_NAMESPACE

View File

@ -154,11 +154,11 @@ private:
++result;
}
#endif
return qustrlen(reinterpret_cast<const ushort *>(str));
return QtPrivate::qustrlen(reinterpret_cast<const ushort *>(str));
}
static qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
{
return qustrlen(reinterpret_cast<const ushort *>(str));
return QtPrivate::qustrlen(reinterpret_cast<const ushort *>(str));
}
template <typename Char>
@ -224,9 +224,9 @@ public:
// QString API
//
Q_REQUIRED_RESULT QByteArray toLatin1() const { return qConvertToLatin1(*this); }
Q_REQUIRED_RESULT QByteArray toUtf8() const { return qConvertToUtf8(*this); }
Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return qConvertToLocal8Bit(*this); }
Q_REQUIRED_RESULT QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
Q_REQUIRED_RESULT QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
Q_REQUIRED_RESULT inline QVector<uint> toUcs4() const; // defined in qvector.h
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar at(qssize_t n) const { return (*this)[n]; }
@ -247,23 +247,23 @@ public:
Q_DECL_RELAXED_CONSTEXPR void chop(qssize_t n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
Q_REQUIRED_RESULT QStringView trimmed() const Q_DECL_NOTHROW { return qTrimmed(*this); }
Q_REQUIRED_RESULT QStringView trimmed() const Q_DECL_NOTHROW { return QtPrivate::trimmed(*this); }
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qStartsWith(*this, s, cs); }
{ return QtPrivate::startsWith(*this, s, cs); }
Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
Q_REQUIRED_RESULT bool startsWith(QChar c) const Q_DECL_NOTHROW
{ return !empty() && front() == c; }
Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qStartsWith(*this, QStringView(&c, 1), cs); }
{ return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return qEndsWith(*this, s, cs); }
{ return QtPrivate::endsWith(*this, s, cs); }
Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
Q_REQUIRED_RESULT bool endsWith(QChar c) const Q_DECL_NOTHROW
{ return !empty() && back() == c; }
Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return qEndsWith(*this, QStringView(&c, 1), cs); }
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
//
// STL compatibility API:

View File

@ -1004,7 +1004,7 @@ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
#endif
QVector<uint> QStringView::toUcs4() const { return qConvertToUcs4(*this); }
QVector<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
QT_END_NAMESPACE

View File

@ -205,10 +205,10 @@ public:
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
inline QPoint pos() const { return p.toPoint(); }
inline QPoint globalPos() const { return g.toPoint(); }
inline int x() const { return p.x(); }
inline int y() const { return p.y(); }
inline int globalX() const { return g.x(); }
inline int globalY() const { return g.y(); }
inline int x() const { return int(p.x()); }
inline int y() const { return int(p.y()); }
inline int globalX() const { return int(g.x()); }
inline int globalY() const { return int(g.y()); }
#endif
inline const QPointF &posF() const { return p; }
inline const QPointF &globalPosF() const { return g; }

View File

@ -859,8 +859,8 @@ inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
{
float xin, yin;
float x, y, w;
xin = point.x();
yin = point.y();
xin = float(point.x());
yin = float(point.y());
x = xin * matrix.m[0][0] +
yin * matrix.m[0][1] +
matrix.m[0][3];
@ -1094,7 +1094,7 @@ inline float *QMatrix4x4::data()
inline void QMatrix4x4::viewport(const QRectF &rect)
{
viewport(rect.x(), rect.y(), rect.width(), rect.height());
viewport(float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()));
}
QT_WARNING_POP

View File

@ -210,8 +210,8 @@ inline QQuaternion QQuaternion::inverted() const
double(yp) * double(yp) +
double(zp) * double(zp);
if (!qFuzzyIsNull(len))
return QQuaternion(double(wp) / len, double(-xp) / len,
double(-yp) / len, double(-zp) / len);
return QQuaternion(float(double(wp) / len), float(double(-xp) / len),
float(double(-yp) / len), float(double(-zp) / len));
return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
}

View File

@ -137,7 +137,7 @@ Q_DECL_CONSTEXPR inline QVector2D::QVector2D(float xpos, float ypos) : xp(xpos),
Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPoint& point) : xp(point.x()), yp(point.y()) {}
Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPointF& point) : xp(point.x()), yp(point.y()) {}
Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())) {}
inline bool QVector2D::isNull() const
{

View File

@ -154,7 +154,7 @@ Q_DECL_CONSTEXPR inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())), zp(0.0f) {}
inline bool QVector3D::isNull() const
{

View File

@ -146,7 +146,7 @@ Q_DECL_CONSTEXPR inline QVector4D::QVector4D(float xpos, float ypos, float zpos,
Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())), zp(0.0f), wp(0.0f) {}
inline bool QVector4D::isNull() const
{

View File

@ -62,9 +62,88 @@ const char Http2clientPreface[clientPrefaceLength] =
0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a,
0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a};
QByteArray default_SETTINGS_to_Base64()
// TODO: (in 5.11) - remove it!
const char *http2ParametersPropertyName = "QT_HTTP2_PARAMETERS_PROPERTY";
ProtocolParameters::ProtocolParameters()
{
Frame frame(default_SETTINGS_frame());
settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = qtDefaultStreamReceiveWindowSize;
settingsFrameData[Settings::ENABLE_PUSH_ID] = 0;
}
bool ProtocolParameters::validate() const
{
// 0. Huffman/indexing: any values are valid and allowed.
// 1. Session receive window size (client side): HTTP/2 starts from the
// default value of 64Kb, if a client code tries to set lesser value,
// the delta would become negative, but this is not allowed.
if (maxSessionReceiveWindowSize < qint32(defaultSessionWindowSize)) {
qCWarning(QT_HTTP2, "Session receive window must be at least 65535 bytes");
return false;
}
// 2. HEADER_TABLE_SIZE: we do not validate HEADER_TABLE_SIZE, considering
// all values as valid. RFC 7540 and 7541 do not provide any lower/upper
// limits. If it's 0 - we do not index anything, if it's too huge - a user
// who provided such a value can potentially have a huge memory footprint,
// up to them to decide.
// 3. SETTINGS_ENABLE_PUSH: RFC 7540, 6.5.2, a value other than 0 or 1 will
// be treated by our peer as a PROTOCOL_ERROR.
if (settingsFrameData.contains(Settings::ENABLE_PUSH_ID)
&& settingsFrameData[Settings::ENABLE_PUSH_ID] > 1) {
qCWarning(QT_HTTP2, "SETTINGS_ENABLE_PUSH can be only 0 or 1");
return false;
}
// 4. SETTINGS_MAX_CONCURRENT_STREAMS : RFC 7540 recommends 100 as the lower
// limit, says nothing about the upper limit. The RFC allows 0, but this makes
// no sense to us at all: there is no way a user can change this later and
// we'll not be able to get any responses on such a connection.
if (settingsFrameData.contains(Settings::MAX_CONCURRENT_STREAMS_ID)
&& !settingsFrameData[Settings::MAX_CONCURRENT_STREAMS_ID]) {
qCWarning(QT_HTTP2, "MAX_CONCURRENT_STREAMS must be a positive number");
return false;
}
// 5. SETTINGS_INITIAL_WINDOW_SIZE.
if (settingsFrameData.contains(Settings::INITIAL_WINDOW_SIZE_ID)) {
const quint32 value = settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID];
// RFC 7540, 6.5.2 (the upper limit). The lower limit is our own - we send
// SETTINGS frame only once and will not be able to change this 0, thus
// we'll suspend all streams.
if (!value || value > quint32(maxSessionReceiveWindowSize)) {
qCWarning(QT_HTTP2, "INITIAL_WINDOW_SIZE must be in the range "
"(0, 2^31-1]");
return false;
}
}
// 6. SETTINGS_MAX_FRAME_SIZE: RFC 7540, 6.5.2, a value outside of the range
// [2^14-1, 2^24-1] will be treated by our peer as a PROTOCOL_ERROR.
if (settingsFrameData.contains(Settings::MAX_FRAME_SIZE_ID)) {
const quint32 value = settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID];
if (value < maxFrameSize || value > maxPayloadSize) {
qCWarning(QT_HTTP2, "MAX_FRAME_SIZE must be in the range [2^14, 2^24-1]");
return false;
}
}
// For SETTINGS_MAX_HEADER_LIST_SIZE RFC 7540 does not provide any specific
// numbers. It's clear, if a value is too small, no header can ever be sent
// by our peer at all. The default value is unlimited and we normally do not
// change this.
//
// Note: the size is calculated as the length of uncompressed (no HPACK)
// name + value + 32 bytes.
return true;
}
QByteArray ProtocolParameters::settingsFrameToBase64() const
{
Frame frame(settingsFrame());
// SETTINGS frame's payload consists of pairs:
// 2-byte-identifier | 4-byte-value == multiple of 6.
Q_ASSERT(frame.payloadSize() && !(frame.payloadSize() % 6));
@ -78,21 +157,35 @@ QByteArray default_SETTINGS_to_Base64()
return wrapper.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}
void prepare_for_protocol_upgrade(QHttpNetworkRequest &request)
Frame ProtocolParameters::settingsFrame() const
{
// 6.5 SETTINGS
FrameWriter builder(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID);
for (auto it = settingsFrameData.cbegin(), end = settingsFrameData.cend();
it != end; ++it) {
builder.append(it.key());
builder.append(it.value());
}
return builder.outboundFrame();
}
void ProtocolParameters::addProtocolUpgradeHeaders(QHttpNetworkRequest *request) const
{
Q_ASSERT(request);
// RFC 2616, 14.10
// RFC 7540, 3.2
QByteArray value(request.headerField("Connection"));
QByteArray value(request->headerField("Connection"));
// We _append_ 'Upgrade':
if (value.size())
value += ", ";
value += "Upgrade, HTTP2-Settings";
request.setHeaderField("Connection", value);
request->setHeaderField("Connection", value);
// This we just (re)write.
request.setHeaderField("Upgrade", "h2c");
request->setHeaderField("Upgrade", "h2c");
// This we just (re)write.
request.setHeaderField("HTTP2-Settings", default_SETTINGS_to_Base64());
request->setHeaderField("HTTP2-Settings", settingsFrameToBase64());
}
void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error,
@ -188,13 +281,6 @@ QNetworkReply::NetworkError qt_error(quint32 errorCode)
return error;
}
bool is_PUSH_PROMISE_enabled()
{
bool ok = false;
const int env = qEnvironmentVariableIntValue("QT_HTTP2_ENABLE_PUSH_PROMISE", &ok);
return ok && env;
}
bool is_protocol_upgraded(const QHttpNetworkReply &reply)
{
if (reply.statusCode() == 101) {
@ -209,21 +295,6 @@ bool is_protocol_upgraded(const QHttpNetworkReply &reply)
return false;
}
Frame default_SETTINGS_frame()
{
// 6.5 SETTINGS
FrameWriter builder(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID);
// MAX frame size (16 kb), disable/enable PUSH_PROMISE
builder.append(Settings::MAX_FRAME_SIZE_ID);
builder.append(quint32(maxFrameSize));
builder.append(Settings::INITIAL_WINDOW_SIZE_ID);
builder.append(initialStreamReceiveWindowSize);
builder.append(Settings::ENABLE_PUSH_ID);
builder.append(quint32(is_PUSH_PROMISE_enabled()));
return builder.outboundFrame();
}
} // namespace Http2
QT_END_NAMESPACE

View File

@ -53,6 +53,7 @@
#include <QtNetwork/qnetworkreply.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qglobal.h>
// Different HTTP/2 constants/values as defined by RFC 7540.
@ -61,6 +62,7 @@ QT_BEGIN_NAMESPACE
class QHttpNetworkRequest;
class QHttpNetworkReply;
class QByteArray;
class QString;
namespace Http2
@ -137,14 +139,54 @@ const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1
// sending WINDOW_UPDATE frames on a stream/session all the time, for each
// 2 DATE frames of size 16K (also default) we'll send a WINDOW_UPDATE frame
// for a given stream and have a download speed order of magnitude lower than
// our own HTTP/1.1 protocol handler. We choose a bigger window size (normally,
// HTTP/2 servers are not afraid to immediately set it to possible max anyway)
// and split this window size between our concurrent streams.
const qint32 initialSessionReceiveWindowSize = defaultSessionWindowSize * 10000;
const qint32 initialStreamReceiveWindowSize = initialSessionReceiveWindowSize / maxConcurrentStreams;
// our own HTTP/1.1 protocol handler. We choose a bigger window size: normally,
// HTTP/2 servers are not afraid to immediately set it to the possible max,
// we do the same and split this window size between our concurrent streams.
const qint32 maxSessionReceiveWindowSize((quint32(1) << 31) - 1);
const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / maxConcurrentStreams;
// The class ProtocolParameters allows client code to customize HTTP/2 protocol
// handler, if needed. Normally, we use our own default parameters (see below).
// In 5.10 we can also use setProperty/property on a QNAM object to pass the
// non-default values to the protocol handler. In 5.11 this will probably become
// a public API.
using RawSettings = QMap<Settings, quint32>;
struct Q_AUTOTEST_EXPORT ProtocolParameters
{
ProtocolParameters();
bool validate() const;
QByteArray settingsFrameToBase64() const;
struct Frame settingsFrame() const;
void addProtocolUpgradeHeaders(QHttpNetworkRequest *request) const;
// HPACK:
// TODO: for now we ignore them (fix it for 5.11, would require changes in HPACK)
bool useHuffman = true;
bool indexStrings = true;
// This parameter is not negotiated via SETTINGS frames, so we have it
// as a member and will convey it to our peer as a WINDOW_UPDATE frame:
qint32 maxSessionReceiveWindowSize = Http2::maxSessionReceiveWindowSize;
// This is our default SETTINGS frame:
//
// SETTINGS_INITIAL_WINDOW_SIZE: (2^31 - 1) / 100
// SETTINGS_ENABLE_PUSH: 0.
//
// Note, whenever we skip some value in our SETTINGS frame, our peer
// will assume the defaults recommended by RFC 7540, which in general
// are good enough, although we (and most browsers) prefer to work
// with larger window sizes.
RawSettings settingsFrameData;
};
// TODO: remove in 5.11
extern const Q_AUTOTEST_EXPORT char *http2ParametersPropertyName;
extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength];
void prepare_for_protocol_upgrade(QHttpNetworkRequest &request);
enum class FrameStatus
{
@ -182,14 +224,15 @@ enum Http2Error
void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error, QString &errorString);
QString qt_error_string(quint32 errorCode);
QNetworkReply::NetworkError qt_error(quint32 errorCode);
bool is_PUSH_PROMISE_enabled();
bool is_protocol_upgraded(const QHttpNetworkReply &reply);
struct Frame default_SETTINGS_frame();
}
} // namespace Http2
Q_DECLARE_LOGGING_CATEGORY(QT_HTTP2)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Http2::Settings)
Q_DECLARE_METATYPE(Http2::ProtocolParameters)
#endif

View File

@ -169,9 +169,34 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
decoder(HPack::FieldLookupTable::DefaultSize),
encoder(HPack::FieldLookupTable::DefaultSize, true)
{
Q_ASSERT(channel);
Q_ASSERT(channel && m_connection);
continuedFrames.reserve(20);
pushPromiseEnabled = is_PUSH_PROMISE_enabled();
const ProtocolParameters params(m_connection->http2Parameters());
Q_ASSERT(params.validate());
maxSessionReceiveWindowSize = params.maxSessionReceiveWindowSize;
const RawSettings &data = params.settingsFrameData;
for (auto param = data.cbegin(), end = data.cend(); param != end; ++param) {
switch (param.key()) {
case Settings::INITIAL_WINDOW_SIZE_ID:
streamInitialReceiveWindowSize = param.value();
break;
case Settings::ENABLE_PUSH_ID:
pushPromiseEnabled = param.value();
break;
case Settings::HEADER_TABLE_SIZE_ID:
case Settings::MAX_CONCURRENT_STREAMS_ID:
case Settings::MAX_FRAME_SIZE_ID:
case Settings::MAX_HEADER_LIST_SIZE_ID:
// These other settings are just recommendations to our peer. We
// only check they are not crazy in ProtocolParameters::validate().
default:
break;
}
}
if (!channel->ssl) {
// We upgraded from HTTP/1.1 to HTTP/2. channel->request was already sent
@ -361,20 +386,25 @@ bool QHttp2ProtocolHandler::sendClientPreface()
if (prefaceSent)
return true;
const qint64 written = m_socket->write(Http2clientPreface,
const qint64 written = m_socket->write(Http2::Http2clientPreface,
Http2::clientPrefaceLength);
if (written != Http2::clientPrefaceLength)
return false;
// 6.5 SETTINGS
frameWriter.setOutboundFrame(default_SETTINGS_frame());
const ProtocolParameters params(m_connection->http2Parameters());
Q_ASSERT(params.validate());
frameWriter.setOutboundFrame(params.settingsFrame());
Q_ASSERT(frameWriter.outboundFrame().payloadSize());
if (!frameWriter.write(*m_socket))
return false;
sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize;
const auto delta = Http2::initialSessionReceiveWindowSize - Http2::defaultSessionWindowSize;
sessionReceiveWindowSize = maxSessionReceiveWindowSize;
// ProtocolParameters::validate does not allow maxSessionReceiveWindowSize
// to be smaller than defaultSessionWindowSize, so everything is OK here with
// 'delta':
const auto delta = maxSessionReceiveWindowSize - Http2::defaultSessionWindowSize;
if (!sendWINDOW_UPDATE(Http2::connectionStreamID, delta))
return false;
@ -524,10 +554,10 @@ void QHttp2ProtocolHandler::handleDATA()
if (!activeStreams.contains(streamID) && !streamWasReset(streamID))
return connectionError(ENHANCE_YOUR_CALM, "DATA on invalid stream");
if (qint32(inboundFrame.payloadSize()) > sessionRecvWindowSize)
if (qint32(inboundFrame.payloadSize()) > sessionReceiveWindowSize)
return connectionError(FLOW_CONTROL_ERROR, "Flow control error");
sessionRecvWindowSize -= inboundFrame.payloadSize();
sessionReceiveWindowSize -= inboundFrame.payloadSize();
if (activeStreams.contains(streamID)) {
auto &stream = activeStreams[streamID];
@ -546,20 +576,20 @@ void QHttp2ProtocolHandler::handleDATA()
if (inboundFrame.flags().testFlag(FrameFlag::END_STREAM)) {
finishStream(stream);
deleteActiveStream(stream.streamID);
} else if (stream.recvWindow < Http2::initialStreamReceiveWindowSize / 2) {
} else if (stream.recvWindow < streamInitialReceiveWindowSize / 2) {
QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection,
Q_ARG(quint32, stream.streamID),
Q_ARG(quint32, Http2::initialStreamReceiveWindowSize - stream.recvWindow));
stream.recvWindow = Http2::initialStreamReceiveWindowSize;
Q_ARG(quint32, streamInitialReceiveWindowSize - stream.recvWindow));
stream.recvWindow = streamInitialReceiveWindowSize;
}
}
}
if (sessionRecvWindowSize < Http2::initialSessionReceiveWindowSize / 2) {
if (sessionReceiveWindowSize < maxSessionReceiveWindowSize / 2) {
QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection,
Q_ARG(quint32, connectionStreamID),
Q_ARG(quint32, Http2::initialSessionReceiveWindowSize - sessionRecvWindowSize));
sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize;
Q_ARG(quint32, maxSessionReceiveWindowSize - sessionReceiveWindowSize));
sessionReceiveWindowSize = maxSessionReceiveWindowSize;
}
}
@ -1200,7 +1230,7 @@ quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, b
const Stream newStream(message, newStreamID,
streamInitialSendWindowSize,
Http2::initialStreamReceiveWindowSize);
streamInitialReceiveWindowSize);
if (!uploadDone) {
if (auto src = newStream.data()) {
@ -1395,8 +1425,7 @@ bool QHttp2ProtocolHandler::tryReserveStream(const Http2::Frame &pushPromiseFram
promise.reservedID = reservedID;
promise.pushHeader = requestHeader;
activeStreams.insert(reservedID, Stream(urlKey, reservedID,
Http2::initialStreamReceiveWindowSize));
activeStreams.insert(reservedID, Stream(urlKey, reservedID, streamInitialReceiveWindowSize));
return true;
}
@ -1430,7 +1459,7 @@ void QHttp2ProtocolHandler::initReplyFromPushPromise(const HttpMessagePair &mess
// Let's pretent we're sending a request now:
Stream closedStream(message, promise.reservedID,
streamInitialSendWindowSize,
Http2::initialStreamReceiveWindowSize);
streamInitialReceiveWindowSize);
closedStream.state = Stream::halfClosedLocal;
activeStreams.insert(promise.reservedID, closedStream);
promisedStream = &activeStreams[promise.reservedID];

View File

@ -172,20 +172,38 @@ private:
bool continuationExpected = false;
std::vector<Http2::Frame> continuedFrames;
// Peer's max number of streams ...
quint32 maxConcurrentStreams = Http2::maxConcurrentStreams;
// Control flow:
// Signed integer, it can become negative (it's still a valid window size):
qint32 sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize;
// This is how many concurrent streams our peer expects from us:
// 100 is the default value, can be updated by the server's SETTINGS
// frame(s):
quint32 maxConcurrentStreams = Http2::maxConcurrentStreams;
// While we allow sending SETTTINGS_MAX_CONCURRENT_STREAMS to limit our peer,
// it's just a hint and we do not actually enforce it (and we can continue
// sending requests and creating streams while maxConcurrentStreams allows).
// Updated by SETTINGS and WINDOW_UPDATE.
// This is the max value, we set it in a ctor from Http2::ProtocolParameters,
// it does not change after that.
qint32 maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize;
// Our session receive window size, default is 64Kb. We'll update it from QNAM's
// Http2::ProtocolParameters. Signed integer since it can become negative
// (it's still a valid window size).
qint32 sessionReceiveWindowSize = Http2::defaultSessionWindowSize;
// Our per-stream receive window size, default is 64 Kb, will be updated
// from QNAM's Http2::ProtocolParameters. Again, signed - can become negative.
qint32 streamInitialReceiveWindowSize = Http2::defaultSessionWindowSize;
// These are our peer's receive window sizes, they will be updated by the
// peer's SETTINGS and WINDOW_UPDATE frames.
qint32 sessionSendWindowSize = Http2::defaultSessionWindowSize;
qint32 streamInitialSendWindowSize = Http2::defaultSessionWindowSize;
// It's unlimited by default, but can be changed via SETTINGS.
// Our peer's header size limitations. It's unlimited by default, but can
// be changed via peer's SETTINGS frame.
quint32 maxHeaderListSize = (std::numeric_limits<quint32>::max)();
// While we can send SETTINGS_MAX_HEADER_LIST_SIZE value (our limit on
// the headers size), we never enforce it, it's just a hint to our peer.
Q_INVOKABLE void resumeSuspendedStreams();
// Our stream IDs (all odd), the first valid will be 1.

View File

@ -435,7 +435,7 @@ QHttpMultiPartPrivate::QHttpMultiPartPrivate() : contentType(QHttpMultiPart::Mix
{
// 24 random bytes, becomes 32 characters when encoded to Base64
quint32 random[6];
QRandomGenerator::fillRange(random);
QRandomGenerator::global()->fillRange(random);
boundary = "boundary_.oOo._"
+ QByteArray::fromRawData(reinterpret_cast<char *>(random), sizeof(random)).toBase64();

View File

@ -1439,6 +1439,23 @@ void QHttpNetworkConnection::setConnectionType(ConnectionType type)
d->connectionType = type;
}
Http2::ProtocolParameters QHttpNetworkConnection::http2Parameters() const
{
Q_D(const QHttpNetworkConnection);
return d->http2Parameters;
}
void QHttpNetworkConnection::setHttp2Parameters(const Http2::ProtocolParameters &params)
{
Q_D(QHttpNetworkConnection);
if (params.validate()) {
d->http2Parameters = params;
} else {
qCWarning(QT_HTTP2)
<< "invalid HTTP/2 parameters, falling back to defaults instead";
}
}
// SSL support below
#ifndef QT_NO_SSL
void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config)

View File

@ -67,6 +67,7 @@
#include <private/qhttpnetworkheader_p.h>
#include <private/qhttpnetworkrequest_p.h>
#include <private/qhttpnetworkreply_p.h>
#include <private/http2protocol_p.h>
#include <private/qhttpnetworkconnectionchannel_p.h>
@ -140,6 +141,9 @@ public:
ConnectionType connectionType();
void setConnectionType(ConnectionType type);
Http2::ProtocolParameters http2Parameters() const;
void setHttp2Parameters(const Http2::ProtocolParameters &params);
#ifndef QT_NO_SSL
void setSslConfiguration(const QSslConfiguration &config);
void ignoreSslErrors(int channel = -1);
@ -283,6 +287,8 @@ public:
QSharedPointer<QNetworkSession> networkSession;
#endif
Http2::ProtocolParameters http2Parameters;
friend class QHttpNetworkConnectionChannel;
};

View File

@ -919,7 +919,9 @@ void QHttpNetworkConnectionChannel::_q_connected()
if (tryProtocolUpgrade) {
// Let's augment our request with some magic headers and try to
// switch to HTTP/2.
Http2::prepare_for_protocol_upgrade(request);
const Http2::ProtocolParameters params(connection->http2Parameters());
Q_ASSERT(params.validate());
params.addProtocolUpgradeHeaders(&request);
}
sendRequest();
}

View File

@ -339,7 +339,11 @@ void QHttpThreadDelegate::startRequest()
httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl,
connectionType,
networkSession);
#endif
#endif // QT_NO_BEARERMANAGEMENT
if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
&& http2Parameters.validate()) {
httpConnection->setHttp2Parameters(http2Parameters);
} // else we ignore invalid parameters and use our own defaults.
#ifndef QT_NO_SSL
// Set the QSslConfiguration from this QNetworkRequest.
if (ssl)
@ -365,7 +369,6 @@ void QHttpThreadDelegate::startRequest()
}
}
// Send the request to the connection
httpReply = httpConnection->sendRequest(httpRequest);
httpReply->setParent(this);

View File

@ -66,6 +66,7 @@
#include <QScopedPointer>
#include "private/qnoncontiguousbytedevice_p.h"
#include "qnetworkaccessauthenticationmanager_p.h"
#include <QtNetwork/private/http2protocol_p.h>
#ifndef QT_NO_HTTP
@ -115,6 +116,7 @@ public:
qint64 removedContentLength;
QNetworkReply::NetworkError incomingErrorCode;
QString incomingErrorDetail;
Http2::ProtocolParameters http2Parameters;
#ifndef QT_NO_BEARERMANAGEMENT
QSharedPointer<QNetworkSession> networkSession;
#endif

View File

@ -789,6 +789,10 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
// Create the HTTP thread delegate
QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
// Propagate Http/2 settings if any
const QVariant blob(manager->property(Http2::http2ParametersPropertyName));
if (blob.isValid() && blob.canConvert<Http2::ProtocolParameters>())
delegate->http2Parameters = blob.value<Http2::ProtocolParameters>();
#ifndef QT_NO_BEARERMANAGEMENT
delegate->networkSession = managerPrivate->getNetworkSession();
#endif

View File

@ -48,6 +48,7 @@
#include <qendian.h>
#include <qstring.h>
#include <qdatetime.h>
#include <qrandom.h>
#ifdef Q_OS_WIN
#include <qmutex.h>
@ -357,7 +358,7 @@ QAuthenticatorPrivate::QAuthenticatorPrivate()
, phase(Start)
, nonceCount(0)
{
cnonce = QCryptographicHash::hash(QByteArray::number(qrand(), 16) + QByteArray::number(qrand(), 16),
cnonce = QCryptographicHash::hash(QByteArray::number(QRandomGenerator::system()->generate64(), 16),
QCryptographicHash::Md5).toHex();
nonceCount = 0;
}

View File

@ -71,7 +71,6 @@ void WriteDeclaration::acceptUI(DomUI *node)
QString className = qualifiedClassName;
m_driver->findOrInsertWidget(node->elementWidget());
QString widgetClassName = node->elementWidget()->attributeClass();
QString exportMacro = node->elementExportMacro();
if (!exportMacro.isEmpty())

View File

@ -1265,7 +1265,7 @@ void WriteInitialization::writeProperties(const QString &varName,
if (stdset) {
setFunction = QLatin1String("->set")
+ propertyName.left(1).toUpper()
+ propertyName.at(0).toUpper()
+ propertyName.midRef(1)
+ QLatin1Char('(');
} else {

View File

@ -96,7 +96,9 @@ public:
}
QRectF closestAcceptableGeometry(const QRectF &rect) const override;
#if QT_CONFIG(opengl)
QOpenGLContext *shareContext() const override;
#endif
};
QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
@ -128,12 +130,14 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return result;
}
#if QT_CONFIG(opengl)
QOpenGLContext *QWidgetWindowPrivate::shareContext() const
{
Q_Q(const QWidgetWindow);
const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget());
return widgetPrivate->shareContext();
}
#endif // opengl
QWidgetWindow::QWidgetWindow(QWidget *widget)
: QWindow(*new QWidgetWindowPrivate(), 0)

View File

@ -364,7 +364,7 @@ void tst_QRandomGenerator::bounded()
QCOMPARE(ivalue, int(expected));
// confirm only the bound now
setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
setRNGControl(control & (SkipHWRNG|SkipSystemRNG));
value = QRandomGenerator::bounded(sup);
QVERIFY(value < sup);
@ -536,7 +536,6 @@ void tst_QRandomGenerator::stdUniformIntDistribution_data()
auto newRow = [](quint32 max) {
QTest::addRow("default:%u", max) << 0U << max;
QTest::addRow("direct:%u", max) << uint(SkipMemfill) << max;
QTest::addRow("system:%u", max) << uint(SkipHWRNG) << max;
#ifdef HAVE_FALLBACK_ENGINE
QTest::addRow("fallback:%u", max) << uint(SkipHWRNG | SkipSystemRNG) << max;
@ -555,7 +554,7 @@ void tst_QRandomGenerator::stdUniformIntDistribution()
{
QFETCH(uint, control);
QFETCH(quint32, max);
setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
setRNGControl(control & (SkipHWRNG|SkipSystemRNG));
{
QRandomGenerator rd;
@ -653,7 +652,6 @@ void tst_QRandomGenerator::stdUniformRealDistribution_data()
auto newRow = [](double min, double sup) {
QTest::addRow("default:%g-%g", min, sup) << 0U << min << sup;
QTest::addRow("direct:%g-%g", min, sup) << uint(SkipMemfill) << min << sup;
QTest::addRow("system:%g-%g", min, sup) << uint(SkipHWRNG) << min << sup;
#ifdef HAVE_FALLBACK_ENGINE
QTest::addRow("fallback:%g-%g", min, sup) << uint(SkipHWRNG | SkipSystemRNG) << min << sup;
@ -673,7 +671,7 @@ void tst_QRandomGenerator::stdUniformRealDistribution()
QFETCH(uint, control);
QFETCH(double, min);
QFETCH(double, sup);
setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
setRNGControl(control & (SkipHWRNG|SkipSystemRNG));
{
QRandomGenerator rd;

View File

@ -482,32 +482,6 @@ struct has_qCompareStrings {
!is_utf8_encoded<LHS>::value && !is_utf8_encoded<RHS>::value };
};
template <typename LHS, typename RHS>
using if_has_qCompareStrings = typename std::enable_if<has_qCompareStrings<LHS, RHS>::value, bool>::type;
template <typename LHS, typename RHS>
using if_lacks_qCompareStrings = typename std::enable_if<!has_qCompareStrings<LHS, RHS>::value, bool>::type;
static inline Q_DECL_CONSTEXPR int sign(int x) Q_DECL_NOTHROW
{
return x < 0 ? -1 :
x > 0 ? +1 :
/*else*/ 0 ;
}
template <typename LHS, typename RHS, if_has_qCompareStrings<LHS, RHS> = true>
int qCompareStringsWrapper(const LHS &lhs, const RHS &rhs, Qt::CaseSensitivity cs, int)
Q_DECL_NOEXCEPT_EXPR(noexcept(qCompareStrings(lhs, rhs, cs)))
{
return qCompareStrings(lhs, rhs, cs);
}
template <typename LHS, typename RHS, if_lacks_qCompareStrings<LHS, RHS> = true>
int qCompareStringsWrapper(const LHS &, const RHS &, Qt::CaseSensitivity, int result)
{
return result;
}
template <typename LHS, typename RHS>
void tst_QStringApiSymmetry::compare_impl() const
{
@ -517,6 +491,7 @@ void tst_QStringApiSymmetry::compare_impl() const
QFETCH(QLatin1String, rhsLatin1);
QFETCH(int, caseSensitiveCompareResult);
QFETCH(const int, caseInsensitiveCompareResult);
Q_UNUSED(caseInsensitiveCompareResult);
const auto lhsU8 = lhsUnicode.toUtf8();
const auto rhsU8 = rhsUnicode.toUtf8();
@ -533,10 +508,6 @@ void tst_QStringApiSymmetry::compare_impl() const
# define QVERIFY_NOEXCEPT(expr)
#endif
QCOMPARE(sign(qCompareStringsWrapper(lhs, rhs, Qt::CaseSensitive, caseSensitiveCompareResult)),
sign(caseSensitiveCompareResult));
QCOMPARE(sign(qCompareStringsWrapper(lhs, rhs, Qt::CaseInsensitive, caseInsensitiveCompareResult)),
sign(caseInsensitiveCompareResult));
#define CHECK(op) \
QVERIFY_NOEXCEPT(lhs op rhs); \
do { if (caseSensitiveCompareResult op 0) { \

View File

@ -64,7 +64,7 @@ public:
m_received.clear();
}
bool event(QEvent *event)
bool event(QEvent *event) override
{
m_received[event->type()]++;
return QWindow::event(event);

View File

@ -76,13 +76,11 @@ void fill_push_header(const HttpHeader &originalRequest, HttpHeader &promisedReq
}
Http2Server::Http2Server(bool h2c, const Http2Settings &ss, const Http2Settings &cs)
Http2Server::Http2Server(bool h2c, const Http2::RawSettings &ss, const Http2::RawSettings &cs)
: serverSettings(ss),
expectedClientSettings(cs),
clearTextHTTP2(h2c)
{
for (const auto &s : cs)
expectedClientSettings[quint16(s.identifier)] = s.value;
responseBody = "<html>\n"
"<head>\n"
"<title>Sample \"Hello, World\" Application</title>\n"
@ -159,11 +157,11 @@ void Http2Server::sendServerSettings()
return;
writer.start(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID);
for (const auto &s : serverSettings) {
writer.append(s.identifier);
writer.append(s.value);
if (s.identifier == Settings::INITIAL_WINDOW_SIZE_ID)
streamRecvWindowSize = s.value;
for (auto it = serverSettings.cbegin(); it != serverSettings.cend(); ++it) {
writer.append(it.key());
writer.append(it.value());
if (it.key() == Settings::INITIAL_WINDOW_SIZE_ID)
streamRecvWindowSize = it.value();
}
writer.write(*socket);
// Now, let's update our peer on a session recv window size:
@ -285,9 +283,9 @@ void Http2Server::incomingConnection(qintptr socketDescriptor)
quint32 Http2Server::clientSetting(Http2::Settings identifier, quint32 defaultValue)
{
const auto it = expectedClientSettings.find(quint16(identifier));
const auto it = expectedClientSettings.find(identifier);
if (it != expectedClientSettings.end())
return it->second;
return it.value();
return defaultValue;
}
@ -623,7 +621,7 @@ void Http2Server::handleSETTINGS()
const auto notFound = expectedClientSettings.end();
while (src != end) {
const auto id = qFromBigEndian<quint16>(src);
const auto id = Http2::Settings(qFromBigEndian<quint16>(src));
const auto value = qFromBigEndian<quint32>(src + 2);
if (expectedClientSettings.find(id) == notFound ||
expectedClientSettings[id] != value) {

View File

@ -48,19 +48,6 @@
QT_BEGIN_NAMESPACE
struct Http2Setting
{
Http2::Settings identifier;
quint32 value = 0;
Http2Setting(Http2::Settings ident, quint32 v)
: identifier(ident),
value(v)
{}
};
using Http2Settings = std::vector<Http2Setting>;
// At the moment we do not have any public API parsing HTTP headers. Even worse -
// the code that can do this exists only in QHttpNetworkReplyPrivate class.
// To be able to access reply's d_func() we have these classes:
@ -78,8 +65,8 @@ class Http2Server : public QTcpServer
{
Q_OBJECT
public:
Http2Server(bool clearText, const Http2Settings &serverSettings,
const Http2Settings &clientSettings);
Http2Server(bool clearText, const Http2::RawSettings &serverSettings,
const Http2::RawSettings &clientSettings);
~Http2Server();
@ -144,8 +131,8 @@ private:
bool settingsSent = false;
bool waitingClientAck = false;
Http2Settings serverSettings;
std::map<quint16, quint32> expectedClientSettings;
Http2::RawSettings serverSettings;
Http2::RawSettings expectedClientSettings;
bool connectionError = false;

View File

@ -30,6 +30,7 @@
#include "http2srv.h"
#include <QtNetwork/private/http2protocol_p.h>
#include <QtNetwork/qnetworkaccessmanager.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
@ -96,8 +97,8 @@ private:
// small payload.
void runEventLoop(int ms = 5000);
void stopEventLoop();
Http2Server *newServer(const Http2Settings &serverSettings,
const Http2Settings &clientSettings = defaultClientSettings);
Http2Server *newServer(const Http2::RawSettings &serverSettings,
const Http2::ProtocolParameters &clientSettings = {});
// Send a get or post request, depending on a payload (empty or not).
void sendRequest(int streamNumber,
QNetworkRequest::Priority priority = QNetworkRequest::NormalPriority,
@ -118,14 +119,10 @@ private:
bool prefaceOK = false;
bool serverGotSettingsACK = false;
static const Http2Settings defaultServerSettings;
static const Http2Settings defaultClientSettings;
static const Http2::RawSettings defaultServerSettings;
};
const Http2Settings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}};
const Http2Settings tst_Http2::defaultClientSettings{{Http2::Settings::MAX_FRAME_SIZE_ID, quint32(Http2::maxFrameSize)},
{Http2::Settings::INITIAL_WINDOW_SIZE_ID, quint32(Http2::initialStreamReceiveWindowSize)},
{Http2::Settings::ENABLE_PUSH_ID, quint32(0)}};
const Http2::RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}};
namespace {
@ -142,27 +139,6 @@ struct ServerDeleter
using ServerPtr = QScopedPointer<Http2Server, ServerDeleter>;
struct EnvVarGuard
{
EnvVarGuard(const char *name, const QByteArray &value)
: varName(name),
prevValue(qgetenv(name))
{
Q_ASSERT(name);
qputenv(name, value);
}
~EnvVarGuard()
{
if (prevValue.size())
qputenv(varName.c_str(), prevValue);
else
qunsetenv(varName.c_str());
}
const std::string varName;
const QByteArray prevValue;
};
} // unnamed namespace
tst_Http2::tst_Http2()
@ -241,9 +217,11 @@ void tst_Http2::multipleRequests()
// Just to make the order a bit more interesting
// we'll index this randomly:
QNetworkRequest::Priority priorities[] = {QNetworkRequest::HighPriority,
QNetworkRequest::NormalPriority,
QNetworkRequest::LowPriority};
const QNetworkRequest::Priority priorities[] = {
QNetworkRequest::HighPriority,
QNetworkRequest::NormalPriority,
QNetworkRequest::LowPriority
};
for (int i = 0; i < nRequests; ++i)
sendRequest(i, priorities[std::rand() % 3]);
@ -258,11 +236,11 @@ void tst_Http2::multipleRequests()
void tst_Http2::flowControlClientSide()
{
// Create a server but impose limits:
// 1. Small MAX frame size, so we test CONTINUATION frames.
// 2. Small client windows so server responses cause client streams
// to suspend and server sends WINDOW_UPDATE frames.
// 3. Few concurrent streams, to test protocol handler can resume
// suspended requests.
// 1. Small client receive windows so server's responses cause client
// streams to suspend and protocol handler has to send WINDOW_UPDATE
// frames.
// 2. Few concurrent streams supported by the server, to test protocol
// handler in the client can suspend and then resume streams.
using namespace Http2;
clearHTTP2State();
@ -271,11 +249,20 @@ void tst_Http2::flowControlClientSide()
nRequests = 10;
windowUpdates = 0;
const Http2Settings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 3}};
Http2::ProtocolParameters params;
// A small window size for a session, and even a smaller one per stream -
// this will result in WINDOW_UPDATE frames both on connection stream and
// per stream.
params.maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize * 5;
params.settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = Http2::defaultSessionWindowSize;
// Inform our manager about non-default settings:
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
ServerPtr srv(newServer(serverSettings));
const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}};
ServerPtr srv(newServer(serverSettings, params));
const QByteArray respond(int(Http2::initialStreamReceiveWindowSize * 5), 'x');
const QByteArray respond(int(Http2::defaultSessionWindowSize * 10), 'x');
srv->setResponseBody(respond);
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
@ -309,7 +296,7 @@ void tst_Http2::flowControlServerSide()
serverPort = 0;
nRequests = 30;
const Http2Settings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 7}};
const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 7}};
ServerPtr srv(newServer(serverSettings));
@ -341,12 +328,12 @@ void tst_Http2::pushPromise()
serverPort = 0;
nRequests = 1;
const EnvVarGuard env("QT_HTTP2_ENABLE_PUSH_PROMISE", "1");
const Http2Settings clientSettings{{Settings::MAX_FRAME_SIZE_ID, quint32(Http2::maxFrameSize)},
{Http2::Settings::INITIAL_WINDOW_SIZE_ID, quint32(Http2::initialStreamReceiveWindowSize)},
{Settings::ENABLE_PUSH_ID, quint32(1)}};
Http2::ProtocolParameters params;
// Defaults are good, except ENABLE_PUSH:
params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1;
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
ServerPtr srv(newServer(defaultServerSettings, clientSettings));
ServerPtr srv(newServer(defaultServerSettings, params));
srv->enablePushPromise(true, QByteArray("/script.js"));
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
@ -420,7 +407,7 @@ void tst_Http2::goaway()
serverPort = 0;
nRequests = 3;
ServerPtr srv(newServer(defaultServerSettings, defaultClientSettings));
ServerPtr srv(newServer(defaultServerSettings));
srv->emulateGOAWAY(responseTimeoutMS);
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
runEventLoop();
@ -463,6 +450,7 @@ void tst_Http2::clearHTTP2State()
windowUpdates = 0;
prefaceOK = false;
serverGotSettingsACK = false;
manager.setProperty(Http2::http2ParametersPropertyName, QVariant());
}
void tst_Http2::runEventLoop(int ms)
@ -478,11 +466,12 @@ void tst_Http2::stopEventLoop()
eventLoop.quit();
}
Http2Server *tst_Http2::newServer(const Http2Settings &serverSettings,
const Http2Settings &clientSettings)
Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings,
const Http2::ProtocolParameters &clientSettings)
{
using namespace Http2;
auto srv = new Http2Server(clearTextHTTP2, serverSettings, clientSettings);
auto srv = new Http2Server(clearTextHTTP2, serverSettings,
clientSettings.settingsFrameData);
using Srv = Http2Server;
using Cl = tst_Http2;

View File

@ -187,7 +187,7 @@ void tst_QHostInfo::initTestCase()
networkSession.reset(new QNetworkSession(networkConfiguration));
if (!networkSession->isOpen()) {
networkSession->open();
QVERIFY(networkSession->waitForOpened(30000));
networkSession->waitForOpened(30000);
}
#endif

View File

@ -224,15 +224,12 @@ public:
return index.isValid() ? qint32(index.internalId()) : qint32(-1);
}
bool canFetchMore(const QModelIndex &) const {
return !fetched;
}
bool canFetchMore(const QModelIndex &) const override { return !fetched; }
void fetchMore(const QModelIndex &) {
fetched = true;
}
void fetchMore(const QModelIndex &) override { fetched = true; }
bool hasChildren(const QModelIndex &parent = QModelIndex()) const {
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override
{
bool hasFetched = fetched;
fetched = true;
bool r = QAbstractItemModel::hasChildren(parent);
@ -240,14 +237,16 @@ public:
return r;
}
int rowCount(const QModelIndex& parent = QModelIndex()) const {
int rowCount(const QModelIndex& parent = QModelIndex()) const override
{
if (!fetched)
qFatal("%s: rowCount should not be called before fetching", Q_FUNC_INFO);
if ((parent.column() > 0) || (level(parent) > levels))
return 0;
return rows;
}
int columnCount(const QModelIndex& parent = QModelIndex()) const {
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{
if ((parent.column() > 0) || (level(parent) > levels))
return 0;
return cols;
@ -259,7 +258,7 @@ public:
return false;
}
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
{
if (row < 0 || column < 0 || (level(parent) > levels) || column >= cols || row >= rows) {
return QModelIndex();
@ -269,14 +268,14 @@ public:
return i;
}
QModelIndex parent(const QModelIndex &index) const
QModelIndex parent(const QModelIndex &index) const override
{
if (!parentHash.contains(index))
return QModelIndex();
return parentHash[index];
}
QVariant data(const QModelIndex &idx, int role) const
QVariant data(const QModelIndex &idx, int role) const override
{
if (!idx.isValid())
return QVariant();

View File

@ -2604,30 +2604,20 @@ namespace {
class MyPaintEngine : public QPaintEngine
{
public:
bool begin(QPaintDevice *)
{
return true;
}
bool begin(QPaintDevice *) override { return true; }
bool end()
{
return true;
}
bool end() override { return true; }
void updateState(const QPaintEngineState &)
{
}
void updateState(const QPaintEngineState &) override { }
void drawPixmap(const QRectF &, const QPixmap &, const QRectF &)
{
}
void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) override { }
void drawTextItem(const QPointF &, const QTextItem &textItem) override
{
itemFonts.append(qMakePair(textItem.text(), textItem.font()));
}
Type type() const { return User; }
Type type() const override { return User; }
QList<QPair<QString, QFont> > itemFonts;