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: Id2e817e85f85c68f5482c9a12912d35590f9d5f8bb10
commit
a7e4b645dc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ linux:!static {
|
|||
} else {
|
||||
SOURCES += global/minimum-linux.S
|
||||
}
|
||||
HEADERS += global/minimum-linux_p.h
|
||||
}
|
||||
|
||||
qtConfig(slog2): \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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, -) \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
|
|||
return seed;
|
||||
}
|
||||
|
||||
seed = QRandomGenerator::generate();
|
||||
seed = QRandomGenerator::system()->generate();
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
return seed;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ¶ms)
|
||||
{
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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 ¶ms);
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) { \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue