Merge "Merge remote-tracking branch 'origin/dev' into 5.11" into refs/staging/5.11
commit
095dbc494c
|
|
@ -119,6 +119,11 @@ Build options:
|
|||
|
||||
-testcocoon .......... Instrument with the TestCocoon code coverage tool [no]
|
||||
-gcov ................ Instrument with the GCov code coverage tool [no]
|
||||
|
||||
-trace [backend] ..... Enable instrumentation with tracepoints.
|
||||
Currently supported backends are 'etw' (Windows) and
|
||||
'lttng' (Linux), or 'yes' for auto-detection. [no]
|
||||
|
||||
-sanitize {address|thread|memory|undefined}
|
||||
Instrument with the specified compiler sanitizer.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ CONFIG += no_docs_target
|
|||
|
||||
SUBDIRS = \
|
||||
ipc \
|
||||
json \
|
||||
mimetypes \
|
||||
serialization \
|
||||
threads \
|
||||
tools
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ CONFIG -= app_bundle
|
|||
TEMPLATE = app
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/json/savegame
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/savegame
|
||||
INSTALLS += target
|
||||
|
||||
SOURCES += main.cpp \
|
||||
|
|
@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) {
|
|||
}
|
||||
|
||||
# Default directories to process
|
||||
QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR
|
||||
QMAKE_DIR_REPLACE_SANE += QGLTF_DIR
|
||||
QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR
|
||||
QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ OBJECTS_DIR = .obj
|
|||
MOC_DIR = .moc
|
||||
RCC_DIR = .rcc
|
||||
UI_DIR = .uic
|
||||
TRACEGEN_DIR = .tracegen
|
||||
intel_icl {
|
||||
# ICL 14.0 has a bug that makes it not find #includes in dirs starting with .
|
||||
MOC_DIR = tmp/moc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
# W A R N I N G
|
||||
# -------------
|
||||
#
|
||||
# This file is not part of the Qt API. It exists purely as an
|
||||
# implementation detail. It may change from version to version
|
||||
# without notice, or even be removed.
|
||||
#
|
||||
# We mean it.
|
||||
#
|
||||
|
||||
qtPrepareTool(QMAKE_TRACEGEN, tracegen)
|
||||
|
||||
isEmpty(TRACEGEN_DIR): TRACEGEN_DIR = .
|
||||
|
||||
PROVIDER_NAME = qt$$lower($$MODULE)
|
||||
INCLUDEPATH += $$absolute_path($$TRACEGEN_DIR, $$OUT_PWD)
|
||||
HEADER_PATH = $$OUT_PWD/$$TRACEGEN_DIR/$${PROVIDER_NAME}_tracepoints_p$${first(QMAKE_EXT_H)}
|
||||
|
||||
!force_bootstrap:if(qtConfig(lttng)|qtConfig(etw)) {
|
||||
SOURCE_PATH = $$OUT_PWD/$$TRACEGEN_DIR/$${PROVIDER_NAME}_tracepoints$${first(QMAKE_EXT_CPP)}
|
||||
|
||||
isEmpty(BUILDS)|build_pass {
|
||||
impl_file_contents = \
|
||||
"$${LITERAL_HASH}define TRACEPOINT_CREATE_PROBES" \
|
||||
"$${LITERAL_HASH}define TRACEPOINT_DEFINE" \
|
||||
"$${LITERAL_HASH}include \"$${HEADER_PATH}\""
|
||||
|
||||
write_file($$SOURCE_PATH, impl_file_contents)|error()
|
||||
}
|
||||
|
||||
GENERATED_SOURCES += $$SOURCE_PATH
|
||||
|
||||
tracegen.input = TRACEPOINT_PROVIDER
|
||||
tracegen.output = $$HEADER_PATH
|
||||
tracegen.variable_out = HEADERS
|
||||
tracegen.depends += $$QMAKE_TRACEGEN_EXE
|
||||
tracegen.CONFIG = target_predeps
|
||||
|
||||
qtConfig(lttng) {
|
||||
tracegen.commands = $$QMAKE_TRACEGEN lttng ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
|
||||
QMAKE_USE_PRIVATE += lttng-ust
|
||||
} else {
|
||||
tracegen.commands = $$QMAKE_TRACEGEN etw ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
|
||||
}
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += tracegen
|
||||
|
||||
DEFINES += Q_TRACEPOINT
|
||||
} else {
|
||||
isEmpty(BUILDS)|build_pass {
|
||||
header_file_contents = "$${LITERAL_HASH}include <private/qtrace_p.h>"
|
||||
write_file($$HEADER_PATH, header_file_contents)|error()
|
||||
}
|
||||
}
|
||||
|
|
@ -77,7 +77,6 @@ DEPEND_SRC = \
|
|||
$(SOURCE_PATH)/src/corelib/global/qrandom.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qdatastream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qdir.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \
|
||||
|
|
@ -91,18 +90,21 @@ DEPEND_SRC = \
|
|||
$(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qsettings.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qtextstream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjson.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsonarray.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjson.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsondocument.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsonobject.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsonparser.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qjsonvalue.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
|
||||
|
|
@ -123,8 +125,6 @@ DEPEND_SRC = \
|
|||
$(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \
|
||||
$(QTSRCS) $(QTSRCS2)
|
||||
# QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this
|
||||
# by configure); QTSRCS2 may include *.mm entries on macOS.
|
||||
|
|
@ -256,9 +256,6 @@ projectgenerator.o: $(QMKSRC)/generators/projectgenerator.cpp
|
|||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
||||
qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
|
@ -367,9 +364,6 @@ qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp
|
|||
qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
|
@ -454,34 +448,40 @@ qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
|
|||
qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjson.o: $(SOURCE_PATH)/src/corelib/json/qjson.cpp
|
||||
qdatastream.o: $(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsondocument.o: $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
|
||||
qjson.o: $(SOURCE_PATH)/src/corelib/serialization/qjson.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsonparser.o: $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
|
||||
qjsondocument.o: $(SOURCE_PATH)/src/corelib/serialization/qjsondocument.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsonarray.o: $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
|
||||
qjsonparser.o: $(SOURCE_PATH)/src/corelib/serialization/qjsonparser.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsonobject.o: $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
|
||||
qjsonarray.o: $(SOURCE_PATH)/src/corelib/serialization/qjsonarray.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsonvalue.o: $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
|
||||
qjsonobject.o: $(SOURCE_PATH)/src/corelib/serialization/qjsonobject.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qjsonvalue.o: $(SOURCE_PATH)/src/corelib/serialization/qjsonvalue.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qxmlstream.o: $(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qxmlutils.o: $(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qtextstream.o: $(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it
|
||||
|
|
|
|||
|
|
@ -197,15 +197,12 @@ qmake_pch.obj:
|
|||
{$(SOURCE_PATH)\src\corelib\plugin}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
{$(SOURCE_PATH)\src\corelib\serialization}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
{$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
{$(SOURCE_PATH)\src\corelib\xml}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
{$(SOURCE_PATH)\src\corelib\json}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
# Make sure qstring_compat.obj and qlibraryinfo.obj aren't compiled with PCH enabled
|
||||
qstring_compat.obj: $(SOURCE_PATH)\src\corelib\tools\qstring_compat.cpp
|
||||
$(CXX) -c $(CXXFLAGS_BARE) $(SOURCE_PATH)\src\corelib\tools\qstring_compat.cpp
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ VPATH += \
|
|||
../src/corelib/kernel \
|
||||
../src/corelib/codecs \
|
||||
../src/corelib/plugin \
|
||||
../src/corelib/xml \
|
||||
../src/corelib/io \
|
||||
../src/corelib/json \
|
||||
../src/corelib/serialization \
|
||||
../tools/shared/windows
|
||||
|
||||
INCLUDEPATH += . \
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
"posix-ipc": { "type": "boolean", "name": "ipc_posix" },
|
||||
"pps": { "type": "boolean", "name": "qqnx_pps" },
|
||||
"slog2": "boolean",
|
||||
"syslog": "boolean"
|
||||
"syslog": "boolean",
|
||||
"trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] }
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -147,6 +148,18 @@
|
|||
"-lrt"
|
||||
]
|
||||
},
|
||||
"lttng-ust": {
|
||||
"label": "lttng-ust",
|
||||
"test": {
|
||||
"include": "lttng/ust-events.h",
|
||||
"main": "lttng_session_destroy(nullptr);"
|
||||
},
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "lttng-ust" },
|
||||
"-llttng-ust"
|
||||
],
|
||||
"use": "libdl"
|
||||
},
|
||||
"pcre2": {
|
||||
"label": "PCRE2",
|
||||
"test": {
|
||||
|
|
@ -858,6 +871,22 @@
|
|||
"section": "Utilities",
|
||||
"output": [ "publicFeature" ]
|
||||
},
|
||||
"lttng": {
|
||||
"label": "LTTNG",
|
||||
"autoDetect": false,
|
||||
"enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)",
|
||||
"disable": "input.trace == 'etw' || input.trace =='no'",
|
||||
"condition": "config.linux && libs.lttng-ust",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"etw": {
|
||||
"label": "ETW",
|
||||
"autoDetect": false,
|
||||
"enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)",
|
||||
"disable": "input.trace == 'lttng' || input.trace == 'no'",
|
||||
"condition": "config.win32",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"topleveldomain": {
|
||||
"label": "QUrl::topLevelDomain()",
|
||||
"purpose": "Provides support for extracting the top level domain from URLs.
|
||||
|
|
@ -907,6 +936,11 @@ Please apply the patch corresponding to your Standard Library vendor, found in
|
|||
"glib",
|
||||
"iconv",
|
||||
"icu",
|
||||
{
|
||||
"message": "Tracing backend",
|
||||
"type": "firstAvailableFeature",
|
||||
"args": "etw lttng"
|
||||
},
|
||||
{
|
||||
"section": "Logging backends",
|
||||
"entries": [
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ MODULE = core # not corelib, as per project file
|
|||
MODULE_CONFIG = moc resources
|
||||
!isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE
|
||||
|
||||
TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints
|
||||
CONFIG += qt_tracepoints
|
||||
|
||||
CONFIG += $$MODULE_CONFIG
|
||||
DEFINES += $$MODULE_DEFINES
|
||||
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
|
||||
|
|
@ -35,13 +38,12 @@ include(thread/thread.pri)
|
|||
include(tools/tools.pri)
|
||||
include(io/io.pri)
|
||||
include(itemmodels/itemmodels.pri)
|
||||
include(json/json.pri)
|
||||
include(plugin/plugin.pri)
|
||||
include(kernel/kernel.pri)
|
||||
include(codecs/codecs.pri)
|
||||
include(serialization/serialization.pri)
|
||||
include(statemachine/statemachine.pri)
|
||||
include(mimetypes/mimetypes.pri)
|
||||
include(xml/xml.pri)
|
||||
|
||||
win32 {
|
||||
LIBS_PRIVATE += -lws2_32
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@
|
|||
#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
|
||||
#define QT_NO_DATASTREAM
|
||||
#define QT_FEATURE_datetimeparser -1
|
||||
#define QT_FEATURE_etw -1
|
||||
#define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1)
|
||||
#define QT_FEATURE_getentropy -1
|
||||
#define QT_NO_GEOM_VARIANT
|
||||
|
|
@ -92,6 +93,7 @@
|
|||
#else
|
||||
# define QT_FEATURE_linkat -1
|
||||
#endif
|
||||
#define QT_FEATURE_lttng -1
|
||||
#define QT_NO_QOBJECT
|
||||
#define QT_FEATURE_process -1
|
||||
#define QT_FEATURE_regularexpression -1
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_N
|
|||
#endif
|
||||
/*!
|
||||
\since 5.11
|
||||
\relates <QFloat16>
|
||||
|
||||
Converts \a len floats from \a in to qfloat16 and stores them in \a out.
|
||||
Both \a in and \a out must have \a len allocated entries.
|
||||
|
|
@ -193,6 +194,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
|
|||
|
||||
/*!
|
||||
\since 5.11
|
||||
\relates <QFloat16>
|
||||
|
||||
Converts \a len qfloat16 from \a in to floats and stores them in \a out.
|
||||
Both \a in and \a out must have \a len allocated entries.
|
||||
|
|
|
|||
|
|
@ -88,6 +88,11 @@
|
|||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
# define QT_NO_UNSHARABLE_CONTAINERS
|
||||
# define QT6_VIRTUAL virtual
|
||||
# define QT6_NOT_VIRTUAL
|
||||
#else
|
||||
# define QT6_VIRTUAL
|
||||
# define QT6_NOT_VIRTUAL virtual
|
||||
#endif
|
||||
|
||||
/* These two macros makes it possible to turn the builtin line expander into a
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Intel Corporation.
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -58,8 +58,6 @@
|
|||
|
||||
#if defined(Q_CC_MSVC)
|
||||
# include <intrin.h>
|
||||
#elif defined(Q_CC_INTEL)
|
||||
# include <immintrin.h> // for _addcarry_u<nn>
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_MSVC)
|
||||
|
|
@ -164,10 +162,33 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
|
|||
}
|
||||
|
||||
#ifndef Q_CLANG_QDOC
|
||||
//
|
||||
// Unsigned overflow math
|
||||
//
|
||||
namespace {
|
||||
// Overflow math.
|
||||
// This provides efficient implementations for int, unsigned, qsizetype and
|
||||
// size_t. Implementations for 8- and 16-bit types will work but may not be as
|
||||
// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
|
||||
|
||||
#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || defined(Q_CC_INTEL)) || QT_HAS_BUILTIN(__builtin_add_overflowx)
|
||||
// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
|
||||
|
||||
template <typename T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
||||
add_overflow(T v1, T v2, T *r)
|
||||
{ return __builtin_add_overflow(v1, v2, r); }
|
||||
|
||||
template <typename T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
||||
sub_overflow(T v1, T v2, T *r)
|
||||
{ return __builtin_sub_overflow(v1, v2, r); }
|
||||
|
||||
template <typename T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
||||
mul_overflow(T v1, T v2, T *r)
|
||||
{ return __builtin_mul_overflow(v1, v2, r); }
|
||||
|
||||
#else
|
||||
// Generic implementations
|
||||
|
||||
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
|
||||
add_overflow(T v1, T v2, T *r)
|
||||
{
|
||||
|
|
@ -176,69 +197,92 @@ add_overflow(T v1, T v2, T *r)
|
|||
return v1 > T(v1 + v2);
|
||||
}
|
||||
|
||||
template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
|
||||
add_overflow(T v1, T v2, T *r)
|
||||
{
|
||||
// Here's how we calculate the overflow:
|
||||
// 1) unsigned addition is well-defined, so we can always execute it
|
||||
// 2) conversion from unsigned back to signed is implementation-
|
||||
// defined and in the implementations we use, it's a no-op.
|
||||
// 3) signed integer overflow happens if the sign of the two input operands
|
||||
// is the same but the sign of the result is different. In other words,
|
||||
// the sign of the result must be the same as the sign of either
|
||||
// operand.
|
||||
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
*r = T(U(v1) + U(v2));
|
||||
|
||||
// If int is two's complement, assume all integer types are too.
|
||||
if (std::is_same<int32_t, int>::value) {
|
||||
// Two's complement equivalent (generates slightly shorter code):
|
||||
// x ^ y is negative if x and y have different signs
|
||||
// x & y is negative if x and y are negative
|
||||
// (x ^ z) & (y ^ z) is negative if x and z have different signs
|
||||
// AND y and z have different signs
|
||||
return ((v1 ^ *r) & (v2 ^ *r)) < 0;
|
||||
}
|
||||
|
||||
bool s1 = (v1 < 0);
|
||||
bool s2 = (v2 < 0);
|
||||
bool sr = (*r < 0);
|
||||
return s1 != sr && s2 != sr;
|
||||
// also: return s1 == s2 && s1 != sr;
|
||||
}
|
||||
|
||||
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
|
||||
sub_overflow(T v1, T v2, T *r)
|
||||
{
|
||||
// unsigned subtractions are well-defined
|
||||
*r = v1 - v2;
|
||||
return v1 < v2;
|
||||
}
|
||||
|
||||
template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
|
||||
sub_overflow(T v1, T v2, T *r)
|
||||
{
|
||||
// See above for explanation. This is the same with some signs reversed.
|
||||
// We can't use add_overflow(v1, -v2, r) because it would be UB if
|
||||
// v2 == std::numeric_limits<T>::min().
|
||||
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
*r = T(U(v1) - U(v2));
|
||||
|
||||
if (std::is_same<int32_t, int>::value)
|
||||
return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
|
||||
|
||||
bool s1 = (v1 < 0);
|
||||
bool s2 = !(v2 < 0);
|
||||
bool sr = (*r < 0);
|
||||
return s1 != sr && s2 != sr;
|
||||
// also: return s1 == s2 && s1 != sr;
|
||||
}
|
||||
|
||||
template <typename T> inline
|
||||
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
||||
mul_overflow(T v1, T v2, T *r)
|
||||
{
|
||||
// use the next biggest type
|
||||
// Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
|
||||
// A fallback is present below.
|
||||
typedef typename QIntegerForSize<sizeof(T) * 2>::Unsigned Larger;
|
||||
using LargerInt = QIntegerForSize<sizeof(T) * 2>;
|
||||
using Larger = typename std::conditional<std::is_signed<T>::value,
|
||||
typename LargerInt::Signed, typename LargerInt::Unsigned>::type;
|
||||
Larger lr = Larger(v1) * Larger(v2);
|
||||
*r = T(lr);
|
||||
return lr > std::numeric_limits<T>::max();
|
||||
return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min();
|
||||
}
|
||||
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
# define HAVE_MUL64_OVERFLOW
|
||||
#endif
|
||||
|
||||
// GCC 5 and Clang have builtins to detect overflows
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uadd_overflow)
|
||||
template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
|
||||
{ return __builtin_uadd_overflow(v1, v2, r); }
|
||||
#endif
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddl_overflow)
|
||||
template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
|
||||
{ return __builtin_uaddl_overflow(v1, v2, r); }
|
||||
#endif
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddll_overflow)
|
||||
template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
|
||||
{ return __builtin_uaddll_overflow(v1, v2, r); }
|
||||
#endif
|
||||
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umul_overflow)
|
||||
template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r)
|
||||
{ return __builtin_umul_overflow(v1, v2, r); }
|
||||
#endif
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umull_overflow)
|
||||
template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
|
||||
{ return __builtin_umull_overflow(v1, v2, r); }
|
||||
#endif
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umulll_overflow)
|
||||
template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
|
||||
{ return __builtin_umulll_overflow(v1, v2, r); }
|
||||
# define HAVE_MUL64_OVERFLOW
|
||||
#endif
|
||||
|
||||
#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
|
||||
# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
|
||||
// We can use intrinsics for the unsigned operations with MSVC
|
||||
template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
|
||||
{ return _addcarry_u32(0, v1, v2, r); }
|
||||
# ifdef Q_CC_MSVC // longs are 32-bit
|
||||
template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
|
||||
{ return _addcarry_u32(0, v1, v2, reinterpret_cast<unsigned *>(r)); }
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
|
||||
|
||||
// 32-bit mul_overflow is fine with the generic code above
|
||||
|
||||
# if defined(Q_PROCESSOR_X86_64)
|
||||
template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
|
||||
{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
|
||||
# ifndef Q_CC_MSVC // longs are 64-bit
|
||||
template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
|
||||
{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
|
||||
#pragma intrinsic(_umul128)
|
||||
# pragma intrinsic(_umul128)
|
||||
template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
|
||||
{
|
||||
// use 128-bit multiplication with the _umul128 intrinsic
|
||||
|
|
@ -247,117 +291,30 @@ template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
|
|||
*r = _umul128(v1, v2, &high);
|
||||
return high;
|
||||
}
|
||||
# define HAVE_MUL64_OVERFLOW
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__)
|
||||
// no 128-bit multiplication, we need to figure out with a slow division
|
||||
template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
|
||||
# pragma intrinsic(_mul128)
|
||||
template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
|
||||
{
|
||||
if (v2 && v1 > std::numeric_limits<quint64>::max() / v2)
|
||||
return true;
|
||||
*r = v1 * v2;
|
||||
return false;
|
||||
}
|
||||
template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
|
||||
{
|
||||
return mul_overflow<quint64>(v1, v2, reinterpret_cast<quint64 *>(r));
|
||||
}
|
||||
#else
|
||||
# undef HAVE_MUL64_OVERFLOW
|
||||
#endif
|
||||
// Use 128-bit multiplication with the _mul128 intrinsic
|
||||
// https://msdn.microsoft.com/en-us/library/82cxdw50.aspx
|
||||
|
||||
//
|
||||
// Signed overflow math
|
||||
//
|
||||
// In C++, signed overflow math is Undefined Behavior. However, many CPUs do implement some way to
|
||||
// check for overflow. Some compilers expose intrinsics to use this functionality. If the no
|
||||
// intrinsic is exposed, overflow checking can be done by widening the result type and "manually"
|
||||
// checking for overflow. Or, alternatively, by using inline assembly to use the CPU features.
|
||||
//
|
||||
// Only int overflow checking is implemented, because it's the only one used.
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_sadd_overflow)
|
||||
inline bool add_overflow(int v1, int v2, int *r)
|
||||
{ return __builtin_sadd_overflow(v1, v2, r); }
|
||||
#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
|
||||
inline bool add_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
quint8 overflow = 0;
|
||||
int res = v1;
|
||||
// This is slightly more complex than the unsigned case above: the sign bit
|
||||
// of 'low' must be replicated as the entire 'high', so the only valid
|
||||
// values for 'high' are 0 and -1.
|
||||
|
||||
asm ("addl %2, %1\n"
|
||||
"seto %0"
|
||||
: "=q" (overflow), "=r" (res)
|
||||
: "r" (v2), "1" (res)
|
||||
: "cc"
|
||||
);
|
||||
*r = res;
|
||||
return overflow;
|
||||
qint64 high;
|
||||
*r = _mul128(v1, v2, &high);
|
||||
if (high == 0)
|
||||
return *r < 0;
|
||||
if (high == -1)
|
||||
return *r >= 0;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
inline bool add_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
qint64 t = qint64(v1) + v2;
|
||||
*r = static_cast<int>(t);
|
||||
return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
|
||||
# endif // x86-64
|
||||
# endif // MSVC x86
|
||||
#endif // !GCC
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_ssub_overflow)
|
||||
inline bool sub_overflow(int v1, int v2, int *r)
|
||||
{ return __builtin_ssub_overflow(v1, v2, r); }
|
||||
#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
|
||||
inline bool sub_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
quint8 overflow = 0;
|
||||
int res = v1;
|
||||
|
||||
asm ("subl %2, %1\n"
|
||||
"seto %0"
|
||||
: "=q" (overflow), "=r" (res)
|
||||
: "r" (v2), "1" (res)
|
||||
: "cc"
|
||||
);
|
||||
*r = res;
|
||||
return overflow;
|
||||
}
|
||||
#else
|
||||
inline bool sub_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
qint64 t = qint64(v1) - v2;
|
||||
*r = static_cast<int>(t);
|
||||
return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_smul_overflow)
|
||||
inline bool mul_overflow(int v1, int v2, int *r)
|
||||
{ return __builtin_smul_overflow(v1, v2, r); }
|
||||
#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
|
||||
inline bool mul_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
quint8 overflow = 0;
|
||||
int res = v1;
|
||||
|
||||
asm ("imul %2, %1\n"
|
||||
"seto %0"
|
||||
: "=q" (overflow), "=r" (res)
|
||||
: "r" (v2), "1" (res)
|
||||
: "cc"
|
||||
);
|
||||
*r = res;
|
||||
return overflow;
|
||||
}
|
||||
#else
|
||||
inline bool mul_overflow(int v1, int v2, int *r)
|
||||
{
|
||||
qint64 t = qint64(v1) * v2;
|
||||
*r = static_cast<int>(t);
|
||||
return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
|
||||
}
|
||||
#endif
|
||||
#endif // Q_CLANG_QDOC
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
|
||||
** 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 QTRACE_P_H
|
||||
#define QTRACE_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.
|
||||
//
|
||||
|
||||
/*
|
||||
* The Qt tracepoints API consists of only three macros:
|
||||
*
|
||||
* - Q_TRACE(tracepoint, args...)
|
||||
* Fires 'tracepoint' if it is enabled.
|
||||
*
|
||||
* - Q_UNCONDITIONAL_TRACE(tracepoint, args...)
|
||||
* Fires 'tracepoint' unconditionally: no check is performed to query
|
||||
* whether 'tracepoint' is enabled.
|
||||
*
|
||||
* - Q_TRACE_ENABLED(tracepoint)
|
||||
* Returns 'true' if 'tracepoint' is enabled; false otherwise.
|
||||
*
|
||||
* When using LTTNG, Q_TRACE, Q_UNCONDITIONAL_TRACE and Q_TRACE_ENABLED map
|
||||
* ultimately to tracepoint(), do_tracepoint() and tracepoint_enabled(),
|
||||
* respectively, described on the lttng-ust manpage (man 3 lttng-ust).
|
||||
*
|
||||
* On ETW, Q_TRACE() and Q_UNCONDITIONAL_TRACE() are equivalent, ultimately
|
||||
* amounting to a call to TraceLoggingWrite(), whereas Q_TRACE_ENABLED()
|
||||
* wraps around TraceLoggingProviderEnabled().
|
||||
*
|
||||
* A tracepoint provider is defined in a separate file, that follows the
|
||||
* following format:
|
||||
*
|
||||
* tracepoint_name(arg_type arg_name, ...)
|
||||
*
|
||||
* For instance:
|
||||
*
|
||||
* qcoreapplication_ctor(int argc, const char * const argv)
|
||||
* qcoreapplication_foo(int argc, const char[10] argv)
|
||||
* qcoreapplication_baz(const char[len] some_string, unsigned int len)
|
||||
* qcoreapplication_qstring(const QString &foo)
|
||||
* qcoreapplication_qrect(const QRect &rect)
|
||||
*
|
||||
* The provider file is then parsed by src/tools/tracegen, which can be
|
||||
* switched to output either ETW or LTTNG tracepoint definitions. The provider
|
||||
* name is deduced to be basename(provider_file).
|
||||
*
|
||||
* To use the above (inside qtcore), you need to include
|
||||
* <providername_tracepoints_p.h>. After that, the following call becomes
|
||||
* possible:
|
||||
*
|
||||
* Q_TRACE(qcoreapplication_qrect, myRect);
|
||||
*
|
||||
* Currently, all C++ primitive non-pointer types are supported for
|
||||
* arguments. Additionally, char * is supported, and is assumed to
|
||||
* be a NULL-terminated string. Finally, the following subset of Qt types also
|
||||
* currently supported:
|
||||
*
|
||||
* - QString
|
||||
* - QByteArray
|
||||
* - QUrl
|
||||
* - QRect
|
||||
*
|
||||
* Dynamic arrays are supported using the syntax illustrated by
|
||||
* qcoreapplication_baz above.
|
||||
*/
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
|
||||
# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__)
|
||||
# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__)
|
||||
# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled()
|
||||
#else
|
||||
# define Q_TRACE(x, ...)
|
||||
# define Q_UNCONDITIONAL_TRACE(x, ...)
|
||||
# define Q_TRACE_ENABLED(x) false
|
||||
#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QTRACE_P_H
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
HEADERS += \
|
||||
io/qabstractfileengine_p.h \
|
||||
io/qbuffer.h \
|
||||
io/qdatastream.h \
|
||||
io/qdatastream_p.h \
|
||||
io/qdataurl_p.h \
|
||||
io/qdebug.h \
|
||||
io/qdebug_p.h \
|
||||
|
|
@ -22,8 +20,6 @@ HEADERS += \
|
|||
io/qlockfile.h \
|
||||
io/qlockfile_p.h \
|
||||
io/qnoncontiguousbytedevice_p.h \
|
||||
io/qtextstream.h \
|
||||
io/qtextstream_p.h \
|
||||
io/qtemporarydir.h \
|
||||
io/qtemporaryfile.h \
|
||||
io/qtemporaryfile_p.h \
|
||||
|
|
@ -57,7 +53,6 @@ HEADERS += \
|
|||
SOURCES += \
|
||||
io/qabstractfileengine.cpp \
|
||||
io/qbuffer.cpp \
|
||||
io/qdatastream.cpp \
|
||||
io/qdataurl.cpp \
|
||||
io/qtldurl.cpp \
|
||||
io/qdebug.cpp \
|
||||
|
|
@ -71,7 +66,6 @@ SOURCES += \
|
|||
io/qlockfile.cpp \
|
||||
io/qnoncontiguousbytedevice.cpp \
|
||||
io/qstorageinfo.cpp \
|
||||
io/qtextstream.cpp \
|
||||
io/qtemporarydir.cpp \
|
||||
io/qtemporaryfile.cpp \
|
||||
io/qresource.cpp \
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
HEADERS += \
|
||||
json/qjson_p.h \
|
||||
json/qjsondocument.h \
|
||||
json/qjsonobject.h \
|
||||
json/qjsonvalue.h \
|
||||
json/qjsonarray.h \
|
||||
json/qjsonwriter_p.h \
|
||||
json/qjsonparser_p.h
|
||||
|
||||
SOURCES += \
|
||||
json/qjson.cpp \
|
||||
json/qjsondocument.cpp \
|
||||
json/qjsonobject.cpp \
|
||||
json/qjsonarray.cpp \
|
||||
json/qjsonvalue.cpp \
|
||||
json/qjsonwriter.cpp \
|
||||
json/qjsonparser.cpp
|
||||
|
|
@ -116,6 +116,12 @@
|
|||
# include <taskLib.h>
|
||||
#endif
|
||||
|
||||
#ifdef QT_BOOTSTRAPPED
|
||||
#include <private/qtrace_p.h>
|
||||
#else
|
||||
#include <qtcore_tracepoints_p.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -790,6 +796,8 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
|
|||
|
||||
void QCoreApplicationPrivate::init()
|
||||
{
|
||||
Q_TRACE(qcoreapplicationprivate_init_entry);
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
QMacAutoReleasePool pool;
|
||||
#endif
|
||||
|
|
@ -873,6 +881,8 @@ void QCoreApplicationPrivate::init()
|
|||
#ifndef QT_NO_QOBJECT
|
||||
is_app_running = true; // No longer starting up.
|
||||
#endif
|
||||
|
||||
Q_TRACE(qcoreapplicationprivate_init_exit);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -112,14 +112,15 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
|
|||
if (CFStringRef mode = runLoopMode(notification.userInfo))
|
||||
m_runLoopModes.push(mode);
|
||||
else
|
||||
qWarning("Encountered run loop push notification without run loop mode!");
|
||||
qCWarning(lcEventDispatcher) << "Encountered run loop push notification without run loop mode!";
|
||||
|
||||
} else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePopNotification"))) {
|
||||
CFStringRef mode = runLoopMode(notification.userInfo);
|
||||
if (CFStringCompare(mode, [self currentMode], 0) == kCFCompareEqualTo)
|
||||
m_runLoopModes.pop();
|
||||
else
|
||||
qWarning("Tried to pop run loop mode '%s' that was never pushed!", qPrintable(QString::fromCFString(mode)));
|
||||
qCWarning(lcEventDispatcher) << "Tried to pop run loop mode"
|
||||
<< qPrintable(QString::fromCFString(mode)) << "that was never pushed!";
|
||||
|
||||
Q_ASSERT(m_runLoopModes.size() >= 1);
|
||||
}
|
||||
|
|
@ -134,6 +135,9 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher");
|
||||
Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers");
|
||||
|
||||
class RunLoopDebugger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -177,10 +181,6 @@ QDebug operator<<(QDebug s, timespec tv)
|
|||
return s;
|
||||
}
|
||||
|
||||
#if DEBUG_EVENT_DISPATCHER
|
||||
uint g_eventDispatcherIndentationLevel = 0;
|
||||
#endif
|
||||
|
||||
static const CFTimeInterval kCFTimeIntervalMinimum = 0;
|
||||
static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max();
|
||||
|
||||
|
|
@ -190,13 +190,7 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
|
|||
: QAbstractEventDispatcher(parent)
|
||||
, m_processEvents(QEventLoop::EventLoopExec)
|
||||
, m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents)
|
||||
, m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity,
|
||||
#if DEBUG_EVENT_DISPATCHER
|
||||
kCFRunLoopAllActivities
|
||||
#else
|
||||
kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting
|
||||
#endif
|
||||
)
|
||||
, m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, kCFRunLoopAllActivities)
|
||||
, m_runLoopModeTracker([[RunLoopModeTracker alloc] init])
|
||||
, m_runLoopTimer(0)
|
||||
, m_blockedRunLoopTimer(0)
|
||||
|
|
@ -247,14 +241,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
bool eventsProcessed = false;
|
||||
|
||||
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
|
||||
qWarning() << "processEvents() flags" << flags << "not supported on iOS";
|
||||
qCWarning(lcEventDispatcher) << "processEvents() flags" << flags << "not supported on iOS";
|
||||
|
||||
qEventDispatcherDebug() << "Entering with " << flags; qIndent();
|
||||
qCDebug(lcEventDispatcher) << "Processing events with flags" << flags;
|
||||
|
||||
if (m_blockedRunLoopTimer) {
|
||||
Q_ASSERT(m_blockedRunLoopTimer == m_runLoopTimer);
|
||||
|
||||
qEventDispatcherDebug() << "Recursing from blocked timer " << m_blockedRunLoopTimer;
|
||||
qCDebug(lcEventDispatcher) << "Recursing from blocked timer" << m_blockedRunLoopTimer;
|
||||
m_runLoopTimer = 0; // Unset current timer to force creation of new timer
|
||||
updateTimers();
|
||||
}
|
||||
|
|
@ -266,7 +260,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
m_postedEventsRunLoopSource.signal();
|
||||
m_processEvents.deferredWakeUp = false;
|
||||
|
||||
qEventDispatcherDebug() << "Processed deferred wake-up";
|
||||
qCDebug(lcEventDispatcher) << "Processed deferred wake-up";
|
||||
}
|
||||
|
||||
// The documentation states that this signal is emitted after the event
|
||||
|
|
@ -287,12 +281,12 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
CFTimeInterval duration = (m_processEvents.flags & QEventLoop::WaitForMoreEvents) ?
|
||||
kCFTimeIntervalDistantFuture : kCFTimeIntervalMinimum;
|
||||
|
||||
qEventDispatcherDebug() << "Calling CFRunLoopRunInMode = " << qPrintable(QString::fromCFString(mode))
|
||||
<< " for " << duration << " ms, processing single source = " << returnAfterSingleSourceHandled; qIndent();
|
||||
qCDebug(lcEventDispatcher) << "Calling CFRunLoopRunInMode =" << qPrintable(QString::fromCFString(mode))
|
||||
<< "for" << duration << "ms, processing single source =" << returnAfterSingleSourceHandled;
|
||||
|
||||
SInt32 result = CFRunLoopRunInMode(mode, duration, returnAfterSingleSourceHandled);
|
||||
|
||||
qUnIndent(); qEventDispatcherDebug() << "result = " << qPrintableResult(result);
|
||||
qCDebug(lcEventDispatcher) << "result =" << qPrintableResult(result);
|
||||
|
||||
eventsProcessed |= (result == kCFRunLoopRunHandledSource
|
||||
|| m_processEvents.processedPostedEvents
|
||||
|
|
@ -316,15 +310,15 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
// immediately, since it has already been exited.
|
||||
|
||||
if (!currentEventLoop()->isRunning()) {
|
||||
qEventDispatcherDebug() << "Top level event loop was exited";
|
||||
qCDebug(lcEventDispatcher) << "Top level event loop was exited";
|
||||
break;
|
||||
} else {
|
||||
qEventDispatcherDebug() << "Top level event loop still running, making another pass";
|
||||
qCDebug(lcEventDispatcher) << "Top level event loop still running, making another pass";
|
||||
}
|
||||
} else {
|
||||
// We were called manually, through processEvents(), and should stop processing
|
||||
// events, even if we didn't finish processing all the queued events.
|
||||
qEventDispatcherDebug() << "Top level processEvents was interrupted";
|
||||
qCDebug(lcEventDispatcher) << "Top level processEvents was interrupted";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +347,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
// date in the past (overdue) will fire on the next run loop pass. The Qt
|
||||
// APIs on the other hand document eg. zero-interval timers to always be
|
||||
// handled after processing all available window-system events.
|
||||
qEventDispatcherDebug() << "Manually processing timers due to overdue timer";
|
||||
qCDebug(lcEventDispatcher) << "Manually processing timers due to overdue timer";
|
||||
processTimers(0);
|
||||
eventsProcessed = true;
|
||||
}
|
||||
|
|
@ -372,7 +366,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
|
||||
if (m_processEvents.deferredWakeUp) {
|
||||
m_postedEventsRunLoopSource.signal();
|
||||
qEventDispatcherDebug() << "Processed deferred wake-up";
|
||||
qCDebug(lcEventDispatcher) << "Processed deferred wake-up";
|
||||
}
|
||||
|
||||
bool wasInterrupted = m_processEvents.wasInterrupted;
|
||||
|
|
@ -385,11 +379,11 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
// others below it (eg, in the case of nested event loops). We need to trigger
|
||||
// another interrupt so that the parent processEvents call has a chance to check
|
||||
// if it should continue.
|
||||
qEventDispatcherDebug() << "Forwarding interrupt in case of nested processEvents";
|
||||
qCDebug(lcEventDispatcher) << "Forwarding interrupt in case of nested processEvents";
|
||||
interrupt();
|
||||
}
|
||||
|
||||
qEventDispatcherDebug() << "Returning with eventsProcessed = " << eventsProcessed; qUnIndent();
|
||||
qCDebug(lcEventDispatcher) << "Returning with eventsProcessed =" << eventsProcessed;
|
||||
|
||||
return eventsProcessed;
|
||||
}
|
||||
|
|
@ -397,15 +391,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
|
|||
bool QEventDispatcherCoreFoundation::processPostedEvents()
|
||||
{
|
||||
if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
|
||||
qEventDispatcherDebug() << "Already processed events this pass";
|
||||
qCDebug(lcEventDispatcher) << "Already processed events this pass";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_processEvents.processedPostedEvents = true;
|
||||
|
||||
qEventDispatcherDebug() << "Sending posted events for " << m_processEvents.flags; qIndent();
|
||||
qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags;
|
||||
QCoreApplication::sendPostedEvents();
|
||||
qUnIndent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -413,12 +406,12 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
|
|||
void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
|
||||
{
|
||||
if (m_processEvents.processedTimers && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
|
||||
qEventDispatcherDebug() << "Already processed timers this pass";
|
||||
qCDebug(lcEventDispatcher) << "Already processed timers this pass";
|
||||
m_processEvents.deferredUpdateTimers = true;
|
||||
return;
|
||||
}
|
||||
|
||||
qEventDispatcherDebug() << "CFRunLoopTimer " << timer << " fired, activating Qt timers"; qIndent();
|
||||
qCDebug(lcEventDispatcher) << "CFRunLoopTimer" << timer << "fired, activating Qt timers";
|
||||
|
||||
// Activating Qt timers might recurse into processEvents() if a timer-callback
|
||||
// brings up a new event-loop or tries to processes events manually. Although
|
||||
|
|
@ -436,15 +429,15 @@ void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
|
|||
m_blockedRunLoopTimer = previouslyBlockedRunLoopTimer;
|
||||
m_processEvents.processedTimers = true;
|
||||
|
||||
qUnIndent();
|
||||
|
||||
// Now that the timer source is unblocked we may need to schedule it again
|
||||
updateTimers();
|
||||
}
|
||||
|
||||
Q_LOGGING_CATEGORY(lcEventDispatcherActivity, "qt.eventdispatcher.activity")
|
||||
|
||||
void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity activity)
|
||||
{
|
||||
qEventDispatcherDebug() << qPrintableActivity(activity);
|
||||
qCDebug(lcEventDispatcherActivity) << "Runloop entered activity" << qPrintableActivity(activity);
|
||||
|
||||
switch (activity) {
|
||||
case kCFRunLoopBeforeWaiting:
|
||||
|
|
@ -463,13 +456,11 @@ void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity act
|
|||
case kCFRunLoopAfterWaiting:
|
||||
emit awake();
|
||||
break;
|
||||
#if DEBUG_EVENT_DISPATCHER
|
||||
case kCFRunLoopEntry:
|
||||
case kCFRunLoopBeforeTimers:
|
||||
case kCFRunLoopBeforeSources:
|
||||
case kCFRunLoopExit:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
|
@ -502,19 +493,19 @@ void QEventDispatcherCoreFoundation::wakeUp()
|
|||
// posted event gets processed on the next processEvents() call, so we flag the
|
||||
// need to do a deferred wake-up.
|
||||
m_processEvents.deferredWakeUp = true;
|
||||
qEventDispatcherDebug() << "Already processed posted events, deferring wakeUp";
|
||||
qCDebug(lcEventDispatcher) << "Already processed posted events, deferring wakeUp";
|
||||
return;
|
||||
}
|
||||
|
||||
m_postedEventsRunLoopSource.signal();
|
||||
CFRunLoopWakeUp(CFRunLoopGetMain());
|
||||
|
||||
qEventDispatcherDebug() << "Signaled posted event run-loop source";
|
||||
qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
|
||||
}
|
||||
|
||||
void QEventDispatcherCoreFoundation::interrupt()
|
||||
{
|
||||
qEventDispatcherDebug() << "Marking current processEvent as interrupted";
|
||||
qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
|
||||
m_processEvents.wasInterrupted = true;
|
||||
CFRunLoopStop(CFRunLoopGetMain());
|
||||
}
|
||||
|
|
@ -540,8 +531,8 @@ void QEventDispatcherCoreFoundation::unregisterSocketNotifier(QSocketNotifier *n
|
|||
|
||||
void QEventDispatcherCoreFoundation::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
|
||||
{
|
||||
qEventDispatcherDebug() << "id = " << timerId << ", interval = " << interval
|
||||
<< ", type = " << timerType << ", object = " << object;
|
||||
qCDebug(lcEventDispatcherTimers) << "Registering timer with id =" << timerId << "interval =" << interval
|
||||
<< "type =" << timerType << "object =" << object;
|
||||
|
||||
Q_ASSERT(timerId > 0 && interval >= 0 && object);
|
||||
Q_ASSERT(object->thread() == thread() && thread() == QThread::currentThread());
|
||||
|
|
@ -557,7 +548,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimer(int timerId)
|
|||
|
||||
bool returnValue = m_timerInfoList.unregisterTimer(timerId);
|
||||
|
||||
qEventDispatcherDebug() << "id = " << timerId << ", timers left: " << m_timerInfoList.size();
|
||||
qCDebug(lcEventDispatcherTimers) << "Unegistered timer with id =" << timerId << "Timers left:" << m_timerInfoList.size();
|
||||
|
||||
updateTimers();
|
||||
return returnValue;
|
||||
|
|
@ -569,7 +560,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimers(QObject *object)
|
|||
|
||||
bool returnValue = m_timerInfoList.unregisterTimers(object);
|
||||
|
||||
qEventDispatcherDebug() << "object = " << object << ", timers left: " << m_timerInfoList.size();
|
||||
qCDebug(lcEventDispatcherTimers) << "Unegistered timers for object =" << object << "Timers left:" << m_timerInfoList.size();
|
||||
|
||||
updateTimers();
|
||||
return returnValue;
|
||||
|
|
@ -612,16 +603,16 @@ void QEventDispatcherCoreFoundation::updateTimers()
|
|||
});
|
||||
|
||||
CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes);
|
||||
qEventDispatcherDebug() << "Created new CFRunLoopTimer " << m_runLoopTimer;
|
||||
qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
|
||||
|
||||
} else {
|
||||
CFRunLoopTimerSetNextFireDate(m_runLoopTimer, timeToFire);
|
||||
qEventDispatcherDebug() << "Re-scheduled CFRunLoopTimer " << m_runLoopTimer;
|
||||
qCDebug(lcEventDispatcherTimers) << "Re-scheduled CFRunLoopTimer" << m_runLoopTimer;
|
||||
}
|
||||
|
||||
m_overdueTimerScheduled = !timespecToSeconds(tv);
|
||||
|
||||
qEventDispatcherDebug() << "Next timeout in " << tv << " seconds";
|
||||
qCDebug(lcEventDispatcherTimers) << "Next timeout in" << tv << "seconds";
|
||||
|
||||
} else {
|
||||
// No Qt timers are registered, so make sure we're not running any CF timers
|
||||
|
|
@ -637,7 +628,7 @@ void QEventDispatcherCoreFoundation::invalidateTimer()
|
|||
return;
|
||||
|
||||
CFRunLoopTimerInvalidate(m_runLoopTimer);
|
||||
qEventDispatcherDebug() << "Invalidated CFRunLoopTimer " << m_runLoopTimer;
|
||||
qCDebug(lcEventDispatcherTimers) << "Invalidated CFRunLoopTimer" << m_runLoopTimer;
|
||||
|
||||
CFRelease(m_runLoopTimer);
|
||||
m_runLoopTimer = 0;
|
||||
|
|
|
|||
|
|
@ -85,19 +85,22 @@
|
|||
// We mean it.
|
||||
//
|
||||
|
||||
#define DEBUG_EVENT_DISPATCHER 0
|
||||
|
||||
#include <QtCore/qabstracteventdispatcher.h>
|
||||
#include <QtCore/private/qtimerinfo_unix_p.h>
|
||||
#include <QtCore/private/qcfsocketnotifier_p.h>
|
||||
#include <QtCore/private/qcore_mac_p.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker));
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
|
||||
|
||||
class QEventDispatcherCoreFoundation;
|
||||
|
||||
template <class T = QEventDispatcherCoreFoundation>
|
||||
|
|
@ -269,17 +272,4 @@ private:
|
|||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#if DEBUG_EVENT_DISPATCHER
|
||||
extern uint g_eventDispatcherIndentationLevel;
|
||||
#define qEventDispatcherDebug() qDebug().nospace() \
|
||||
<< qPrintable(QString(QLatin1String("| ")).repeated(g_eventDispatcherIndentationLevel)) \
|
||||
<< __FUNCTION__ << "(): "
|
||||
#define qIndent() ++g_eventDispatcherIndentationLevel
|
||||
#define qUnIndent() --g_eventDispatcherIndentationLevel
|
||||
#else
|
||||
#define qEventDispatcherDebug() QT_NO_QDEBUG_MACRO()
|
||||
#define qIndent()
|
||||
#define qUnIndent()
|
||||
#endif
|
||||
|
||||
#endif // QEVENTDISPATCHER_CF_P_H
|
||||
|
|
|
|||
|
|
@ -3892,6 +3892,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
|
|||
\sa setValue(), value()
|
||||
*/
|
||||
|
||||
/*! \fn static inline QVariant fromStdVariant(const std::variant<T, Types...> &value)
|
||||
\since 5.11
|
||||
|
||||
Returns a QVariant with the type and value of the active variant of \a value. If
|
||||
the active type is std::monostate a default QVariant is returned.
|
||||
|
||||
\note With this method you do not need to register the variant as a Qt metatype,
|
||||
since the std::variant is resolved before being stored. The component types
|
||||
should be registered however.
|
||||
|
||||
\sa fromValue()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template<typename T> QVariant qVariantFromValue(const T &value)
|
||||
\relates QVariant
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@
|
|||
#include <QtCore/qbytearraylist.h>
|
||||
#endif
|
||||
|
||||
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
|
||||
#include <variant>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
|
|
@ -355,6 +359,16 @@ class Q_CORE_EXPORT QVariant
|
|||
static inline QVariant fromValue(const T &value)
|
||||
{ return qVariantFromValue(value); }
|
||||
|
||||
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
|
||||
template<typename... Types>
|
||||
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
|
||||
{
|
||||
if (value.valueless_by_exception())
|
||||
return QVariant();
|
||||
return std::visit([](const auto &arg) { return fromValue(arg); }, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
bool canConvert() const
|
||||
{ return canConvert(qMetaTypeId<T>()); }
|
||||
|
|
@ -503,6 +517,11 @@ inline QVariant qVariantFromValue(const T &t)
|
|||
template <>
|
||||
inline QVariant qVariantFromValue(const QVariant &t) { return t; }
|
||||
|
||||
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
|
||||
template <>
|
||||
inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); }
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline void qVariantSetValue(QVariant &v, const T &t)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -466,6 +466,8 @@ QStringList QMimeType::suffixes() const
|
|||
*/
|
||||
QString QMimeType::preferredSuffix() const
|
||||
{
|
||||
if (isDefault()) // workaround for unwanted *.bin suffix for octet-stream, https://bugs.freedesktop.org/show_bug.cgi?id=101667, fixed upstream in 1.10
|
||||
return QString();
|
||||
const QStringList suffixList = suffixes();
|
||||
return suffixList.isEmpty() ? QString() : suffixList.at(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
#include "qjsonobject.h"
|
||||
#include "qjsonarray.h"
|
||||
|
||||
#include <qtcore_tracepoints_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QFactoryLoaderPrivate : public QObjectPrivate
|
||||
|
|
@ -142,6 +144,9 @@ void QFactoryLoader::update()
|
|||
if (qt_debug_component()) {
|
||||
qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
|
||||
}
|
||||
|
||||
Q_TRACE(qfactoryloader_update, fileName);
|
||||
|
||||
library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
|
||||
if (!library->isPlugin()) {
|
||||
if (qt_debug_component()) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@
|
|||
#include "qelfparser_p.h"
|
||||
#include "qmachparser_p.h"
|
||||
|
||||
#include <qtcore_tracepoints_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef QT_NO_DEBUG
|
||||
|
|
@ -535,6 +537,8 @@ bool QLibraryPrivate::load()
|
|||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
Q_TRACE(qlibraryprivate_load_entry, fileName);
|
||||
|
||||
bool ret = load_sys();
|
||||
if (qt_debug_component()) {
|
||||
if (ret) {
|
||||
|
|
@ -551,6 +555,8 @@ bool QLibraryPrivate::load()
|
|||
installCoverageTool(this);
|
||||
}
|
||||
|
||||
Q_TRACE(qlibraryprivate_load_exit, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ static QUuid _q_uuidFromHex(const char *src)
|
|||
return QUuid();
|
||||
}
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
|
||||
{
|
||||
QByteArray hashResult;
|
||||
|
|
@ -172,7 +171,6 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
|
|||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class QUuid
|
||||
|
|
@ -510,12 +508,12 @@ QUuid QUuid::createUuidV3(const QUuid &ns, const QByteArray &baseData)
|
|||
{
|
||||
return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData)
|
||||
{
|
||||
return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
Creates a QUuid object from the binary representation of the UUID, as
|
||||
|
|
|
|||
|
|
@ -201,18 +201,20 @@ public:
|
|||
static QUuid createUuid();
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData);
|
||||
#endif
|
||||
static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData);
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData)
|
||||
{
|
||||
return QUuid::createUuidV3(ns, baseData.toUtf8());
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData)
|
||||
{
|
||||
return QUuid::createUuidV5(ns, baseData.toUtf8());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
QUuid::Variant variant() const Q_DECL_NOTHROW;
|
||||
QUuid::Version version() const Q_DECL_NOTHROW;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
qcoreapplicationprivate_init_entry()
|
||||
qcoreapplicationprivate_init_exit()
|
||||
qfactoryloader_update(const QString &fileName)
|
||||
qlibraryprivate_load_entry(const QString &fileName)
|
||||
qlibraryprivate_load_exit(bool success)
|
||||
|
|
@ -154,14 +154,7 @@ static inline bool useCompressed(const QString &s)
|
|||
{
|
||||
if (s.length() >= 0x8000)
|
||||
return false;
|
||||
const ushort *uc = (const ushort *)s.constData();
|
||||
const ushort *e = uc + s.length();
|
||||
while (uc < e) {
|
||||
if (*uc > 0xff)
|
||||
return false;
|
||||
++uc;
|
||||
}
|
||||
return true;
|
||||
return QtPrivate::isLatin1(s);
|
||||
}
|
||||
|
||||
static inline int qStringSize(const QString &string, bool compress)
|
||||
|
|
@ -409,6 +409,11 @@ QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
|
|||
/*!
|
||||
Creates a new stream reader that reads from \a data.
|
||||
|
||||
This function should only be used if the XML header either says the encoding
|
||||
is "UTF-8" or lacks any encoding information (the latter is the case of
|
||||
QXmlStreamWriter writing to a QString). Any other encoding is likely going to
|
||||
cause data corruption ("mojibake").
|
||||
|
||||
\sa addData(), clear(), setDevice()
|
||||
*/
|
||||
QXmlStreamReader::QXmlStreamReader(const QString &data)
|
||||
|
|
@ -3268,6 +3273,9 @@ QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
|
|||
|
||||
|
||||
/*! Constructs a stream writer that writes into \a string.
|
||||
*
|
||||
* Note that when writing to QString, QXmlStreamWriter ignores the codec set
|
||||
* with setCodec(). See that function for more information.
|
||||
*/
|
||||
QXmlStreamWriter::QXmlStreamWriter(QString *string)
|
||||
: d_ptr(new QXmlStreamWriterPrivate(this))
|
||||
|
|
@ -3326,6 +3334,12 @@ QIODevice *QXmlStreamWriter::device() const
|
|||
gets written when you call writeStartDocument(). Call this
|
||||
function before calling writeStartDocument().
|
||||
|
||||
\note When writing the XML to a QString, the codec information is ignored
|
||||
and the XML header will not include any encoding information, since all
|
||||
QStrings are UTF-16. If you later convert the QString to an 8-bit format,
|
||||
you must arrange for the encoding information to be transmitted
|
||||
out-of-band.
|
||||
|
||||
\sa codec()
|
||||
*/
|
||||
void QXmlStreamWriter::setCodec(QTextCodec *codec)
|
||||
|
|
@ -3345,6 +3359,12 @@ void QXmlStreamWriter::setCodec(QTextCodec *codec)
|
|||
"ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
|
||||
recognized, nothing happens.
|
||||
|
||||
\note When writing the XML to a QString, the codec information is ignored
|
||||
and the XML header will not include any encoding information, since all
|
||||
QStrings are UTF-16. If you later convert the QString to an 8-bit format,
|
||||
you must arrange for the encoding information to be transmitted
|
||||
out-of-band.
|
||||
|
||||
\sa QTextCodec::codecForName()
|
||||
*/
|
||||
void QXmlStreamWriter::setCodec(const char *codecName)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# Qt data formats core module
|
||||
|
||||
HEADERS += \
|
||||
serialization/qdatastream.h \
|
||||
serialization/qdatastream_p.h \
|
||||
serialization/qjson_p.h \
|
||||
serialization/qjsondocument.h \
|
||||
serialization/qjsonobject.h \
|
||||
serialization/qjsonvalue.h \
|
||||
serialization/qjsonarray.h \
|
||||
serialization/qjsonwriter_p.h \
|
||||
serialization/qjsonparser_p.h \
|
||||
serialization/qtextstream.h \
|
||||
serialization/qtextstream_p.h \
|
||||
serialization/qxmlstream.h \
|
||||
serialization/qxmlstream_p.h \
|
||||
serialization/qxmlutils_p.h
|
||||
|
||||
SOURCES += \
|
||||
serialization/qdatastream.cpp \
|
||||
serialization/qjson.cpp \
|
||||
serialization/qjsondocument.cpp \
|
||||
serialization/qjsonobject.cpp \
|
||||
serialization/qjsonarray.cpp \
|
||||
serialization/qjsonvalue.cpp \
|
||||
serialization/qjsonwriter.cpp \
|
||||
serialization/qjsonparser.cpp \
|
||||
serialization/qtextstream.cpp \
|
||||
serialization/qxmlstream.cpp \
|
||||
serialization/qxmlutils.cpp
|
||||
|
|
@ -311,16 +311,14 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
|
|||
#ifndef QT_NO_THREAD
|
||||
|
||||
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
|
||||
static void setCurrentThreadName(pthread_t threadId, const char *name)
|
||||
static void setCurrentThreadName(const char *name)
|
||||
{
|
||||
# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||
Q_UNUSED(threadId);
|
||||
prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
|
||||
# elif defined(Q_OS_MAC)
|
||||
Q_UNUSED(threadId);
|
||||
pthread_setname_np(name);
|
||||
# elif defined(Q_OS_QNX)
|
||||
pthread_setname_np(threadId, name);
|
||||
pthread_setname_np(pthread_self(), name);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
|
@ -361,14 +359,13 @@ void *QThreadPrivate::start(void *arg)
|
|||
|
||||
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
|
||||
{
|
||||
// sets the name of the current thread.
|
||||
QString objectName = thr->objectName();
|
||||
|
||||
pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load());
|
||||
if (Q_LIKELY(objectName.isEmpty()))
|
||||
setCurrentThreadName(thread_id, thr->metaObject()->className());
|
||||
// Sets the name of the current thread. We can only do this
|
||||
// when the thread is starting, as we don't have a cross
|
||||
// platform way of setting the name of an arbitrary thread.
|
||||
if (Q_LIKELY(thr->objectName().isEmpty()))
|
||||
setCurrentThreadName(thr->metaObject()->className());
|
||||
else
|
||||
setCurrentThreadName(thread_id, objectName.toLocal8Bit());
|
||||
setCurrentThreadName(thr->objectName().toLocal8Bit());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -300,6 +300,46 @@ void QBitArray::fill(bool value, int begin, int end)
|
|||
setBit(begin++, value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn const char *QBitArray::bits() const
|
||||
\since 5.11
|
||||
|
||||
Returns a pointer to a dense bit array for this QBitArray. Bits are counted
|
||||
upwards from the least significant bit in each byte. The the number of bits
|
||||
relevant in the last byte is given by \c{size() % 8}.
|
||||
|
||||
\sa fromBits(), size()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 5.11
|
||||
|
||||
Creates a QBitArray with the dense bit array located at \a data, with \a
|
||||
len bits. The byte array at \a data must be at least \a size / 8 (rounded up)
|
||||
bytes long.
|
||||
|
||||
If \a size is not a multiple of 8, this function will include the lowest
|
||||
\a size % 8 bits from the last byte in \a data.
|
||||
|
||||
\sa bits()
|
||||
*/
|
||||
QBitArray QBitArray::fromBits(const char *data, qsizetype size)
|
||||
{
|
||||
QBitArray result;
|
||||
qsizetype nbytes = (size + 7) / 8;
|
||||
|
||||
result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
|
||||
char *bits = result.d.data();
|
||||
memcpy(bits + 1, data, nbytes);
|
||||
|
||||
// clear any unused bits from the last byte
|
||||
if (size & 7)
|
||||
bits[nbytes] &= 0xffU >> (size & 7);
|
||||
|
||||
*bits = result.d.size() * 8 - size;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*! \fn bool QBitArray::isDetached() const
|
||||
|
||||
\internal
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ public:
|
|||
|
||||
inline void truncate(int pos) { if (pos < size()) resize(pos); }
|
||||
|
||||
const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
|
||||
static QBitArray fromBits(const char *data, qsizetype len);
|
||||
|
||||
public:
|
||||
typedef QByteArray::DataPtr DataPtr;
|
||||
inline DataPtr &data_ptr() { return d.data_ptr(); }
|
||||
|
|
|
|||
|
|
@ -177,55 +177,37 @@
|
|||
# define QT_FUNCTION_TARGET(x)
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__))
|
||||
#ifdef Q_PROCESSOR_X86
|
||||
/* -- x86 intrinsic support -- */
|
||||
|
||||
# if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2)
|
||||
// MSVC doesn't define __SSE2__, so do it ourselves
|
||||
# define __SSE__ 1
|
||||
# define __SSE2__ 1
|
||||
# endif
|
||||
|
||||
# ifdef __SSE2__
|
||||
// #include the intrinsics
|
||||
# include <immintrin.h>
|
||||
# endif
|
||||
|
||||
# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
|
||||
// GCC 4.4 and Clang 2.8 added a few more intrinsics there
|
||||
# include <x86intrin.h>
|
||||
# endif
|
||||
|
||||
# if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__))
|
||||
// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros
|
||||
// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// SSE2 is handled by _M_IX86_FP below
|
||||
# define __SSE3__ 1
|
||||
# define __SSSE3__ 1
|
||||
# define __SSE3__ 1
|
||||
# define __SSSE3__ 1
|
||||
// no Intel CPU supports SSE4a, so don't define it
|
||||
# define __SSE4_1__ 1
|
||||
# define __SSE4_2__ 1
|
||||
# ifndef __AVX__
|
||||
# define __AVX__ 1
|
||||
# define __SSE4_1__ 1
|
||||
# define __SSE4_2__ 1
|
||||
# ifndef __AVX__
|
||||
# define __AVX__ 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// SSE intrinsics
|
||||
#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
#if defined(QT_LINUXBASE)
|
||||
/// this is an evil hack - the posix_memalign declaration in LSB
|
||||
/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
|
||||
# define posix_memalign _lsb_hack_posix_memalign
|
||||
# include <emmintrin.h>
|
||||
# undef posix_memalign
|
||||
#else
|
||||
# include <emmintrin.h>
|
||||
#endif
|
||||
#if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2)
|
||||
# define __SSE__ 1
|
||||
# define __SSE2__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// SSE3 intrinsics
|
||||
#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
|
||||
// SSSE3 intrinsics
|
||||
#if defined(__SSSE3__) || (defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
|
||||
// SSE4.1 intrinsics
|
||||
#if defined(__SSE4_1__) || (defined(QT_COMPILER_SUPPORTS_SSE4_1) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
// SSE4.2 intrinsics
|
||||
#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
#include <nmmintrin.h>
|
||||
|
||||
# if defined(__SSE4_2__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
|
||||
// POPCNT instructions:
|
||||
|
|
@ -233,13 +215,8 @@
|
|||
// (but neither MSVC nor the Intel compiler define this macro)
|
||||
# define __POPCNT__ 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// AVX intrinsics
|
||||
#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
// immintrin.h is the ultimate header, we don't need anything else after this
|
||||
#include <immintrin.h>
|
||||
|
||||
# if defined(__AVX__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
|
||||
// AES, PCLMULQDQ instructions:
|
||||
// All processors that support AVX support AES, PCLMULQDQ
|
||||
|
|
@ -255,11 +232,6 @@
|
|||
# define __F16C__ 1
|
||||
# define __RDRND__ 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
|
||||
# include <wmmintrin.h>
|
||||
#endif
|
||||
|
||||
#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
|
||||
#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
|
||||
|
|
@ -288,19 +260,7 @@
|
|||
#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
|
||||
#define QT_FUNCTION_TARGET_STRING_SHA "sha"
|
||||
|
||||
// other x86 intrinsics
|
||||
#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \
|
||||
|| (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \
|
||||
|| defined(Q_CC_INTEL))
|
||||
# define QT_COMPILER_SUPPORTS_X86INTRIN
|
||||
# ifdef Q_CC_INTEL
|
||||
// The Intel compiler has no <x86intrin.h> -- all intrinsics are in <immintrin.h>;
|
||||
# include <immintrin.h>
|
||||
# else
|
||||
// GCC 4.4 and Clang 2.8 added a few more intrinsics there
|
||||
# include <x86intrin.h>
|
||||
# endif
|
||||
#endif
|
||||
#endif /* Q_PROCESSOR_X86 */
|
||||
|
||||
// Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html
|
||||
// This should be tweaked with an "upper version" of clang once we know which release fixes the
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Intel Corporation.
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -251,6 +251,151 @@ inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __SSE2__
|
||||
static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
|
||||
{
|
||||
# if defined(__AVX2__)
|
||||
// AVX2 implementation: test 32 bytes at a time
|
||||
const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
|
||||
while (ptr + 32 < end) {
|
||||
__m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
|
||||
if (!_mm256_testz_si256(mask256, data))
|
||||
return false;
|
||||
ptr += 32;
|
||||
}
|
||||
|
||||
const __m128i mask = _mm256_castsi256_si128(mask256);
|
||||
# elif defined(__SSE4_1__)
|
||||
// SSE 4.1 implementation: test 32 bytes at a time (two 16-byte
|
||||
// comparisons, unrolled)
|
||||
const __m128i mask = _mm_set1_epi32(maskval);
|
||||
while (ptr + 32 < end) {
|
||||
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
__m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
|
||||
if (!_mm_testz_si128(mask, data1))
|
||||
return false;
|
||||
if (!_mm_testz_si128(mask, data2))
|
||||
return false;
|
||||
ptr += 32;
|
||||
}
|
||||
# endif
|
||||
# if defined(__SSE4_1__)
|
||||
// AVX2 and SSE4.1: final 16-byte comparison
|
||||
if (ptr + 16 < end) {
|
||||
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
if (!_mm_testz_si128(mask, data1))
|
||||
return false;
|
||||
ptr += 16;
|
||||
}
|
||||
# else
|
||||
// SSE2 implementation: test 16 bytes at a time.
|
||||
const __m128i mask = _mm_set1_epi32(maskval);
|
||||
while (ptr + 16 < end) {
|
||||
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
__m128i masked = _mm_andnot_si128(mask, data);
|
||||
__m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
|
||||
if (quint16(_mm_movemask_epi8(comparison)) != 0xffff)
|
||||
return false;
|
||||
ptr += 16;
|
||||
}
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW
|
||||
{
|
||||
const char *ptr = s.begin();
|
||||
const char *end = s.end();
|
||||
|
||||
#if defined(__AVX2__)
|
||||
if (!simdTestMask(ptr, end, 0x80808080))
|
||||
return false;
|
||||
#elif defined(__SSE2__)
|
||||
// Testing for the high bit can be done efficiently with just PMOVMSKB
|
||||
while (ptr + 16 < end) {
|
||||
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
quint32 mask = _mm_movemask_epi8(data);
|
||||
if (mask)
|
||||
return false;
|
||||
ptr += 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (ptr + 4 < end) {
|
||||
quint32 data = qFromUnaligned<quint32>(ptr);
|
||||
if (data & 0x80808080U)
|
||||
return false;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
while (ptr != end) {
|
||||
if (quint8(*ptr++) & 0x80)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
|
||||
{
|
||||
const QChar *ptr = s.begin();
|
||||
const QChar *end = s.end();
|
||||
|
||||
#ifdef __SSE2__
|
||||
const char *ptr8 = reinterpret_cast<const char *>(ptr);
|
||||
const char *end8 = reinterpret_cast<const char *>(end);
|
||||
if (!simdTestMask(ptr8, end8, 0xff80ff80))
|
||||
return false;
|
||||
ptr = reinterpret_cast<const QChar *>(ptr8);
|
||||
#endif
|
||||
|
||||
while (ptr != end) {
|
||||
if ((*ptr++).unicode() & 0xff80)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW
|
||||
{
|
||||
const QChar *ptr = s.begin();
|
||||
const QChar *end = s.end();
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
const char *ptr8 = reinterpret_cast<const char *>(ptr);
|
||||
const char *end8 = reinterpret_cast<const char *>(end);
|
||||
if (!simdTestMask(ptr8, end8, 0xff00ff00))
|
||||
return false;
|
||||
ptr = reinterpret_cast<const QChar *>(ptr8);
|
||||
#elif defined(__SSE2__)
|
||||
// Testing if every other byte is non-zero can be done efficiently by
|
||||
// using PUNPCKHBW (unpack high order bytes) and comparing that to zero.
|
||||
while (ptr + 32 < end) {
|
||||
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
__m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
|
||||
__m128i high = _mm_unpackhi_epi8(data1, data2);
|
||||
__m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
|
||||
if (_mm_movemask_epi8(comparison))
|
||||
return false;
|
||||
ptr += 16;
|
||||
}
|
||||
if (ptr + 16 < end) {
|
||||
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||
__m128i high = _mm_unpackhi_epi8(data1, data1);
|
||||
__m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
|
||||
if (_mm_movemask_epi8(comparison))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (ptr != end) {
|
||||
if ((*ptr++).unicode() > 0xff)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// conversion between Latin 1 and UTF-16
|
||||
void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
|
||||
{
|
||||
|
|
@ -2441,6 +2586,21 @@ QString &QString::remove(int pos, int len)
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void removeStringImpl(QString &s, const T &needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
const int needleSize = needle.size();
|
||||
if (needleSize) {
|
||||
if (needleSize == 1) {
|
||||
s.remove(needle.front(), cs);
|
||||
} else {
|
||||
int i = 0;
|
||||
while ((i = s.indexOf(needle, i, cs)) != -1)
|
||||
s.remove(i, needleSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes every occurrence of the given \a str string in this
|
||||
string, and returns a reference to this string.
|
||||
|
|
@ -2454,11 +2614,27 @@ QString &QString::remove(int pos, int len)
|
|||
*/
|
||||
QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (str.d->size) {
|
||||
int i = 0;
|
||||
while ((i = indexOf(str, i, cs)) != -1)
|
||||
remove(i, str.d->size);
|
||||
}
|
||||
removeStringImpl(*this, str, cs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.11
|
||||
\overload
|
||||
|
||||
Removes every occurrence of the given \a str string in this
|
||||
string, and returns a reference to this string.
|
||||
|
||||
If \a cs is Qt::CaseSensitive (default), the search is
|
||||
case sensitive; otherwise the search is case insensitive.
|
||||
|
||||
This is the same as \c replace(str, "", cs).
|
||||
|
||||
\sa replace()
|
||||
*/
|
||||
QString &QString::remove(QLatin1String str, Qt::CaseSensitivity cs)
|
||||
{
|
||||
removeStringImpl(*this, str, cs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,12 @@ Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
|
|||
// Qt 4.x compatibility
|
||||
typedef QLatin1String QLatin1Literal;
|
||||
|
||||
//
|
||||
// QLatin1String inline implementations
|
||||
//
|
||||
inline bool QtPrivate::isLatin1(QLatin1String) Q_DECL_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//
|
||||
// QStringView members that require QLatin1String:
|
||||
//
|
||||
|
|
@ -477,6 +483,7 @@ public:
|
|||
|
||||
QString &remove(int i, int len);
|
||||
QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||
QString &remove(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||
QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
|
||||
QString &replace(int i, int len, QChar after);
|
||||
QString &replace(int i, int len, const QChar *s, int slen);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,11 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
|
|||
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> convertToUcs4(QStringView str);
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isRightToLeft(QStringView string);
|
||||
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) Q_DECL_NOTHROW; // in qstring.h
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) Q_DECL_NOTHROW;
|
||||
|
||||
} // namespace QtPRivate
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -725,8 +725,7 @@
|
|||
vector.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value)
|
||||
/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value)
|
||||
\fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, T &&value)
|
||||
|
||||
\overload
|
||||
|
|
|
|||
|
|
@ -607,8 +607,7 @@
|
|||
\sa append(), insert()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <typename T> void QVector<T>::insert(int i, const T &value)
|
||||
/*! \fn template <typename T> void QVector<T>::insert(int i, const T &value)
|
||||
\fn template <typename T> void QVector<T>::insert(int i, T &&value)
|
||||
|
||||
Inserts \a value at index position \a i in the vector. If \a i is
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
# Qt xml core module
|
||||
|
||||
HEADERS += \
|
||||
xml/qxmlstream.h \
|
||||
xml/qxmlstream_p.h \
|
||||
xml/qxmlutils_p.h
|
||||
|
||||
SOURCES += \
|
||||
xml/qxmlstream.cpp \
|
||||
xml/qxmlutils.cpp
|
||||
|
|
@ -95,3 +95,6 @@ qtConfig(angle) {
|
|||
qtConfig(egl): CMAKE_EGL_INCDIRS = $$cmakePortablePaths($$QMAKE_INCDIR_EGL)
|
||||
|
||||
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist
|
||||
|
||||
TRACEPOINT_PROVIDER = $$PWD/qtgui.tracepoints
|
||||
CONFIG += qt_tracepoints
|
||||
|
|
|
|||
|
|
@ -278,8 +278,24 @@ void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles)
|
|||
|
||||
if (newValues != values) {
|
||||
values.swap(newValues);
|
||||
if (model)
|
||||
model->d_func()->itemChanged(q);
|
||||
if (model) {
|
||||
QVector<int> roleKeys;
|
||||
roleKeys.reserve(roles.size() + 1);
|
||||
bool hasEditRole = false;
|
||||
bool hasDisplayRole = false;
|
||||
for (auto it = roles.keyBegin(); it != roles.keyEnd(); ++it) {
|
||||
roleKeys.push_back(*it);
|
||||
if (*it == Qt::EditRole)
|
||||
hasEditRole = true;
|
||||
else if (*it == Qt::DisplayRole)
|
||||
hasDisplayRole = true;
|
||||
}
|
||||
if (hasEditRole && !hasDisplayRole)
|
||||
roleKeys.push_back(Qt::DisplayRole);
|
||||
else if (!hasEditRole && hasDisplayRole)
|
||||
roleKeys.push_back(Qt::EditRole);
|
||||
model->d_func()->itemChanged(q, roleKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,7 +570,7 @@ bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QSta
|
|||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QStandardItemModelPrivate::itemChanged(QStandardItem *item)
|
||||
void QStandardItemModelPrivate::itemChanged(QStandardItem *item, const QVector<int> &roles)
|
||||
{
|
||||
Q_Q(QStandardItemModel);
|
||||
Q_ASSERT(item);
|
||||
|
|
@ -570,8 +586,8 @@ void QStandardItemModelPrivate::itemChanged(QStandardItem *item)
|
|||
}
|
||||
} else {
|
||||
// Normal item
|
||||
QModelIndex index = q->indexFromItem(item);
|
||||
emit q->dataChanged(index, index);
|
||||
const QModelIndex index = q->indexFromItem(item);
|
||||
emit q->dataChanged(index, index, roles);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -885,6 +901,9 @@ void QStandardItem::setData(const QVariant &value, int role)
|
|||
{
|
||||
Q_D(QStandardItem);
|
||||
role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
|
||||
const QVector<int> roles((role == Qt::DisplayRole) ?
|
||||
QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
|
||||
QVector<int>({role}));
|
||||
QVector<QStandardItemData>::iterator it;
|
||||
for (it = d->values.begin(); it != d->values.end(); ++it) {
|
||||
if ((*it).role == role) {
|
||||
|
|
@ -896,13 +915,13 @@ void QStandardItem::setData(const QVariant &value, int role)
|
|||
d->values.erase(it);
|
||||
}
|
||||
if (d->model)
|
||||
d->model->d_func()->itemChanged(this);
|
||||
d->model->d_func()->itemChanged(this, roles);
|
||||
return;
|
||||
}
|
||||
}
|
||||
d->values.append(QStandardItemData(role, value));
|
||||
if (d->model)
|
||||
d->model->d_func()->itemChanged(this);
|
||||
d->model->d_func()->itemChanged(this, roles);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ public:
|
|||
bool dropMimeData (const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
// ### Qt 6: add changed roles
|
||||
void itemChanged(QStandardItem *item);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ public:
|
|||
}
|
||||
|
||||
void sort(QStandardItem *parent, int column, Qt::SortOrder order);
|
||||
void itemChanged(QStandardItem *item);
|
||||
void itemChanged(QStandardItem *item, const QVector<int> &roles = QVector<int>());
|
||||
void rowsAboutToBeInserted(QStandardItem *parent, int start, int end);
|
||||
void columnsAboutToBeInserted(QStandardItem *parent, int start, int end);
|
||||
void rowsAboutToBeRemoved(QStandardItem *parent, int start, int end);
|
||||
|
|
|
|||
|
|
@ -3761,14 +3761,25 @@ static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
|
|||
|
||||
static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQueryEvent *e)
|
||||
{
|
||||
QDebugStateSaver saver(d);
|
||||
d.noquote();
|
||||
const Qt::InputMethodQueries queries = e->queries();
|
||||
d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries)
|
||||
<< noshowbase << dec << ", {";
|
||||
for (unsigned mask = 1; mask <= Qt::ImTextAfterCursor; mask<<=1) {
|
||||
for (unsigned mask = 1; mask <= Qt::ImInputItemClipRectangle; mask<<=1) {
|
||||
if (queries & mask) {
|
||||
const QVariant value = e->value(static_cast<Qt::InputMethodQuery>(mask));
|
||||
if (value.isValid())
|
||||
d << '[' << showbase << hex << mask << noshowbase << dec << '=' << value << "],";
|
||||
const Qt::InputMethodQuery query = static_cast<Qt::InputMethodQuery>(mask);
|
||||
const QVariant value = e->value(query);
|
||||
if (value.isValid()) {
|
||||
d << '[';
|
||||
QtDebugUtils::formatQEnum(d, query);
|
||||
d << '=';
|
||||
if (query == Qt::ImHints)
|
||||
QtDebugUtils::formatQFlags(d, Qt::InputMethodHints(value.toInt()));
|
||||
else
|
||||
d << value.toString();
|
||||
d << "],";
|
||||
}
|
||||
}
|
||||
}
|
||||
d << "})";
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@
|
|||
# include <QtCore/QLibraryInfo>
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#include <qtgui_tracepoints_p.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -1360,6 +1362,8 @@ void QGuiApplicationPrivate::eventDispatcherReady()
|
|||
|
||||
void QGuiApplicationPrivate::init()
|
||||
{
|
||||
Q_TRACE(qguiapplicationprivate_init_entry);
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
QMacAutoReleasePool pool;
|
||||
#endif
|
||||
|
|
@ -1522,6 +1526,8 @@ void QGuiApplicationPrivate::init()
|
|||
if (!QGuiApplicationPrivate::displayName)
|
||||
QObject::connect(q, &QGuiApplication::applicationNameChanged,
|
||||
q, &QGuiApplication::applicationDisplayNameChanged);
|
||||
|
||||
Q_TRACE(qguiapplicationprivate_init_exit);
|
||||
}
|
||||
|
||||
extern void qt_cleanupFontDatabase();
|
||||
|
|
@ -1756,6 +1762,8 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra
|
|||
|
||||
void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
|
||||
{
|
||||
Q_TRACE(qguiapplicationprivate_processwsevents_entry, e->type);
|
||||
|
||||
switch(e->type) {
|
||||
case QWindowSystemInterfacePrivate::Mouse:
|
||||
QGuiApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
|
||||
|
|
@ -1864,6 +1872,8 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
|
|||
qWarning() << "Unknown user input event type:" << e->type;
|
||||
break;
|
||||
}
|
||||
|
||||
Q_TRACE(qguiapplicationprivate_processwsevents_exit, e->type);
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
|
|
|
|||
|
|
@ -418,6 +418,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
|
|||
return QPlatformTheme::defaultThemeHint(QPlatformTheme::UiEffects);
|
||||
case WheelScrollLines:
|
||||
return QPlatformTheme::defaultThemeHint(QPlatformTheme::WheelScrollLines);
|
||||
case MouseQuickSelectionThreshold:
|
||||
return QPlatformTheme::defaultThemeHint(QPlatformTheme::MouseQuickSelectionThreshold);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ public:
|
|||
UiEffects,
|
||||
WheelScrollLines,
|
||||
ShowShortcutsInContextMenus,
|
||||
MouseQuickSelectionThreshold
|
||||
};
|
||||
|
||||
virtual QVariant styleHint(StyleHint hint) const;
|
||||
|
|
|
|||
|
|
@ -559,6 +559,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
|
|||
dist = defaultThemeHint(MouseDoubleClickDistance).toInt(&ok) * 2;
|
||||
return QVariant(ok ? dist : 10);
|
||||
}
|
||||
case MouseQuickSelectionThreshold:
|
||||
return QVariant(10);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ public:
|
|||
WheelScrollLines,
|
||||
TouchDoubleTapDistance,
|
||||
ShowShortcutsInContextMenus,
|
||||
IconFallbackSearchPaths
|
||||
IconFallbackSearchPaths,
|
||||
MouseQuickSelectionThreshold
|
||||
};
|
||||
|
||||
enum DialogType {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ public:
|
|||
, m_tabFocusBehavior(-1)
|
||||
, m_uiEffects(-1)
|
||||
, m_wheelScrollLines(-1)
|
||||
, m_mouseQuickSelectionThreshold(-1)
|
||||
{}
|
||||
|
||||
int m_mouseDoubleClickInterval;
|
||||
|
|
@ -90,6 +91,7 @@ public:
|
|||
int m_tabFocusBehavior;
|
||||
int m_uiEffects;
|
||||
int m_wheelScrollLines;
|
||||
int m_mouseQuickSelectionThreshold;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
@ -537,4 +539,38 @@ void QStyleHints::setWheelScrollLines(int scrollLines)
|
|||
emit wheelScrollLinesChanged(scrollLines);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the mouse quick selection threshold.
|
||||
\internal
|
||||
\sa mouseQuickSelectionThreshold()
|
||||
\since 5.11
|
||||
*/
|
||||
void QStyleHints::setMouseQuickSelectionThreshold(int threshold)
|
||||
{
|
||||
Q_D(QStyleHints);
|
||||
if (d->m_mouseQuickSelectionThreshold == threshold)
|
||||
return;
|
||||
d->m_mouseQuickSelectionThreshold = threshold;
|
||||
emit mouseDoubleClickIntervalChanged(threshold);
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QStyleHints::mouseQuickSelectionThreshold
|
||||
\brief Quick selection mouse threshold in QLineEdit.
|
||||
|
||||
This property defines how much the mouse cursor should be moved along the y axis
|
||||
to trigger a quick selection during a normal QLineEdit text selection.
|
||||
|
||||
If the property value is less than or equal to 0, the quick selection feature is disabled.
|
||||
|
||||
\since 5.11
|
||||
*/
|
||||
int QStyleHints::mouseQuickSelectionThreshold() const
|
||||
{
|
||||
Q_D(const QStyleHints);
|
||||
if (d->m_mouseQuickSelectionThreshold >= 0)
|
||||
return d->m_mouseQuickSelectionThreshold;
|
||||
return themeableHint(QPlatformTheme::MouseQuickSelectionThreshold, QPlatformIntegration::MouseQuickSelectionThreshold).toInt();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
|
|||
Q_PROPERTY(bool singleClickActivation READ singleClickActivation STORED false CONSTANT FINAL)
|
||||
Q_PROPERTY(bool useHoverEffects READ useHoverEffects WRITE setUseHoverEffects NOTIFY useHoverEffectsChanged FINAL)
|
||||
Q_PROPERTY(int wheelScrollLines READ wheelScrollLines NOTIFY wheelScrollLinesChanged FINAL)
|
||||
Q_PROPERTY(int mouseQuickSelectionThreshold READ mouseQuickSelectionThreshold WRITE setMouseQuickSelectionThreshold NOTIFY mouseQuickSelectionThresholdChanged FINAL)
|
||||
|
||||
public:
|
||||
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
|
||||
|
|
@ -104,6 +105,8 @@ public:
|
|||
void setUseHoverEffects(bool useHoverEffects);
|
||||
int wheelScrollLines() const;
|
||||
void setWheelScrollLines(int scrollLines);
|
||||
void setMouseQuickSelectionThreshold(int threshold);
|
||||
int mouseQuickSelectionThreshold() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void cursorFlashTimeChanged(int cursorFlashTime);
|
||||
|
|
@ -115,6 +118,7 @@ Q_SIGNALS:
|
|||
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
|
||||
void useHoverEffectsChanged(bool useHoverEffects);
|
||||
void wheelScrollLinesChanged(int scrollLines);
|
||||
void mouseQuickSelectionThresholdChanged(int threshold);
|
||||
|
||||
private:
|
||||
friend class QGuiApplication;
|
||||
|
|
|
|||
|
|
@ -174,29 +174,31 @@ template<QImage::Format Format>
|
|||
static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
|
||||
Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
|
||||
Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
|
||||
auto conversion = [](uint s) {
|
||||
// MSVC needs these constexpr defined in here otherwise it will create a capture.
|
||||
Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
|
||||
Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
|
||||
Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
|
||||
|
||||
Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
|
||||
Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
|
||||
Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
|
||||
Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
|
||||
|
||||
Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
|
||||
Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
|
||||
Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
|
||||
Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
|
||||
Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
|
||||
Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
uint red = (src[i] >> redShift<Format>()) & redMask;
|
||||
uint green = (src[i] >> greenShift<Format>()) & greenMask;
|
||||
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
|
||||
uint red = (s >> redShift<Format>()) & redMask;
|
||||
uint green = (s >> greenShift<Format>()) & greenMask;
|
||||
uint blue = (s >> blueShift<Format>()) & blueMask;
|
||||
|
||||
red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
|
||||
green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
|
||||
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
|
||||
buffer[i] = 0xff000000 | red | green | blue;
|
||||
}
|
||||
return 0xff000000 | red | green | blue;
|
||||
};
|
||||
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -348,21 +350,21 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *
|
|||
|
||||
// RGB32 -> RGB888 is not a precision loss.
|
||||
if (!dither || (rWidth == 8 && gWidth == 8 && bWidth == 8)) {
|
||||
Q_CONSTEXPR uint rMask = (1 << rWidth) - 1;
|
||||
Q_CONSTEXPR uint gMask = (1 << gWidth) - 1;
|
||||
Q_CONSTEXPR uint bMask = (1 << bWidth) - 1;
|
||||
auto conversion = [](uint s) {
|
||||
const uint c = fromRGB ? s : qUnpremultiply(s);
|
||||
Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
|
||||
Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
|
||||
|
||||
Q_CONSTEXPR uchar rRightShift = 24 - rWidth;
|
||||
Q_CONSTEXPR uchar gRightShift = 16 - gWidth;
|
||||
Q_CONSTEXPR uchar bRightShift = 8 - bWidth;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint c = fromRGB ? src[i] : qUnpremultiply(src[i]);
|
||||
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
|
||||
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
|
||||
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
|
||||
buffer[i] = r | g | b;
|
||||
}
|
||||
return r | g | b;
|
||||
};
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
|
||||
} else {
|
||||
// We do ordered dither by using a rounding conversion, but instead of
|
||||
// adding half of input precision, we add the adjusted result from the
|
||||
|
|
@ -394,32 +396,32 @@ template<QImage::Format Format, bool fromRGB>
|
|||
static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *dither)
|
||||
{
|
||||
Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
|
||||
Q_CONSTEXPR uchar rWidth = redWidth<Format>();
|
||||
Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
|
||||
|
||||
if (!dither) {
|
||||
Q_CONSTEXPR uint aMask = (1 << aWidth) - 1;
|
||||
Q_CONSTEXPR uint rMask = (1 << rWidth) - 1;
|
||||
Q_CONSTEXPR uint gMask = (1 << gWidth) - 1;
|
||||
Q_CONSTEXPR uint bMask = (1 << bWidth) - 1;
|
||||
auto conversion = [](uint c) {
|
||||
Q_CONSTEXPR uint aMask = (1 << alphaWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
|
||||
Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
|
||||
|
||||
Q_CONSTEXPR uchar aRightShift = 32 - aWidth;
|
||||
Q_CONSTEXPR uchar rRightShift = 24 - rWidth;
|
||||
Q_CONSTEXPR uchar gRightShift = 16 - gWidth;
|
||||
Q_CONSTEXPR uchar bRightShift = 8 - bWidth;
|
||||
Q_CONSTEXPR uchar aRightShift = 32 - alphaWidth<Format>();
|
||||
Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
|
||||
Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
|
||||
|
||||
Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint c = src[i];
|
||||
Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
|
||||
const uint a = fromRGB ? aOpaque : (((c >> aRightShift) & aMask) << alphaShift<Format>());
|
||||
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
|
||||
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
|
||||
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
|
||||
buffer[i] = a | r | g | b;
|
||||
}
|
||||
return a | r | g | b;
|
||||
};
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
|
||||
} else {
|
||||
Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
|
||||
Q_CONSTEXPR uchar rWidth = redWidth<Format>();
|
||||
Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
|
||||
Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
|
||||
|
||||
const uint *bayer_line = qt_bayer_matrix[dither->y & 15];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint c = src[i];
|
||||
|
|
@ -514,8 +516,7 @@ static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint
|
|||
static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = RGBA2ARGB(src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, RGBA2ARGB);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -568,8 +569,7 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin
|
|||
static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = ARGB2RGBA(src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, ARGB2RGBA);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -695,8 +695,7 @@ static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const u
|
|||
static const uint *QT_FASTCALL convertRGBXFromRGB32(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = ARGB2RGBA(0xff000000 | src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint c) { return ARGB2RGBA(0xff000000 | c); });
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -713,8 +712,7 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui
|
|||
const QVector<QRgb> *, QDitherInfo *dither)
|
||||
{
|
||||
if (!dither) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qConvertA2rgb30ToArgb32<PixelOrder>(src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertA2rgb30ToArgb32<PixelOrder>);
|
||||
} else {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint c = src[i];
|
||||
|
|
@ -796,8 +794,7 @@ template<QtPixelOrder PixelOrder>
|
|||
static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qConvertArgb32ToA2rgb30<PixelOrder>(src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertArgb32ToA2rgb30<PixelOrder>);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -814,8 +811,7 @@ template<QtPixelOrder PixelOrder>
|
|||
static const uint *QT_FASTCALL convertRGB30FromARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(src[i]));
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertRgb32ToRgb30<PixelOrder>);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, i
|
|||
::memcpy(dst, src, length * sizeof(QRgba64));
|
||||
} else {
|
||||
const uint ca = const_alpha | (const_alpha << 8); // adjust to [0-65535]
|
||||
const uint cia = 65535 - const_alpha;
|
||||
const uint cia = 65535 - ca;
|
||||
|
||||
int x = 0;
|
||||
|
||||
|
|
@ -493,7 +493,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int
|
|||
if (const_alpha != 255)
|
||||
color = multiplyAlpha255(color, const_alpha);
|
||||
|
||||
const uint minusAlphaOfColor = ~ushort(color.alpha());
|
||||
const uint minusAlphaOfColor = 65535 - color.alpha();
|
||||
int x = 0;
|
||||
quint64 *dst = (quint64 *) destPixels;
|
||||
const __m256i colorVector = _mm256_set1_epi64x(color);
|
||||
|
|
|
|||
|
|
@ -1104,22 +1104,30 @@ inline int qBlue565(quint16 rgb) {
|
|||
return (b << 3) | (b >> 2);
|
||||
}
|
||||
|
||||
// We manually unalias the variables to make sure the compiler
|
||||
// fully optimizes both aliased and unaliased cases.
|
||||
#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
|
||||
if (src == buffer) { \
|
||||
for (int i = 0; i < count; ++i) \
|
||||
buffer[i] = conversion(buffer[i]); \
|
||||
} else { \
|
||||
for (int i = 0; i < count; ++i) \
|
||||
buffer[i] = conversion(src[i]); \
|
||||
}
|
||||
|
||||
|
||||
static Q_ALWAYS_INLINE const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qPremultiply(src[i]);
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qPremultiply(RGBA2ARGB(src[i]));
|
||||
UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
const uint qt_bayer_matrix[16][16] = {
|
||||
{ 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
|
||||
0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
qfontdatabase_addapplicationfont(const QString &filename)
|
||||
qfontdatabase_load(const QString &family, int pointSize)
|
||||
qfontdatabase_loadengine(const QString &family, int pointSize)
|
||||
qfontdatabaseprivate_addappfont(const QString &fileName)
|
||||
qguiapplicationprivate_init_entry()
|
||||
qguiapplicationprivate_init_exit()
|
||||
qguiapplicationprivate_processwsevents_entry(int type)
|
||||
qguiapplicationprivate_processwsevents_exit(int type)
|
||||
|
|
@ -74,6 +74,7 @@
|
|||
# define FM_DEBUG if (false) qDebug
|
||||
#endif
|
||||
|
||||
#include <qtgui_tracepoints_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -1009,6 +1010,8 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
|
|||
QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
|
||||
|
||||
if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
|
||||
Q_TRACE(qfontdatabase_loadengine, request.family, request.pointSize);
|
||||
|
||||
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
|
||||
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
|
||||
if (!request.fallBackFamilies.isEmpty()) {
|
||||
|
|
@ -2439,6 +2442,8 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
|
|||
font.data = fontData;
|
||||
font.fileName = fileName;
|
||||
|
||||
Q_TRACE(qfontdatabaseprivate_addappfont, fileName);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < applicationFonts.count(); ++i)
|
||||
if (applicationFonts.at(i).families.isEmpty())
|
||||
|
|
@ -2494,6 +2499,9 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
|
|||
QFile f(fileName);
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
return -1;
|
||||
|
||||
Q_TRACE(qfontdatabase_addapplicationfont, fileName);
|
||||
|
||||
data = f.readAll();
|
||||
}
|
||||
QMutexLocker locker(fontDatabaseMutex());
|
||||
|
|
@ -2792,6 +2800,8 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
|
|||
|
||||
QFontEngine *fe = nullptr;
|
||||
|
||||
Q_TRACE(qfontdatabase_load, req.family, req.pointSize);
|
||||
|
||||
req.fallBackFamilies = fallBackFamilies;
|
||||
if (!req.fallBackFamilies.isEmpty())
|
||||
req.family = req.fallBackFamilies.takeFirst();
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ QT_BEGIN_NAMESPACE
|
|||
was specified, QNetworkAccessManager gives up, without attempting to
|
||||
fall back to HTTP/1.1. If both HTTP2AllowedAttribute and
|
||||
Http2DirectAttribute are set, Http2DirectAttribute takes priority.
|
||||
(This value was introduced in 5.10.)
|
||||
(This value was introduced in 5.11.)
|
||||
|
||||
\omitvalue ResourceTypeAttribute
|
||||
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
|
|||
d->peerVerifyMode == other.d->peerVerifyMode &&
|
||||
d->peerVerifyDepth == other.d->peerVerifyDepth &&
|
||||
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
|
||||
d->backendConfig == other.d->backendConfig &&
|
||||
d->sslOptions == other.d->sslOptions &&
|
||||
d->sslSession == other.d->sslSession &&
|
||||
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
|
||||
|
|
@ -263,6 +264,7 @@ bool QSslConfiguration::isNull() const
|
|||
d->privateKey.isNull() &&
|
||||
d->peerCertificate.isNull() &&
|
||||
d->peerCertificateChain.count() == 0 &&
|
||||
d->backendConfig.isEmpty() &&
|
||||
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
|
||||
d->sslSession.isNull() &&
|
||||
d->sslSessionTicketLifeTimeHint == -1 &&
|
||||
|
|
@ -869,6 +871,60 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame
|
|||
d->dhParams = dhparams;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.11
|
||||
|
||||
Returns the backend-specific configuration.
|
||||
|
||||
Only options set by addBackendConfig() or setBackendConfig() will be
|
||||
returned. The internal standard configuration of the backend is not reported.
|
||||
|
||||
\sa setBackendConfigOption(), setBackendConfig()
|
||||
*/
|
||||
QMap<QByteArray, QVariant> QSslConfiguration::backendConfig() const
|
||||
{
|
||||
return d->backendConfig;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.11
|
||||
|
||||
Sets an option in the backend-specific configuration.
|
||||
|
||||
Options supported by the OpenSSL (>= 1.0.2) backend are available in the \l
|
||||
{https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#SUPPORTED-CONFIGURATION-FILE-COMMANDS}
|
||||
{supported configuration file commands} documentation. The expected type for
|
||||
the \a value parameter is a QByteArray for all options. The \l
|
||||
{https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#EXAMPLES}{examples}
|
||||
show how to use some of the options.
|
||||
|
||||
\note The backend-specific configuration will be applied after the general
|
||||
configuration. Using the backend-specific configuration to set a general
|
||||
configuration option again will overwrite the general configuration option.
|
||||
|
||||
\sa backendConfig(), setBackendConfig()
|
||||
*/
|
||||
void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVariant &value)
|
||||
{
|
||||
d->backendConfig[name] = value;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.11
|
||||
|
||||
Sets or clears the backend-specific configuration.
|
||||
|
||||
Without a \a backendConfig parameter this function will clear the
|
||||
backend-specific configuration. More information about the supported
|
||||
options is available in the documentation of addBackendConfig().
|
||||
|
||||
\sa backendConfig(), setBackendConfigOption()
|
||||
*/
|
||||
void QSslConfiguration::setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig)
|
||||
{
|
||||
d->backendConfig = backendConfig;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#define QSSLCONFIGURATION_H
|
||||
|
||||
#include <QtNetwork/qtnetworkglobal.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qshareddata.h>
|
||||
#include <QtNetwork/qsslsocket.h>
|
||||
#include <QtNetwork/qssl.h>
|
||||
|
|
@ -149,6 +150,10 @@ public:
|
|||
QSslDiffieHellmanParameters diffieHellmanParameters() const;
|
||||
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
|
||||
|
||||
QMap<QByteArray, QVariant> backendConfig() const;
|
||||
void setBackendConfigOption(const QByteArray &name, const QVariant &value);
|
||||
void setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig = QMap<QByteArray, QVariant>());
|
||||
|
||||
static QSslConfiguration defaultConfiguration();
|
||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
||||
#include "qsslconfiguration.h"
|
||||
#include "qlist.h"
|
||||
|
|
@ -123,6 +124,8 @@ public:
|
|||
|
||||
QSslDiffieHellmanParameters dhParams;
|
||||
|
||||
QMap<QByteArray, QVariant> backendConfig;
|
||||
|
||||
QByteArray sslSession;
|
||||
int sslSessionTicketLifeTimeHint;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static inline QString msgErrorSettingBackendConfig(const QString &why)
|
||||
{
|
||||
return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
|
||||
}
|
||||
|
||||
QSslContext::QSslContext()
|
||||
: ctx(0),
|
||||
pkey(0),
|
||||
|
|
@ -237,4 +242,70 @@ QString QSslContext::errorString() const
|
|||
return errorStr;
|
||||
}
|
||||
|
||||
// static
|
||||
void QSslContext::applyBackendConfig(QSslContext *sslContext)
|
||||
{
|
||||
if (sslContext->sslConfiguration.backendConfig().isEmpty())
|
||||
return;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
|
||||
QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
|
||||
if (cctx) {
|
||||
q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
|
||||
q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
|
||||
|
||||
const auto &backendConfig = sslContext->sslConfiguration.backendConfig();
|
||||
for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) {
|
||||
if (!i.value().canConvert(QMetaType::QByteArray)) {
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(
|
||||
QSslSocket::tr("Expecting QByteArray for %1").arg(
|
||||
QString::fromUtf8(i.key())));
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray &value = i.value().toByteArray();
|
||||
const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
|
||||
if (result == 2)
|
||||
continue;
|
||||
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
switch (result) {
|
||||
case 0:
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(
|
||||
QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
|
||||
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
|
||||
return;
|
||||
case 1:
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(
|
||||
QSslSocket::tr("Wrong value for %1 (%2)").arg(
|
||||
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
|
||||
return;
|
||||
default:
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(
|
||||
QSslSocket::tr("Unrecognized command %1 = %2").arg(
|
||||
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
}
|
||||
} else {
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
}
|
||||
} else
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
{
|
||||
// specific algorithms requested, but not possible to set
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
sslContext->errorStr = msgErrorSettingBackendConfig(
|
||||
QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ init_context:
|
|||
#ifdef OPENSSL_NO_EC
|
||||
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
return;
|
||||
#else
|
||||
// Set the curves to be used.
|
||||
std::vector<int> curves;
|
||||
|
|
@ -269,9 +270,12 @@ init_context:
|
|||
if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
|
||||
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
applyBackendConfig(sslContext);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue