summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/animation/qvariantanimation.cpp6
-rw-r--r--src/corelib/codecs/qutfcodec.cpp47
-rw-r--r--src/corelib/corelib.pro16
-rw-r--r--src/corelib/doc/qtcore.qdocconf1
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp10
-rw-r--r--src/corelib/doc/snippets/qloggingcategory/main.cpp31
-rw-r--r--src/corelib/global/archdetect.cpp133
-rw-r--r--src/corelib/global/global.pri7
-rw-r--r--src/corelib/global/qcompilerdetection.h106
-rw-r--r--src/corelib/global/qflags.h17
-rw-r--r--src/corelib/global/qglobal.cpp723
-rw-r--r--src/corelib/global/qglobal.h41
-rw-r--r--src/corelib/global/qglobalstatic.h2
-rw-r--r--src/corelib/global/qhooks.cpp69
-rw-r--r--src/corelib/global/qhooks_p.h (renamed from src/corelib/io/qloggingcategory_p.h)42
-rw-r--r--src/corelib/global/qlibraryinfo.cpp65
-rw-r--r--src/corelib/global/qlogging.cpp240
-rw-r--r--src/corelib/global/qlogging.h8
-rw-r--r--src/corelib/global/qnamespace.h12
-rw-r--r--src/corelib/global/qnamespace.qdoc27
-rw-r--r--src/corelib/global/qnumeric.cpp2
-rw-r--r--src/corelib/global/qsysinfo.h15
-rw-r--r--src/corelib/global/qsystemdetection.h12
-rw-r--r--src/corelib/global/qtypeinfo.h2
-rw-r--r--src/corelib/io/io.pri1
-rw-r--r--src/corelib/io/qdatastream.cpp36
-rw-r--r--src/corelib/io/qdatastream.h8
-rw-r--r--src/corelib/io/qdebug.cpp96
-rw-r--r--src/corelib/io/qdebug.h99
-rw-r--r--src/corelib/io/qfiledevice.cpp11
-rw-r--r--src/corelib/io/qfiledevice.h4
-rw-r--r--src/corelib/io/qfileselector.cpp9
-rw-r--r--src/corelib/io/qfsfileengine.cpp16
-rw-r--r--src/corelib/io/qfsfileengine_p.h1
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp8
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp20
-rw-r--r--src/corelib/io/qlockfile_win.cpp25
-rw-r--r--src/corelib/io/qloggingcategory.cpp88
-rw-r--r--src/corelib/io/qloggingcategory.h32
-rw-r--r--src/corelib/io/qloggingregistry.cpp52
-rw-r--r--src/corelib/io/qloggingregistry_p.h6
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp39
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h6
-rw-r--r--src/corelib/io/qsavefile.cpp24
-rw-r--r--src/corelib/io/qsavefile_p.h1
-rw-r--r--src/corelib/io/qsettings.cpp297
-rw-r--r--src/corelib/io/qstandardpaths.cpp35
-rw-r--r--src/corelib/io/qstandardpaths.h4
-rw-r--r--src/corelib/io/qstandardpaths_android.cpp5
-rw-r--r--src/corelib/io/qstandardpaths_blackberry.cpp5
-rw-r--r--src/corelib/io/qstandardpaths_ios.mm3
-rw-r--r--src/corelib/io/qstandardpaths_mac.cpp16
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp8
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp34
-rw-r--r--src/corelib/io/qstandardpaths_winrt.cpp7
-rw-r--r--src/corelib/io/qtemporaryfile.cpp3
-rw-r--r--src/corelib/io/qtextstream.cpp4
-rw-r--r--src/corelib/io/qurl.cpp64
-rw-r--r--src/corelib/io/qurl.h9
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp60
-rw-r--r--src/corelib/io/qwinoverlappedionotifier_p.h1
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp4
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.cpp24
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp24
-rw-r--r--src/corelib/json/qjson_p.h71
-rw-r--r--src/corelib/json/qjsonarray.cpp25
-rw-r--r--src/corelib/json/qjsonarray.h14
-rw-r--r--src/corelib/json/qjsondocument.cpp2
-rw-r--r--src/corelib/json/qjsonobject.cpp43
-rw-r--r--src/corelib/json/qjsonobject.h15
-rw-r--r--src/corelib/json/qjsonvalue.cpp19
-rw-r--r--src/corelib/json/qjsonvalue.h8
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp9
-rw-r--r--src/corelib/kernel/qcoreapplication.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp30
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h38
-rw-r--r--src/corelib/kernel/qcoreevent.cpp102
-rw-r--r--src/corelib/kernel/qcoreevent.h11
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp250
-rw-r--r--src/corelib/kernel/qfunctions_winrt.h95
-rw-r--r--src/corelib/kernel/qmath.h52
-rw-r--r--src/corelib/kernel/qmath.qdoc33
-rw-r--r--src/corelib/kernel/qmetaobject.cpp57
-rw-r--r--src/corelib/kernel/qmetatype.cpp5
-rw-r--r--src/corelib/kernel/qmetatype.h53
-rw-r--r--src/corelib/kernel/qmimedata.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp37
-rw-r--r--src/corelib/kernel/qtimer.cpp185
-rw-r--r--src/corelib/kernel/qtimer.h64
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp13
-rw-r--r--src/corelib/mimetypes/qmimetype.h5
-rw-r--r--src/corelib/plugin/qlibrary.cpp39
-rw-r--r--src/corelib/plugin/qlibrary_p.h7
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp1
-rw-r--r--src/corelib/plugin/qpluginloader.cpp11
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp39
-rw-r--r--src/corelib/statemachine/qabstractstate.h4
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h3
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp33
-rw-r--r--src/corelib/statemachine/qabstracttransition.h14
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp28
-rw-r--r--src/corelib/statemachine/qhistorystate.h16
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp21
-rw-r--r--src/corelib/statemachine/qsignaltransition.h17
-rw-r--r--src/corelib/statemachine/qstate.cpp42
-rw-r--r--src/corelib/statemachine/qstate.h21
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp42
-rw-r--r--src/corelib/statemachine/qstatemachine.h4
-rw-r--r--src/corelib/thread/qgenericatomic.h12
-rw-r--r--src/corelib/thread/qthread_p.h23
-rw-r--r--src/corelib/thread/qthread_win.cpp147
-rw-r--r--src/corelib/thread/qthread_winrt.cpp458
-rw-r--r--src/corelib/thread/thread.pri5
-rw-r--r--src/corelib/tools/qarraydata.cpp33
-rw-r--r--src/corelib/tools/qarraydata.h16
-rw-r--r--src/corelib/tools/qarraydataops.h16
-rw-r--r--src/corelib/tools/qbytearray.cpp81
-rw-r--r--src/corelib/tools/qbytearray.h50
-rw-r--r--src/corelib/tools/qchar.cpp8
-rw-r--r--src/corelib/tools/qchar.h66
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp22
-rw-r--r--src/corelib/tools/qcommandlineparser.h1
-rw-r--r--src/corelib/tools/qdatetime.cpp8
-rw-r--r--src/corelib/tools/qdatetime.h20
-rw-r--r--src/corelib/tools/qfreelist_p.h4
-rw-r--r--src/corelib/tools/qhash.cpp39
-rw-r--r--src/corelib/tools/qhash.h105
-rw-r--r--src/corelib/tools/qiterator.h13
-rw-r--r--src/corelib/tools/qiterator.qdoc20
-rw-r--r--src/corelib/tools/qline.cpp14
-rw-r--r--src/corelib/tools/qline.h14
-rw-r--r--src/corelib/tools/qlist.cpp6
-rw-r--r--src/corelib/tools/qlist.h16
-rw-r--r--src/corelib/tools/qlocale.cpp14
-rw-r--r--src/corelib/tools/qlocale_p.h27
-rw-r--r--src/corelib/tools/qlocale_tools.cpp6
-rw-r--r--src/corelib/tools/qpoint.cpp13
-rw-r--r--src/corelib/tools/qrect.cpp12
-rw-r--r--src/corelib/tools/qrect.h36
-rw-r--r--src/corelib/tools/qregularexpression.cpp114
-rw-r--r--src/corelib/tools/qregularexpression.h9
-rw-r--r--src/corelib/tools/qringbuffer_p.h318
-rw-r--r--src/corelib/tools/qscopedvaluerollback.cpp11
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h9
-rw-r--r--src/corelib/tools/qset.h9
-rw-r--r--src/corelib/tools/qshareddata.cpp32
-rw-r--r--src/corelib/tools/qshareddata.h19
-rw-r--r--src/corelib/tools/qsharedpointer.cpp104
-rw-r--r--src/corelib/tools/qsharedpointer.h11
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h108
-rw-r--r--src/corelib/tools/qsimd.cpp162
-rw-r--r--src/corelib/tools/qsimd_p.h127
-rw-r--r--src/corelib/tools/qsize.cpp12
-rw-r--r--src/corelib/tools/qstring.cpp308
-rw-r--r--src/corelib/tools/qstring.h9
-rw-r--r--src/corelib/tools/qstringlist.cpp72
-rw-r--r--src/corelib/tools/qstringlist.h13
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp55
-rw-r--r--src/corelib/tools/qtimezoneprivate_p.h11
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp2
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp4
-rw-r--r--src/corelib/tools/qtools_p.h2
-rw-r--r--src/corelib/tools/qunicodetables.cpp8
-rw-r--r--src/corelib/tools/qvector.cpp28
-rw-r--r--src/corelib/tools/qvector.h54
-rw-r--r--src/corelib/tools/tools.pri16
-rw-r--r--src/corelib/xml/qxmlstream.cpp8
171 files changed, 5443 insertions, 1916 deletions
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index a23a6a7cda..61fe6e8c88 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -206,11 +206,11 @@ void QVariantAnimationPrivate::convertValues(int t)
//this ensures that all the keyValues are of type t
for (int i = 0; i < keyValues.count(); ++i) {
QVariantAnimation::KeyValue &pair = keyValues[i];
- pair.second.convert(static_cast<QVariant::Type>(t));
+ pair.second.convert(t);
}
//we also need update to the current interval if needed
- currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
- currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
+ currentInterval.start.second.convert(t);
+ currentInterval.end.second.convert(t);
//... and the interpolator
updateInterpolator();
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index 4fb32dcc59..9139e61700 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -100,27 +100,44 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const
for ( ; end - src >= 16; src += 16, dst += 16) {
__m128i data = _mm_loadu_si128((__m128i*)src);
+#ifdef __AVX2__
+ const int BitSpacing = 2;
+ // load and zero extend to an YMM register
+ const __m256i extended = _mm256_cvtepu8_epi16(data);
+
+ uint n = _mm256_movemask_epi8(extended);
+ if (!n) {
+ // store
+ _mm256_storeu_si256((__m256i*)dst, extended);
+ continue;
+ }
+#else
+ const int BitSpacing = 1;
+
// check if everything is ASCII
// movemask extracts the high bit of every byte, so n is non-zero if something isn't ASCII
uint n = _mm_movemask_epi8(data);
- if (n) {
- // copy the front part that is still ASCII
- while (!(n & 1)) {
- *dst++ = *src++;
- n >>= 1;
- }
+ if (!n) {
+ // unpack
+ _mm_storeu_si128((__m128i*)dst, _mm_unpacklo_epi8(data, _mm_setzero_si128()));
+ _mm_storeu_si128(1+(__m128i*)dst, _mm_unpackhi_epi8(data, _mm_setzero_si128()));
+ continue;
+ }
+#endif
- // find the next probable ASCII character
- // we don't want to load 16 bytes again in this loop if we know there are non-ASCII
- // characters still coming
- n = _bit_scan_reverse(n);
- nextAscii = src + n + 1;
- return false;
+ // copy the front part that is still ASCII
+ while (!(n & 1)) {
+ *dst++ = *src++;
+ n >>= BitSpacing;
}
- // unpack
- _mm_storeu_si128((__m128i*)dst, _mm_unpacklo_epi8(data, _mm_setzero_si128()));
- _mm_storeu_si128(1+(__m128i*)dst, _mm_unpackhi_epi8(data, _mm_setzero_si128()));
+ // find the next probable ASCII character
+ // we don't want to load 16 bytes again in this loop if we know there are non-ASCII
+ // characters still coming
+ n = _bit_scan_reverse(n);
+ nextAscii = src + (n / BitSpacing) + 1;
+ return false;
+
}
return src == end;
}
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 812aee3252..2d78041752 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -31,6 +31,7 @@ ANDROID_PERMISSIONS = \
android.permission.WRITE_EXTERNAL_STORAGE
load(qt_module)
+load(qfeatures)
include(animation/animation.pri)
include(arch/arch.pri)
@@ -84,7 +85,6 @@ cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cma
cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake
load(cmake_functions)
-load(qfeatures)
CMAKE_DISABLED_FEATURES = $$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ")
@@ -116,17 +116,3 @@ ctest_qt5_module_files.files += $$ctest_macros_file.output $$cmake_extras_mkspec
ctest_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5Core
INSTALLS += ctest_qt5_module_files cmake_qt5_umbrella_module_files
-
-mips_dsp:*-g++* {
- HEADERS += $$MIPS_DSP_HEADERS
-
- mips_dsp_corelib_assembler.commands = $$QMAKE_CXX -c
- mips_dsp_corelib_assembler.commands += $(CXXFLAGS) $(INCPATH) -mips32r2 -mdsp ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
- mips_dsp_corelib_assembler.dependency_type = TYPE_C
- mips_dsp_corelib_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
- mips_dsp_corelib_assembler.input = MIPS_DSP_ASM
- mips_dsp_corelib_assembler.variable_out = OBJECTS
- mips_dsp_corelib_assembler.name = assembling[mips_dsp] ${QMAKE_FILE_IN}
- silent:mips_dsp_corelib_assembler.commands = @echo assembling[mips_dsp] ${QMAKE_FILE_IN} && $$mips_dsp_corelib_assembler.commands
- QMAKE_EXTRA_COMPILERS += mips_dsp_corelib_assembler
-}
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index c9c8f1da54..7c879cbbfd 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtCore
description = Qt Core Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = core
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index b907c9acb1..d804514584 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -136,9 +136,9 @@ int roundedValueB = qRound(valueB);
qreal valueA = 42949672960.3;
qreal valueB = 42949672960.7;
-int roundedValueA = qRound(valueA);
+qint64 roundedValueA = qRound64(valueA);
// roundedValueA = 42949672960
-int roundedValueB = qRound(valueB);
+qint64 roundedValueB = qRound64(valueB);
// roundedValueB = 42949672961
//! [12]
@@ -305,7 +305,7 @@ void load(const QString &fileName)
{
QFile file(fileName);
if (!file.exists())
- qCritical("File '%s' does not exist!", qPrintable(fileName));
+ qCritical("File '%s' does not exist!", qUtf8Printable(fileName));
}
//! [28]
@@ -424,7 +424,7 @@ void TheClass::addLabels()
//! [37]
-qWarning("%s: %s", qPrintable(key), qPrintable(value));
+qWarning("%s: %s", qUtf8Printable(key), qUtf8Printable(value));
//! [37]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index 8c21083976..aa0473964c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -297,3 +297,13 @@ while (i != hash.end() && i.key() == "plenty") {
++i;
}
//! [26]
+
+//! [qhashbits]
+inline uint qHash(const std::vector<int> &key, uint seed = 0)
+{
+ if (key.empty())
+ return seed;
+ else
+ return qHashBits(&key.front(), key.size() * sizeof(int), seed);
+}
+//! [qhashbits]
diff --git a/src/corelib/doc/snippets/qloggingcategory/main.cpp b/src/corelib/doc/snippets/qloggingcategory/main.cpp
index 628243dbdd..3c6424921e 100644
--- a/src/corelib/doc/snippets/qloggingcategory/main.cpp
+++ b/src/corelib/doc/snippets/qloggingcategory/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@@ -43,12 +43,15 @@
//![1]
// in a header
-Q_DECLARE_LOGGING_CATEGORY(QT_DRIVER_USB)
+Q_DECLARE_LOGGING_CATEGORY(driverUsb)
// in one source file
-Q_LOGGING_CATEGORY(QT_DRIVER_USB, "qt.driver.usb")
+Q_LOGGING_CATEGORY(driverUsb, "driver.usb")
//![1]
+//![5]
+Q_LOGGING_CATEGORY(driverUsbEvents, "driver.usb.events", QtWarningMsg)
+//![5]
// Completely made up example, inspired by en.wikipedia.org/wiki/USB :)
struct UsbEntry {
@@ -76,8 +79,8 @@ QLoggingCategory::CategoryFilter oldCategoryFilter;
void myCategoryFilter(QLoggingCategory *category)
{
- // configure qt.driver.usb category here, otherwise forward to to default filter.
- if (qstrcmp(category->categoryName(), "qt.driver.usb") == 0)
+ // configure driver.usb category here, otherwise forward to to default filter.
+ if (qstrcmp(category->categoryName(), "driver.usb") == 0)
category->setEnabled(QtDebugMsg, true);
else
oldCategoryFilter(category);
@@ -89,7 +92,7 @@ int main(int argc, char *argv[])
QCoreApplication a(argc, argv);
//![2]
- QLoggingCategory::setFilterRules(QStringLiteral("qt.driver.usb.debug=true"));
+ QLoggingCategory::setFilterRules(QStringLiteral("driver.usb.debug=true"));
//![2]
//![22]
@@ -103,48 +106,48 @@ oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![3]
//![4]
- // usbEntries() will only be called if QT_DRIVER_USB category is enabled
- qCDebug(QT_DRIVER_USB) << "devices: " << usbEntries();
+ // usbEntries() will only be called if driverUsb category is enabled
+ qCDebug(driverUsb) << "devices: " << usbEntries();
//![4]
{
//![10]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCDebug(category) << "a debug message";
//![10]
}
{
//![11]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCWarning(category) << "a warning message";
//![11]
}
{
//![12]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCCritical(category) << "a critical message";
//![12]
}
{
//![13]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCDebug(category, "a debug message logged into category %s", category.categoryName());
//![13]
}
{
//![14]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCWarning(category, "a warning message logged into category %s", category.categoryName());
//![14]
}
{
//![15]
- QLoggingCategory category("qt.driver.usb");
+ QLoggingCategory category("driver.usb");
qCCritical(category, "a critical message logged into category %s", category.categoryName());
//![15]
}
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
new file mode 100644
index 0000000000..e35595e727
--- /dev/null
+++ b/src/corelib/global/archdetect.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qprocessordetection.h"
+
+// main part: processor type
+#if defined(Q_PROCESSOR_ALPHA)
+# define ARCH_PROCESSOR "alpha"
+#elif defined(Q_PROCESSOR_ARM_32)
+# define ARCH_PROCESSOR "arm"
+#elif defined(Q_PROCESSOR_ARM_64)
+# define ARCH_PROCESSOR "arm64"
+#elif defined(Q_PROCESSOR_AVR32)
+# define ARCH_PROCESSOR "avr32"
+#elif defined(Q_PROCESSOR_BLACKFIN)
+# define ARCH_PROCESSOR "bfin"
+#elif defined(Q_PROCESSOR_X86_32)
+# define ARCH_PROCESSOR "i386"
+#elif defined(Q_PROCESSOR_X86_64)
+# define ARCH_PROCESSOR "x86_64"
+#elif defined(Q_PROCESSOR_IA64)
+# define ARCH_PROCESSOR "ia64"
+#elif defined(Q_PROCESSOR_MIPS_64)
+# define ARCH_PROCESSOR "mips64"
+#elif defined(Q_PROCESSOR_MIPS)
+# define ARCH_PROCESSOR "mips"
+#elif defined(Q_PROCESSOR_POWER_32)
+# define ARCH_PROCESSOR "power"
+#elif defined(Q_PROCESSOR_POWER_64)
+# define ARCH_PROCESSOR "power64"
+#elif defined(Q_PROCESSOR_S390_X)
+# define ARCH_PROCESSOR "s390x"
+#elif defined(Q_PROCESSOR_S390)
+# define ARCH_PROCESSOR "s390"
+#elif defined(Q_PROCESSOR_SH)
+# define ARCH_PROCESSOR "sh"
+#elif defined(Q_PROCESSORS_SPARC_64)
+# define ARCH_PROCESSOR "sparc64"
+#elif defined(Q_PROCESSOR_SPARC_V9)
+# define ARCH_PROCESSOR "sparcv9"
+#elif defined(Q_PROCESSOR_SPARC)
+# define ARCH_PROCESSOR "sparc"
+#else
+# define ARCH_PROCESSOR "unknown"
+#endif
+
+// endinanness
+#if defined(Q_LITTLE_ENDIAN)
+# define ARCH_ENDIANNESS "little_endian"
+#elif defined(Q_BIG_ENDIAN)
+# define ARCH_ENDIANNESS "big_endian"
+#endif
+
+// pointer type
+#if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64))
+# define ARCH_POINTER "llp64"
+#elif defined(__LP64__) || QT_POINTER_SIZE - 0 == 8
+# define ARCH_POINTER "lp64"
+#else
+# define ARCH_POINTER "ilp32"
+#endif
+
+// qreal type, if not double (includes the dash)
+#ifdef QT_COORD_TYPE_STRING
+# define ARCH_COORD_TYPE "-qreal_" QT_COORD_TYPE_STRING
+#else
+# define ARCH_COORD_TYPE ""
+#endif
+
+// secondary: ABI string (includes the dash)
+#if defined(__ARM_EABI__) || defined(__mips_eabi)
+# define ARCH_ABI1 "-eabi"
+#elif defined(_MIPS_SIM)
+# if _MIPS_SIM == _ABIO32
+# define ARCH_ABI1 "-o32"
+# elif _MIPS_SIM == _ABIN32
+# define ARCH_ABI1 "-n32"
+# elif _MIPS_SIM == _ABI64
+# define ARCH_ABI1 "-n64"
+# elif _MIPS_SIM == _ABIO64
+# define ARCH_ABI1 "-o64"
+# endif
+#else
+# define ARCH_ABI1 ""
+#endif
+#if defined(__ARM_PCS_VFP) || defined(__mips_hard_float)
+# define ARCH_ABI2 "-hardfloat"
+#else
+# define ARCH_ABI2 ""
+#endif
+
+#define ARCH_ABI ARCH_ABI1 ARCH_ABI2
+
+#define ARCH_FULL ARCH_PROCESSOR "-" ARCH_ENDIANNESS "-" ARCH_POINTER ARCH_COORD_TYPE ARCH_ABI
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index efa585ff3e..fb0e7fd708 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -16,15 +16,18 @@ HEADERS += \
global/qsysinfo.h \
global/qisenum.h \
global/qtypetraits.h \
- global/qflags.h
+ global/qflags.h \
+ global/qhooks_p.h
SOURCES += \
+ global/archdetect.cpp \
global/qglobal.cpp \
global/qglobalstatic.cpp \
global/qlibraryinfo.cpp \
global/qmalloc.cpp \
global/qnumeric.cpp \
- global/qlogging.cpp
+ global/qlogging.cpp \
+ global/qhooks.cpp
# qlibraryinfo.cpp includes qconfig.cpp
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index b12f944357..693d7e5c75 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
@@ -89,7 +89,9 @@
# define Q_CC_MSVC
# define Q_CC_MSVC_NET
# define Q_OUTOFLINE_TEMPLATE inline
-# define Q_NO_TEMPLATE_FRIENDS
+# if _MSC_VER < 1600
+# define Q_NO_TEMPLATE_FRIENDS
+# endif
# define Q_COMPILER_MANGLES_RETURN_TYPE
# define Q_FUNC_INFO __FUNCSIG__
# define Q_ALIGNOF(type) __alignof(type)
@@ -200,6 +202,8 @@
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
# define Q_NORETURN __attribute__((__noreturn__))
# define Q_REQUIRED_RESULT __attribute__ ((__warn_unused_result__))
+# define Q_DECL_PURE_FUNCTION __attribute__((pure))
+# define Q_DECL_CONST_FUNCTION __attribute__((const))
# if !defined(QT_MOC_CPP)
# define Q_PACKED __attribute__ ((__packed__))
# ifndef __ARM_EABI__
@@ -439,59 +443,55 @@
/*
* C++11 support
*
- * Paper Macro
+ * Paper Macro SD-6 macro
* N2341 Q_COMPILER_ALIGNAS
* N2341 Q_COMPILER_ALIGNOF
* N2427 Q_COMPILER_ATOMICS
- * N2761 Q_COMPILER_ATTRIBUTES
+ * N2761 Q_COMPILER_ATTRIBUTES __cpp_attributes = 200809
* N2541 Q_COMPILER_AUTO_FUNCTION
* N1984 N2546 Q_COMPILER_AUTO_TYPE
* N2437 Q_COMPILER_CLASS_ENUM
- * N2235 Q_COMPILER_CONSTEXPR
- * N2343 N3276 Q_COMPILER_DECLTYPE
+ * N2235 Q_COMPILER_CONSTEXPR __cpp_constexpr = 200704
+ * N2343 N3276 Q_COMPILER_DECLTYPE __cpp_decltype = 200707
* N2346 Q_COMPILER_DEFAULT_MEMBERS
* N2346 Q_COMPILER_DELETE_MEMBERS
* N1986 Q_COMPILER_DELEGATING_CONSTRUCTORS
* N2437 Q_COMPILER_EXPLICIT_CONVERSIONS
- * N3206 N3272 Q_COMPILER_EXPLICIT_OVERRIDES (v0.9 and above only)
+ * N3206 N3272 Q_COMPILER_EXPLICIT_OVERRIDES
* N1987 Q_COMPILER_EXTERN_TEMPLATES
* N2540 Q_COMPILER_INHERITING_CONSTRUCTORS
* N2672 Q_COMPILER_INITIALIZER_LISTS
- * N2658 N2927 Q_COMPILER_LAMBDA (v1.0 and above only)
+ * N2658 N2927 Q_COMPILER_LAMBDA __cpp_lambdas = 200907
* N2756 Q_COMPILER_NONSTATIC_MEMBER_INIT
* N2855 N3050 Q_COMPILER_NOEXCEPT
* N2431 Q_COMPILER_NULLPTR
* N2930 Q_COMPILER_RANGE_FOR
- * N2442 Q_COMPILER_RAW_STRINGS
+ * N2442 Q_COMPILER_RAW_STRINGS __cpp_raw_strings = 200710
* N2439 Q_COMPILER_REF_QUALIFIERS
- * N2118 N2844 N3053 Q_COMPILER_RVALUE_REFS (Note: GCC 4.3 implements only the oldest)
- * N1720 Q_COMPILER_STATIC_ASSERT
+ * N2118 N2844 N3053 Q_COMPILER_RVALUE_REFS __cpp_rvalue_references = 200610
+ * N1720 Q_COMPILER_STATIC_ASSERT __cpp_static_assert = 200410
* N2258 Q_COMPILER_TEMPLATE_ALIAS
* N2659 Q_COMPILER_THREAD_LOCAL
- * N2765 Q_COMPILER_UDL
- * N2442 Q_COMPILER_UNICODE_STRINGS
+ * N2660 Q_COMPILER_THREADSAFE_STATICS
+ * N2765 Q_COMPILER_UDL __cpp_user_defined_literals = 200809
+ * N2442 Q_COMPILER_UNICODE_STRINGS __cpp_unicode_literals = 200710
* N2640 Q_COMPILER_UNIFORM_INIT
* N2544 Q_COMPILER_UNRESTRICTED_UNIONS
* N1653 Q_COMPILER_VARIADIC_MACROS
- * N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES
- *
- * C++1y proposed features
- *
- * N3472 Q_COMPILER_BINARY_LITERALS
- * N3649 Q_COMPILER_GENERIC_LAMBDA
- * N3638 Q_COMPILER_LAMBDA_CAPTURES
- * N3652 Q_COMPILER_RELAXED_CONSTEXPR_FUNCTIONS
- * N3386 N3638 Q_COMPILER_RETURN_TYPE_DEDUCTION
- * N3651 Q_COMPILER_VARIABLE_TEMPLATES
+ * N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES __cpp_variadic_templates = 200704
*
- * C++14 Technical Specifications / C++17:
- * N3639 Q_COMPILER_VLA (see also Q_COMPILER_RESTRICTED_VLA)
+ * For any future version of the C++ standard, we use only the SD-6 macro.
+ * For full listing, see
+ * http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
*
+ * C++ extensions:
+ * Q_COMPILER_RESTRICTED_VLA variable-length arrays, prior to __cpp_runtime_arrays
*/
#ifdef Q_CC_INTEL
# define Q_COMPILER_RESTRICTED_VLA
# define Q_COMPILER_VARIADIC_MACROS // C++11 feature supported as an extension in other modes, too
+# define Q_COMPILER_THREADSAFE_STATICS
# if __INTEL_COMPILER < 1200
# define Q_NO_TEMPLATE_FRIENDS
# endif
@@ -533,18 +533,28 @@
// causes issues with QArrayData and QtPrivate::RefCount - Intel issue ID 6000056211, bug DPD200534796
//# define Q_COMPILER_CONSTEXPR
# define Q_COMPILER_DELEGATING_CONSTRUCTORS
+# define Q_COMPILER_EXPLICIT_CONVERSIONS
# define Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_COMPILER_NONSTATIC_MEMBER_INIT
+# define Q_COMPILER_RANGE_FOR
# define Q_COMPILER_RAW_STRINGS
# define Q_COMPILER_REF_QUALIFIERS
# define Q_COMPILER_UNRESTRICTED_UNIONS
# endif
+# if __INTEL_COMPILER >= 1500
+# define Q_COMPILER_ALIGNAS
+# define Q_COMPILER_ALIGNOF
+# define Q_COMPILER_INHERITING_CONSTRUCTORS
+# define Q_COMPILER_THREAD_LOCAL
+# define Q_COMPILER_UDL
+# endif
# endif
#endif
#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
/* General C++ features */
# define Q_COMPILER_RESTRICTED_VLA
+# define Q_COMPILER_THREADSAFE_STATICS
# if !__has_feature(cxx_exceptions)
# ifndef QT_NO_EXCEPTIONS
# define QT_NO_EXCEPTIONS
@@ -671,8 +681,7 @@
# endif
# endif
-/* C++1y features, see http://clang.llvm.org/cxx_status.html and
- * http://clang.llvm.org/docs/LanguageExtensions.html#checks-for-standard-language-features */
+/* C++1y features, deprecated macros. Do not update this list. */
# if __cplusplus > 201103L
//# if __has_feature(cxx_binary_literals)
//# define Q_COMPILER_BINARY_LITERALS // see above
@@ -696,10 +705,18 @@
# define Q_COMPILER_VLA
# endif
# endif
+
+# if defined(__has_warning)
+# if __has_warning("-Wunused-private-field")
+# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
+# endif
+# endif
+
#endif // Q_CC_CLANG
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# define Q_COMPILER_RESTRICTED_VLA
+# define Q_COMPILER_THREADSAFE_STATICS
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
// GCC supports binary literals in C, C++98 and C++11 modes
# define Q_COMPILER_BINARY_LITERALS
@@ -773,7 +790,7 @@
# endif
# if __cplusplus > 201103L
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409
- /* C++1y features in GCC 4.9 */
+ /* C++1y features in GCC 4.9 - deprecated, do not update this list */
//# define Q_COMPILER_BINARY_LITERALS // already supported since GCC 4.3 as an extension
# define Q_COMPILER_LAMBDA_CAPTURES
# define Q_COMPILER_RETURN_TYPE_DEDUCTION
@@ -782,6 +799,7 @@
#endif
#if defined(Q_CC_MSVC) && !defined(Q_CC_INTEL)
+# if defined(__cplusplus)
# if _MSC_VER >= 1400
/* C++11 features supported in VC8 = VC2005: */
# define Q_COMPILER_VARIADIC_MACROS
@@ -804,8 +822,10 @@
/* C++11 features supported in VC10 = VC2010: */
# define Q_COMPILER_AUTO_FUNCTION
# define Q_COMPILER_AUTO_TYPE
-# define Q_COMPILER_LAMBDA
# define Q_COMPILER_DECLTYPE
+# define Q_COMPILER_EXTERN_TEMPLATES
+# define Q_COMPILER_LAMBDA
+# define Q_COMPILER_NULLPTR
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_STATIC_ASSERT
// MSVC's library has std::initializer_list, but the compiler does not support the braces initialization
@@ -817,7 +837,6 @@
# undef Q_DECL_OVERRIDE /* undo 2005/2008 settings... */
# undef Q_DECL_FINAL /* undo 2005/2008 settings... */
# define Q_COMPILER_EXPLICIT_OVERRIDES /* ...and use std C++11 now */
-# define Q_COMPILER_RANGE_FOR
# define Q_COMPILER_CLASS_ENUM
# define Q_COMPILER_ATOMICS
# endif /* VC 11 */
@@ -840,6 +859,7 @@
# define Q_COMPILER_INITIALIZER_LISTS
# endif /* VC 12 SP 2 RC */
+# endif /* __cplusplus */
#endif /* Q_CC_MSVC */
#ifdef __cplusplus
@@ -864,6 +884,13 @@
# undef Q_COMPILER_RVALUE_REFS
# undef Q_COMPILER_REF_QUALIFIERS
# endif
+# if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC)
+// Mac OS X: Apple's low-level implementation of the C++ support library
+// (libc++abi.dylib, shared between libstdc++ and libc++) has deadlocks. The
+// C++11 standard requires the deadlocks to be removed, so this will eventually
+// be fixed; for now, let's disable this.
+# undef Q_COMPILER_THREADSAFE_STATICS
+# endif
#endif
/*
@@ -976,6 +1003,9 @@
#ifndef Q_DECL_UNUSED
# define Q_DECL_UNUSED
#endif
+#ifndef Q_DECL_UNUSED_MEMBER
+# define Q_DECL_UNUSED_MEMBER
+#endif
#ifndef Q_FUNC_INFO
# if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC)
# define Q_FUNC_INFO __FILE__ "(line number unavailable)"
@@ -989,17 +1019,11 @@
#ifndef Q_DECL_NS_RETURNS_AUTORELEASED
# define Q_DECL_NS_RETURNS_AUTORELEASED
#endif
-
-/*
- Workaround for static const members on MSVC++.
-*/
-
-#if defined(Q_CC_MSVC)
-# define QT_STATIC_CONST static
-# define QT_STATIC_CONST_IMPL
-#else
-# define QT_STATIC_CONST static const
-# define QT_STATIC_CONST_IMPL const
+#ifndef Q_DECL_PURE_FUNCTION
+# define Q_DECL_PURE_FUNCTION
+#endif
+#ifndef Q_DECL_CONST_FUNCTION
+# define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION
#endif
/*
diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h
index bdfc453e08..097f2760b4 100644
--- a/src/corelib/global/qflags.h
+++ b/src/corelib/global/qflags.h
@@ -47,6 +47,10 @@
#include <QtCore/qtypeinfo.h>
#include <QtCore/qtypetraits.h>
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+#include <initializer_list>
+#endif
+
QT_BEGIN_NAMESPACE
class QFlag
@@ -116,6 +120,11 @@ public:
Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {}
Q_DECL_CONSTEXPR inline QFlags(QFlag f) : i(f) {}
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags)
+ : i(initializer_list_helper(flags.begin(), flags.end())) {}
+#endif
+
inline QFlags &operator&=(int mask) { i &= mask; return *this; }
inline QFlags &operator&=(uint mask) { i &= mask; return *this; }
inline QFlags &operator&=(Enum mask) { i &= Int(mask); return *this; }
@@ -139,6 +148,14 @@ public:
Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); }
private:
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
+ typename std::initializer_list<Enum>::const_iterator end)
+ {
+ return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
+ }
+#endif
+
Int i;
};
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 6b5638d336..a0c943df62 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -80,6 +81,21 @@
#include <private/qjni_p.h>
#endif
+#if defined(Q_OS_BLACKBERRY)
+# include <bps/deviceinfo.h>
+#endif
+
+#if defined(Q_OS_SOLARIS)
+# include <sys/systeminfo.h>
+#endif
+
+#ifdef Q_OS_UNIX
+#include <sys/utsname.h>
+#include <private/qcore_unix_p.h>
+#endif
+
+#include "archdetect.cpp"
+
QT_BEGIN_NAMESPACE
#if !QT_DEPRECATED_SINCE(5, 0)
@@ -258,6 +274,16 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
*/
/*!
+ \fn QFlags::QFlags(std::initializer_list<Enum> flags)
+ \since 5.4
+
+ Constructs a QFlags object initialized with all \a flags
+ combined using the bitwise OR operator.
+
+ \sa operator|=(), operator|()
+*/
+
+/*!
\fn QFlags &QFlags::operator=(const QFlags &other)
Assigns \a other to this object and returns a reference to this
@@ -568,8 +594,8 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
64-bit integer literals in a platform-independent way. The
Q_CHECK_PTR() macro prints a warning containing the source code's
file name and line number, saying that the program ran out of
- memory, if the pointer is 0. The qPrintable() macro represent an
- easy way of printing text.
+ memory, if the pointer is 0. The qPrintable() and qUtf8Printable()
+ macros represent an easy way of printing text.
Finally, the QT_POINTER_SIZE macro expands to the size of a
pointer in bytes, and the QT_VERSION and QT_VERSION_STR macros
@@ -1096,6 +1122,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_10_7 OS X 10.7
\value MV_10_8 OS X 10.8
\value MV_10_9 OS X 10.9
+ \value MV_10_10 OS X 10.10
\value MV_Unknown An unknown and currently unsupported platform
\value MV_CHEETAH Apple codename for MV_10_0
@@ -1108,6 +1135,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_LION Apple codename for MV_10_7
\value MV_MOUNTAINLION Apple codename for MV_10_8
\value MV_MAVERICKS Apple codename for MV_10_9
+ \value MV_YOSEMITE Apple codename for MV_10_10
\value MV_IOS iOS (any)
\value MV_IOS_4_3 iOS 4.3
@@ -1117,6 +1145,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
\value MV_IOS_6_1 iOS 6.1
\value MV_IOS_7_0 iOS 7.0
\value MV_IOS_7_1 iOS 7.1
+ \value MV_IOS_8_0 iOS 8.0
\sa WinVersion
*/
@@ -1500,6 +1529,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for Alpha processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1509,6 +1540,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARM processors. Qt currently
supports three optional ARM revisions: \l Q_PROCESSOR_ARM_V5, \l
Q_PROCESSOR_ARM_V6, and \l Q_PROCESSOR_ARM_V7.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V5
@@ -1516,6 +1549,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv5 processors. The \l
Q_PROCESSOR_ARM macro is also defined when Q_PROCESSOR_ARM_V5 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V6
@@ -1524,6 +1559,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv6 processors. The \l
Q_PROCESSOR_ARM and \l Q_PROCESSOR_ARM_V5 macros are also defined when
Q_PROCESSOR_ARM_V6 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_ARM_V7
@@ -1532,6 +1569,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for ARMv7 processors. The \l
Q_PROCESSOR_ARM, \l Q_PROCESSOR_ARM_V5, and \l Q_PROCESSOR_ARM_V6 macros
are also defined when Q_PROCESSOR_ARM_V7 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1539,6 +1578,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for AVR32 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1546,6 +1587,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
\relates <QtGlobal>
Defined if the application is compiled for Blackfin processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1554,6 +1597,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for IA-64 processors. This includes
all Itanium and Itanium 2 processors.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1564,6 +1609,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
supports seven MIPS revisions: \l Q_PROCESSOR_MIPS_I, \l
Q_PROCESSOR_MIPS_II, \l Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, \l
Q_PROCESSOR_MIPS_V, \l Q_PROCESSOR_MIPS_32, and \l Q_PROCESSOR_MIPS_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_I
@@ -1571,6 +1618,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-I processors. The \l
Q_PROCESSOR_MIPS macro is also defined when Q_PROCESSOR_MIPS_I is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_II
@@ -1579,6 +1628,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-II processors. The \l
Q_PROCESSOR_MIPS and \l Q_PROCESSOR_MIPS_I macros are also defined when
Q_PROCESSOR_MIPS_II is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_32
@@ -1587,6 +1638,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS32 processors. The \l
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
are also defined when Q_PROCESSOR_MIPS_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_III
@@ -1595,6 +1648,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for MIPS-III processors. The \l
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, and \l Q_PROCESSOR_MIPS_II macros
are also defined when Q_PROCESSOR_MIPS_III is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_IV
@@ -1604,6 +1659,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, and \l
Q_PROCESSOR_MIPS_III macros are also defined when Q_PROCESSOR_MIPS_IV is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_V
@@ -1613,6 +1670,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
Q_PROCESSOR_MIPS_III, and \l Q_PROCESSOR_MIPS_IV macros are also defined
when Q_PROCESSOR_MIPS_V is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_MIPS_64
@@ -1622,6 +1681,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Q_PROCESSOR_MIPS, \l Q_PROCESSOR_MIPS_I, \l Q_PROCESSOR_MIPS_II, \l
Q_PROCESSOR_MIPS_III, \l Q_PROCESSOR_MIPS_IV, and \l Q_PROCESSOR_MIPS_V
macros are also defined when Q_PROCESSOR_MIPS_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1631,6 +1692,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for POWER processors. Qt currently
supports two Power variants: \l Q_PROCESSOR_POWER_32 and \l
Q_PROCESSOR_POWER_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_POWER_32
@@ -1639,6 +1702,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 32-bit Power processors. The \l
Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_32 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_POWER_64
@@ -1647,6 +1712,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 64-bit Power processors. The \l
Q_PROCESSOR_POWER macro is also defined when Q_PROCESSOR_POWER_64 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1655,6 +1722,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for S/390 processors. Qt supports
one optional variant of S/390: Q_PROCESSOR_S390_X.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_S390_X
@@ -1662,6 +1731,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for S/390x processors. The \l
Q_PROCESSOR_S390 macro is also defined when Q_PROCESSOR_S390_X is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1670,6 +1741,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SuperH processors. Qt currently
supports one SuperH revision: \l Q_PROCESSOR_SH_4A.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_SH_4A
@@ -1677,6 +1750,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SuperH 4A processors. The \l
Q_PROCESSOR_SH macro is also defined when Q_PROCESSOR_SH_4A is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1685,6 +1760,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SPARC processors. Qt currently
supports one optional SPARC revision: \l Q_PROCESSOR_SPARC_V9.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_SPARC_V9
@@ -1693,6 +1770,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for SPARC V9 processors. The \l
Q_PROCESSOR_SPARC macro is also defined when Q_PROCESSOR_SPARC_V9 is
defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1701,6 +1780,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for x86 processors. Qt currently
supports two x86 variants: \l Q_PROCESSOR_X86_32 and \l Q_PROCESSOR_X86_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_X86_32
@@ -1709,6 +1790,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 32-bit x86 processors. This
includes all i386, i486, i586, and i686 processors. The \l Q_PROCESSOR_X86
macro is also defined when Q_PROCESSOR_X86_32 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
\macro Q_PROCESSOR_X86_64
@@ -1717,6 +1800,8 @@ bool qSharedBuild() Q_DECL_NOTHROW
Defined if the application is compiled for 64-bit x86 processors. This
includes all AMD64, Intel 64, and other x86_64/x64 processors. The \l
Q_PROCESSOR_X86 macro is also defined when Q_PROCESSOR_X86_64 is defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
*/
/*!
@@ -1838,7 +1923,7 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
if (winver)
return winver;
#ifdef Q_OS_WINRT
- winver = QSysInfo::WV_WINDOWS8;
+ winver = QSysInfo::WV_WINDOWS8_1;
#else
winver = QSysInfo::WV_NT;
const OSVERSIONINFO osver = winOsVersion();
@@ -1931,9 +2016,613 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
return winver;
}
+static const char *winVer_helper()
+{
+ switch (int(QSysInfo::WindowsVersion)) {
+ case QSysInfo::WV_NT:
+ return "NT";
+ case QSysInfo::WV_2000:
+ return "2000";
+ case QSysInfo::WV_XP:
+ return "XP";
+ case QSysInfo::WV_2003:
+ return "2003";
+ case QSysInfo::WV_VISTA:
+ return "Vista";
+ case QSysInfo::WV_WINDOWS7:
+ return "7";
+ case QSysInfo::WV_WINDOWS8:
+ return "8";
+ case QSysInfo::WV_WINDOWS8_1:
+ return "8.1";
+
+ case QSysInfo::WV_CE:
+ return "CE";
+ case QSysInfo::WV_CENET:
+ return "CENET";
+ case QSysInfo::WV_CE_5:
+ return "CE5";
+ case QSysInfo::WV_CE_6:
+ return "CE6";
+ }
+ // unknown, future version
+ return 0;
+}
+
const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
#endif
+#if defined(Q_OS_UNIX)
+# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
+# define USE_ETC_OS_RELEASE
+struct QUnixOSVersion
+{
+ // from /etc/os-release
+ QString productType; // $ID
+ QString productVersion; // $VERSION_ID
+ QString prettyName; // $PRETTY_NAME
+};
+
+static QString unquote(const char *begin, const char *end)
+{
+ if (*begin == '"') {
+ Q_ASSERT(end[-1] == '"');
+ return QString::fromLatin1(begin + 1, end - begin - 2);
+ }
+ return QString::fromLatin1(begin, end - begin);
+}
+
+static bool readEtcOsRelease(QUnixOSVersion &v)
+{
+ // we're avoiding QFile here
+ int fd = qt_safe_open("/etc/os-release", O_RDONLY);
+ if (fd == -1)
+ return false;
+
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) == -1) {
+ qt_safe_close(fd);
+ return false;
+ }
+
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
+ qt_safe_close(fd);
+
+ const char *ptr = buffer.constData();
+ const char *end = buffer.constEnd();
+ const char *eol;
+ for ( ; ptr != end; ptr = eol + 1) {
+ static const char idString[] = "ID=";
+ static const char prettyNameString[] = "PRETTY_NAME=";
+ static const char versionIdString[] = "VERSION_ID=";
+
+ // find the end of the line after ptr
+ eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
+ if (!eol)
+ eol = end - 1;
+
+ // note: we're doing a binary search here, so comparison
+ // must always be sorted
+ int cmp = strncmp(ptr, idString, strlen(idString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(idString);
+ v.productType = unquote(ptr, eol);
+ continue;
+ }
+
+ cmp = strncmp(ptr, prettyNameString, strlen(prettyNameString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(prettyNameString);
+ v.prettyName = unquote(ptr, eol);
+ continue;
+ }
+
+ cmp = strncmp(ptr, versionIdString, strlen(versionIdString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(versionIdString);
+ v.productVersion = unquote(ptr, eol);
+ continue;
+ }
+ }
+
+ return true;
+}
+# endif // USE_ETC_OS_RELEASE
+#endif // Q_OS_UNIX
+
+
+/*!
+ \since 5.4
+
+ Returns the architecture of the CPU that Qt was compiled for, in text
+ format. Note that this may not match the actual CPU that the application is
+ running on if there's an emulation layer or if the CPU supports multiple
+ architectures (like x86-64 processors supporting i386 applications). To
+ detect that, use currentCpuArchitecture().
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new CPU types may be added over time.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "arm"
+ \li "arm64"
+ \li "i386"
+ \li "ia64"
+ \li "mips"
+ \li "mips64"
+ \li "power"
+ \li "power64"
+ \li "sparc"
+ \li "sparcv9"
+ \li "x86_64"
+ \endlist
+
+ \sa QSysInfo::buildAbi(), QSysInfo::currentCpuArchitecture()
+*/
+QString QSysInfo::buildCpuArchitecture()
+{
+ return QStringLiteral(ARCH_PROCESSOR);
+}
+
+/*!
+ \since 5.4
+
+ Returns the architecture of the CPU that the application is running on, in
+ text format. Note that this function depends on what the OS will report and
+ may not detect the actual CPU architecture if the OS hides that information
+ or is unable to provide it. For example, a 32-bit OS running on a 64-bit
+ CPU is usually unable to determine the CPU is actually capable of running
+ 64-bit programs.
+
+ Values returned by this function are mostly stable: an attempt will be made
+ to ensure that they stay constant over time and match the values returned
+ by QSysInfo::builldCpuArchitecture(). However, due to the nature of the
+ operating system functions being used, there may be discrepancies.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "arm"
+ \li "arm64"
+ \li "i386"
+ \li "ia64"
+ \li "mips"
+ \li "mips64"
+ \li "power"
+ \li "power64"
+ \li "sparc"
+ \li "sparcv9"
+ \li "x86_64"
+ \endlist
+
+ \sa QSysInfo::buildAbi(), QSysInfo::buildCpuArchitecture()
+ */
+QString QSysInfo::currentCpuArchitecture()
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ // We don't need to catch all the CPU architectures in this function;
+ // only those where the host CPU might be different than the build target
+ // (usually, 64-bit platforms).
+ SYSTEM_INFO info;
+ GetNativeSystemInfo(&info);
+ switch (info.wProcessorArchitecture) {
+# ifdef PROCESSOR_ARCHITECTURE_AMD64
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ return QStringLiteral("x86_64");
+# endif
+# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
+ case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+# endif
+ case PROCESSOR_ARCHITECTURE_IA64:
+ return QStringLiteral("ia64");
+ }
+#elif defined(Q_OS_UNIX)
+ long ret = -1;
+ struct utsname u;
+
+# if defined(Q_OS_SOLARIS)
+ // We need a special call for Solaris because uname(2) on x86 returns "i86pc" for
+ // both 32- and 64-bit CPUs. Reference:
+ // http://docs.oracle.com/cd/E18752_01/html/816-5167/sysinfo-2.html#REFMAN2sysinfo-2
+ // http://fxr.watson.org/fxr/source/common/syscall/systeminfo.c?v=OPENSOLARIS
+ // http://fxr.watson.org/fxr/source/common/conf/param.c?v=OPENSOLARIS;im=10#L530
+ if (ret == -1)
+ ret = sysinfo(SI_ARCHITECTURE_64, u.machine, sizeof u.machine);
+# endif
+
+ if (ret == -1)
+ ret = uname(&u);
+
+ // we could use detectUnixVersion() above, but we only need a field no other function does
+ if (ret != -1) {
+ // the use of QT_BUILD_INTERNAL here is simply to ensure all branches build
+ // as we don't often build on some of the less common platforms
+# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
+ if (strcmp(u.machine, "aarch64") == 0)
+ return QStringLiteral("arm64");
+ if (strncmp(u.machine, "armv", 4) == 0)
+ return QStringLiteral("arm");
+# endif
+# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
+ // harmonize "powerpc" and "ppc" to "power"
+ if (strncmp(u.machine, "ppc", 3) == 0)
+ return QLatin1String("power") + QLatin1String(u.machine + 3);
+ if (strncmp(u.machine, "powerpc", 7) == 0)
+ return QLatin1String("power") + QLatin1String(u.machine + 7);
+ if (strcmp(u.machine, "Power Macintosh") == 0)
+ return QLatin1String("power");
+# endif
+# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
+ // Solaris sysinfo(2) (above) uses "sparcv9", but uname -m says "sun4u";
+ // Linux says "sparc64"
+ if (strcmp(u.machine, "sun4u") == 0 || strcmp(u.machine, "sparc64") == 0)
+ return QStringLiteral("sparcv9");
+ if (strcmp(u.machine, "sparc32") == 0)
+ return QStringLiteral("sparc");
+# endif
+# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
+ // harmonize all "i?86" to "i386"
+ if (strlen(u.machine) == 4 && u.machine[0] == 'i'
+ && u.machine[2] == '8' && u.machine[3] == '6')
+ return QStringLiteral("i386");
+ if (strcmp(u.machine, "amd64") == 0) // Solaris
+ return QStringLiteral("x86_64");
+# endif
+ return QString::fromLatin1(u.machine);
+ }
+#endif
+ return buildCpuArchitecture();
+}
+
+/*!
+ \since 5.4
+
+ Returns the full architecture string that Qt was compiled for. This string
+ is useful for identifying different, incompatible builds. For example, it
+ can be used as an identifier to request an upgrade package from a server.
+
+ The values returned from this function are kept stable as follows: the
+ mandatory components of the result will not change in future versions of
+ Qt, but optional suffixes may be added.
+
+ The returned value is composed of three or more parts, separated by dashes
+ ("-"). They are:
+
+ \table
+ \header \li Component \li Value
+ \row \li CPU Architecture \li The same as QSysInfo::buildCpuArchitecture(), such as "arm", "i386", "mips" or "x86_64"
+ \row \li Endianness \li "little_endian" or "big_endian"
+ \row \li Word size \li Whether it's a 32- or 64-bit application. Possible values are:
+ "llp64" (Windows 64-bit), "lp64" (Unix 64-bit), "ilp32" (32-bit)
+ \row \li (Optional) ABI \li Zero or more components identifying different ABIs possible in this architecture.
+ Currently, Qt has optional ABI components for ARM and MIPS processors: one
+ component is the main ABI (such as "eabi", "o32", "n32", "o64"); another is
+ whether the calling convention is using hardware floating point registers ("hardfloat"
+ is present).
+
+ Additionally, if Qt was configured with \c{-qreal float}, the ABI option tag "qreal_float"
+ will be present. If Qt was configured with another type as qreal, that type is present after
+ "qreal_", with all characters other than letters and digits escaped by an underscore, followed
+ by two hex digits. For example, \c{-qreal long double} becomes "qreal_long_20double".
+ \endtable
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+QString QSysInfo::buildAbi()
+{
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks
+ // QStringLiteral on MSVC. Since the concatenation behavior we want is specified
+ // the same C++11 paper as the Unicode strings, we'll use that macro and hope
+ // that Microsoft implements the new behavior when they add support for Unicode strings.
+ return QStringLiteral(ARCH_FULL);
+#else
+ return QLatin1String(ARCH_FULL);
+#endif
+}
+
+static QString unknownText()
+{
+ return QStringLiteral("unknown");
+}
+
+/*!
+ \since 5.4
+
+ Returns the type of the operating system kernel Qt was compiled for. It's
+ also the kernel the application is running on, unless the host operating
+ system is running a form of compatibility or virtualization layer.
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new OS kernel types may be added over time.
+
+ On Windows, this function returns the type of Windows kernel, like "wince"
+ or "winnt". On Unix systems, it returns the same as the output of \c{uname
+ -s} (lowercased).
+
+ Note that this function may return surprising values: it returns "linux"
+ for all operating systems running Linux (including Android), "qnx" for all
+ operating systems running QNX (including BlackBerry 10), "freebsd" for
+ Debian/kFreeBSD, and "darwin" for OS X and iOS. For information on the type
+ of product the application is running on, see productType().
+
+ \sa QFileSelector, kernelVersion(), productType(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::kernelType()
+{
+#if defined(Q_OS_WINCE)
+ return QStringLiteral("wince");
+#elif defined(Q_OS_WIN)
+ return QStringLiteral("winnt");
+#elif defined(Q_OS_UNIX)
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.sysname).toLower();
+#endif
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns the release version of the operating system kernel. On Windows, it
+ returns the version of the NT or CE kernel. On Unix systems, including
+ Android, BlackBerry and OS X, it returns the same as the \c{uname -r}
+ command would return.
+
+ If the version could not be determined, this function may return an empty
+ string.
+
+ \sa kernelType(), productType(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::kernelVersion()
+{
+#ifdef Q_OS_WINRT
+ // TBD
+ return QString();
+#elif defined(Q_OS_WIN)
+ const OSVERSIONINFO osver = winOsVersion();
+ return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
+ + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
+#else
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.release);
+ return QString();
+#endif
+}
+
+
+/*!
+ \since 5.4
+
+ Returns the product name of the operating system this application is
+ running in. If the application is running on some sort of emulation or
+ virtualization layer (such as WINE on a Unix system), this function will
+ inspect the emulation / virtualization layer.
+
+ Values returned by this function are stable and will not change over time,
+ so applications can rely on the returned value as an identifier, except
+ that new OS types may be added over time.
+
+ \b{Linux and Android note}: this function returns "android" for Linux
+ systems running Android userspace, notably when using the Bionic library.
+ For all other Linux systems, regardless of C library being used, it tries
+ to determine the distribution name and returns that. If determining the
+ distribution name failed, it returns "unknown".
+
+ \b{BlackBerry note}: this function returns "blackberry" for QNX systems
+ running the BlackBerry userspace, but "qnx" for all other QNX-based
+ systems.
+
+ \b{Darwin, OS X and iOS note}: this function returns "osx" for OS X
+ systems, "ios" for iOS systems and "darwin" in case the system could not be
+ determined.
+
+ \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and
+ "unknown" otherwise.
+
+ \b{Windows note}: this function returns "winphone" for builds for Windows
+ Phone, "winrt" for WinRT builds, "wince" for Windows CE and Embedded
+ Compact builds, and "windows" for normal desktop builds.
+
+ For other Unix-type systems, this function usually returns "unknown".
+
+ \sa QFileSelector, kernelType(), kernelVersion(), productVersion(), prettyProductName()
+*/
+QString QSysInfo::productType()
+{
+ // similar, but not identical to QFileSelectorPrivate::platformSelectors
+#if defined(Q_OS_WINPHONE)
+ return QStringLiteral("winphone");
+#elif defined(Q_OS_WINRT)
+ return QStringLiteral("winrt");
+#elif defined(Q_OS_WINCE)
+ return QStringLiteral("wince");
+#elif defined(Q_OS_WIN)
+ return QStringLiteral("windows");
+
+#elif defined(Q_OS_BLACKBERRY)
+ return QStringLiteral("blackberry");
+#elif defined(Q_OS_QNX)
+ return QStringLiteral("qnx");
+
+#elif defined(Q_OS_ANDROID)
+ return QStringLiteral("android");
+
+#elif defined(Q_OS_IOS)
+ return QStringLiteral("ios");
+#elif defined(Q_OS_OSX)
+ return QStringLiteral("osx");
+#elif defined(Q_OS_DARWIN)
+ return QStringLiteral("darwin");
+
+#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
+ QUnixOSVersion unixOsVersion;
+ readEtcOsRelease(unixOsVersion);
+ if (!unixOsVersion.productType.isEmpty())
+ return unixOsVersion.productType;
+#endif
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns the product version of the operating system in string form. If the
+ version could not be determined, this function returns "unknown".
+
+ It will return the Android, BlackBerry, iOS, OS X, Windows full-product
+ versions on those systems. In particular, on OS X, iOS and Windows, the
+ returned string is similar to the macVersion() or windowsVersion() enums.
+
+ On Linux systems, it will try to determine the distribution version and will
+ return that. This is also done on Debian/kFreeBSD, so this function will
+ return Debian version in that case.
+
+ In all other Unix-type systems, this function always returns "unknown".
+
+ \note The version string returned from this function is only guaranteed to
+ be orderable on Android, BlackBerry, OS X and iOS. On Windows, some Windows
+ versions are text ("XP" and "Vista", for example). On Linux, the version of
+ the distribution may jump unexpectedly, please refer to the distribution's
+ documentation for versioning practices.
+
+ \sa kernelType(), kernelVersion(), productType(), prettyProductName()
+*/
+QString QSysInfo::productVersion()
+{
+#if defined(Q_OS_IOS)
+ int major = (int(MacintoshVersion) >> 4) & 0xf;
+ int minor = int(MacintoshVersion) & 0xf;
+ if (Q_LIKELY(major < 10 && minor < 10)) {
+ char buf[4] = { char(major + '0'), '.', char(minor + '0'), '\0' };
+ return QString::fromLatin1(buf, 3);
+ }
+ return QString::number(major) + QLatin1Char('.') + QString::number(minor);
+#elif defined(Q_OS_OSX)
+ int minor = int(MacintoshVersion) - 2; // we're not running on Mac OS 9
+ Q_ASSERT(minor < 100);
+ char buf[] = "10.0\0";
+ if (Q_LIKELY(minor < 10)) {
+ buf[3] += minor;
+ } else {
+ buf[3] += minor / 10;
+ buf[4] = '0' + minor % 10;
+ }
+ return QString::fromLatin1(buf);
+#elif defined(Q_OS_WIN)
+ const char *version = winVer_helper();
+ if (version)
+ return QString::fromLatin1(version).toLower();
+ // fall through
+
+// Android and Blackberry should not fall through to the Unix code
+#elif defined(Q_OS_ANDROID)
+ // TBD
+#elif defined(Q_OS_BLACKBERRY)
+ deviceinfo_details_t *deviceInfo;
+ if (deviceinfo_get_details(&deviceInfo) == BPS_SUCCESS) {
+ QString bbVersion = QString::fromLatin1(deviceinfo_details_get_device_os_version(deviceInfo));
+ deviceinfo_free_details(&deviceInfo);
+ return bbVersion;
+ }
+#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
+ QUnixOSVersion unixOsVersion;
+ readEtcOsRelease(unixOsVersion);
+ if (!unixOsVersion.productVersion.isEmpty())
+ return unixOsVersion.productVersion;
+#endif
+
+ // fallback
+ return unknownText();
+}
+
+/*!
+ \since 5.4
+
+ Returns a prettier form of productType() and productVersion(), containing
+ other tokens like the operating system type, codenames and other
+ information. The result of this function is suitable for displaying to the
+ user, but not for long-term storage, as the string may change with updates
+ to Qt.
+
+ If productType() is "unknown", this function will instead use the
+ kernelType() and kernelVersion() functions.
+
+ \sa kernelType(), kernelVersion(), productType(), productVersion()
+*/
+QString QSysInfo::prettyProductName()
+{
+#if defined(Q_OS_IOS)
+ return QLatin1String("iOS ") + productVersion();
+#elif defined(Q_OS_OSX)
+ // get the known codenames
+ const char *basename = 0;
+ switch (int(MacintoshVersion)) {
+ case MV_CHEETAH:
+ case MV_PUMA:
+ case MV_JAGUAR:
+ case MV_PANTHER:
+ case MV_TIGER:
+ // This version of Qt does not run on those versions of OS X
+ // so this case label will never be reached
+ Q_UNREACHABLE();
+ break;
+ case MV_LEOPARD:
+ basename = "Mac OS X Leopard (";
+ break;
+ case MV_SNOWLEOPARD:
+ basename = "Mac OS X Snow Leopard (";
+ break;
+ case MV_LION:
+ basename = "Mac OS X Lion (";
+ break;
+ case MV_MOUNTAINLION:
+ basename = "OS X Mountain Lion (";
+ break;
+ case MV_MAVERICKS:
+ basename = "OS X Mavericks (";
+ break;
+ case MV_YOSEMITE:
+ basename = "OS X Yosemite (";
+ break;
+ }
+ if (basename)
+ return QLatin1String(basename) + productVersion() + QLatin1Char(')');
+
+ // a future version of OS X
+ return QLatin1String("OS X ") + productVersion();
+#elif defined(Q_OS_WINPHONE)
+ return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_WIN)
+ return QLatin1String("Windows ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_ANDROID)
+ return QLatin1String("Android ") + productVersion();
+#elif defined(Q_OS_BLACKBERRY)
+ return QLatin1String("BlackBerry ") + productVersion();
+#elif defined(Q_OS_UNIX)
+# ifdef USE_ETC_OS_RELEASE
+ QUnixOSVersion unixOsVersion;
+ readEtcOsRelease(unixOsVersion);
+ if (!unixOsVersion.prettyName.isEmpty())
+ return unixOsVersion.prettyName;
+# endif
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLatin1(u.sysname) + QLatin1Char(' ') + QString::fromLatin1(u.release);
+#endif
+ return unknownText();
+}
/*!
\macro void Q_ASSERT(bool test)
@@ -2815,17 +3504,31 @@ int qrand()
qPrintable() is used. This is because the array returned by
QString::toLocal8Bit() will fall out of scope.
+ \note qDebug(), qWarning(), qCritical(), qFatal() expect %s
+ arguments to be UTF-8 encoded, while qPrintable() converts to
+ local 8-bit encoding. Therefore qUtf8Printable() should be used
+ for logging strings instead of qPrintable().
+
+ \sa qUtf8Printable()
+*/
+
+/*!
+ \macro const char *qUtf8Printable(const QString &str)
+ \relates <QtGlobal>
+ \since 5.4
+
+ Returns \a str as a \c{const char *}. This is equivalent to
+ \a{str}.toUtf8().constData().
+
+ The char pointer will be invalid after the statement in which
+ qUtf8Printable() is used. This is because the array returned by
+ QString::toUtf8() will fall out of scope.
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 37
- \note qDebug(), qWarning(), qCritical(), qFatal() expect %s
- arguments to be UTF-8 encoded, while qPrintable() converts to
- local 8-bit encoding. Therefore using qPrintable for logging
- strings is only safe if the argument contains only ASCII
- characters.
-
- \sa qDebug(), qWarning(), qCritical(), qFatal()
+ \sa qPrintable(), qDebug(), qWarning(), qCritical(), qFatal()
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 255eb6c00b..5210d80953 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -45,11 +45,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "5.3.2"
+#define QT_VERSION_STR "5.4.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050302
+#define QT_VERSION 0x050400
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -649,6 +649,10 @@ inline void qUnused(T &x) { (void)x; }
# define qPrintable(string) QString(string).toLocal8Bit().constData()
#endif
+#ifndef qUtf8Printable
+# define qUtf8Printable(string) QString(string).toUtf8().constData()
+#endif
+
class QString;
Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
@@ -865,22 +869,37 @@ Q_CORE_EXPORT void qFreeAligned(void *ptr);
# endif
#endif
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT)
-/* make use of typeof-extension */
+#if defined(Q_COMPILER_DECLTYPE) || (defined(Q_CC_GNU) && !defined(Q_CC_RVCT))
+/* make use of decltype or GCC's __typeof__ extension */
template <typename T>
class QForeachContainer {
public:
- inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
+ inline QForeachContainer(const T& t) : c(t), i(c.begin()), e(c.end()), control(1) { }
const T c;
- int brk;
typename T::const_iterator i, e;
+ int control;
};
-#define Q_FOREACH(variable, container) \
-for (QForeachContainer<__typeof__((container))> _container_((container)); \
- !_container_.brk && _container_.i != _container_.e; \
- __extension__ ({ ++_container_.brk; ++_container_.i; })) \
- for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
+# ifdef Q_COMPILER_DECLTYPE
+# define QT_FOREACH_DECLTYPE(x) typename QtPrivate::remove_reference<decltype(x)>::type
+# else
+# define QT_FOREACH_DECLTYPE(x) __typeof__((x))
+# endif
+
+// Explanation of the control word:
+// - it's initialized to 1
+// - that means both the inner and outer loops start
+// - if there were no breaks, at the end of the inner loop, it's set to 0, which
+// causes it to exit (the inner loop is run exactly once)
+// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing
+// the outer loop to continue executing
+// - if there was a break inside the inner loop, it will exit with control still
+// set to 1; in that case, the outer loop will invert it to 0 and will exit too
+# define Q_FOREACH(variable, container) \
+for (QForeachContainer<QT_FOREACH_DECLTYPE(container)> _container_((container)); \
+ _container_.control && _container_.i != _container_.e; \
+ ++_container_.i, _container_.control ^= 1) \
+ for (variable = *_container_.i; _container_.control; _container_.control = 0)
#else
diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h
index 1c44569dbd..31e2e634a8 100644
--- a/src/corelib/global/qglobalstatic.h
+++ b/src/corelib/global/qglobalstatic.h
@@ -57,7 +57,7 @@ enum GuardValues {
};
}
-#if defined(QT_NO_THREAD) || (defined(Q_CC_GNU) && !defined(Q_OS_MAC))
+#if defined(QT_NO_THREAD) || defined(Q_COMPILER_THREADSAFE_STATICS)
// some compilers support thread-safe statics
// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
// support it. C++11 also requires this behavior.
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
new file mode 100644
index 0000000000..0032e87401
--- /dev/null
+++ b/src/corelib/global/qhooks.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhooks_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// Only add to the end, and bump version if you do.
+quintptr Q_CORE_EXPORT qtHookData[] = {
+ 1, // hook data version
+ QHooks::LastHookIndex, // size of qtHookData
+ QT_VERSION,
+
+ // AddQObject, void(*)(QObject*), called for every constructed QObject
+ // Note: this is called from the QObject constructor, ie. the sub-class
+ // constructors haven't run yet.
+ 0,
+
+ // RemoveQObject, void(*)(QObject*), called for every destructed QObject
+ // Note: this is called from the QObject destructor, ie. the object
+ // you get as an argument is already largely invalid.
+ 0,
+
+ // Startup, void(*)(), called once QCoreApplication is operational
+ 0
+};
+
+Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/io/qloggingcategory_p.h b/src/corelib/global/qhooks_p.h
index 7802f017fd..012f91fa66 100644
--- a/src/corelib/io/qloggingcategory_p.h
+++ b/src/corelib/global/qhooks_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -39,28 +39,36 @@
**
****************************************************************************/
-#ifndef QLOGGINGCATEGORY_P_H
-#define QLOGGINGCATEGORY_P_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of a number of Qt sources files. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
+#ifndef QHOOKS_H
+#define QHOOKS_H
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
-// unique pointer to default category
-// (allows to compare for pointers instead of strings)
-extern const char qtDefaultCategoryName[];
+class QObject;
+
+namespace QHooks {
+
+enum HookIndex {
+ HookDataVersion = 0,
+ HookDataSize = 1,
+ QtVersion = 2,
+ AddQObject = 3,
+ RemoveQObject = 4,
+ Startup = 5,
+ LastHookIndex
+};
+
+typedef void(*AddQObjectCallback)(QObject*);
+typedef void(*RemoveQObjectCallback)(QObject*);
+typedef void(*StartupCallback)();
+
+}
+
+extern quintptr Q_CORE_EXPORT qtHookData[];
QT_END_NAMESPACE
-#endif // QLOGGINGCATEGORY_P_H
+#endif
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 174c1d0d8d..f2ebeb6a03 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -67,6 +68,7 @@ QString qt_libraryInfoFile()
#endif
#include "qconfig.cpp"
+#include "archdetect.cpp"
QT_BEGIN_NAMESPACE
@@ -255,7 +257,37 @@ QLibraryInfo::buildDate()
}
#endif //QT_NO_DATESTRING
-#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
+#if defined(Q_CC_INTEL) // must be before GNU, Clang and MSVC because ICC/ICL claim to be them
+# ifdef __INTEL_CLANG_COMPILER
+# define ICC_COMPAT "Clang"
+# elif defined(__INTEL_MS_COMPAT_LEVEL)
+# define ICC_COMPAT "Microsoft"
+# elif defined(__GNUC__)
+# define ICC_COMPAT "GCC"
+# else
+# define ICC_COMPAT "no"
+# endif
+# if __INTEL_COMPILER == 1300
+# define ICC_VERSION "13.0"
+# elif __INTEL_COMPILER == 1310
+# define ICC_VERSION "13.1"
+# elif __INTEL_COMPILER == 1400
+# define ICC_VERSION "14.0"
+# elif __INTEL_COMPILER == 1500
+# define ICC_VERSION "15.0"
+# else
+# define ICC_VERSION QT_STRINGIFY(__INTEL_COMPILER)
+# endif
+# ifdef __INTEL_COMPILER_UPDATE
+# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION "." QT_STRINGIFY(__INTEL_COMPILER_UPDATE) \
+ " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
+ ICC_COMPAT " compatibility]"
+# else
+# define COMPILER_STRING "Intel(R) C++ " ICC_VERSION \
+ " build " QT_STRINGIFY(__INTEL_COMPILER_BUILD_DATE) " [" \
+ ICC_COMPAT " compatibility]"
+# endif
+#elif defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
# ifdef __apple_build_version__ // Apple clang has other version numbers
# define COMPILER_STRING "Clang " __clang_version__ " (Apple)"
# else
@@ -273,11 +305,22 @@ QLibraryInfo::buildDate()
# elif _MSC_VER < 1900
# define COMPILER_STRING "MSVC 2013"
# else
-# define COMPILER_STRING "MSVC <unknown version>"
+# define COMPILER_STRING "MSVC _MSC_VER " QT_STRINGIFY(_MSC_VER)
# endif
#else
# define COMPILER_STRING "<unknown compiler>"
#endif
+#ifdef QT_NO_DEBUG
+# define DEBUG_STRING " release"
+#else
+# define DEBUG_STRING " debug"
+#endif
+#ifdef QT_SHARED
+# define SHARED_STRING " shared (dynamic)"
+#else
+# define SHARED_STRING " static"
+#endif
+#define QT_BUILD_STR "Qt " QT_VERSION_STR " (" ARCH_FULL SHARED_STRING DEBUG_STRING " build; by " COMPILER_STRING ")"
/*!
Returns a string describing how this version of Qt was built.
@@ -289,21 +332,7 @@ QLibraryInfo::buildDate()
const char *QLibraryInfo::build() Q_DECL_NOTHROW
{
- static const char data[] = "Qt " QT_VERSION_STR " (" __DATE__ ", "
- COMPILER_STRING ", "
-#if QT_POINTER_SIZE == 4
- "32"
-#else
- "64"
-#endif
- " bit, "
-#ifdef QT_NO_DEBUG
- "release"
-#else
- "debug"
-#endif
- " build)";
- return data;
+ return QT_BUILD_STR;
}
/*!
@@ -590,7 +619,7 @@ extern const char qt_core_interpreter[] __attribute__((section(".interp")))
extern "C" void qt_core_boilerplate();
void qt_core_boilerplate()
{
- printf("This is the QtCore library version " QT_VERSION_STR "\n"
+ printf("This is the QtCore library version " QT_BUILD_STR "\n"
"Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n"
"Contact: http://www.qt-project.org/legal\n"
"\n"
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index ca0fb1bb23..013efec3d5 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,6 +49,8 @@
#include "qmutex.h"
#include "qloggingcategory.h"
#ifndef QT_BOOTSTRAPPED
+#include "qelapsedtimer.h"
+#include "qdatetime.h"
#include "qcoreapplication.h"
#include "qthread.h"
#include "private/qloggingregistry_p.h"
@@ -70,6 +73,22 @@
# include <unistd.h>
#endif
+#if !defined QT_NO_REGULAREXPRESSION && !defined(QT_BOOTSTRAPPED)
+#ifdef __has_include
+#if __has_include(<cxxabi.h>) && __has_include(<execinfo.h>)
+#define QLOGGING_HAVE_BACKTRACE
+#endif
+#elif defined(__GLIBCXX__) && defined(__GLIBC__) // (because older version of gcc don't have __has_include)
+#define QLOGGING_HAVE_BACKTRACE
+#endif
+
+#ifdef QLOGGING_HAVE_BACKTRACE
+#include <qregularexpression.h>
+#include <cxxabi.h>
+#include <execinfo.h>
+#endif
+#endif
+
#include <stdio.h>
QT_BEGIN_NAMESPACE
@@ -171,89 +190,15 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha
}
#endif
-#if !defined(QT_NO_EXCEPTIONS)
-/*!
- \internal
- Uses a local buffer to output the message. Not locale safe + cuts off
- everything after character 255, but will work in out of memory situations.
- Stop the execution afterwards.
-*/
-static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL_NOEXCEPT
-{
- char emergency_buf[256] = { '\0' };
- emergency_buf[sizeof emergency_buf - 1] = '\0';
-#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) && (defined(Q_OS_WINCE) || defined(Q_OS_WINRT)) \
- || defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
- wchar_t emergency_bufL[sizeof emergency_buf];
-#endif
-
- if (msg)
- qvsnprintf(emergency_buf, sizeof emergency_buf - 1, msg, ap);
-
-#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
-# if defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
- convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf);
- OutputDebugStringW(emergency_bufL);
-# else
- if (qWinLogToStderr()) {
- fprintf(stderr, "%s\n", emergency_buf);
- fflush(stderr);
- } else {
- OutputDebugStringA(emergency_buf);
- }
-# endif
-#else
- fprintf(stderr, "%s\n", emergency_buf);
- fflush(stderr);
-#endif
-
- if (isFatal(msgType)) {
-#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
- // get the current report mode
- int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
- _CrtSetReportMode(_CRT_ERROR, reportMode);
-# ifndef Q_OS_WINCE // otherwise already converted to wchar_t above
- convert_to_wchar_t_elided(emergency_bufL, sizeof emergency_buf, emergency_buf);
-# endif
- int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__), __LINE__,
- _CRT_WIDE(QT_VERSION_STR),
- emergency_bufL);
- if (ret == 1)
- _CrtDbgBreak();
-#endif
-
-#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
- abort(); // trap; generates core dump
-#else
- exit(1); // goodbye cruel world
-#endif
- }
-}
-#endif
-
/*!
\internal
*/
static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg,
va_list ap, QString &buf)
{
-#if !defined(QT_NO_EXCEPTIONS)
- if (std::uncaught_exception()) {
- qEmergencyOut(msgType, msg, ap);
- return;
- }
-#endif
- if (msg) {
- QT_TRY {
- buf = QString().vsprintf(msg, ap);
- } QT_CATCH(const std::bad_alloc &) {
-#if !defined(QT_NO_EXCEPTIONS)
- qEmergencyOut(msgType, msg, ap);
- // don't rethrow - we use qWarning and friends in destructors.
- return;
-#endif
- }
- }
+
+ if (msg)
+ buf = QString().vsprintf(msg, ap);
qt_message_print(msgType, context, buf);
}
@@ -834,6 +779,8 @@ static const char functionTokenC[] = "%{function}";
static const char pidTokenC[] = "%{pid}";
static const char appnameTokenC[] = "%{appname}";
static const char threadidTokenC[] = "%{threadid}";
+static const char timeTokenC[] = "%{time"; //not a typo: this command has arguments
+static const char backtraceTokenC[] = "%{backtrace"; //ditto
static const char ifCategoryTokenC[] = "%{if-category}";
static const char ifDebugTokenC[] = "%{if-debug}";
static const char ifWarningTokenC[] = "%{if-warning}";
@@ -854,9 +801,18 @@ struct QMessagePattern {
// 0 terminated arrays of literal tokens / literal or placeholder tokens
const char **literals;
const char **tokens;
+ QString timeFormat;
+#ifdef QLOGGING_HAVE_BACKTRACE
+ int backtraceDepth;
+ QString backtraceSeparator;
+#endif
bool fromEnvironment;
static QBasicMutex mutex;
+#ifndef QT_BOOTSTRAPPED
+ QElapsedTimer timer;
+ QDateTime startTime;
+#endif
};
QBasicMutex QMessagePattern::mutex;
@@ -864,8 +820,18 @@ QBasicMutex QMessagePattern::mutex;
QMessagePattern::QMessagePattern()
: literals(0)
, tokens(0)
+#ifdef QLOGGING_HAVE_BACKTRACE
+ , backtraceDepth(5)
+ , backtraceSeparator(QLatin1Char('|'))
+#endif
, fromEnvironment(false)
+#ifndef QT_BOOTSTRAPPED
+ , startTime(QDateTime::currentDateTime())
+#endif
{
+#ifndef QT_BOOTSTRAPPED
+ timer.start();
+#endif
const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
if (envPattern.isEmpty()) {
setPattern(QLatin1String(defaultPattern));
@@ -953,6 +919,31 @@ void QMessagePattern::setPattern(const QString &pattern)
tokens[i] = appnameTokenC;
else if (lexeme == QLatin1String(threadidTokenC))
tokens[i] = threadidTokenC;
+ else if (lexeme.startsWith(QLatin1String(timeTokenC))) {
+ tokens[i] = timeTokenC;
+ int spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
+ if (spaceIdx > 0)
+ timeFormat = lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2);
+ } else if (lexeme.startsWith(QLatin1String(backtraceTokenC))) {
+#ifdef QLOGGING_HAVE_BACKTRACE
+ tokens[i] = backtraceTokenC;
+ QRegularExpression depthRx(QStringLiteral(" depth=(?|\"([^\"]*)\"|([^ }]*))"));
+ QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))"));
+ QRegularExpressionMatch m = depthRx.match(lexeme);
+ if (m.hasMatch()) {
+ int depth = m.capturedRef(1).toInt();
+ if (depth <= 0)
+ error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} depth must be a number greater than 0\n");
+ else
+ backtraceDepth = depth;
+ }
+ m = separatorRx.match(lexeme);
+ if (m.hasMatch())
+ backtraceSeparator = m.captured(1);
+#else
+ error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n");
+#endif
+ }
#define IF_TOKEN(LEVEL) \
else if (lexeme == QLatin1String(LEVEL)) { \
@@ -1061,10 +1052,20 @@ static void slog2_default_handler(QtMsgType msgType, const char *message)
Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
/*!
- \internal
-*/
-Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
- const QString &str)
+ \relates <QtGlobal>
+ \since 5.4
+
+ Generates a formatted string out of the \a type, \a context, \a str arguments.
+
+ qFormatLogMessage returns a QString that is formatted according to the current message pattern.
+ It can be used by custom message handlers to format output similar to Qt's default message
+ handler.
+
+ The function is thread-safe.
+
+ \sa qInstallMessageHandler(), qSetMessagePattern()
+ */
+QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
{
QString message;
@@ -1122,6 +1123,64 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont
} else if (token == threadidTokenC) {
message.append(QLatin1String("0x"));
message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16));
+#ifdef QLOGGING_HAVE_BACKTRACE
+ } else if (token == backtraceTokenC) {
+ QVarLengthArray<void*, 32> buffer(15 + pattern->backtraceDepth);
+ int n = backtrace(buffer.data(), buffer.size());
+ if (n > 0) {
+ QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(buffer.data(), n));
+ int numberPrinted = 0;
+ for (int i = 0; i < n && numberPrinted < pattern->backtraceDepth; ++i) {
+ QString trace = QString::fromLatin1(strings.data()[i]);
+ // The results of backtrace_symbols looks like this:
+ // /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
+ // The offset and function name are optional.
+ // This regexp tries to extract the librry name (without the path) and the function name.
+ // This code is protected by QMessagePattern::mutex so it is thread safe on all compilers
+ static QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"),
+ QRegularExpression::OptimizeOnFirstUsageOption);
+
+ QRegularExpressionMatch m = rx.match(trace);
+ if (m.hasMatch()) {
+ // skip the trace from QtCore that are because of the qDebug itself
+ QString library = m.captured(1);
+ QString function = m.captured(2);
+ if (!numberPrinted && library.contains(QLatin1String("Qt5Core"))
+ && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive)
+ || function.contains(QLatin1String("QDebug")))) {
+ continue;
+ }
+
+ if (function.startsWith(QLatin1String("_Z"))) {
+ QScopedPointer<char, QScopedPointerPodDeleter> demangled(
+ abi::__cxa_demangle(function.toUtf8(), 0, 0, 0));
+ if (demangled)
+ function = QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
+ }
+
+ if (numberPrinted > 0)
+ message.append(pattern->backtraceSeparator);
+
+ if (function.isEmpty())
+ message += QLatin1Char('?') + library + QLatin1Char('?');
+ else
+ message += function;
+
+ } else {
+ if (numberPrinted == 0)
+ continue;
+ message += pattern->backtraceSeparator + QLatin1String("???");
+ }
+ numberPrinted++;
+ }
+ }
+#endif
+ } else if (token == timeTokenC) {
+ quint64 ms = pattern->timer.elapsed();
+ if (pattern->timeFormat.isEmpty())
+ message.append(QString().sprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000)));
+ else
+ message.append(pattern->startTime.addMSecs(ms).toString(pattern->timeFormat));
#endif
} else if (token == ifCategoryTokenC) {
if (!context.category || (strcmp(context.category, "default") == 0))
@@ -1229,7 +1288,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
bool toConsole;
};
- QString logMessage = qMessageFormatString(type, context, buf);
+ QString logMessage = qFormatLogMessage(type, context, buf);
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
if (!qWinLogToStderr()) {
@@ -1503,6 +1562,17 @@ void qErrnoWarning(int code, const char *msg, ...)
\row \li \c %{pid} \li QCoreApplication::applicationPid()
\row \li \c %{threadid} \li ID of current thread
\row \li \c %{type} \li "debug", "warning", "critical" or "fatal"
+ \row \li \c %{time} \li time of the message, in seconds since the process started
+ \row \li \c %{time format} \li system time when the message occurred, formatted by
+ passing the \c format to \l QDateTime::toString()
+ \row \li \c{%{backtrace [depth=N] [separator="..."]}} \li A backtrace with the number of frames
+ specified by the optional \c depth parameter (defaults to 5), and separated by the optional
+ \c separator parameter (defaults to "|").
+ This expansion is available only on some platforms (currently only platfoms using glibc).
+ Names are only known for exported functions. If you want to see the name of every function
+ in your application, use \c{QMAKE_LFLAGS += -rdynamic}.
+ When reading backtraces, take into account that frames might be missing due to inlining or
+ tail call optimization.
\endtable
You can also use conditionals on the type of the message using \c %{if-debug},
@@ -1514,7 +1584,7 @@ void qErrnoWarning(int code, const char *msg, ...)
Example:
\code
- QT_MESSAGE_PATTERN="[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
+ QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
\endcode
The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
@@ -1523,7 +1593,7 @@ void qErrnoWarning(int code, const char *msg, ...)
environment variable; if both qSetMessagePattern() is called and QT_MESSAGE_PATTERN is
set, the environment variable takes precedence.
- qSetMessagePattern() has no effect if a custom message handler is installed.
+ Custom message handlers can use qFormatLogMessage() to take \a pattern into account.
\sa qInstallMessageHandler(), {Debugging Techniques}
*/
diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h
index 6ebffa3ba1..fe965ec7f5 100644
--- a/src/corelib/global/qlogging.h
+++ b/src/corelib/global/qlogging.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -65,9 +65,9 @@ class QMessageLogContext
{
Q_DISABLE_COPY(QMessageLogContext)
public:
- Q_DECL_CONSTEXPR QMessageLogContext() : version(1), line(0), file(0), function(0), category(0) {}
+ Q_DECL_CONSTEXPR QMessageLogContext() : version(2), line(0), file(0), function(0), category(0) {}
Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName)
- : version(1), line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
+ : version(2), line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
void copy(const QMessageLogContext &logContext);
@@ -167,6 +167,8 @@ typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QS
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);
Q_CORE_EXPORT void qSetMessagePattern(const QString &messagePattern);
+Q_CORE_EXPORT QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context,
+ const QString &buf);
QT_END_NAMESPACE
#endif // QLOGGING_H
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 839d352d36..6dfd8e3ab1 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -499,6 +499,8 @@ public:
WA_X11DoNotAcceptFocus = 126,
WA_MacNoShadow = 127,
+ WA_AlwaysStackOnTop = 128,
+
// Add new attributes before this line
WA_AttributeCount
};
@@ -521,6 +523,7 @@ public:
AA_ForceRasterWidgets = 14,
AA_UseDesktopOpenGL = 15,
AA_UseOpenGLES = 16,
+ AA_UseSoftwareOpenGL = 17,
// Add new attributes before this line
AA_AttributeCount
@@ -1011,6 +1014,15 @@ public:
Key_Info = 0x0100011b,
Key_Settings = 0x0100011c,
+ Key_MicVolumeUp = 0x0100011d,
+ Key_MicVolumeDown = 0x0100011e,
+
+ Key_New = 0x01000120,
+ Key_Open = 0x01000121,
+ Key_Find = 0x01000122,
+ Key_Undo = 0x01000123,
+ Key_Redo = 0x01000124,
+
Key_MediaLast = 0x0100ffff,
// Keypad navigation keys
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index a47f2e2945..f6ea3a3a81 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -168,14 +168,26 @@
\value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces,
and do not support non-native GL-based child widgets.
- \value AA_UseDesktopOpenGL Forces the usage of the desktop OpenGL on
- platforms that use dynamic loading of the OpenGL implementation.
+ \value AA_UseDesktopOpenGL Forces the usage of desktop OpenGL (for example,
+ \e opengl32.dll or \e libGL.so) on platforms that use dynamic loading
+ of the OpenGL implementation.
This value has been added in Qt 5.3.
- \value AA_UseOpenGLES Forces the usage of OpenGL ES 2.0 on platforms that
- use dynamic loading of the OpenGL implementation.
+ \value AA_UseOpenGLES Forces the usage of OpenGL ES 2.0 or higher on
+ platforms that use dynamic loading of the OpenGL implementation.
This value has been added in Qt 5.3.
+ \value AA_UseSoftwareOpenGL Forces the usage of a software based OpenGL
+ implementation on platforms that use dynamic loading of the OpenGL
+ implementation. This will typically be a patched build of
+ \l{http://www.mesa3d.org/llvmpipe.html}{Mesa llvmpipe}, providing
+ OpenGL 2.1. The value may have no effect if no such OpenGL
+ implementation is available. The default name of this library is
+ QtSoftwareOpenGL.dll and can be overridden by setting the environment
+ variable \e QT_OPENGL_DLL. See the platform-specific pages, for
+ instance \l{Qt for Windows}, for more information. This value has
+ been added in Qt 5.4.
+
The following values are obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
@@ -1191,6 +1203,13 @@
to this top level window. This attribute has no effect on non-X11
platforms.
+ \value WA_AlwaysStackOnTop Since Qt 5.4, this value forces QOpenGLWidget and
+ QQuickWidget to be drawn last, on top of other widgets. Ignored for other
+ type of widgets. Setting this attribute breaks the stacking order, but
+ allows having a semi-transparent OpenGL widget with other widgets visible
+ underneath. It is strongly recommended to call update() on the widget's
+ top-level window after enabling or disabling this attribute.
+
\omitvalue WA_SetLayoutDirection
\omitvalue WA_InputMethodTransparent
\omitvalue WA_WState_CompressKeys
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index 7d8bd8c3c6..21d0209dd7 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -140,6 +140,7 @@ static inline quint32 f2i(float f)
\endcode
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint32 qFloatDistance(float a, float b)
@@ -197,6 +198,7 @@ static inline quint64 d2i(double d)
\sa qFuzzyCompare()
+ \since 5.2
\relates <QtGlobal>
*/
Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index 38735c12de..3a443938f9 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -136,6 +136,7 @@ public:
MV_10_7 = 0x0009,
MV_10_8 = 0x000A,
MV_10_9 = 0x000B,
+ MV_10_10 = 0x000C,
/* codenames */
MV_CHEETAH = MV_10_0,
@@ -148,6 +149,7 @@ public:
MV_LION = MV_10_7,
MV_MOUNTAINLION = MV_10_8,
MV_MAVERICKS = MV_10_9,
+ MV_YOSEMITE = MV_10_10,
/* iOS */
MV_IOS = 1 << 8,
@@ -157,11 +159,22 @@ public:
MV_IOS_6_0 = Q_MV_IOS(6, 0),
MV_IOS_6_1 = Q_MV_IOS(6, 1),
MV_IOS_7_0 = Q_MV_IOS(7, 0),
- MV_IOS_7_1 = Q_MV_IOS(7, 1)
+ MV_IOS_7_1 = Q_MV_IOS(7, 1),
+ MV_IOS_8_0 = Q_MV_IOS(8, 0)
};
static const MacVersion MacintoshVersion;
static MacVersion macVersion();
#endif
+
+ static QString buildCpuArchitecture();
+ static QString currentCpuArchitecture();
+ static QString buildAbi();
+
+ static QString kernelType();
+ static QString kernelVersion();
+ static QString productType();
+ static QString productVersion();
+ static QString prettyProductName();
};
QT_END_NAMESPACE
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 0431e10133..b2e99ac259 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -235,6 +235,9 @@
# if !defined(__MAC_10_9)
# define __MAC_10_9 1090
# endif
+# if !defined(__MAC_10_10)
+# define __MAC_10_10 101000
+# endif
# if !defined(MAC_OS_X_VERSION_10_7)
# define MAC_OS_X_VERSION_10_7 1070
# endif
@@ -244,6 +247,9 @@
# if !defined(MAC_OS_X_VERSION_10_9)
# define MAC_OS_X_VERSION_10_9 1090
# endif
+# if !defined(MAC_OS_X_VERSION_10_10)
+# define MAC_OS_X_VERSION_10_10 101000
+# endif
#
# if !defined(__IPHONE_4_3)
# define __IPHONE_4_3 40300
@@ -263,6 +269,12 @@
# if !defined(__IPHONE_7_0)
# define __IPHONE_7_0 70000
# endif
+# if !defined(__IPHONE_7_1)
+# define __IPHONE_7_1 70100
+# endif
+# if !defined(__IPHONE_8_0)
+# define __IPHONE_8_0 80000
+# endif
#endif
#ifdef __LSB_VERSION__
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 8478e08416..70dc623e0c 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -64,7 +64,7 @@ public:
isComplex = true,
isStatic = true,
isLarge = (sizeof(T)>sizeof(void*)),
- isDummy = false,
+ isDummy = false, //### Qt6: remove
sizeOf = sizeof(T)
};
};
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index f651860e08..7afff7ff81 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -51,7 +51,6 @@ HEADERS += \
io/qfileselector.h \
io/qfileselector_p.h \
io/qloggingcategory.h \
- io/qloggingcategory_p.h \
io/qloggingregistry_p.h
SOURCES += \
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index a6fbffee7e..127244e994 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -250,10 +250,6 @@ QT_BEGIN_NAMESPACE
if (q_status != Ok) \
return retVal;
-enum {
- DefaultStreamVersion = QDataStream::Qt_5_3
-};
-
/*!
Constructs a data stream that has no I/O device.
@@ -265,7 +261,7 @@ QDataStream::QDataStream()
dev = 0;
owndev = false;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -287,7 +283,7 @@ QDataStream::QDataStream(QIODevice *d)
dev = d; // set device
owndev = false;
byteorder = BigEndian; // default byte order
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -315,7 +311,7 @@ QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -339,7 +335,7 @@ QDataStream::QDataStream(const QByteArray &a)
dev = buf;
owndev = true;
byteorder = BigEndian;
- ver = DefaultStreamVersion;
+ ver = Qt_DefaultCompiledVersion;
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
q_status = Ok;
}
@@ -542,6 +538,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_1 Version 14 (Qt 5.1)
\value Qt_5_2 Version 15 (Qt 5.2)
\value Qt_5_3 Same as Qt_5_2
+ \value Qt_5_4 Version 16 (Qt 5.4)
+ \omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
*/
@@ -557,7 +555,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
/*!
\fn void QDataStream::setVersion(int v)
- Sets the version number of the data serialization format to \a v.
+ Sets the version number of the data serialization format to \a v,
+ a value of the \l Version enum.
You don't \e have to set a version if you are using the current
version of Qt, but for your own custom binary formats we
@@ -571,25 +570,6 @@ void QDataStream::setByteOrder(ByteOrder bo)
with an earlier version of Qt, use this function to modify the
serialization format used by QDataStream.
- \table
- \header \li Qt Version \li QDataStream Version
- \row \li Qt 5.2 \li 15
- \row \li Qt 5.1 \li 14
- \row \li Qt 5.0 \li 13
- \row \li Qt 4.6 \li 12
- \row \li Qt 4.5 \li 11
- \row \li Qt 4.4 \li 10
- \row \li Qt 4.3 \li 9
- \row \li Qt 4.2 \li 8
- \row \li Qt 4.0, 4.1 \li 7
- \row \li Qt 3.3 \li 6
- \row \li Qt 3.1, 3.2 \li 5
- \row \li Qt 3.0 \li 4
- \row \li Qt 2.1, 2.2, 2.3 \li 3
- \row \li Qt 2.0 \li 2
- \row \li Qt 1.x \li 1
- \endtable
-
The \l Version enum provides symbolic constants for the different
versions of Qt. For example:
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 28f1d51a12..808fbe73f6 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -88,10 +88,12 @@ public:
Qt_5_0 = 13,
Qt_5_1 = 14,
Qt_5_2 = 15,
- Qt_5_3 = Qt_5_2
-#if QT_VERSION >= 0x050400
-#error Add the datastream version for this Qt version
+ Qt_5_3 = Qt_5_2,
+ Qt_5_4 = 16,
+#if QT_VERSION >= 0x050500
+#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
+ Qt_DefaultCompiledVersion = Qt_5_4
};
enum ByteOrder {
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 3370cce6d5..b0411f9dd9 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -79,6 +79,18 @@ QT_BEGIN_NAMESPACE
used to write debugging information to files and other devices. The constructor
that accepts a QString is used to write to a string for display or serialization.
+ \section1 Formatting Options
+
+ QDebug formats output so that it's easily readable. It automatically adds spaces
+ between arguments, and adds quotes around QString, QByteArray, QChar arguments.
+
+ You can tweak these options through the space(), nospace() and quote(), noquote()
+ methods. Furthermore, \l{QTextStream manipulators} can be piped into a QDebug
+ stream.
+
+ QDebugStateSaver limits changes to the formatting to the current scope.
+ resetFormat() resets the options to the default ones.
+
\section1 Writing Custom Types to a Stream
Many standard types can be written to QDebug objects, and Qt provides support for
@@ -128,6 +140,20 @@ QT_BEGIN_NAMESPACE
Flushes any pending data to be written and destroys the debug stream.
*/
+// Has been defined in the header / inlined before Qt 5.4
+QDebug::~QDebug()
+{
+ if (!--stream->ref) {
+ if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
+ stream->buffer.chop(1);
+ if (stream->message_output) {
+ qt_message_output(stream->type,
+ stream->context,
+ stream->buffer);
+ }
+ delete stream;
+ }
+}
/*!
\fn QDebug::swap(QDebug &other)
@@ -138,6 +164,21 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ Resets the stream formatting options, bringing it back to its original constructed state.
+
+ \sa space(), quote()
+ \since 5.4
+*/
+QDebug &QDebug::resetFormat()
+{
+ stream->ts.reset();
+ stream->space = true;
+ if (stream->context.version > 1)
+ stream->flags = 0;
+ return *this;
+}
+
+/*!
\fn QDebug &QDebug::space()
Writes a space character to the debug stream and returns a reference to
@@ -188,6 +229,41 @@ QT_BEGIN_NAMESPACE
\sa QDebugStateSaver
*/
+
+/*!
+ \fn QDebug &QDebug::quote()
+ \since 5.4
+
+ Enables automatic insertion of quotation characters around QChar, QString and QByteArray
+ contents and returns a reference to the stream.
+
+ Quoting is enabled by default.
+
+ \sa noquote(), maybeQuote()
+*/
+
+/*!
+ \fn QDebug &QDebug::noquote()
+ \since 5.4
+
+ Disables automatic insertion of quotation characters around QChar, QString and QByteArray
+ contents and returns a reference to the stream.
+
+ \sa quote(), maybeQuote()
+*/
+
+/*!
+ \fn QDebug &QDebug::maybeQuote(char c)
+ \since 5.4
+
+ Writes a character \a c to the debug stream, depending on the
+ current setting for automatic insertion of quotes, and returns a reference to the stream.
+
+ The default character is a double quote \c{"}.
+
+ \sa quote(), noquote()
+*/
+
/*!
\fn QDebug &QDebug::operator<<(QChar t)
@@ -334,7 +410,9 @@ QT_BEGIN_NAMESPACE
\brief Convenience class for custom QDebug operators
- Saves the settings used by QDebug, and restores them upon destruction.
+ Saves the settings used by QDebug, and restores them upon destruction,
+ then calls maybeSpace(), to separate arguments with a space if
+ autoInsertSpaces() was true at the time of constructing the QDebugStateSaver.
The automatic insertion of spaces between writes is one of the settings
that QDebugStateSaver stores for the duration of the current block.
@@ -352,19 +430,33 @@ public:
QDebugStateSaverPrivate(QDebug &dbg)
: m_dbg(dbg),
m_spaces(dbg.autoInsertSpaces()),
+ m_flags(0),
m_streamParams(dbg.stream->ts.d_ptr->params)
{
+ if (m_dbg.stream->context.version > 1)
+ m_flags = m_dbg.stream->flags;
}
void restoreState()
{
+ const bool currentSpaces = m_dbg.autoInsertSpaces();
+ if (currentSpaces && !m_spaces)
+ if (m_dbg.stream->buffer.endsWith(QLatin1Char(' ')))
+ m_dbg.stream->buffer.chop(1);
+
m_dbg.setAutoInsertSpaces(m_spaces);
m_dbg.stream->ts.d_ptr->params = m_streamParams;
+ if (m_dbg.stream->context.version > 1)
+ m_dbg.stream->flags = m_flags;
+
+ if (!currentSpaces && m_spaces)
+ m_dbg.stream->ts << ' ';
}
QDebug &m_dbg;
// QDebug state
const bool m_spaces;
+ int m_flags;
// QTextStream state
const QTextStreamPrivate::Params m_streamParams;
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index bdaaa05768..6b81d9431f 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -61,9 +61,9 @@ class Q_CORE_EXPORT QDebug
friend class QMessageLogger;
friend class QDebugStateSaverPrivate;
struct Stream {
- Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
- Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
- Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true) {}
+ Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {}
+ Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {}
+ Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true), flags(0) {}
QTextStream ts;
QString buffer;
int ref;
@@ -71,6 +71,18 @@ class Q_CORE_EXPORT QDebug
bool space;
bool message_output;
QMessageLogContext context;
+
+ enum FormatFlag {
+ NoQuotes = 0x1
+ };
+
+ // ### Qt 6: unify with space, introduce own version member
+ bool testFlag(FormatFlag flag) const { return (context.version > 1) ? (flags & flag) : false; }
+ void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } }
+ void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } }
+
+ // added in 5.4
+ int flags;
} *stream;
public:
inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
@@ -78,22 +90,11 @@ public:
inline QDebug(QtMsgType t) : stream(new Stream(t)) {}
inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }
inline QDebug &operator=(const QDebug &other);
- inline ~QDebug() {
- if (!--stream->ref) {
- if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
- stream->buffer.chop(1);
- if (stream->message_output) {
- QT_TRY {
- qt_message_output(stream->type,
- stream->context,
- stream->buffer);
- } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
- }
- delete stream;
- }
- }
+ ~QDebug();
inline void swap(QDebug &other) { qSwap(stream, other.stream); }
+ QDebug &resetFormat();
+
inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
inline QDebug &nospace() { stream->space = false; return *this; }
inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
@@ -101,7 +102,11 @@ public:
bool autoInsertSpaces() const { return stream->space; }
void setAutoInsertSpaces(bool b) { stream->space = b; }
- inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
+ inline QDebug &quote() { stream->unsetFlag(Stream::NoQuotes); return *this; }
+ inline QDebug &noquote() { stream->setFlag(Stream::NoQuotes); return *this; }
+ inline QDebug &maybeQuote(char c = '"') { if (!(stream->testFlag(Stream::NoQuotes))) stream->ts << c; return *this; }
+
+ inline QDebug &operator<<(QChar t) { maybeQuote('\''); stream->ts << t; maybeQuote('\''); return maybeSpace(); }
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
@@ -115,10 +120,10 @@ public:
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
- inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const QString & t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
- inline QDebug &operator<<(QLatin1String t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
- inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(QLatin1String t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
+ inline QDebug &operator<<(const QByteArray & t) { maybeQuote(); stream->ts << t; maybeQuote(); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
@@ -150,6 +155,9 @@ public:
inline QNoDebug &space() { return *this; }
inline QNoDebug &nospace() { return *this; }
inline QNoDebug &maybeSpace() { return *this; }
+ inline QNoDebug &quote() { return *this; }
+ inline QNoDebug &noquote() { return *this; }
+ inline QNoDebug &maybeQuote(const char = '"') { return *this; }
template<typename T>
inline QNoDebug &operator<<(const T &) { return *this; }
@@ -164,13 +172,8 @@ inline QDebug &QDebug::operator=(const QDebug &other)
return *this;
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QList<T> &list)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << '(';
@@ -184,13 +187,8 @@ inline QDebug operator<<(QDebug debug, const QList<T> &list)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <typename T>
-inline QDebug &operator<<(QDebug debug, const QVector<T> &vec)
-#else
template <typename T>
inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QVector";
@@ -198,13 +196,8 @@ inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
return operator<<(debug, vec.toList());
}
-#if defined(FORCE_UREF)
-template <class aKey, class aT>
-inline QDebug &operator<<(QDebug debug, const QMap<aKey, aT> &map)
-#else
template <class aKey, class aT>
inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QMap(";
@@ -217,13 +210,8 @@ inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class aKey, class aT>
-inline QDebug &operator<<(QDebug debug, const QHash<aKey, aT> &hash)
-#else
template <class aKey, class aT>
inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QHash(";
@@ -235,13 +223,8 @@ inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class T1, class T2>
-inline QDebug &operator<<(QDebug debug, const QPair<T1, T2> &pair)
-#else
template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
@@ -258,13 +241,8 @@ inline QDebug operator<<(QDebug debug, const QSet<T> &set)
return operator<<(debug, set.toList());
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
-#endif
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QContiguousCache(";
@@ -278,29 +256,24 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
return debug.maybeSpace();
}
-#if defined(FORCE_UREF)
-template <class T>
-inline QDebug &operator<<(QDebug debug, const QFlags<T> &flags)
-#else
template <class T>
inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
-#endif
{
- const bool oldSetting = debug.autoInsertSpaces();
- debug.nospace() << "QFlags(";
+ QDebugStateSaver saver(debug);
+ debug.resetFormat();
+ debug.nospace() << "QFlags(" << hex << showbase;
bool needSeparator = false;
for (uint i = 0; i < sizeof(T) * 8; ++i) {
if (flags.testFlag(T(1 << i))) {
if (needSeparator)
- debug.nospace() << '|';
+ debug << '|';
else
needSeparator = true;
- debug.nospace() << "0x" << QByteArray::number(typename QFlags<T>::Int(1) << i, 16).constData();
+ debug << (typename QFlags<T>::Int(1) << i);
}
}
debug << ')';
- debug.setAutoInsertSpaces(oldSetting);
- return debug.maybeSpace();
+ return debug;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index f7e58a7bed..33cb6037f5 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -680,6 +680,13 @@ bool QFileDevice::setPermissions(Permissions permissions)
function.
\value NoOptions No options.
+ \value MapPrivateOption The mapped memory will be private, so any
+ modifications will not be visible to other processes and will not
+ be written to disk. Any such modifications will be lost when the
+ memory is unmapped. It is unspecified whether modifications made
+ to the file made after the mapping is created will be visible through
+ the mapped memory. This flag is not supported on Windows CE.
+ This enum value was introduced in Qt 5.4.
*/
/*!
@@ -689,6 +696,10 @@ bool QFileDevice::setPermissions(Permissions permissions)
or a new file is opened with this object, any maps that have not been
unmapped will automatically be unmapped.
+ The mapping will have the same open mode as the file (read and/or write),
+ except when using MapPrivateOption, in which case it is always possible
+ to write to the mapped memory.
+
Any mapping options can be passed through \a flags.
Returns a pointer to the memory or 0 if there is an error.
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index fc2779086a..4b13ffe589 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -112,8 +112,10 @@ public:
virtual Permissions permissions() const;
virtual bool setPermissions(Permissions permissionSpec);
+ // ### Qt 6: rename to MemoryMapFlag & make it a QFlags
enum MemoryMapFlags {
- NoOptions = 0
+ NoOptions = 0,
+ MapPrivateOption = 0x0001
};
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 0fa1f02f5c..639310876a 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -51,10 +51,6 @@
#include <QtCore/QLocale>
#include <QtCore/QDebug>
-#ifdef Q_OS_UNIX
-#include <sys/utsname.h>
-#endif
-
QT_BEGIN_NAMESPACE
//Environment variable to allow tooling full control of file selectors
@@ -360,6 +356,7 @@ void QFileSelectorPrivate::updateSelectors()
QStringList QFileSelectorPrivate::platformSelectors()
{
+ // similar, but not identical to QSysInfo::osType
QStringList ret;
#if defined(Q_OS_WIN)
ret << QStringLiteral("windows");
@@ -390,9 +387,7 @@ QStringList QFileSelectorPrivate::platformSelectors()
ret << QStringLiteral("osx");
# endif
# else
- struct utsname u;
- if (uname(&u) != -1)
- ret << QString::fromLatin1(u.sysname).toLower();
+ ret << QSysInfo::kernelType();
# endif
#endif
return ret;
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 998a3334c9..3c4a2fac0b 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -179,9 +179,7 @@ QFSFileEngine::~QFSFileEngine()
} while (ret == -1 && errno == EINTR);
}
}
- QList<uchar*> keys = d->maps.keys();
- for (int i = 0; i < keys.count(); ++i)
- unmap(keys.at(i));
+ d->unmapAll();
}
/*!
@@ -463,6 +461,18 @@ qint64 QFSFileEngine::size() const
return d->nativeSize();
}
+/*!
+ \internal
+*/
+void QFSFileEnginePrivate::unmapAll()
+{
+ if (!maps.isEmpty()) {
+ const QList<uchar*> keys = maps.keys(); // Make a copy since unmap() modifies the map.
+ for (int i = 0; i < keys.count(); ++i)
+ unmap(keys.at(i));
+ }
+}
+
#ifndef Q_OS_WIN
/*!
\internal
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 21f38fea1d..b0610b1459 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -175,6 +175,7 @@ public:
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
+ void unmapAll();
mutable QFileSystemMetaData metaData;
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 064a1a511f..f9c6c8ab98 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -713,6 +713,12 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
+ int sharemode = MAP_SHARED;
+ if (flags & QFileDevice::MapPrivateOption) {
+ sharemode = MAP_PRIVATE;
+ access |= PROT_WRITE;
+ }
+
#if defined(Q_OS_INTEGRITY)
int pageSize = sysconf(_SC_PAGESIZE);
#else
@@ -730,7 +736,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
realOffset &= ~(QT_OFF_T(pageSize - 1));
void *mapAddress = QT_MMAP((void*)0, realSize,
- access, MAP_SHARED, nativeHandle(), realOffset);
+ access, sharemode, nativeHandle(), realOffset);
if (MAP_FAILED != mapAddress) {
uchar *address = extra + static_cast<uchar*>(mapAddress);
maps[address] = QPair<int,size_t>(extra, realSize);
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index fb4107b95d..81aed5f7b4 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -965,6 +965,21 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
return 0;
}
+ // check/setup args to map
+ DWORD access = 0;
+ if (flags & QFileDevice::MapPrivateOption) {
+#ifdef FILE_MAP_COPY
+ access = FILE_MAP_COPY;
+#else
+ q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported");
+ return 0;
+#endif
+ } else if (openMode & QIODevice::WriteOnly) {
+ access = FILE_MAP_WRITE;
+ } else if (openMode & QIODevice::ReadOnly) {
+ access = FILE_MAP_READ;
+ }
+
if (mapHandle == NULL) {
// get handle to the file
HANDLE handle = fileHandle;
@@ -1011,11 +1026,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
}
}
- // setup args to map
- DWORD access = 0;
- if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ;
- if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE;
-
DWORD offsetHi = offset >> 32;
DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
SYSTEM_INFO sysinfo;
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 28f6b02a64..00c8a85bcc 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -50,6 +50,11 @@
QT_BEGIN_NAMESPACE
+static inline QByteArray localHostName()
+{
+ return qgetenv("COMPUTERNAME");
+}
+
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
const QFileSystemEntry fileEntry(fileName);
@@ -98,7 +103,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
fileData += '\n';
fileData += qAppName().toUtf8();
fileData += '\n';
- //fileData += localHostname(); // gethostname requires winsock init, see QHostInfo...
+ fileData += localHostName();
fileData += '\n';
DWORD bytesWritten = 0;
QLockFile::LockError error = QLockFile::NoError;
@@ -123,14 +128,16 @@ bool QLockFilePrivate::isApparentlyStale() const
// On WinRT there seems to be no way of obtaining information about other
// processes due to sandboxing
#ifndef Q_OS_WINRT
- HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
- if (!procHandle)
- return true;
- // We got a handle but check if process is still alive
- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
- ::CloseHandle(procHandle);
- if (dwR == WAIT_TIMEOUT)
- return true;
+ if (hostname == QString::fromLocal8Bit(localHostName())) {
+ HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+ if (!procHandle)
+ return true;
+ // We got a handle but check if process is still alive
+ DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+ ::CloseHandle(procHandle);
+ if (dwR == WAIT_TIMEOUT)
+ return true;
+ }
#endif // !Q_OS_WINRT
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 07245ddea2..a368e92932 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qloggingcategory.h"
-#include "qloggingcategory_p.h"
#include "qloggingregistry_p.h"
QT_BEGIN_NAMESPACE
@@ -82,7 +81,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section1 Creating category objects
- The Q_LOGGING_CATEGORY() and the Q_DECLARE_LOGGING_CATEGORY() macros
+ The Q_DECLARE_LOGGING_CATEGORY() and Q_LOGGING_CATEGORY() macros
conveniently declare and create QLoggingCategory objects:
\snippet qloggingcategory/main.cpp 1
@@ -101,13 +100,21 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
\section1 Default category configuration
- In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
- \l isCriticalEnabled() will return \c true.
+ Both the QLoggingCategory constructor and the Q_LOGGING_CATEGORY() macro
+ accept an optional QtMsgType argument, which disables all message types with
+ a lower severity. That is, a category declared with
+
+ \snippet qloggingcategory/main.cpp 5
+
+ will log messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but will
+ ignore messages of type \c QtDebugMsg.
+
+ If no argument is passed, all messages will be logged.
\section1 Configuring Categories
- Categories can be centrally configured by either setting logging rules,
- or by installing a custom filter.
+ The default configuration of categories can be overridden either by setting logging
+ rules, or by installing a custom filter.
\section2 Logging Rules
@@ -131,7 +138,13 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
are automatically loaded from the \c [Rules] section of a logging
configuration file. Such configuration files are looked up in the QtProject
configuration directory, or explicitly set in a \c QT_LOGGING_CONF
- environment variable.
+ environment variable:
+
+ \code
+ [Rules]
+ *.debug=false
+ driver.usb.debug=true
+ \endcode
Rules set by \l setFilterRules() take precedence over rules specified
in the QtProject configuration directory, and can, in turn, be
@@ -177,7 +190,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
/*!
Constructs a QLoggingCategory object with the provided \a category name.
- The object becomes the local identifier for the category.
+ All message types for this category are enabled by default.
If \a category is \c{0}, the category name is changed to \c "default".
*/
@@ -185,23 +198,35 @@ QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
name(0)
{
- Q_UNUSED(d);
- Q_UNUSED(placeholder);
- enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
+ init(category, QtDebugMsg);
+}
- const bool isDefaultCategory
- = (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
+/*!
+ Constructs a QLoggingCategory object with the provided \a category name,
+ and enables all messages with types more severe or equal than \a enableForLevel.
- // normalize "default" category name, so that we can just do
- // pointer comparison in QLoggingRegistry::updateCategory
- if (isDefaultCategory) {
- name = qtDefaultCategoryName;
- } else {
+ If \a category is \c{0}, the category name is changed to \c "default".
+
+ \since 5.4
+*/
+QLoggingCategory::QLoggingCategory(const char *category, QtMsgType enableForLevel)
+ : d(0),
+ name(0)
+{
+ init(category, enableForLevel);
+}
+
+void QLoggingCategory::init(const char *category, QtMsgType severityLevel)
+{
+ enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
+
+ if (category)
name = category;
- }
+ else
+ name = qtDefaultCategoryName;
if (QLoggingRegistry *reg = QLoggingRegistry::instance())
- reg->registerCategory(this);
+ reg->registerCategory(this, severityLevel);
}
/*!
@@ -501,6 +526,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
*/
/*!
\macro Q_DECLARE_LOGGING_CATEGORY(name)
+ \sa Q_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
@@ -512,11 +538,12 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro Q_LOGGING_CATEGORY(name, string)
+ \sa Q_DECLARE_LOGGING_CATEGORY()
\relates QLoggingCategory
\since 5.2
Defines a logging category \a name, and makes it configurable under the
- \a string identifier.
+ \a string identifier. By default, all message types are enabled.
Only one translation unit in a library or executable can define a category
with a specific name.
@@ -524,4 +551,21 @@ void QLoggingCategory::setFilterRules(const QString &rules)
This macro must be used outside of a class or method.
*/
+/*!
+ \macro Q_LOGGING_CATEGORY(name, string, msgType)
+ \sa Q_DECLARE_LOGGING_CATEGORY()
+ \relates QLoggingCategory
+ \since 5.4
+
+ Defines a logging category \a name, and makes it configurable under the
+ \a string identifier. By default, messages of QtMsgType \a msgType
+ and more severe are enabled, types with a lower severity are disabled.
+
+ Only one translation unit in a library or executable can define a category
+ with a specific name.
+
+ This macro must be used outside of a class or method. It is only defined
+ if variadic macros are supported.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 573af2105c..cca2031108 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -51,7 +51,9 @@ class Q_CORE_EXPORT QLoggingCategory
{
Q_DISABLE_COPY(QLoggingCategory)
public:
+ // ### Qt 6: Merge constructors
explicit QLoggingCategory(const char *category);
+ QLoggingCategory(const char *category, QtMsgType severityLevel);
~QLoggingCategory();
bool isEnabled(QtMsgType type) const;
@@ -80,7 +82,9 @@ public:
static void setFilterRules(const QString &rules);
private:
- void *d; // reserved for future use
+ void init(const char *category, QtMsgType severityLevel);
+
+ Q_DECL_UNUSED_MEMBER void *d; // reserved for future use
const char *name;
#ifdef Q_BIG_ENDIAN
@@ -100,22 +104,20 @@ private:
AtomicBools bools;
QBasicAtomicInt enabled;
};
- bool placeholder[4]; // reserve for future use
+ Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \
extern const QLoggingCategory &name();
-// relies on QLoggingCategory(QString) being thread safe!
-#define Q_LOGGING_CATEGORY(name, string) \
+#if defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
+
+#define Q_LOGGING_CATEGORY(name, ...) \
const QLoggingCategory &name() \
{ \
- static const QLoggingCategory category(string); \
+ static const QLoggingCategory category(__VA_ARGS__); \
return category; \
}
-
-#ifdef Q_COMPILER_VARIADIC_MACROS
-
#define qCDebug(category, ...) \
for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug(__VA_ARGS__)
@@ -126,14 +128,22 @@ private:
for (bool qt_category_enabled = category().isCriticalEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical(__VA_ARGS__)
-#else
+#else // defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
+
+// Optional msgType argument not supported
+#define Q_LOGGING_CATEGORY(name, string) \
+ const QLoggingCategory &name() \
+ { \
+ static const QLoggingCategory category(string); \
+ return category; \
+ }
// check for enabled category inside QMessageLogger.
#define qCDebug qDebug
#define qCWarning qWarning
#define qCCritical qCritical
-#endif // Q_COMPILER_VARIADIC_MACROS
+#endif // Q_COMPILER_VARIADIC_MACROS || defined(Q_MOC_RUN)
#if defined(QT_NO_DEBUG_OUTPUT)
# undef qCDebug
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index 575150f148..3ce0a571b4 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qloggingregistry_p.h"
-#include "qloggingcategory_p.h"
#include <QtCore/qfile.h>
#include <QtCore/qstandardpaths.h>
@@ -131,15 +130,15 @@ void QLoggingRule::parse(const QStringRef &pattern)
// strip trailing ".messagetype"
if (pattern.endsWith(QLatin1String(".debug"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".debug"));
+ pattern.length() - 6); // strlen(".debug")
messageType = QtDebugMsg;
} else if (pattern.endsWith(QLatin1String(".warning"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".warning"));
+ pattern.length() - 8); // strlen(".warning")
messageType = QtWarningMsg;
} else if (pattern.endsWith(QLatin1String(".critical"))) {
p = QStringRef(pattern.string(), pattern.position(),
- pattern.length() - strlen(".critical"));
+ pattern.length() - 9); // strlen(".critical")
messageType = QtCriticalMsg;
} else {
p = pattern;
@@ -261,12 +260,12 @@ void QLoggingRegistry::init()
if (!rulesFilePath.isEmpty()) {
QFile file(QFile::decodeName(rulesFilePath));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
if (qtLoggingDebug())
debugMsg("Loading \"%s\" ...",
QDir::toNativeSeparators(file.fileName()).toUtf8().constData());
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
envRules = parser.rules();
}
}
@@ -285,12 +284,12 @@ void QLoggingRegistry::init()
if (!envPath.isEmpty()) {
QFile file(envPath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
if (qtLoggingDebug())
debugMsg("Loading \"%s\" ...",
QDir::toNativeSeparators(envPath).toUtf8().constData());
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
configRules = parser.rules();
}
}
@@ -307,12 +306,12 @@ void QLoggingRegistry::init()
This method might be called concurrently for the same category object.
*/
-void QLoggingRegistry::registerCategory(QLoggingCategory *cat)
+void QLoggingRegistry::registerCategory(QLoggingCategory *cat, QtMsgType enableForLevel)
{
QMutexLocker locker(&registryMutex);
if (!categories.contains(cat)) {
- categories.append(cat);
+ categories.insert(cat, enableForLevel);
(*categoryFilter)(cat);
}
}
@@ -324,8 +323,7 @@ void QLoggingRegistry::registerCategory(QLoggingCategory *cat)
void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
{
QMutexLocker locker(&registryMutex);
-
- categories.removeOne(cat);
+ categories.remove(cat);
}
/*!
@@ -341,7 +339,7 @@ void QLoggingRegistry::setApiRules(const QString &content)
QMutexLocker locker(&registryMutex);
if (qtLoggingDebug())
- debugMsg("Loading logging rules set by Qt API ...");
+ debugMsg("Loading logging rules set by QLoggingCategory::setFilterRules ...");
apiRules = parser.rules();
@@ -361,7 +359,7 @@ void QLoggingRegistry::updateRules()
rules = configRules + apiRules + envRules;
- foreach (QLoggingCategory *cat, categories)
+ foreach (QLoggingCategory *cat, categories.keys())
(*categoryFilter)(cat);
}
@@ -380,7 +378,7 @@ QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter)
QLoggingCategory::CategoryFilter old = categoryFilter;
categoryFilter = filter;
- foreach (QLoggingCategory *cat, categories)
+ foreach (QLoggingCategory *cat, categories.keys())
(*categoryFilter)(cat);
return old;
@@ -397,18 +395,22 @@ QLoggingRegistry *QLoggingRegistry::instance()
*/
void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
{
- // QLoggingCategory() normalizes "default" strings
- // to qtDefaultCategoryName
- bool debug = true;
+ QLoggingRegistry *reg = QLoggingRegistry::instance();
+ Q_ASSERT(reg->categories.contains(cat));
+ QtMsgType enableForLevel = reg->categories.value(cat);
+
+ bool debug = (enableForLevel == QtDebugMsg) ? true : false;
+ bool warning = (enableForLevel <= QtWarningMsg) ? true : false;
+ bool critical = (enableForLevel <= QtCriticalMsg) ? true : false;
+
+ // hard-wired implementation of
+ // qt.*.debug=false
+ // qt.debug=false
char c;
if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.'))
debug = false;
- bool warning = true;
- bool critical = true;
-
QString categoryName = QLatin1String(cat->categoryName());
- QLoggingRegistry *reg = QLoggingRegistry::instance();
foreach (const QLoggingRule &item, reg->rules) {
int filterpass = item.pass(categoryName, QtDebugMsg);
if (filterpass != 0)
diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h
index 48804cfc2b..ce2503b32c 100644
--- a/src/corelib/io/qloggingregistry_p.h
+++ b/src/corelib/io/qloggingregistry_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -113,7 +113,7 @@ public:
void init();
- void registerCategory(QLoggingCategory *category);
+ void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel);
void unregisterCategory(QLoggingCategory *category);
void setApiRules(const QString &content);
@@ -134,7 +134,7 @@ private:
QVector<QLoggingRule> envRules;
QVector<QLoggingRule> apiRules;
QVector<QLoggingRule> rules;
- QList<QLoggingCategory*> categories;
+ QHash<QLoggingCategory*,QtMsgType> categories;
QLoggingCategory::CategoryFilter categoryFilter;
friend class ::tst_QLoggingRegistry;
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index b1e4dd7584..4c5fb38c67 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -506,6 +506,25 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *dev
}
/*!
+ Create a QNonContiguousByteDevice out of a QIODevice, return it in a QSharedPointer.
+ For QFile, QBuffer and all other QIODevice, sequential or not.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer *buffer = qobject_cast<QBuffer*>(device))
+ return QSharedPointer<QNonContiguousByteDeviceBufferImpl>::create(buffer);
+
+ // ### FIXME special case if device is a QFile that supports map()
+ // then we can actually deal with the file without using read/peek
+
+ // generic QIODevice
+ return QSharedPointer<QNonContiguousByteDeviceIoDeviceImpl>::create(device); // FIXME
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer<QRingBuffer> ringBuffer)
Create a QNonContiguousByteDevice out of a QRingBuffer.
@@ -518,6 +537,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer
}
/*!
+ Create a QNonContiguousByteDevice out of a QRingBuffer, return it in a QSharedPointer.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QSharedPointer<QRingBuffer> ringBuffer)
+{
+ return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(qMove(ringBuffer));
+}
+
+/*!
\fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
Create a QNonContiguousByteDevice out of a QByteArray.
@@ -530,6 +559,16 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *by
}
/*!
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QByteArray *byteArray)
+{
+ return QSharedPointer<QNonContiguousByteDeviceByteArrayImpl>::create(byteArray);
+}
+
+/*!
\fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
Wrap the \a byteDevice (possibly again) into a QIODevice.
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index 4606ac2686..1e746db80f 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -90,8 +90,14 @@ class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
{
public:
static QNonContiguousByteDevice* create(QIODevice *device);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QIODevice *device);
+
static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QByteArray *byteArray);
+
static QNonContiguousByteDevice* create(QSharedPointer<QRingBuffer> ringBuffer);
+ static QSharedPointer<QNonContiguousByteDevice> createShared(QSharedPointer<QRingBuffer> ringBuffer);
+
static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
};
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 2b901c7ccd..8be4125ef5 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -205,14 +205,32 @@ bool QSaveFile::open(OpenMode mode)
d->writeError = QFileDevice::WriteError;
return false;
}
- d->fileEngine = new QTemporaryFileEngine(d->fileName);
+
+ if (existingFile.isDir()) {
+ d->setError(QFileDevice::WriteError, QSaveFile::tr("Filename refers to a directory"));
+ d->writeError = QFileDevice::WriteError;
+ return false;
+ }
+
+ // Resolve symlinks. Don't use QFileInfo::canonicalFilePath so it still give the expected
+ // target even if the file does not exist
+ d->finalFileName = d->fileName;
+ if (existingFile.isSymLink()) {
+ int maxDepth = 128;
+ while (--maxDepth && existingFile.isSymLink())
+ existingFile.setFile(existingFile.symLinkTarget());
+ if (maxDepth > 0)
+ d->finalFileName = existingFile.filePath();
+ }
+
+ d->fileEngine = new QTemporaryFileEngine(d->finalFileName);
// Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine.
if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
QFileDevice::FileError err = d->fileEngine->error();
#ifdef Q_OS_UNIX
if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) {
delete d->fileEngine;
- d->fileEngine = QAbstractFileEngine::create(d->fileName);
+ d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
d->useTemporaryFile = false;
QFileDevice::open(mode);
@@ -285,7 +303,7 @@ bool QSaveFile::commit()
// atomically replace old file with new file
// Can't use QFile::rename for that, must use the file engine directly
Q_ASSERT(d->fileEngine);
- if (!d->fileEngine->renameOverwrite(d->fileName)) {
+ if (!d->fileEngine->renameOverwrite(d->finalFileName)) {
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
d->fileEngine->remove();
delete d->fileEngine;
diff --git a/src/corelib/io/qsavefile_p.h b/src/corelib/io/qsavefile_p.h
index b9efd1ee7c..2134c4c9bc 100644
--- a/src/corelib/io/qsavefile_p.h
+++ b/src/corelib/io/qsavefile_p.h
@@ -70,6 +70,7 @@ protected:
~QSaveFilePrivate();
QString fileName;
+ QString finalFileName; // fileName with symbolic links resolved
QFileDevice::FileError writeError;
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 1748170324..663ad3cc1b 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -53,6 +53,7 @@
#include "qmutex.h"
#include "qlibraryinfo.h"
#include "qtemporaryfile.h"
+#include "qstandardpaths.h"
#ifndef QT_NO_TEXTCODEC
# include "qtextcodec.h"
@@ -68,6 +69,11 @@
#include "qcoreapplication.h"
#endif
+#ifndef QT_BOOTSTRAPPED
+#include "qsavefile.h"
+#include "qlockfile.h"
+#endif
+
#ifdef Q_OS_VXWORKS
# include <ioLib.h>
#endif
@@ -101,12 +107,6 @@ using namespace ABI::Windows::Storage;
#define CSIDL_APPDATA 0x001a // <username>\Application Data
#endif
-#ifdef Q_AUTOTEST_EXPORT
-# define Q_AUTOTEST_EXPORT_HELPER Q_AUTOTEST_EXPORT
-#else
-# define Q_AUTOTEST_EXPORT_HELPER static
-#endif
-
// ************************************************************************
// QConfFile
@@ -141,101 +141,6 @@ static QBasicMutex settingsGlobalMutex;
static QSettings::Format globalDefaultFormat = QSettings::NativeFormat;
-#ifndef Q_OS_WIN
-inline bool qt_isEvilFsTypeName(const char *name)
-{
- return (qstrncmp(name, "nfs", 3) == 0
- || qstrncmp(name, "autofs", 6) == 0
- || qstrncmp(name, "cachefs", 7) == 0);
-}
-
-#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <sys/param.h>
-# include <sys/mount.h>
-QT_END_INCLUDE_NAMESPACE
-
-Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
-{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return qt_isEvilFsTypeName(buf.f_fstypename);
-}
-
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <sys/vfs.h>
-# ifdef QT_LINUXBASE
- // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
-# include <sys/statfs.h>
-# endif
-QT_END_INCLUDE_NAMESPACE
-# ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC 0x00006969
-# endif
-# ifndef AUTOFS_SUPER_MAGIC
-# define AUTOFS_SUPER_MAGIC 0x00000187
-# endif
-# ifndef AUTOFSNG_SUPER_MAGIC
-# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
-# endif
-
-Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
-{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return buf.f_type == NFS_SUPER_MAGIC
- || buf.f_type == AUTOFS_SUPER_MAGIC
- || buf.f_type == AUTOFSNG_SUPER_MAGIC;
-}
-
-#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
- || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
- || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <sys/statvfs.h>
-QT_END_INCLUDE_NAMESPACE
-
-Q_AUTOTEST_EXPORT_HELPER bool qIsLikelyToBeNfs(int handle)
-{
- struct statvfs buf;
- if (fstatvfs(handle, &buf) != 0)
- return false;
-#if defined(Q_OS_NETBSD)
- return qt_isEvilFsTypeName(buf.f_fstypename);
-#else
- return qt_isEvilFsTypeName(buf.f_basetype);
-#endif
-}
-#else
-Q_AUTOTEST_EXPORT_HELPER inline bool qIsLikelyToBeNfs(int /* handle */)
-{
- return true;
-}
-#endif
-
-static bool unixLock(int handle, int lockType)
-{
- /*
- NFS hangs on the fcntl() call below when statd or lockd isn't
- running. There's no way to detect this. Our work-around for
- now is to disable locking when we detect NFS (or AutoFS or
- CacheFS, which are probably wrapping NFS).
- */
- if (qIsLikelyToBeNfs(handle))
- return false;
-
- struct flock fl;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_type = lockType;
- return fcntl(handle, F_SETLKW, &fl) == 0;
-}
-#endif
-
QConfFile::QConfFile(const QString &fileName, bool _userPerms)
: name(fileName), size(0), ref(1), userPerms(_userPerms)
{
@@ -1140,6 +1045,8 @@ static void initDefaultPaths(QMutexLocker *locker)
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
#else
+
+#ifdef QT_NO_STANDARDPATHS
QString userPath;
char *env = getenv("XDG_CONFIG_HOME");
if (env == 0) {
@@ -1153,6 +1060,9 @@ static void initDefaultPaths(QMutexLocker *locker)
userPath += QLatin1Char('/');
userPath += QFile::decodeName(env);
}
+#else
+ QString userPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
+#endif
userPath += QLatin1Char('/');
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
@@ -1457,105 +1367,30 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
return;
}
+#ifndef QT_BOOTSTRAPPED
/*
- Open the configuration file and try to use it using a named
- semaphore on Windows and an advisory lock on Unix-based
- systems. This protect us against other QSettings instances
- trying to access the same file from other threads or
- processes.
-
- As it stands now, the locking mechanism doesn't work for
- .plist files.
- */
- QFile file(confFile->name);
- bool createFile = !file.exists();
- if (!readOnly && confFile->isWritable())
- file.open(QFile::ReadWrite);
- if (!file.isOpen())
- file.open(QFile::ReadOnly);
-
- if (!createFile && !file.isOpen())
- setStatus(QSettings::AccessError);
-
-#ifdef Q_OS_WIN
- HANDLE readSemaphore = 0;
- HANDLE writeSemaphore = 0;
- static const int FileLockSemMax = 50;
- int numReadLocks = readOnly ? 1 : FileLockSemMax;
-
- if (file.isOpen()) {
- // Acquire the write lock if we will be writing
- if (!readOnly) {
- QString writeSemName = QLatin1String("QSettingsWriteSem ");
- writeSemName.append(file.fileName());
-
-#ifndef Q_OS_WINRT
- writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
-#else
- writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS);
-#endif
+ Use a lockfile in order to protect us against other QSettings instances
+ trying to write the same settings at the same time.
- if (writeSemaphore) {
-#ifndef Q_OS_WINRT
- WaitForSingleObject(writeSemaphore, INFINITE);
-#else
- WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE);
-#endif
- } else {
- setStatus(QSettings::AccessError);
- return;
- }
- }
-
- // Acquire all the read locks if we will be writing, to make sure nobody
- // reads while we're writing. If we are only reading, acquire a single
- // read lock.
- QString readSemName(QLatin1String("QSettingsReadSem "));
- readSemName.append(file.fileName());
-
-#ifndef Q_OS_WINRT
- readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
-#else
- readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS);
-#endif
-
- if (readSemaphore) {
- for (int i = 0; i < numReadLocks; ++i)
-#ifndef Q_OS_WINRT
- WaitForSingleObject(readSemaphore, INFINITE);
-#else
- WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE);
-#endif
- } else {
+ We only need to lock if we are actually writing as only concurrent writes are a problem.
+ Concurrent read and write are not a problem because the writing operation is atomic.
+ */
+ QLockFile lockFile(confFile->name + QLatin1String(".lock"));
+ if (!readOnly) {
+ if (!confFile->isWritable() || !lockFile.lock() ) {
setStatus(QSettings::AccessError);
- if (writeSemaphore != 0) {
- ReleaseSemaphore(writeSemaphore, 1, 0);
- CloseHandle(writeSemaphore);
- }
return;
}
}
-#else
- if (file.isOpen())
- unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK);
#endif
- // If we have created the file, apply the file perms
- if (file.isOpen()) {
- if (createFile) {
- QFile::Permissions perms = file.permissions() | QFile::ReadOwner | QFile::WriteOwner;
- if (!confFile->userPerms)
- perms |= QFile::ReadGroup | QFile::ReadOther;
- file.setPermissions(perms);
- }
- }
-
/*
We hold the lock. Let's reread the file if it has changed
since last time we read it.
*/
QFileInfo fileInfo(confFile->name);
bool mustReadFile = true;
+ bool createFile = !fileInfo.exists();
if (!readOnly)
mustReadFile = (confFile->size != fileInfo.size()
@@ -1565,6 +1400,12 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
confFile->unparsedIniSections.clear();
confFile->originalKeys.clear();
+ QFile file(confFile->name);
+ if (!createFile && !file.open(QFile::ReadOnly)) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
/*
Files that we can't read (because of permissions or
because they don't exist) are treated as empty files.
@@ -1615,42 +1456,40 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
ensureAllSectionsParsed(confFile);
ParsedSettingsMap mergedKeys = confFile->mergedKeyMap();
- if (file.isWritable()) {
#ifdef Q_OS_MAC
- if (format == QSettings::NativeFormat) {
- ok = writePlistFile(confFile->name, mergedKeys);
- } else
+ if (format == QSettings::NativeFormat) {
+ ok = writePlistFile(confFile->name, mergedKeys);
+ } else
#endif
- {
- file.seek(0);
- file.resize(0);
+ {
+#ifndef QT_BOOTSTRAPPED
+ QSaveFile sf(confFile->name);
+#else
+ QFile sf(confFile->name);
+#endif
+ if (!sf.open(QIODevice::WriteOnly)) {
+ setStatus(QSettings::AccessError);
+ ok = false;
+ } else if (format <= QSettings::IniFormat) {
+ ok = writeIniFile(sf, mergedKeys);
+ } else {
+ if (writeFunc) {
+ QSettings::SettingsMap tempOriginalKeys;
- if (format <= QSettings::IniFormat) {
- ok = writeIniFile(file, mergedKeys);
- if (!ok) {
- // try to restore old data; might work if the disk was full and the new data
- // was larger than the old data
- file.seek(0);
- file.resize(0);
- writeIniFile(file, confFile->originalKeys);
+ ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
+ while (i != mergedKeys.constEnd()) {
+ tempOriginalKeys.insert(i.key(), i.value());
+ ++i;
}
+ ok = writeFunc(sf, tempOriginalKeys);
} else {
- if (writeFunc) {
- QSettings::SettingsMap tempOriginalKeys;
-
- ParsedSettingsMap::const_iterator i = mergedKeys.constBegin();
- while (i != mergedKeys.constEnd()) {
- tempOriginalKeys.insert(i.key(), i.value());
- ++i;
- }
- ok = writeFunc(file, tempOriginalKeys);
- } else {
- ok = false;
- }
+ ok = false;
}
}
- } else {
- ok = false;
+#ifndef QT_BOOTSTRAPPED
+ if (ok)
+ ok = sf.commit();
+#endif
}
if (ok) {
@@ -1662,24 +1501,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
QFileInfo fileInfo(confFile->name);
confFile->size = fileInfo.size();
confFile->timeStamp = fileInfo.lastModified();
+
+ // If we have created the file, apply the file perms
+ if (createFile) {
+ QFile::Permissions perms = fileInfo.permissions() | QFile::ReadOwner | QFile::WriteOwner;
+ if (!confFile->userPerms)
+ perms |= QFile::ReadGroup | QFile::ReadOther;
+ QFile(confFile->name).setPermissions(perms);
+ }
} else {
setStatus(QSettings::AccessError);
}
}
-
- /*
- Release the file lock.
- */
-#ifdef Q_OS_WIN
- if (readSemaphore != 0) {
- ReleaseSemaphore(readSemaphore, numReadLocks, 0);
- CloseHandle(readSemaphore);
- }
- if (writeSemaphore != 0) {
- ReleaseSemaphore(writeSemaphore, 1, 0);
- CloseHandle(writeSemaphore);
- }
-#endif
}
enum { Space = 0x1, Special = 0x2 };
@@ -2505,12 +2338,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes
that rule again but only for the native format (plist files).
- \li On Unix and Mac OS X systems, the advisory file locking is disabled
- if NFS (or AutoFS or CacheFS) is detected to work around a bug in the
- NFS fcntl() implementation, which hangs forever if statd or lockd aren't
- running. Also, the locking isn't performed when accessing \c .plist
- files.
-
\li On the BlackBerry platform, applications run in a sandbox. They are not
allowed to read or write outside of this sandbox. This involves the
following limitations:
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index bd9fa68d93..8c47ad1391 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -117,10 +117,9 @@ QT_BEGIN_NAMESPACE
\value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix
systems, this is equal to the HOME environment variable. This value might be
generic or application-specific, but the returned path is never empty.
- \value DataLocation Returns a directory location where persistent
- application data can be stored. This is an application-specific directory. To obtain a
- path to store data to be shared with other applications, use
- QStandardPaths::GenericDataLocation. The returned path is never empty.
+ \value DataLocation Returns the same value as AppLocalDataLocation. This enumeration value
+ is deprecated. Using AppDataLocation is preferable since on Windows, the roaming path is
+ recommended.
\value CacheLocation Returns a directory location where user-specific
non-essential (cached) data should be written. This is an application-specific directory.
The returned path is never empty.
@@ -142,6 +141,15 @@ QT_BEGIN_NAMESPACE
\value GenericConfigLocation Returns a directory location where user-specific
configuration files shared between multiple applications should be written.
This is a generic value and the returned path is never empty.
+ \value AppDataLocation Returns a directory location where persistent
+ application data can be stored. This is an application-specific directory.
+ To obtain a path to store data to be shared with other applications, use
+ QStandardPaths::GenericDataLocation. The returned path is never empty.
+ On the Windows operating system, this returns the roaming path.
+ This enum value was added in Qt 5.4.
+ \value AppLocalDataLocation Returns the local settings path on the Windows operating
+ system. On all other platforms, it returns the same value as AppDataLocation.
+ This enum value was added in Qt 5.4.
The following table gives examples of paths on different operating systems.
The first path is the writable path (unless noted). Other, additional
@@ -200,6 +208,12 @@ QT_BEGIN_NAMESPACE
\row \li GenericCacheLocation
\li "~/Library/Caches", "/Library/Caches"
\li "C:/Users/<USER>/AppData/Local/cache"
+ \row \li AppDataLocation
+ \li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
+ \li "C:/Users/<USER>/AppData/Roaming/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data"
+ \row \li AppLocalDataLocation
+ \li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
+ \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data"
\endtable
\table
@@ -255,6 +269,12 @@ QT_BEGIN_NAMESPACE
\row \li GenericCacheLocation
\li "<APPROOT>/data/Cache" (there is no shared cache)
\li "~/.cache"
+ \row \li AppDataLocation
+ \li "<APPROOT>/data", "<APPROOT>/app/native/assets"
+ \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
+ \row \li AppLocalDataLocation
+ \li "<APPROOT>/data", "<APPROOT>/app/native/assets"
+ \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>"
\endtable
\table
@@ -293,6 +313,8 @@ QT_BEGIN_NAMESPACE
\li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads"
\row \li GenericCacheLocation
\li "<APPROOT>/cache" (there is no shared cache)
+ \row \li AppDataLocation
+ \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
\endtable
In the table above, \c <APPNAME> is usually the organization name, the
@@ -534,8 +556,6 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Temporary Directory");
case HomeLocation:
return QCoreApplication::translate("QStandardPaths", "Home");
- case DataLocation:
- return QCoreApplication::translate("QStandardPaths", "Application Data");
case CacheLocation:
return QCoreApplication::translate("QStandardPaths", "Cache");
case GenericDataLocation:
@@ -550,6 +570,9 @@ QString QStandardPaths::displayName(StandardLocation type)
return QCoreApplication::translate("QStandardPaths", "Shared Cache");
case DownloadLocation:
return QCoreApplication::translate("QStandardPaths", "Download");
+ case AppDataLocation:
+ case AppLocalDataLocation:
+ return QCoreApplication::translate("QStandardPaths", "Application Data");
}
// not reached
return QString();
diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h
index 08d6d7b50c..b93adbf156 100644
--- a/src/corelib/io/qstandardpaths.h
+++ b/src/corelib/io/qstandardpaths.h
@@ -70,7 +70,9 @@ public:
ConfigLocation,
DownloadLocation,
GenericCacheLocation,
- GenericConfigLocation
+ GenericConfigLocation,
+ AppDataLocation,
+ AppLocalDataLocation = DataLocation
};
static QString writableLocation(StandardLocation type);
diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp
index 60b285a3d6..9bd4b4b428 100644
--- a/src/corelib/io/qstandardpaths_android.cpp
+++ b/src/corelib/io/qstandardpaths_android.cpp
@@ -244,7 +244,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return getFilesDir() + testDir() + QLatin1String("/settings");
case QStandardPaths::GenericDataLocation:
return getExternalStorageDirectory() + testDir();
- case QStandardPaths::DataLocation:
+ case QStandardPaths::AppDataLocation:
+ case QStandardPaths::AppLocalDataLocation:
return getFilesDir() + testDir();
case QStandardPaths::GenericCacheLocation:
case QStandardPaths::RuntimeLocation:
@@ -301,7 +302,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
<< getExternalFilesDir("DIRECTORY_DOWNLOADS");
}
- if (type == DataLocation) {
+ if (type == AppDataLocation || type == AppLocalDataLocation) {
return QStringList() << writableLocation(type)
<< getExternalFilesDir();
}
diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp
index ec2e61bd15..2e9d62cd05 100644
--- a/src/corelib/io/qstandardpaths_blackberry.cpp
+++ b/src/corelib/io/qstandardpaths_blackberry.cpp
@@ -63,7 +63,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
const QString sharedRoot = sharedDir.absolutePath();
switch (type) {
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
return QDir::homePath() + testModeInsert();
case DesktopLocation:
case HomeLocation:
@@ -108,7 +109,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
if (type == FontsLocation)
return QStringList(QLatin1String("/base/usr/fonts"));
- if (type == DataLocation)
+ if (type == AppDataLocation || type == AppLocalDataLocation)
dirs.append(QDir::homePath() + testModeInsert() + QLatin1String("native/assets"));
const QString localDir = writableLocation(type);
diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm
index e2100045a6..cdca28b8b5 100644
--- a/src/corelib/io/qstandardpaths_ios.mm
+++ b/src/corelib/io/qstandardpaths_ios.mm
@@ -90,7 +90,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case HomeLocation:
location = bundlePath();
break;
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
location = pathForDirectory(NSDocumentDirectory);
break;
diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp
index aff9112fb7..a27920899c 100644
--- a/src/corelib/io/qstandardpaths_mac.cpp
+++ b/src/corelib/io/qstandardpaths_mac.cpp
@@ -83,7 +83,8 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
return kTemporaryFolderType;
case QStandardPaths::GenericDataLocation:
case QStandardPaths::RuntimeLocation:
- case QStandardPaths::DataLocation:
+ case QStandardPaths::AppDataLocation:
+ case QStandardPaths::AppLocalDataLocation:
return kApplicationSupportFolderType;
case QStandardPaths::GenericCacheLocation:
case QStandardPaths::CacheLocation:
@@ -128,7 +129,7 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain)
QString path = getFullPath(ref);
- if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation)
+ if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || type == QStandardPaths::CacheLocation)
appendOrganizationAndApp(path);
return path;
}
@@ -140,9 +141,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString path;
switch (type) {
case GenericDataLocation:
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
path = qttestDir + QLatin1String("/Application Support");
- if (type == DataLocation)
+ if (type != GenericDataLocation)
appendOrganizationAndApp(path);
return path;
case GenericCacheLocation:
@@ -165,7 +167,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case TempLocation:
return QDir::tempPath();
case GenericDataLocation:
- case DataLocation:
+ case AppLocalDataLocation:
case GenericCacheLocation:
case CacheLocation:
case RuntimeLocation:
@@ -179,13 +181,13 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
- if (type == GenericDataLocation || type == DataLocation || type == GenericCacheLocation || type == CacheLocation) {
+ if (type == GenericDataLocation || type == AppDataLocation || type == AppLocalDataLocation || type == GenericCacheLocation || type == CacheLocation) {
const QString path = macLocation(type, kOnAppropriateDisk);
if (!path.isEmpty())
dirs.append(path);
}
- if (type == DataLocation) {
+ if (type == AppDataLocation || type == AppLocalDataLocation) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle);
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index e2ed7c3766..cde1e4bc72 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -90,7 +90,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
appendOrganizationAndApp(xdgCacheHome);
return xdgCacheHome;
}
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
{
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
@@ -98,7 +99,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share");
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
- if (type == QStandardPaths::DataLocation)
+ if (type == AppDataLocation || type == AppLocalDataLocation)
appendOrganizationAndApp(xdgDataHome);
return xdgDataHome;
}
@@ -305,7 +306,8 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
for (int i = 0; i < dirs.count(); ++i)
dirs[i].append(QLatin1String("/applications"));
break;
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
dirs = xdgDataDirs();
for (int i = 0; i < dirs.count(); ++i)
appendOrganizationAndApp(dirs[i]);
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 062ab49207..aaa390ac34 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -81,6 +81,18 @@ static QString convertCharArray(const wchar_t *path)
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
}
+static inline int clsidForAppDataLocation(QStandardPaths::StandardLocation type)
+{
+#ifndef Q_OS_WINCE
+ return type == QStandardPaths::AppDataLocation ?
+ CSIDL_APPDATA : // "Roaming" path
+ CSIDL_LOCAL_APPDATA; // Local path
+#else
+ Q_UNUSED(type)
+ return CSIDL_APPDATA;
+#endif
+}
+
QString QStandardPaths::writableLocation(StandardLocation type)
{
QString result;
@@ -92,15 +104,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
wchar_t path[MAX_PATH];
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it)
- case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows
+ case GenericConfigLocation: // same as GenericDataLocation on Windows
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
-#if defined Q_OS_WINCE
- if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE))
-#else
- if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
-#endif
+ if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE))
result = convertCharArray(path);
if (isTestModeEnabled())
result += QLatin1String("/qttest");
@@ -165,7 +174,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
// Although Microsoft has a Cache key it is a pointer to IE's cache, not a cache
// location for everyone. Most applications seem to be using a
// cache directory located in their AppData directory
- return writableLocation(DataLocation) + QLatin1String("/cache");
+ return writableLocation(AppLocalDataLocation) + QLatin1String("/cache");
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
@@ -192,11 +201,12 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
{
wchar_t path[MAX_PATH];
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it)
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows (oversight, but too late to fix it)
case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation:
- if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) {
+ if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) {
QString result = convertCharArray(path);
if (type != GenericDataLocation && type != GenericConfigLocation) {
#ifndef QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp
index feafdf2e7c..81b9d10baf 100644
--- a/src/corelib/io/qstandardpaths_winrt.cpp
+++ b/src/corelib/io/qstandardpaths_winrt.cpp
@@ -73,9 +73,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString result;
switch (type) {
- case ConfigLocation: // same as DataLocation, on Windows
+ case ConfigLocation: // same as AppLocalDataLocation, on Windows
case GenericConfigLocation: // same as GenericDataLocation, on Windows
- case DataLocation:
+ case AppDataLocation:
+ case AppLocalDataLocation:
case GenericDataLocation: {
ComPtr<IApplicationDataStatics> applicationDataStatics;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics)))
@@ -98,7 +99,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
break;
}
case CacheLocation:
- return writableLocation(DataLocation) + QLatin1String("/cache");
+ return writableLocation(AppLocalDataLocation) + QLatin1String("/cache");
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 3cade0ed25..bc6c2f1f06 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -235,6 +235,8 @@ static bool createFileFromTemplate(NativeFileHandle &file,
//************* QTemporaryFileEngine
QTemporaryFileEngine::~QTemporaryFileEngine()
{
+ Q_D(QFSFileEngine);
+ d->unmapAll();
QFSFileEngine::close();
}
@@ -363,6 +365,7 @@ bool QTemporaryFileEngine::remove()
Q_D(QFSFileEngine);
// Since the QTemporaryFileEngine::close() does not really close the file,
// we must explicitly call QFSFileEngine::close() before we remove it.
+ d->unmapAll();
QFSFileEngine::close();
if (QFSFileEngine::remove()) {
d->fileEntry.clear();
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 288a939ab2..4002ce8694 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -2203,7 +2203,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// add thousands group separators. For backward compatibility we
// don't add a group separator for C locale.
- if (locale != QLocale::c())
+ if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
const QLocaleData *dd = locale.d->m_data;
@@ -2414,6 +2414,8 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::CapitalEorX;
if (numberFlags() & ForcePoint)
flags |= QLocaleData::Alternate;
+ if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator))
+ flags |= QLocaleData::ThousandsGroup;
const QLocaleData *dd = d->locale.d->m_data;
QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 7018b333f2..51c48b88d7 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -364,6 +364,29 @@
*/
/*!
+ \enum QUrl::UserInputResolutionOption
+ \since 5.4
+
+ The user input resolution options define how fromUserInput() should
+ interpret strings that could either be a relative path or the short
+ form of a HTTP URL. For instance \c{file.pl} can be either a local file
+ or the URL \c{http://file.pl}.
+
+ \value DefaultResolution The default resolution mechanism is to check
+ whether a local file exists, in the working
+ directory given to fromUserInput, and only
+ return a local path in that case. Otherwise a URL
+ is assumed.
+ \value AssumeLocalFile This option makes fromUserInput() always return
+ a local path unless the input contains a scheme, such as
+ \c{http://file.pl}. This is useful for applications
+ such as text editors, which are able to create
+ the file if it doesn't exist.
+
+ \sa fromUserInput()
+*/
+
+/*!
\fn QUrl::QUrl(QUrl &&other)
Move-constructs a QUrl instance, making it point at the same
@@ -3715,11 +3738,15 @@ bool QUrl::isDetached() const
"//servername/path/to/file.txt". Note that only certain platforms can
actually open this file using QFile::open().
+ An empty \a localFile leads to an empty URL (since Qt 5.4).
+
\sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators()
*/
QUrl QUrl::fromLocalFile(const QString &localFile)
{
QUrl url;
+ if (localFile.isEmpty())
+ return url;
url.setScheme(fileScheme());
QString deslashified = QDir::fromNativeSeparators(localFile);
@@ -4095,6 +4122,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Returns a valid URL from a user supplied \a userInput string if one can be
deducted. In the case that is not possible, an invalid QUrl() is returned.
+ This overload takes a \a workingDirectory path, in order to be able to
+ handle relative paths. This is especially useful when handling command
+ line arguments.
+ If \a workingDirectory is empty, no handling of relative paths will be done,
+ so this method will behave like its one argument overload.
+
+ By default, an input string that looks like a relative path will only be treated
+ as such if the file actually exists in the given working directory.
+
+ If the application can handle files that don't exist yet, it should pass the
+ flag AssumeLocalFile in \a options.
+
+ \since 5.4
+*/
+QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options)
+{
+ QString trimmedString = userInput.trimmed();
+
+ if (trimmedString.isEmpty())
+ return QUrl();
+
+ // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
+ QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
+ if (url.isRelative() && !QDir::isAbsolutePath(trimmedString)) {
+ QFileInfo fileInfo(QDir(workingDirectory), trimmedString);
+ if ((options & AssumeLocalFile) || fileInfo.exists())
+ return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ }
+
+ return fromUserInput(trimmedString);
+}
+
+/*!
+ Returns a valid URL from a user supplied \a userInput string if one can be
+ deducted. In the case that is not possible, an invalid QUrl() is returned.
+
\since 4.6
Most applications that can browse the web, allow the user to input a URL
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 602e91ce30..d621d7ef03 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -199,7 +199,16 @@ public:
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
+ enum UserInputResolutionOption {
+ DefaultResolution,
+ AssumeLocalFile
+ };
+ Q_DECLARE_FLAGS(UserInputResolutionOptions, UserInputResolutionOption)
+
static QUrl fromUserInput(const QString &userInput);
+ // ### Qt6 merge with fromUserInput(QString), by adding = QString()
+ static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory,
+ UserInputResolutionOptions options = DefaultResolution);
bool isValid() const;
QString errorString() const;
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
index 33583afb78..06746c0597 100644
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ b/src/corelib/io/qwinoverlappedionotifier.cpp
@@ -41,6 +41,7 @@
#include "qwinoverlappedionotifier_p.h"
#include <qdebug.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qpointer.h>
#include <qqueue.h>
@@ -293,35 +294,58 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
}
/*!
- * Wait synchronously for the notified signal.
+ * Wait synchronously for any notified signal.
*
- * The function returns true if the notified signal was emitted for
- * the I/O operation that corresponds to the OVERLAPPED object.
+ * The function returns a pointer to the OVERLAPPED object corresponding to the completed I/O
+ * operation. In case no I/O operation was completed during the \a msec timeout, this function
+ * returns a null pointer.
*/
-bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
+OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
{
Q_D(QWinOverlappedIoNotifier);
if (!d->iocp->isRunning()) {
- qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier.");
- return false;
+ qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
+ return 0;
}
+ if (msecs == 0)
+ d->iocp->drainQueue();
+
+ switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) {
+ case WAIT_OBJECT_0:
+ ReleaseSemaphore(d->hSemaphore, 1, NULL);
+ return d->_q_notified();
+ case WAIT_TIMEOUT:
+ return 0;
+ default:
+ qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed.");
+ return 0;
+ }
+}
+
+/*!
+ * Wait synchronously for the notified signal.
+ *
+ * The function returns true if the notified signal was emitted for
+ * the I/O operation that corresponds to the OVERLAPPED object.
+ */
+bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
+{
+ int t = msecs;
+ QElapsedTimer stopWatch;
+ stopWatch.start();
forever {
- if (msecs == 0)
- d->iocp->drainQueue();
- DWORD result = WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
- if (result == WAIT_OBJECT_0) {
- ReleaseSemaphore(d->hSemaphore, 1, NULL);
- if (d->_q_notified() == overlapped)
- return true;
- continue;
- } else if (result == WAIT_TIMEOUT) {
+ OVERLAPPED *triggeredOverlapped = waitForAnyNotified(t);
+ if (!triggeredOverlapped)
return false;
+ if (triggeredOverlapped == overlapped)
+ return true;
+ if (msecs != -1) {
+ t = msecs - stopWatch.elapsed();
+ if (t < 0)
+ return false;
}
}
-
- qErrnoWarning("QWinOverlappedIoNotifier::waitForNotified: WaitForSingleObject failed.");
- return false;
}
/*!
diff --git a/src/corelib/io/qwinoverlappedionotifier_p.h b/src/corelib/io/qwinoverlappedionotifier_p.h
index f90fd2e615..25c0f3a081 100644
--- a/src/corelib/io/qwinoverlappedionotifier_p.h
+++ b/src/corelib/io/qwinoverlappedionotifier_p.h
@@ -76,6 +76,7 @@ public:
Qt::HANDLE handle() const;
void setEnabled(bool enabled);
+ OVERLAPPED *waitForAnyNotified(int msecs);
bool waitForNotified(int msecs, OVERLAPPED *overlapped);
Q_SIGNALS:
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index ad5722626e..fd70bcddce 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -990,9 +990,9 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
- \fn void *QModelIndex::internalId() const
+ \fn quintptr QModelIndex::internalId() const
- Returns a \c{qint64} used by the model to associate
+ Returns a \c{quintptr} used by the model to associate
the index with the internal data structure.
\sa QAbstractItemModel::createIndex()
diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp
index 2f1f4921f7..5250e2bf15 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.cpp
+++ b/src/corelib/itemmodels/qabstractproxymodel.cpp
@@ -394,6 +394,30 @@ QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const
/*!
\reimp
+ \since 5.4
+ */
+bool QAbstractProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QAbstractProxyModel);
+ const QModelIndex source = mapToSource(index(row, column, parent));
+ return d->model->canDropMimeData(data, action, source.row(), source.column(), source.parent());
+}
+
+/*!
+ \reimp
+ \since 5.4
+ */
+bool QAbstractProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ Q_D(QAbstractProxyModel);
+ const QModelIndex source = mapToSource(index(row, column, parent));
+ return d->model->dropMimeData(data, action, source.row(), source.column(), source.parent());
+}
+
+/*!
+ \reimp
*/
QStringList QAbstractProxyModel::mimeTypes() const
{
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index 9b26d6cead..f1d3d0b07c 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -91,6 +91,10 @@ public:
QModelIndex sibling(int row, int column, const QModelIndex &idx) const;
QMimeData* mimeData(const QModelIndexList &indexes) const;
+ bool canDropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE;
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions() const;
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index 883aa5b982..0a75d5998a 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -979,6 +979,22 @@ static QItemSelection mergeIndexes(const QVector<QPersistentModelIndex> &indexes
/*!
\internal
+ Sort predicate function for QItemSelectionModelPrivate::_q_layoutChanged(),
+ sorting by parent first in addition to operator<(). This is to prevent
+ fragmentation of the selection by grouping indexes with the same row, column
+ of different parents next to each other, which may happen when a selection
+ spans sub-trees.
+*/
+static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, const QPersistentModelIndex &i2)
+{
+ const QModelIndex parent1 = i1.parent();
+ const QModelIndex parent2 = i2.parent();
+ return parent1 == parent2 ? i1 < i2 : parent1 < parent2;
+}
+
+/*!
+ \internal
+
Merge the selected indexes into selection ranges again.
*/
void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
@@ -1011,8 +1027,10 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIn
if (hint != QAbstractItemModel::VerticalSortHint) {
// sort the "new" selection, as preparation for merging
- std::stable_sort(savedPersistentIndexes.begin(), savedPersistentIndexes.end());
- std::stable_sort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end());
+ std::stable_sort(savedPersistentIndexes.begin(), savedPersistentIndexes.end(),
+ qt_PersistentModelIndexLessThan);
+ std::stable_sort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end(),
+ qt_PersistentModelIndexLessThan);
// update the selection by merging the individual indexes
ranges = mergeIndexes(savedPersistentIndexes);
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index 7d0162938d..92330175ba 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -61,6 +61,8 @@
#include <qstring.h>
#include <qendian.h>
#include <qnumeric.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmutex.h>
#include <limits.h>
#include <limits>
@@ -776,6 +778,75 @@ private:
Q_DISABLE_COPY(Data)
};
+struct ObjectUndefinedKeys
+{
+ static void insertKey(const QJsonObject *object, int index, const QString &key)
+ {
+ QMutexLocker lock(&mutex);
+ keys()[object][index] = key;
+ }
+ static QString takeKey(const QJsonObject *object, int index)
+ {
+ QMutexLocker lock(&mutex);
+ return keys()[object].take(index);
+ }
+ static void removeKeys(const QJsonObject *object)
+ {
+ QMutexLocker lock(&mutex);
+ keys().remove(object);
+ }
+private:
+ typedef QHash<const QJsonObject*, QHash<int, QString> > KeysHash;
+ static KeysHash &keys()
+ {
+ static KeysHash keys;
+ return keys;
+ }
+ static QBasicMutex mutex;
+};
+
+} // namespace QJsonPrivate
+
+struct QJsonValueRef::UnionHelper
+{
+ static inline QJsonObject *untaggedPointer(QJsonObject *object)
+ {
+ const quintptr Mask = ~quintptr(0) << 2;
+ return reinterpret_cast<QJsonObject*>(quintptr(object) & Mask);
+ }
+ static inline QJsonObject *taggedPointer(QJsonObject *object)
+ {
+ const quintptr Mask = 1;
+ return reinterpret_cast<QJsonObject*>(quintptr(object) | Mask);
+ }
+
+ static void setValueAt(QJsonValueRef *ref, QJsonValue value)
+ {
+ using namespace QJsonPrivate;
+ QJsonObject *object = untaggedPointer(ref->o);
+ if (ref->o != object)
+ object->insert(ObjectUndefinedKeys::takeKey(object, ref->index), value);
+ else
+ object->setValueAt(ref->index, value);
+ }
+
+ static QJsonValue valueAt(const QJsonValueRef *ref)
+ {
+ QJsonObject *object = untaggedPointer(ref->o);
+ if (ref->o != object)
+ return QJsonValue::Undefined;
+ return ref->o->valueAt(ref->index);
+ }
+};
+
+/*!
+ \internal
+ Constructor that creates reference to an undefined value in \a object.
+*/
+inline QJsonValueRef::QJsonValueRef(QJsonObject *object, const QString &key)
+ : o(UnionHelper::taggedPointer(object)), is_object(true), index(qHash(key))
+{
+ QJsonPrivate::ObjectUndefinedKeys::insertKey(object, index, key);
}
QT_END_NAMESPACE
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp
index 61bb158ff5..c1e831192a 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/json/qjsonarray.cpp
@@ -138,6 +138,18 @@ QJsonArray::QJsonArray()
}
/*!
+ \fn QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
+ \since 5.4
+ Creates an array initialized from \a args initialization list.
+
+ QJsonArray can be constructed in a way similar to JSON notation,
+ for example:
+ \code
+ QJsonArray array = { 1, 2.2, QString() };
+ \endcode
+ */
+
+/*!
\internal
*/
QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array)
@@ -149,6 +161,19 @@ QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array)
}
/*!
+ This method replaces part of QJsonArray(std::initializer_list<QJsonValue> args) .
+ The constructor needs to be inline, but we do not want to leak implementation details
+ of this class.
+ \note this method is called for an uninitialized object
+ \internal
+ */
+void QJsonArray::initialize()
+{
+ d = 0;
+ a = 0;
+}
+
+/*!
Deletes the array.
*/
QJsonArray::~QJsonArray()
diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h
index 84c162f0a0..4cada7cec1 100644
--- a/src/corelib/json/qjsonarray.h
+++ b/src/corelib/json/qjsonarray.h
@@ -44,6 +44,9 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qiterator.h>
+#if defined(Q_COMPILER_INITIALIZER_LISTS)
+#include <initializer_list>
+#endif
QT_BEGIN_NAMESPACE
@@ -56,6 +59,16 @@ class Q_CORE_EXPORT QJsonArray
{
public:
QJsonArray();
+
+#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
+ QJsonArray(std::initializer_list<QJsonValue> args)
+ {
+ initialize();
+ for (std::initializer_list<QJsonValue>::const_iterator i = args.begin(); i != args.end(); ++i)
+ append(*i);
+ }
+#endif
+
~QJsonArray();
QJsonArray(const QJsonArray &other);
@@ -212,6 +225,7 @@ private:
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array);
+ void initialize();
void compact();
void detach(uint reserve = 0);
diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp
index 90ce8c63a5..097e665b68 100644
--- a/src/corelib/json/qjsondocument.cpp
+++ b/src/corelib/json/qjsondocument.cpp
@@ -331,7 +331,7 @@ QByteArray QJsonDocument::toJson() const
\value Compact Defines a compact output as follows:
\code
- {"Array": [true,999,"string"],"Key": "Value","null": null}
+ {"Array":[true,999,"string"],"Key":"Value","null":null}
\endcode
*/
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index 27e51cf4ac..cfd797990f 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -116,6 +116,20 @@ QJsonObject::QJsonObject()
}
/*!
+ \fn QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+ \since 5.4
+ Constructs a QJsonObject instance initialized from \a args initialization list.
+ For example:
+ \code
+ QJsonObject object
+ {
+ {"property1", 1},
+ {"property2", 2}
+ };
+ \endcode
+*/
+
+/*!
\internal
*/
QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object)
@@ -126,6 +140,19 @@ QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object)
d->ref.ref();
}
+/*!
+ This method replaces part of the QJsonObject(std::initializer_list<QPair<QString, QJsonValue>> args) body.
+ The constructor needs to be inline, but we do not want to leak implementation details
+ of this class.
+ \note this method is called for an uninitialized object
+ \internal
+ */
+
+void QJsonObject::initialize()
+{
+ d = 0;
+ o = 0;
+}
/*!
Destroys the object.
@@ -134,6 +161,7 @@ QJsonObject::~QJsonObject()
{
if (d && !d->ref.deref())
delete d;
+ QJsonPrivate::ObjectUndefinedKeys::removeKeys(this); // ### Qt6 move it to ~QJsonValueRef
}
/*!
@@ -254,7 +282,7 @@ bool QJsonObject::isEmpty() const
QJsonValue QJsonObject::value(const QString &key) const
{
if (!d)
- return QJsonValue();
+ return QJsonValue(QJsonValue::Undefined);
bool keyExists;
int i = o->indexOf(key, &keyExists);
@@ -290,14 +318,9 @@ QJsonValue QJsonObject::operator [](const QString &key) const
*/
QJsonValueRef QJsonObject::operator [](const QString &key)
{
- // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist
bool keyExists = false;
int index = o ? o->indexOf(key, &keyExists) : -1;
- if (!keyExists) {
- iterator i = insert(key, QJsonValue());
- index = i.i;
- }
- return QJsonValueRef(this, index);
+ return keyExists ? QJsonValueRef(this, index) : QJsonValueRef(this, key);
}
/*!
@@ -1001,7 +1024,9 @@ void QJsonObject::compact()
detach();
d->compact();
- o = static_cast<QJsonPrivate::Object *>(d->header->root());
+ using namespace QJsonPrivate;
+ o = static_cast<Object *>(d->header->root());
+ ObjectUndefinedKeys::removeKeys(this); // ### Qt6 move it to ~QJsonValueRef
}
/*!
@@ -1038,6 +1063,8 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
insert(e->key(), val);
}
+QBasicMutex QJsonPrivate::ObjectUndefinedKeys::mutex;
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
{
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h
index ad3184b1f2..92dd19af5e 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/json/qjsonobject.h
@@ -44,6 +44,10 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qiterator.h>
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+#include <QtCore/qpair.h>
+#include <initializer_list>
+#endif
QT_BEGIN_NAMESPACE
@@ -55,6 +59,16 @@ class Q_CORE_EXPORT QJsonObject
{
public:
QJsonObject();
+
+#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
+ QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+ {
+ initialize();
+ for (std::initializer_list<QPair<QString, QJsonValue> >::const_iterator i = args.begin(); i != args.end(); ++i)
+ insert(i->first, i->second);
+ }
+#endif
+
~QJsonObject();
QJsonObject(const QJsonObject &other);
@@ -195,6 +209,7 @@ private:
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object);
+ void initialize();
void detach(uint reserve = 0);
void compact();
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index 4c4838d314..6e40308de3 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -606,15 +606,19 @@ bool QJsonValue::operator==(const QJsonValue &other) const
case Array:
if (base == other.base)
return true;
- if (!base || !other.base)
- return false;
+ if (!base)
+ return !other.base->length;
+ if (!other.base)
+ return !base->length;
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base))
== QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.base));
case Object:
if (base == other.base)
return true;
- if (!base || !other.base)
- return false;
+ if (!base)
+ return !other.base->length;
+ if (!other.base)
+ return !base->length;
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base))
== QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.base));
}
@@ -669,11 +673,10 @@ void QJsonValue::detach()
However, they are not explicitly documented here.
*/
-
QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
{
if (is_object)
- o->setValueAt(index, val);
+ UnionHelper::setValueAt(this, val);
else
a->replace(index, val);
@@ -683,7 +686,7 @@ QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
{
if (is_object)
- o->setValueAt(index, ref);
+ UnionHelper::setValueAt(this, ref);
else
a->replace(index, ref);
@@ -704,7 +707,7 @@ QJsonValue QJsonValueRef::toValue() const
{
if (!is_object)
return a->at(index);
- return o->valueAt(index);
+ return UnionHelper::valueAt(this);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h
index fe028990c0..a00bc0b72f 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/json/qjsonvalue.h
@@ -149,6 +149,7 @@ public:
: a(array), is_object(false), index(idx) {}
QJsonValueRef(QJsonObject *object, int idx)
: o(object), is_object(true), index(idx) {}
+ inline QJsonValueRef(QJsonObject *object, const QString &key);
inline operator QJsonValue() const { return toValue(); }
QJsonValueRef &operator = (const QJsonValue &val);
@@ -170,6 +171,12 @@ public:
QJsonArray toArray() const;
QJsonObject toObject() const;
+ // ### Qt 6: Add default values
+ inline bool toBool(bool defaultValue) const { return toValue().toBool(defaultValue); }
+ inline int toInt(int defaultValue) const { return toValue().toInt(defaultValue); }
+ inline double toDouble(double defaultValue) const { return toValue().toDouble(defaultValue); }
+ inline QString toString(const QString &defaultValue) const { return toValue().toString(defaultValue); }
+
inline bool operator==(const QJsonValue &other) const { return toValue() == other; }
inline bool operator!=(const QJsonValue &other) const { return toValue() != other; }
@@ -182,6 +189,7 @@ private:
};
uint is_object : 1;
uint index : 31;
+ struct UnionHelper;
};
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 6868eb6a1e..7f2e28e800 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -71,6 +71,7 @@
#include <private/qfactoryloader_p.h>
#include <private/qfunctions_p.h>
#include <private/qlocale_p.h>
+#include <private/qhooks_p.h>
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_UNIX)
@@ -564,8 +565,8 @@ void QCoreApplicationPrivate::initLocale()
/*!
\class QCoreApplication
\inmodule QtCore
- \brief The QCoreApplication class provides an event loop for console Qt
- applications.
+ \brief The QCoreApplication class provides an event loop for Qt
+ applications without UI.
This class is used by non-GUI applications to provide their event
loop. For non-GUI application that uses Qt, there should be exactly
@@ -765,6 +766,10 @@ void QCoreApplication::init()
qt_call_pre_routines();
qt_startup_hook();
+#ifndef QT_BOOTSTRAPPED
+ if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
+ reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
+#endif
#ifndef QT_NO_QOBJECT
QCoreApplicationPrivate::is_app_running = true; // No longer starting up.
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index d8c52fbf1d..195c8da43f 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -219,7 +219,6 @@ private:
friend class QApplicationPrivate;
friend class QGuiApplication;
friend class QGuiApplicationPrivate;
- friend class QETWidget;
friend class QWidget;
friend class QWidgetWindow;
friend class QWidgetPrivate;
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index d784267a65..f0c9e4e1c2 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -96,6 +96,7 @@ public:
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
bool sendThroughObjectEventFilters(QObject *, QEvent *);
bool notify_helper(QObject *, QEvent *);
+ static inline void setEventSpontaneous(QEvent *e, bool spontaneous) { e->spont = spontaneous; }
virtual void createEventDispatcher();
virtual void eventDispatcherReady();
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 65ca6b0dcb..0ce3f00472 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -145,14 +145,30 @@ QString QCoreApplicationPrivate::appName() const
qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
*****************************************************************************/
-#if defined(Q_OS_WINCE)
-Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
- int cmdShow, int &argc, QVector<char *> &argv)
-#else
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+
+// ### Qt6: FIXME: Remove this function. It is only there since for binary
+// compatibility for applications built with Qt 5.3 using qtmain.lib which calls it.
+// In Qt 5.4, qtmain.lib was changed to use CommandLineToArgvW() without calling into Qt5Core.
Q_CORE_EXPORT
void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+{
+ Q_UNUSED(instance)
+ Q_UNUSED(prevInstance)
+ Q_UNUSED(cmdShow)
+
+ const QStringList wArgv = qWinCmdArgs(QString::fromLocal8Bit(cmdParam));
+ argv.clear();
+ argc = wArgv.size();
+ foreach (const QString &wArg, wArgv)
+ argv.append(_strdup(wArg.toLocal8Bit().constData()));
+}
+
+#elif defined(Q_OS_WINCE)
+
+Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
int cmdShow, int &argc, QVector<char *> &argv)
-#endif
{
static bool already_called = false;
@@ -172,6 +188,8 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
Q_UNUSED(prevInstance);
}
+#endif // Q_OS_WINCE
+
#ifndef QT_NO_QOBJECT
void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
index 93c80205ab..84d9be20e5 100644
--- a/src/corelib/kernel/qcorecmdlineargs_p.h
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -56,14 +56,34 @@
#include "QtCore/qstring.h"
#include "QtCore/qstringlist.h"
+#if defined(Q_OS_WIN)
+# ifdef Q_OS_WIN32
+# include <qt_windows.h> // first to suppress min, max macros.
+# include <shlobj.h>
+# else
+# include "QtCore/qvector.h"
+# include <qt_windows.h>
+# endif
+
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN32)
+
+static inline QStringList qWinCmdArgs(const QString &cmdLine)
+{
+ QStringList result;
+ int size;
+ if (wchar_t **argv = CommandLineToArgvW((const wchar_t *)cmdLine.utf16(), &size)) {
+ result.reserve(size);
+ wchar_t **argvEnd = argv + size;
+ for (wchar_t **a = argv; a < argvEnd; ++a)
+ result.append(QString::fromWCharArray(*a));
+ LocalFree(argv);
+ }
+ return result;
+}
-QT_BEGIN_INCLUDE_NAMESPACE
-# include "QtCore/qvector.h"
-# include <qt_windows.h>
-QT_END_INCLUDE_NAMESPACE
+#elif defined(Q_OS_WINCE) // Q_OS_WIN32
// template implementation of the parsing algorithm
// this is used from qcoreapplication_win.cpp and the tools (rcc, uic...)
@@ -149,7 +169,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[])
return qWinCmdArgs(cmdLine);
}
-#else // Q_OS_WIN && !Q_OS_WINRT
+#elif defined(Q_OS_WINRT) // Q_OS_WINCE
static inline QStringList qCmdLineArgs(int argc, char *argv[])
{
@@ -159,8 +179,10 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[])
return args;
}
-#endif // !Q_OS_WIN || Q_OS_WINRT
+#endif // Q_OS_WINRT
QT_END_NAMESPACE
+#endif // Q_OS_WIN
+
#endif // QCORECMDLINEARGS_WIN_P_H
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index edf262b8af..8d5a39115a 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -43,8 +43,9 @@
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
-#include "qmutex.h"
-#include "qset.h"
+#include "qbasicatomic.h"
+
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -192,6 +193,7 @@ QT_BEGIN_NAMESPACE
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
\value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
+ \value ReadOnlyChange Widget's read-only state has changed (since Qt 5.4).
\value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
\value Resize Widget's size changed (QResizeEvent).
\value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent).
@@ -389,13 +391,71 @@ QEvent::~QEvent()
The return value of this function is not defined for paint events.
*/
-class QEventUserEventRegistration
-{
-public:
- QMutex mutex;
- QSet<int> set;
+namespace {
+template <size_t N>
+struct QBasicAtomicBitField {
+ enum {
+ BitsPerInt = std::numeric_limits<uint>::digits,
+ NumInts = (N + BitsPerInt - 1) / BitsPerInt,
+ NumBits = N
+ };
+
+ // This atomic int points to the next (possibly) free ID saving
+ // the otherwise necessary scan through 'data':
+ QBasicAtomicInteger<uint> next;
+ QBasicAtomicInteger<uint> data[NumInts];
+
+ bool allocateSpecific(int which) Q_DECL_NOTHROW
+ {
+ QBasicAtomicInteger<uint> &entry = data[which / BitsPerInt];
+ const uint old = entry.load();
+ const uint bit = 1U << (which % BitsPerInt);
+ return !(old & bit) // wasn't taken
+ && entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
+
+ // don't update 'next' here - it's unlikely that it will need
+ // to be updated, in the general case, and having 'next'
+ // trailing a bit is not a problem, as it is just a starting
+ // hint for allocateNext(), which, when wrong, will just
+ // result in a few more rounds through the allocateNext()
+ // loop.
+ }
+
+ int allocateNext() Q_DECL_NOTHROW
+ {
+ // Unroll loop to iterate over ints, then bits? Would save
+ // potentially a lot of cmpxchgs, because we can scan the
+ // whole int before having to load it again.
+
+ // Then again, this should never execute many iterations, so
+ // leave like this for now:
+ for (uint i = next.load(); i < NumBits; ++i) {
+ if (allocateSpecific(i)) {
+ // remember next (possibly) free id:
+ const uint oldNext = next.load();
+ next.testAndSetRelaxed(oldNext, qMax(i + 1, oldNext));
+ return i;
+ }
+ }
+ return -1;
+ }
};
-Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
+
+} // unnamed namespace
+
+typedef QBasicAtomicBitField<QEvent::MaxUser - QEvent::User + 1> UserEventTypeRegistry;
+
+static UserEventTypeRegistry userEventTypeRegistry;
+
+static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW
+{
+ // if the type hint hasn't been registered yet, take it:
+ if (id < UserEventTypeRegistry::NumBits && id >= 0 && userEventTypeRegistry.allocateSpecific(id))
+ return id;
+
+ // otherwise, ignore hint:
+ return userEventTypeRegistry.allocateNext();
+}
/*!
\since 4.4
@@ -410,30 +470,10 @@ Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
Returns -1 if all available values are already taken or the
program is shutting down.
*/
-int QEvent::registerEventType(int hint)
+int QEvent::registerEventType(int hint) Q_DECL_NOTHROW
{
- QEventUserEventRegistration *userEventRegistration
- = userEventRegistrationHelper();
- if (!userEventRegistration)
- return -1;
-
- QMutexLocker locker(&userEventRegistration->mutex);
-
- // if the type hint hasn't been registered yet, take it
- if (hint >= QEvent::User && hint <= QEvent::MaxUser && !userEventRegistration->set.contains(hint)) {
- userEventRegistration->set.insert(hint);
- return hint;
- }
-
- // find a free event type, starting at MaxUser and decreasing
- int id = QEvent::MaxUser;
- while (userEventRegistration->set.contains(id) && id >= QEvent::User)
- --id;
- if (id >= QEvent::User) {
- userEventRegistration->set.insert(id);
- return id;
- }
- return -1;
+ const int result = registerEventTypeZeroBased(QEvent::MaxUser - hint);
+ return result < 0 ? -1 : QEvent::MaxUser - result ;
}
/*!
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 8b58fdf55f..cd7689f842 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -150,6 +150,8 @@ public:
WindowUnblocked = 104, // windows modal blocking has ended
WindowStateChange = 105,
+ ReadOnlyChange = 106, // readonly state has changed
+
ToolTip = 110,
WhatsThis = 111,
StatusTip = 112,
@@ -300,7 +302,7 @@ public:
inline void accept() { m_accept = true; }
inline void ignore() { m_accept = false; }
- static int registerEventType(int hint = -1);
+ static int registerEventType(int hint = -1) Q_DECL_NOTHROW;
protected:
QEventPrivate *d;
@@ -316,17 +318,10 @@ private:
friend class QCoreApplicationPrivate;
friend class QThreadData;
friend class QApplication;
- friend class QApplicationPrivate;
friend class QShortcutMap;
- friend class QETWidget;
friend class QGraphicsView;
- friend class QGraphicsViewPrivate;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
- friend class QWidgetWindow;
-#ifndef QT_NO_GESTURES
- friend class QGestureManager;
-#endif
};
class Q_CORE_EXPORT QTimerEvent : public QEvent
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 242aa9e695..6060f34b47 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -136,7 +136,7 @@ protected:
virtual int select(int nfds,
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- timespec *timeout) Q_DECL_FINAL;
+ timespec *timeout);
};
class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 1d4b57642c..91a97885ee 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include <QtCore/QHash>
+#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
@@ -71,8 +72,44 @@ public:
struct WinRTTimerInfo // internal timer info
{
- WinRTTimerInfo() : timer(0) {}
+ WinRTTimerInfo(int timerId, int timerInterval, Qt::TimerType timerType, QObject *object, QEventDispatcherWinRT *dispatcher)
+ : isFinished(false), id(timerId), interval(timerInterval), timerType(timerType), obj(object), inTimerEvent(false), dispatcher(dispatcher)
+ {
+ }
+
+ void cancel()
+ {
+ if (isFinished) {
+ delete this;
+ return;
+ }
+ isFinished = true;
+ if (!timer)
+ return;
+
+ HRESULT hr = timer->Cancel();
+ RETURN_VOID_IF_FAILED("Failed to cancel timer");
+ }
+
+ HRESULT timerExpired(IThreadPoolTimer *)
+ {
+ if (isFinished)
+ return S_OK;
+ if (dispatcher)
+ QCoreApplication::postEvent(dispatcher, new QTimerEvent(id));
+ return S_OK;
+ }
+ HRESULT timerDestroyed(IThreadPoolTimer *)
+ {
+ if (isFinished)
+ delete this;
+ else
+ isFinished = true;
+ return S_OK;
+ }
+
+ bool isFinished;
int id;
int interval;
Qt::TimerType timerType;
@@ -80,6 +117,7 @@ struct WinRTTimerInfo // internal timer info
QObject *obj; // - object to receive events
bool inTimerEvent;
ComPtr<IThreadPoolTimer> timer;
+ QPointer<QEventDispatcherWinRT> dispatcher;
};
class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
@@ -90,15 +128,8 @@ public:
QEventDispatcherWinRTPrivate();
~QEventDispatcherWinRTPrivate();
- void registerTimer(WinRTTimerInfo *t);
- void unregisterTimer(WinRTTimerInfo *t);
- void sendTimerEvent(int timerId);
-
private:
- static HRESULT timerExpiredCallback(IThreadPoolTimer *timer);
-
QHash<int, WinRTTimerInfo*> timerDict;
- QHash<IThreadPoolTimer *, int> timerIds;
ComPtr<IThreadPoolTimerStatics> timerFactory;
ComPtr<ICoreDispatcher> coreDispatcher;
@@ -111,28 +142,22 @@ QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
{
Q_D(QEventDispatcherWinRT);
- // Only look up the event dispatcher in the main thread
- if (QThread::currentThread() != QCoreApplicationPrivate::theMainThread)
- return;
-
- ComPtr<ICoreApplication> application;
+ // Obtain the WinRT Application, view, and window
+ ComPtr<ICoreImmersiveApplication> application;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
- if (SUCCEEDED(hr)) {
- ComPtr<ICoreApplicationView> view;
- hr = application->GetCurrentView(&view);
- if (SUCCEEDED(hr)) {
- ComPtr<ICoreWindow> window;
- hr = view->get_CoreWindow(&window);
- if (SUCCEEDED(hr)) {
- hr = window->get_Dispatcher(&d->coreDispatcher);
- if (SUCCEEDED(hr))
- return;
- }
- }
- }
- qCritical("QEventDispatcherWinRT: Unable to capture the core dispatcher. %s",
- qPrintable(qt_error_string(hr)));
+ RETURN_VOID_IF_FAILED("Failed to activate the application factory");
+
+ ComPtr<ICoreApplicationView> view;
+ hr = application->get_MainView(&view);
+ RETURN_VOID_IF_FAILED("Failed to get the main view");
+
+ ComPtr<ICoreWindow> window;
+ hr = view->get_CoreWindow(&window);
+ RETURN_VOID_IF_FAILED("Failed to get the core window");
+
+ hr = window->get_Dispatcher(&d->coreDispatcher);
+ RETURN_VOID_IF_FAILED("Failed to get the core dispatcher");
}
QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
@@ -150,8 +175,15 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
bool didProcess = false;
forever {
// Process native events
- if (d->coreDispatcher)
- d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+ if (d->coreDispatcher) {
+ boolean hasThreadAccess;
+ HRESULT hr = d->coreDispatcher->get_HasThreadAccess(&hasThreadAccess);
+ if (SUCCEEDED(hr) && hasThreadAccess) {
+ hr = d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to process events");
+ }
+ }
// Dispatch accumulated user events
didProcess = sendPostedEvents(flags);
@@ -162,13 +194,12 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
break;
// Short sleep if there is nothing to do
- if (flags & QEventLoop::WaitForMoreEvents) {
- emit aboutToBlock();
- WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE);
- emit awake();
- } else {
+ if (!(flags & QEventLoop::WaitForMoreEvents))
break;
- }
+
+ emit aboutToBlock();
+ WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE);
+ emit awake();
}
d->interrupt = false;
return didProcess;
@@ -213,15 +244,28 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
}
Q_D(QEventDispatcherWinRT);
- WinRTTimerInfo *t = new WinRTTimerInfo();
- t->id = timerId;
- t->interval = interval;
- t->timerType = timerType;
- t->obj = object;
- t->inTimerEvent = false;
-
- d->registerTimer(t);
+
+ WinRTTimerInfo *t = new WinRTTimerInfo(timerId, interval, timerType, object, this);
+ t->timeout = qt_msectime() + interval;
d->timerDict.insert(t->id, t);
+
+ // Don't use timer factory for zero-delay timers
+ if (interval == 0u) {
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(timerId));
+ return;
+ }
+
+ TimeSpan period;
+ period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
+ HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
+ Callback<ITimerElapsedHandler>(t, &WinRTTimerInfo::timerExpired).Get(), period,
+ Callback<ITimerDestroyedHandler>(t, &WinRTTimerInfo::timerDestroyed).Get(), &t->timer);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to create periodic timer");
+ delete t;
+ d->timerDict.remove(t->id);
+ return;
+ }
}
bool QEventDispatcherWinRT::unregisterTimer(int timerId)
@@ -237,11 +281,11 @@ bool QEventDispatcherWinRT::unregisterTimer(int timerId)
Q_D(QEventDispatcherWinRT);
- WinRTTimerInfo *t = d->timerDict.value(timerId);
+ WinRTTimerInfo *t = d->timerDict.take(timerId);
if (!t)
return false;
- d->unregisterTimer(t);
+ t->cancel();
return true;
}
@@ -258,9 +302,13 @@ bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
}
Q_D(QEventDispatcherWinRT);
- foreach (WinRTTimerInfo *t, d->timerDict) {
- if (t->obj == object)
- d->unregisterTimer(t);
+ for (QHash<int, WinRTTimerInfo *>::iterator it = d->timerDict.begin(); it != d->timerDict.end();) {
+ if (it.value()->obj == object) {
+ it.value()->cancel();
+ it = d->timerDict.erase(it);
+ continue;
+ }
+ ++it;
}
return true;
}
@@ -341,40 +389,41 @@ void QEventDispatcherWinRT::startingUp()
void QEventDispatcherWinRT::closingDown()
{
Q_D(QEventDispatcherWinRT);
- foreach (WinRTTimerInfo *t, d->timerDict)
- d->unregisterTimer(t);
d->timerDict.clear();
- d->timerIds.clear();
}
bool QEventDispatcherWinRT::event(QEvent *e)
{
Q_D(QEventDispatcherWinRT);
- if (e->type() == QEvent::ZeroTimerEvent) {
- QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
- WinRTTimerInfo *t = d->timerDict.value(zte->timerId());
- if (t) {
+ bool ret = false;
+ switch (e->type()) {
+ case QEvent::ZeroTimerEvent:
+ ret = true;
+ // fall through
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e);
+ const int id = timerEvent->timerId();
+ if (WinRTTimerInfo *t = d->timerDict.value(id)) {
+ if (t->inTimerEvent) // but don't allow event to recurse
+ break;
t->inTimerEvent = true;
- QTimerEvent te(zte->timerId());
+ QTimerEvent te(id);
QCoreApplication::sendEvent(t->obj, &te);
- t = d->timerDict.value(zte->timerId());
- if (t) {
+ if (t = d->timerDict.value(id)) {
if (t->interval == 0 && t->inTimerEvent) {
// post the next zero timer event as long as the timer was not restarted
- QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(id));
}
-
t->inTimerEvent = false;
}
}
- return true;
- } else if (e->type() == QEvent::Timer) {
- QTimerEvent *te = static_cast<QTimerEvent*>(e);
- d->sendTimerEvent(te->timerId());
}
- return QAbstractEventDispatcher::event(e);
+ default:
+ break;
+ }
+ return ret ? true : QAbstractEventDispatcher::event(e);
}
QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate()
@@ -391,73 +440,4 @@ QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate()
CoUninitialize();
}
-void QEventDispatcherWinRTPrivate::registerTimer(WinRTTimerInfo *t)
-{
- Q_Q(QEventDispatcherWinRT);
-
- bool ok = false;
- uint interval = t->interval;
- if (interval == 0u) {
- // optimization for single-shot-zero-timer
- QCoreApplication::postEvent(q, new QZeroTimerEvent(t->id));
- ok = true;
- } else {
- TimeSpan period;
- period.Duration = interval * 10000; // TimeSpan is based on 100-nanosecond units
- ok = SUCCEEDED(timerFactory->CreatePeriodicTimer(
- Callback<ITimerElapsedHandler>(&QEventDispatcherWinRTPrivate::timerExpiredCallback).Get(), period, &t->timer));
- if (ok)
- timerIds.insert(t->timer.Get(), t->id);
- }
- t->timeout = qt_msectime() + interval;
- if (!ok)
- qErrnoWarning("QEventDispatcherWinRT::registerTimer: Failed to create a timer");
-}
-
-void QEventDispatcherWinRTPrivate::unregisterTimer(WinRTTimerInfo *t)
-{
- if (t->timer) {
- timerIds.remove(t->timer.Get());
- t->timer->Cancel();
- }
- timerDict.remove(t->id);
- delete t;
-}
-
-void QEventDispatcherWinRTPrivate::sendTimerEvent(int timerId)
-{
- WinRTTimerInfo *t = timerDict.value(timerId);
- if (t && !t->inTimerEvent) {
- // send event, but don't allow it to recurse
- t->inTimerEvent = true;
-
- QTimerEvent e(t->id);
- QCoreApplication::sendEvent(t->obj, &e);
-
- // timer could have been removed
- t = timerDict.value(timerId);
- if (t)
- t->inTimerEvent = false;
- }
-}
-
-HRESULT QEventDispatcherWinRTPrivate::timerExpiredCallback(IThreadPoolTimer *timer)
-{
- QThread *thread = QThread::currentThread();
- if (!thread)
- return E_FAIL;
-
- QAbstractEventDispatcher *eventDispatcher = thread->eventDispatcher();
- if (!eventDispatcher)
- return E_FAIL;
-
- QEventDispatcherWinRTPrivate *d = static_cast<QEventDispatcherWinRTPrivate *>(get(eventDispatcher));
- int timerId = d->timerIds.value(timer, -1);
- if (timerId < 0)
- return E_FAIL; // A callback was received after the timer was canceled
-
- QCoreApplication::postEvent(eventDispatcher, new QTimerEvent(timerId));
- return S_OK;
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h
index fa2b2e12ff..5f051c3ea6 100644
--- a/src/corelib/kernel/qfunctions_winrt.h
+++ b/src/corelib/kernel/qfunctions_winrt.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -46,6 +46,10 @@
#ifdef Q_OS_WINRT
+#include <QtCore/QThread>
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/qt_windows.h>
+
QT_BEGIN_NAMESPACE
#ifdef QT_BUILD_CORE_LIB
@@ -118,5 +122,94 @@ generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *)
generate_inline_return_func0(tzset, void)
generate_inline_return_func0(_tzset, void)
+// Convenience macros for handling HRESULT values
+#define RETURN_IF_FAILED(msg, ret) \
+ if (FAILED(hr)) { \
+ qErrnoWarning(hr, msg); \
+ ret; \
+ }
+
+#define RETURN_HR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return hr)
+#define RETURN_OK_IF_FAILED(msg) RETURN_IF_FAILED(msg, return S_OK)
+#define RETURN_FALSE_IF_FAILED(msg) RETURN_IF_FAILED(msg, return false)
+#define RETURN_VOID_IF_FAILED(msg) RETURN_IF_FAILED(msg, return)
+
+#define Q_ASSERT_SUCCEEDED(hr) \
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+
+namespace Microsoft { namespace WRL { template <typename T> class ComPtr; } }
+
+namespace QWinRTFunctions {
+
+// Synchronization methods
+enum AwaitStyle
+{
+ YieldThread = 0,
+ ProcessThreadEvents = 1,
+ ProcessMainThreadEvents = 2
+};
+
+template <typename T>
+static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle)
+{
+ Microsoft::WRL::ComPtr<IAsyncInfo> asyncInfo;
+ HRESULT hr = asyncOp.As(&asyncInfo);
+ if (FAILED(hr))
+ return hr;
+
+ AsyncStatus status;
+ switch (awaitStyle) {
+ case ProcessMainThreadEvents:
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ QCoreApplication::processEvents();
+ break;
+ case ProcessThreadEvents:
+ if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) {
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ dispatcher->processEvents(QEventLoop::AllEvents);
+ break;
+ }
+ // fall through
+ default:
+ case YieldThread:
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started)
+ QThread::yieldCurrentThread();
+ break;
+ }
+
+ if (FAILED(hr) || status != Completed) {
+ HRESULT ec;
+ hr = asyncInfo->get_ErrorCode(&ec);
+ if (FAILED(hr))
+ return hr;
+ return ec;
+ }
+
+ return hr;
+}
+
+template <typename T>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread)
+{
+ HRESULT hr = _await_impl(asyncOp, awaitStyle);
+ if (FAILED(hr))
+ return hr;
+
+ return asyncOp->GetResults();
+}
+
+template <typename T, typename U>
+static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, U *results, AwaitStyle awaitStyle = YieldThread)
+{
+ HRESULT hr = _await_impl(asyncOp, awaitStyle);
+ if (FAILED(hr))
+ return hr;
+
+ return asyncOp->GetResults(results);
+}
+
+} // QWinRTFunctions
+
#endif // Q_OS_WINRT
#endif // QFUNCTIONS_WINRT_H
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
index 21e23b9eb0..e29285a0d7 100644
--- a/src/corelib/kernel/qmath.h
+++ b/src/corelib/kernel/qmath.h
@@ -49,6 +49,7 @@
#include <math.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qcompilerdetection.h>
QT_BEGIN_NAMESPACE
@@ -286,6 +287,57 @@ Q_DECL_CONSTEXPR inline double qRadiansToDegrees(double radians)
return radians * (180 / M_PI);
}
+
+#if defined(Q_CC_GNU)
+// clz instructions exist in at least MIPS, ARM, PowerPC and X86, so we can assume this builtin always maps to an efficient instruction.
+inline quint32 qNextPowerOfTwo(quint32 v)
+{
+ if (v == 0)
+ return 1;
+ return 2U << (31 ^ __builtin_clz(v));
+}
+
+inline quint64 qNextPowerOfTwo(quint64 v)
+{
+ if (v == 0)
+ return 1;
+ return Q_UINT64_C(2) << (63 ^ __builtin_clzll(v));
+}
+#else
+inline quint32 qNextPowerOfTwo(quint32 v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+inline quint64 qNextPowerOfTwo(quint64 v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ ++v;
+ return v;
+}
+#endif
+
+inline quint32 qNextPowerOfTwo(qint32 v)
+{
+ return qNextPowerOfTwo(quint32(v));
+}
+
+inline quint64 qNextPowerOfTwo(qint64 v)
+{
+ return qNextPowerOfTwo(quint64(v));
+}
+
QT_END_NAMESPACE
#endif // QMATH_H
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
index 04dbbb0a3b..430a420eeb 100644
--- a/src/corelib/kernel/qmath.qdoc
+++ b/src/corelib/kernel/qmath.qdoc
@@ -215,4 +215,37 @@
\snippet code/src_corelib_kernel_qmath.cpp 3
\sa qDegreesToRadians()
+
+/*!
+ \fn quint32 qNextPowerOfTwo(quint32 value)
+ \relates <QtMath>
+ \since 5.4
+
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^31 it returns 0.
+*/
+
+/*!
+ \fn quint32 qNextPowerOfTwo(qint32 value)
+ \relates <QtMath>
+ \since 5.4
+ \overload
+
+ This function returns the nearest power of two greater than \a value. For negative values it returns 0.
+*/
+
+/*!
+ \fn quint64 qNextPowerOfTwo(quint64 value)
+ \relates <QtMath>
+ \since 5.4
+
+ This function returns the nearest power of two greater than \a value. For 0 it returns 1, and for values larger than or equal to 2^63 it returns 0.
+*/
+
+/*!
+ \fn quint64 qNextPowerOfTwo(qint64 value)
+ \relates <QtMath>
+ \since 5.4
+ \overload
+
+ This function returns the nearest power of two greater than \a value. For negative values it returns 0.
*/
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 5be94429b4..cb63718680 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -163,11 +163,6 @@ static inline const char *rawStringData(const QMetaObject *mo, int index)
return stringData(mo, index).data();
}
-static inline int stringSize(const QMetaObject *mo, int index)
-{
- return stringData(mo, index).size();
-}
-
static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
{
if (typeInfo & IsUnresolvedType) {
@@ -308,6 +303,11 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
return object->qt_metacall(cl, idx, argv);
}
+static inline const char *objectClassName(const QMetaObject *m)
+{
+ return rawStringData(m, priv(m->d.data)->className);
+}
+
/*!
Returns the class name.
@@ -315,7 +315,7 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
*/
const char *QMetaObject::className() const
{
- return rawStringData(this, 0);
+ return objectClassName(this);
}
/*!
@@ -369,7 +369,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(rawStringData(this, 0), s, c, n);
+ return QCoreApplication::translate(objectClassName(this), s, c, n);
}
#endif // QT_NO_TRANSLATION
@@ -728,7 +728,7 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
QMetaMethod conflictMethod = m->d.superdata->method(conflict);
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
conflictMethod.methodSignature().constData(),
- rawStringData(m->d.superdata, 0), rawStringData(m, 0));
+ objectClassName(m->d.superdata), objectClassName(m));
}
}
#endif
@@ -938,7 +938,7 @@ bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
{
while (self) {
- if (strcmp(rawStringData(self, 0), name) == 0)
+ if (strcmp(objectClassName(self), name) == 0)
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
@@ -1117,7 +1117,7 @@ QMetaProperty QMetaObject::property(int index) const
result.menum = enumerator(indexOfEnumerator(type));
if (!result.menum.isValid()) {
const char *enum_name = type;
- const char *scope_name = rawStringData(this, 0);
+ const char *scope_name = objectClassName(this);
char *scope_buffer = 0;
const char *colon = strrchr(enum_name, ':');
@@ -1339,6 +1339,27 @@ QByteArray QMetaObject::normalizedSignature(const char *method)
enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
/*!
+ Returns the signatures of all methods whose name matches \a nonExistentMember,
+ or an empty QByteArray if there are no matches.
+*/
+static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, const char *nonExistentMember)
+{
+ QByteArray candidateMessage;
+ // Prevent full string comparison in every iteration.
+ const QByteArray memberByteArray = nonExistentMember;
+ for (int i = 0; i < metaObject->methodCount(); ++i) {
+ const QMetaMethod method = metaObject->method(i);
+ if (method.name() == memberByteArray)
+ candidateMessage.append(" " + method.methodSignature() + '\n');
+ }
+ if (!candidateMessage.isEmpty()) {
+ candidateMessage.prepend("\nCandidates are:\n");
+ candidateMessage.chop(1);
+ }
+ return candidateMessage;
+}
+
+/*!
Invokes the \a member (a signal or a slot name) on the object \a
obj. Returns \c true if the member could be invoked. Returns \c false
if there is no such member or the parameters did not match.
@@ -1455,8 +1476,9 @@ bool QMetaObject::invokeMethod(QObject *obj,
}
if (idx < 0 || idx >= meta->methodCount()) {
- qWarning("QMetaObject::invokeMethod: No such method %s::%s",
- meta->className(), sig.constData());
+ // This method doesn't belong to us; print out a nice warning with candidates.
+ qWarning("QMetaObject::invokeMethod: No such method %s::%s%s",
+ meta->className(), sig.constData(), findMethodCandidates(meta, member).constData());
return false;
}
QMetaMethod method = meta->method(idx);
@@ -2412,7 +2434,7 @@ bool QMetaEnum::isFlag() const
*/
const char *QMetaEnum::scope() const
{
- return mobj?rawStringData(mobj, 0) : 0;
+ return mobj ? objectClassName(mobj) : 0;
}
/*!
@@ -2444,7 +2466,8 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i) {
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
if (ok != 0)
*ok = true;
@@ -2512,12 +2535,14 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
key += scope + 2;
}
int i;
- for (i = count-1; i >= 0; --i)
- if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
+ for (i = count-1; i >= 0; --i) {
+ const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
+ if ((!scope || (className.size() == int(scope) && strncmp(qualified_key.constData(), className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
value |= mobj->d.data[data + 2*i + 1];
break;
}
+ }
if (i < 0) {
if (ok != 0)
*ok = false;
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index f74c592e8c..a5fd0c9102 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -2405,4 +2405,9 @@ const QMetaObject *metaObjectForQWidget()
}
}
+namespace QtMetaTypePrivate {
+const bool VectorBoolElements::true_element = true;
+const bool VectorBoolElements::false_element = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 3b35a51e2c..32fd5bd153 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -782,7 +782,7 @@ private:
};
template<typename const_iterator>
-struct IteratorOwner
+struct IteratorOwnerCommon
{
static void assign(void **ptr, const_iterator iterator)
{
@@ -804,6 +804,15 @@ struct IteratorOwner
delete static_cast<const_iterator*>(*ptr);
}
+ static bool equal(void * const *it, void * const *other)
+ {
+ return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
+ }
+};
+
+template<typename const_iterator>
+struct IteratorOwner : IteratorOwnerCommon<const_iterator>
+{
static const void *getData(void * const *iterator)
{
return &**static_cast<const_iterator*>(*iterator);
@@ -813,16 +822,41 @@ struct IteratorOwner
{
return &*it;
}
+};
- static bool equal(void * const *it, void * const *other)
+struct Q_CORE_EXPORT VectorBoolElements
+{
+ static const bool true_element;
+ static const bool false_element;
+};
+
+template<>
+struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
+{
+public:
+ static const void *getData(void * const *iterator)
{
- return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
+ return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
+ &VectorBoolElements::true_element : &VectorBoolElements::false_element;
+ }
+
+ static const void *getData(const std::vector<bool>::const_iterator& it)
+ {
+ return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
}
};
+
template<typename value_type>
struct IteratorOwner<const value_type*>
{
- static void assign(void **ptr, const value_type *iterator )
+private:
+ // We need to disable typed overloads of assign() and getData() if the value_type
+ // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
+ // type as part of the overload signature.
+ struct Dummy {};
+ typedef typename QtPrivate::if_<QtPrivate::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
+public:
+ static void assign(void **ptr, const value_type_OR_Dummy *iterator )
{
*ptr = const_cast<value_type*>(iterator);
}
@@ -847,7 +881,7 @@ struct IteratorOwner<const value_type*>
return *iterator;
}
- static const void *getData(const value_type *it)
+ static const void *getData(const value_type_OR_Dummy *it)
{
return it;
}
@@ -894,11 +928,11 @@ struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
template<typename T>
struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return t->size(); } };
+{ static int size(const std::vector<T> *t) { return int(t->size()); } };
template<typename T>
struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *t) { return t->size(); } };
+{ static int size(const std::list<T> *t) { return int(t->size()); } };
class QSequentialIterableImpl
{
@@ -1278,6 +1312,11 @@ namespace QtPrivate
enum { Value = false };
};
template<>
+ struct IsPointerToTypeDerivedFromQObject<const void*>
+ {
+ enum { Value = false };
+ };
+ template<>
struct IsPointerToTypeDerivedFromQObject<QObject*>
{
enum { Value = true };
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
index 5d2adb0561..3f2cd5a36a 100644
--- a/src/corelib/kernel/qmimedata.cpp
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -294,7 +294,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty
data is encoded.
On Windows, the MIME format does not always map directly to the
- clipboard formats. Qt provides QWindowsMime to map clipboard
+ clipboard formats. Qt provides QWinMime to map clipboard
formats to open-standard MIME formats. Similarly, the
QMacPasteboardMime maps MIME to Mac flavors.
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 5e8a97cdc0..fb01df3099 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -63,6 +63,7 @@
#include <qsharedpointer.h>
#include <private/qorderedmutexlocker_p.h>
+#include <private/qhooks_p.h>
#include <new>
@@ -138,6 +139,7 @@ static inline QMutex *signalSlotLock(const QObject *o)
uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
}
+// ### Qt >= 5.6, remove qt_add/removeObject
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{}
@@ -820,6 +822,8 @@ QObject::QObject(QObject *parent)
}
}
qt_addObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
+ reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
/*!
@@ -851,6 +855,8 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
}
}
qt_addObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
+ reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
/*!
@@ -1028,6 +1034,8 @@ QObject::~QObject()
d->deleteChildren();
qt_removeObject(this);
+ if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
+ reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
if (d->parent) // remove it from parent object
d->setParent_helper(0);
@@ -3504,7 +3512,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
\a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
*/
-static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv,
+ QMutexLocker &locker)
{
const int *argumentTypes = c->argumentTypes.load();
if (!argumentTypes && argumentTypes != &DIRECT_CONNECTION_ONLY) {
@@ -3529,8 +3538,28 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
Q_CHECK_PTR(args);
types[0] = 0; // return type
args[0] = 0; // return value
- for (int n = 1; n < nargs; ++n)
- args[n] = QMetaType::create((types[n] = argumentTypes[n-1]), argv[n]);
+
+ if (nargs > 1) {
+ for (int n = 1; n < nargs; ++n)
+ types[n] = argumentTypes[n-1];
+
+ locker.unlock();
+ for (int n = 1; n < nargs; ++n)
+ args[n] = QMetaType::create(types[n], argv[n]);
+ locker.relock();
+
+ if (!c->receiver) {
+ locker.unlock();
+ // we have been disconnected while the mutex was unlocked
+ for (int n = 1; n < nargs; ++n)
+ QMetaType::destroy(types[n], args[n]);
+ free(types);
+ free(args);
+ locker.relock();
+ return;
+ }
+ }
+
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
@@ -3630,7 +3659,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
// put into the event queue
if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal_index, c, argv ? argv : empty_argv);
+ queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
continue;
#ifndef QT_NO_THREAD
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index db6ff568bd..97aae6f7e0 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -260,26 +260,50 @@ class QSingleShotTimer : public QObject
{
Q_OBJECT
int timerId;
+ bool hasValidReceiver;
+ QPointer<const QObject> receiver;
+ QtPrivate::QSlotObjectBase *slotObj;
public:
~QSingleShotTimer();
QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m);
+ QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
+
Q_SIGNALS:
void timeout();
protected:
void timerEvent(QTimerEvent *);
};
-QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
- : QObject(QAbstractEventDispatcher::instance())
+QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member)
+ : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(0)
+{
+ timerId = startTimer(msec, timerType);
+ connect(this, SIGNAL(timeout()), r, member);
+}
+
+QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
+ : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(r), receiver(r), slotObj(slotObj)
{
- connect(this, SIGNAL(timeout()), receiver, member);
timerId = startTimer(msec, timerType);
+ if (r && thread() != r->thread()) {
+ // We need the invocation to happen in the receiver object's thread.
+ // So, move QSingleShotTimer to the correct thread. Before that occurs, we
+ // shall remove the parent from the object.
+ setParent(0);
+ moveToThread(r->thread());
+
+ // Given we're also parentless now, we should take defence against leaks
+ // in case the application quits before we expire.
+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
+ }
}
QSingleShotTimer::~QSingleShotTimer()
{
if (timerId > 0)
killTimer(timerId);
+ if (slotObj)
+ slotObj->destroyIfLastRef();
}
void QSingleShotTimer::timerEvent(QTimerEvent *)
@@ -289,7 +313,18 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
if (timerId > 0)
killTimer(timerId);
timerId = -1;
- emit timeout();
+
+ if (slotObj) {
+ // If the receiver was destroyed, skip this part
+ if (Q_LIKELY(!receiver.isNull() || !hasValidReceiver)) {
+ // We allocate only the return type - we previously checked the function had
+ // no arguments.
+ void *args[1] = { 0 };
+ slotObj->call(const_cast<QObject*>(receiver.data()), args);
+ }
+ } else {
+ emit timeout();
+ }
// we would like to use delete later here, but it feels like a
// waste to post a new event to handle this event, so we just unset the flag
@@ -298,6 +333,25 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
}
/*!
+ \internal
+
+ Implementation of the template version of singleShot
+
+ \a msec is the timer interval
+ \a timerType is the timer type
+ \a receiver is the receiver object, can be null. In such a case, it will be the same
+ as the final sender class.
+ \a slot a pointer only used when using Qt::UniqueConnection
+ \a slotObj the slot object
+ */
+void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj)
+{
+ new QSingleShotTimer(msec, timerType, receiver, slotObj);
+}
+
+/*!
\reentrant
This static function calls a slot after a given time interval.
@@ -357,6 +411,129 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
}
}
+/*!\fn void QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls a member function of a QObject after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The \a receiver is the receiving object and the \a method is the member function. The
+ time interval is \a msec milliseconds.
+
+ If \a receiver is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a receiver. The receiver's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls a member function of a QObject after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The \a receiver is the receiving object and the \a method is the member function. The
+ time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ If \a receiver is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a receiver. The receiver's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, const QObject *context, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds.
+
+ If \a context is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a context. The context's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
+/*!\fn void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor)
+
+ \since 5.4
+
+ \overload
+ \reentrant
+ This static function calls \a functor after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \l{QObject::timerEvent()}{timerEvent} or
+ create a local QTimer object.
+
+ The time interval is \a msec milliseconds. The \a timerType affects the
+ accuracy of the timer.
+
+ If \a context is destroyed before the interval occurs, the method will not be called.
+ The function will be run in the thread of \a context. The context's thread must have
+ a running Qt event loop.
+
+ \sa start()
+*/
+
/*!
\property QTimer::singleShot
\brief whether the timer is a single-shot timer
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 3484f4dba8..6439070805 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -81,6 +81,67 @@ public:
static void singleShot(int msec, const QObject *receiver, const char *member);
static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);
+#ifdef Q_QDOC
+ static void singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);
+ static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method);
+ static void singleShot(int msec, Functor functor);
+ static void singleShot(int msec, Qt::TimerType timerType, Functor functor);
+ static void singleShot(int msec, const QObject *context, Functor functor);
+ static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
+#else
+ // singleShot to a QObject slot
+ template <typename Func1>
+ static inline void singleShot(int msec, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, receiver, slot);
+ }
+ template <typename Func1>
+ static inline void singleShot(int msec, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
+ Func1 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SlotType;
+
+ //compilation error if the slot has arguments.
+ Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 0,
+ "The slot must not have any arguments.");
+
+ singleShotImpl(msec, timerType, receiver,
+ new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot));
+ }
+ // singleShot to a functor or function pointer (without context)
+ template <typename Func1>
+ static inline void singleShot(int msec, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, Q_NULLPTR, slot);
+ }
+ template <typename Func1>
+ static inline void singleShot(int msec, Qt::TimerType timerType, Func1 slot)
+ {
+ singleShot(msec, timerType, Q_NULLPTR, slot);
+ }
+ // singleShot to a functor or function pointer (with context)
+ template <typename Func1>
+ static inline typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
+ !QtPrivate::is_same<const char*, Func1>::value, void>::Type
+ singleShot(int msec, QObject *context, Func1 slot)
+ {
+ singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, context, slot);
+ }
+ template <typename Func1>
+ static inline typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
+ !QtPrivate::is_same<const char*, Func1>::value, void>::Type
+ singleShot(int msec, Qt::TimerType timerType, QObject *context, Func1 slot)
+ {
+ //compilation error if the slot has arguments.
+ typedef QtPrivate::FunctionPointer<Func1> SlotType;
+ Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) <= 0, "The slot must not have any arguments.");
+
+ singleShotImpl(msec, timerType, context,
+ new QtPrivate::QFunctorSlotObject<Func1, 0,
+ typename QtPrivate::List_Left<void, 0>::Value, void>(slot));
+ }
+#endif
+
public Q_SLOTS:
void start(int msec);
@@ -103,6 +164,9 @@ private:
inline int startTimer(int){ return -1;}
inline void killTimer(int){}
+ static void singleShotImpl(int msec, Qt::TimerType timerType,
+ const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
+
int id, inter, del;
uint single : 1;
uint nulltimer : 1;
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 0ffa186d2e..a23e545729 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -443,4 +443,17 @@ bool QMimeType::inherits(const QString &mimeTypeName) const
return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QMimeType &mime)
+{
+ QDebugStateSaver saver(debug);
+ if (!mime.isValid()) {
+ debug.nospace() << "QMimeType(invalid)";
+ } else {
+ debug.nospace() << "QMimeType(" << mime.name() << ")";
+ }
+ return debug;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 24d043eebc..d5acbc2184 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -110,5 +110,10 @@ protected:
Q_DECLARE_SHARED(QMimeType)
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMimeType &mime);
+#endif
+
QT_END_NAMESPACE
#endif // QMIMETYPE_H
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 50281b632a..8af38acf51 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -455,7 +455,7 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con
lib = new QLibraryPrivate(fileName, version, loadHints);
// track this library
- if (Q_LIKELY(data))
+ if (Q_LIKELY(data) && !fileName.isEmpty())
data->libraryMap.insert(fileName, lib);
lib->libraryRefCount.ref();
@@ -475,7 +475,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
// no one else is using
Q_ASSERT(lib->libraryUnloadCount.load() == 0);
- if (Q_LIKELY(data)) {
+ if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
Q_ASSERT(lib == that);
Q_UNUSED(that);
@@ -485,9 +485,9 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
- loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{
+ loadHintsInt.store(loadHints);
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
@@ -508,7 +508,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
if (pHnd)
return;
- loadHints = lh;
+ loadHintsInt.store(lh);
}
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
@@ -518,6 +518,12 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
return resolve_sys(symbol);
}
+void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
+{
+ // this locks a global mutex
+ QMutexLocker lock(&qt_library_mutex);
+ mergeLoadHints(lh);
+}
bool QLibraryPrivate::load()
{
@@ -914,13 +920,12 @@ void QLibrary::setFileName(const QString &fileName)
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName);
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, QString(), lh);
}
QString QLibrary::fileName() const
@@ -943,13 +948,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString(), lh);
}
/*!
@@ -965,13 +969,12 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver
{
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
}
- d = QLibraryPrivate::findOrCreate(fileName, version);
- d->loadHints = lh;
+ d = QLibraryPrivate::findOrCreate(fileName, version, lh);
}
/*!
@@ -1102,6 +1105,12 @@ QString QLibrary::errorString() const
By default, none of these flags are set, so libraries will be loaded with
lazy symbol resolution, and will not export external symbols for resolution
in other dynamically-loaded libraries.
+
+ \note Setting this property after the library has been loaded has no effect
+ and loadHints() will not reflect those changes.
+
+ \note This property is shared among all QLibrary instances that refer to
+ the same library.
*/
void QLibrary::setLoadHints(LoadHints hints)
{
@@ -1109,12 +1118,12 @@ void QLibrary::setLoadHints(LoadHints hints)
d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
d->errorString.clear();
}
- d->loadHints = hints;
+ d->setLoadHints(hints);
}
QLibrary::LoadHints QLibrary::loadHints() const
{
- return d ? d->loadHints : (QLibrary::LoadHints)0;
+ return d ? d->loadHints() : QLibrary::LoadHints();
}
/* Internal, for debugging */
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index e58d18e87b..df95d1342d 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -94,6 +94,10 @@ public:
void release();
QFunctionPointer resolve(const char *);
+ QLibrary::LoadHints loadHints() const
+ { return QLibrary::LoadHints(loadHintsInt.load()); }
+ void setLoadHints(QLibrary::LoadHints lh);
+
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = 0);
static QStringList suffixes_sys(const QString &fullVersion);
@@ -104,7 +108,6 @@ public:
QJsonObject metaData;
QString errorString;
- QLibrary::LoadHints loadHints;
void updatePluginState();
bool isPlugin();
@@ -126,6 +129,8 @@ private:
bool unload_sys();
QFunctionPointer resolve_sys(const char *);
+ QAtomicInt loadHintsInt;
+
/// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded
QAtomicInt libraryRefCount;
/// counts how many times load() or loadPlugin() were called
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 43e2b5c15b..b9af143f35 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -162,6 +162,7 @@ bool QLibraryPrivate::load_sys()
dlFlags |= BIND_DEFERRED;
}
#else
+ int loadHints = this->loadHints();
if (loadHints & QLibrary::ResolveAllSymbolsHint) {
dlFlags |= RTLD_NOW;
} else {
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 2c139669e6..f34c019823 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -339,7 +339,7 @@ void QPluginLoader::setFileName(const QString &fileName)
#if defined(QT_SHARED)
QLibrary::LoadHints lh;
if (d) {
- lh = d->loadHints;
+ lh = d->loadHints();
d->release();
d = 0;
did_load = false;
@@ -405,17 +405,12 @@ void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
d->errorString.clear();
}
- d->loadHints = loadHints;
+ d->setLoadHints(loadHints);
}
QLibrary::LoadHints QPluginLoader::loadHints() const
{
- if (!d) {
- QPluginLoader *that = const_cast<QPluginLoader *>(this);
- that->d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
- that->d->errorString.clear();
- }
- return d->loadHints;
+ return d ? d->loadHints() : QLibrary::LoadHints();
}
/*!
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
index 62b7e448f5..da1eff9b4c 100644
--- a/src/corelib/statemachine/qabstractstate.cpp
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -79,8 +79,17 @@ QT_BEGIN_NAMESPACE
function to perform custom processing when the state is exited.
*/
+/*!
+ \property QAbstractState::active
+ \since 5.4
+
+ \brief the active property of this state. A state is active between
+ entered() and exited() signals.
+*/
+
+
QAbstractStatePrivate::QAbstractStatePrivate(StateType type)
- : stateType(type), isMachine(false), parentState(0)
+ : stateType(type), isMachine(false), active(false), parentState(0)
{
}
@@ -121,11 +130,19 @@ void QAbstractStatePrivate::emitEntered()
{
Q_Q(QAbstractState);
emit q->entered(QAbstractState::QPrivateSignal());
+ if (!active) {
+ active = true;
+ emit q->activeChanged(true);
+ }
}
void QAbstractStatePrivate::emitExited()
{
Q_Q(QAbstractState);
+ if (active) {
+ active = false;
+ emit q->activeChanged(false);
+ }
emit q->exited(QAbstractState::QPrivateSignal());
}
@@ -174,6 +191,17 @@ QStateMachine *QAbstractState::machine() const
}
/*!
+ Returns whether this state is active.
+
+ \sa activeChanged(bool), entered(), exited()
+*/
+bool QAbstractState::active() const
+{
+ Q_D(const QAbstractState);
+ return d->active;
+}
+
+/*!
\fn QAbstractState::onExit(QEvent *event)
This function is called when the state is exited. The given \a event is what
@@ -204,6 +232,15 @@ QStateMachine *QAbstractState::machine() const
*/
/*!
+ \fn QAbstractState::activeChanged(bool active)
+ \since 5.4
+
+ This signal is emitted when the active property is changed.
+
+ \sa QAbstractState::active, entered(), exited()
+*/
+
+/*!
\reimp
*/
bool QAbstractState::event(QEvent *e)
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
index a6ac248b85..4318a5b419 100644
--- a/src/corelib/statemachine/qabstractstate.h
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -56,12 +56,15 @@ class QAbstractStatePrivate;
class Q_CORE_EXPORT QAbstractState : public QObject
{
Q_OBJECT
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
public:
~QAbstractState();
QState *parentState() const;
QStateMachine *machine() const;
+ bool active() const;
+
Q_SIGNALS:
void entered(
#if !defined(Q_QDOC)
@@ -73,6 +76,7 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void activeChanged(bool active);
protected:
QAbstractState(QState *parent = 0);
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
index b0334dfbb5..40431a8fcb 100644
--- a/src/corelib/statemachine/qabstractstate_p.h
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -85,8 +85,9 @@ public:
void emitEntered();
void emitExited();
- uint stateType:31;
+ uint stateType:30;
uint isMachine:1;
+ bool active:1;
mutable QState *parentState;
};
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index 49091de8a8..e446c69519 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -201,10 +201,15 @@ QAbstractState *QAbstractTransition::targetState() const
void QAbstractTransition::setTargetState(QAbstractState* target)
{
Q_D(QAbstractTransition);
+ if ((d->targetStates.size() == 1 && target == d->targetStates.at(0).data()) ||
+ (d->targetStates.isEmpty() && target == 0)) {
+ return;
+ }
if (!target)
d->targetStates.clear();
else
setTargetStates(QList<QAbstractState*>() << target);
+ emit targetStateChanged(QPrivateSignal());
}
/*!
@@ -229,18 +234,26 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const
void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
{
Q_D(QAbstractTransition);
-
+ QList<QPointer<QAbstractState> > copy(d->targetStates);
+ bool sameList = true;
for (int i = 0; i < targets.size(); ++i) {
QAbstractState *target = targets.at(i);
if (!target) {
qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
return;
+ } else {
+ sameList &= copy.removeOne(target);
}
}
+ sameList &= copy.isEmpty();
+
d->targetStates.clear();
for (int i = 0; i < targets.size(); ++i)
d->targetStates.append(targets.at(i));
+
+ if (!sameList)
+ emit targetStatesChanged(QPrivateSignal());
}
/*!
@@ -324,6 +337,24 @@ QList<QAbstractAnimation*> QAbstractTransition::animations() const
*/
/*!
+ \fn QAbstractTransition::targetStateChanged()
+ \since 5.4
+
+ This signal is emitted when the targetState property is changed.
+
+ \sa QAbstractTransition::targetState
+*/
+
+/*!
+ \fn QAbstractTransition::targetStatesChanged()
+ \since 5.4
+
+ This signal is emitted when the targetStates property is changed.
+
+ \sa QAbstractTransition::targetStates
+*/
+
+/*!
\reimp
*/
bool QAbstractTransition::event(QEvent *e)
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index a35ad4ca96..ac3b40e55e 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -65,8 +65,8 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject
{
Q_OBJECT
Q_PROPERTY(QState* sourceState READ sourceState)
- Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState)
- Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates)
+ Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged)
+ Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged)
public:
QAbstractTransition(QState *sourceState = 0);
virtual ~QAbstractTransition();
@@ -91,6 +91,16 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void targetStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void targetStatesChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
protected:
virtual bool eventTest(QEvent *event) = 0;
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
index 65ac2a77a0..1706d86afd 100644
--- a/src/corelib/statemachine/qhistorystate.cpp
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -181,7 +181,10 @@ void QHistoryState::setDefaultState(QAbstractState *state)
"to this history state's group (%p)", state, parentState());
return;
}
- d->defaultState = state;
+ if (d->defaultState != state) {
+ d->defaultState = state;
+ emit defaultStateChanged(QHistoryState::QPrivateSignal());
+ }
}
/*!
@@ -199,7 +202,10 @@ QHistoryState::HistoryType QHistoryState::historyType() const
void QHistoryState::setHistoryType(HistoryType type)
{
Q_D(QHistoryState);
- d->historyType = type;
+ if (d->historyType != type) {
+ d->historyType = type;
+ emit historyTypeChanged(QHistoryState::QPrivateSignal());
+ }
}
/*!
@@ -226,6 +232,24 @@ bool QHistoryState::event(QEvent *e)
return QAbstractState::event(e);
}
+/*!
+ \fn QHistoryState::defaultStateChanged()
+ \since 5.4
+
+ This signal is emitted when the defaultState property is changed.
+
+ \sa QHistoryState::defaultState
+*/
+
+/*!
+ \fn QHistoryState::historyTypeChanged()
+ \since 5.4
+
+ This signal is emitted when the historyType property is changed.
+
+ \sa QHistoryState::historyType
+*/
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
index 62278ac47a..024c7e4b1f 100644
--- a/src/corelib/statemachine/qhistorystate.h
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -53,8 +53,8 @@ class QHistoryStatePrivate;
class Q_CORE_EXPORT QHistoryState : public QAbstractState
{
Q_OBJECT
- Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState)
- Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType)
+ Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged)
+ Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType NOTIFY historyTypeChanged)
Q_ENUMS(HistoryType)
public:
enum HistoryType {
@@ -72,6 +72,18 @@ public:
HistoryType historyType() const;
void setHistoryType(HistoryType type);
+Q_SIGNALS:
+ void defaultStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void historyTypeChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+
protected:
void onEntry(QEvent *event);
void onExit(QEvent *event);
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
index f1f4786bcc..259aaf52e9 100644
--- a/src/corelib/statemachine/qsignaltransition.cpp
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -185,6 +185,7 @@ void QSignalTransition::setSenderObject(const QObject *sender)
d->unregister();
d->sender = sender;
d->maybeRegister();
+ emit senderObjectChanged(QPrivateSignal());
}
/*!
@@ -207,6 +208,7 @@ void QSignalTransition::setSignal(const QByteArray &signal)
d->unregister();
d->signal = signal;
d->maybeRegister();
+ emit signalChanged(QPrivateSignal());
}
/*!
@@ -245,6 +247,24 @@ bool QSignalTransition::event(QEvent *e)
return QAbstractTransition::event(e);
}
+/*!
+ \fn QSignalTransition::senderObjectChanged()
+ \since 5.4
+
+ This signal is emitted when the senderObject property is changed.
+
+ \sa QSignalTransition::senderObject
+*/
+
+/*!
+ \fn QSignalTransition::signalChanged()
+ \since 5.4
+
+ This signal is emitted when the signal property is changed.
+
+ \sa QSignalTransition::signal
+*/
+
void QSignalTransitionPrivate::callOnTransition(QEvent *e)
{
Q_Q(QSignalTransition);
@@ -260,6 +280,7 @@ void QSignalTransitionPrivate::callOnTransition(QEvent *e)
}
}
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
index 12f021d78e..792fb12a14 100644
--- a/src/corelib/statemachine/qsignaltransition.h
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -53,8 +53,9 @@ class QSignalTransitionPrivate;
class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
{
Q_OBJECT
- Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject)
- Q_PROPERTY(QByteArray signal READ signal WRITE setSignal)
+ Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject NOTIFY senderObjectChanged)
+ Q_PROPERTY(QByteArray signal READ signal WRITE setSignal NOTIFY signalChanged)
+
public:
QSignalTransition(QState *sourceState = 0);
QSignalTransition(const QObject *sender, const char *signal,
@@ -73,6 +74,18 @@ protected:
bool event(QEvent *e);
+Q_SIGNALS:
+ void senderObjectChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void signalChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+
private:
Q_DISABLE_COPY(QSignalTransition)
Q_DECLARE_PRIVATE(QSignalTransition)
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index f3b4c5f235..e9baddc569 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -309,7 +309,10 @@ void QState::setErrorState(QAbstractState *state)
return;
}
- d->errorState = state;
+ if (d->errorState != state) {
+ d->errorState = state;
+ emit errorStateChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -491,7 +494,10 @@ void QState::setInitialState(QAbstractState *state)
state, this);
return;
}
- d->initialState = state;
+ if (d->initialState != state) {
+ d->initialState = state;
+ emit initialStateChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -509,7 +515,10 @@ QState::ChildMode QState::childMode() const
void QState::setChildMode(ChildMode mode)
{
Q_D(QState);
- d->childMode = mode;
+ if (d->childMode != mode) {
+ d->childMode = mode;
+ emit childModeChanged(QState::QPrivateSignal());
+ }
}
/*!
@@ -549,6 +558,33 @@ bool QState::event(QEvent *e)
\sa QState::assignProperty(), QAbstractTransition::addAnimation()
*/
+/*!
+ \fn QState::childModeChanged()
+ \since 5.4
+
+ This signal is emitted when the childMode property is changed.
+
+ \sa QState::childMode
+*/
+
+/*!
+ \fn QState::initialStateChanged()
+ \since 5.4
+
+ This signal is emitted when the initialState property is changed.
+
+ \sa QState::initialState
+*/
+
+/*!
+ \fn QState::errorStateChanged()
+ \since 5.4
+
+ This signal is emitted when the errorState property is changed.
+
+ \sa QState::errorState
+*/
+
QT_END_NAMESPACE
#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
index a5f2509ffb..09c98c30c6 100644
--- a/src/corelib/statemachine/qstate.h
+++ b/src/corelib/statemachine/qstate.h
@@ -58,9 +58,9 @@ class QStatePrivate;
class Q_CORE_EXPORT QState : public QAbstractState
{
Q_OBJECT
- Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
- Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
- Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode)
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState NOTIFY initialStateChanged)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState NOTIFY errorStateChanged)
+ Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode NOTIFY childModeChanged)
Q_ENUMS(ChildMode RestorePolicy)
public:
enum ChildMode {
@@ -108,6 +108,21 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void childModeChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void initialStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
+ void errorStateChanged(
+#if !defined(Q_QDOC)
+ QPrivateSignal
+#endif
+ );
protected:
void onEntry(QEvent *event);
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index d2e2368ca9..a147b85eb7 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -163,6 +163,13 @@ QT_BEGIN_NAMESPACE
QState::DontRestoreProperties.
*/
+/*!
+ \property QStateMachine::running
+ \since 5.4
+
+ \brief the running state of this state machine
+*/
+
#ifndef QT_NO_ANIMATION
/*!
\property QStateMachine::animated
@@ -1362,6 +1369,11 @@ void QStateMachinePrivate::_q_start()
{
Q_Q(QStateMachine);
Q_ASSERT(state == Starting);
+ foreach (QAbstractState *state, configuration) {
+ QAbstractStatePrivate *abstractStatePrivate = QAbstractStatePrivate::get(state);
+ abstractStatePrivate->active = false;
+ emit state->activeChanged(false);
+ }
configuration.clear();
qDeleteAll(internalEventQueue);
internalEventQueue.clear();
@@ -1409,6 +1421,7 @@ void QStateMachinePrivate::_q_start()
#endif
emit q->started(QStateMachine::QPrivateSignal());
+ emit q->runningChanged(true);
if (stopProcessingReason == Finished) {
// The state machine immediately reached a final state.
@@ -1416,6 +1429,7 @@ void QStateMachinePrivate::_q_start()
state = NotRunning;
unregisterAllTransitions();
emitFinished();
+ emit q->runningChanged(false);
} else {
_q_process();
}
@@ -1498,12 +1512,14 @@ void QStateMachinePrivate::_q_process()
cancelAllDelayedEvents();
unregisterAllTransitions();
emitFinished();
+ emit q->runningChanged(false);
break;
case Stopped:
state = NotRunning;
cancelAllDelayedEvents();
unregisterAllTransitions();
emit q->stopped(QStateMachine::QPrivateSignal());
+ emit q->runningChanged(false);
break;
}
}
@@ -2117,7 +2133,7 @@ bool QStateMachine::isRunning() const
the main application event loop started with QCoreApplication::exec() or
QApplication::exec().
- \sa started(), finished(), stop(), initialState()
+ \sa started(), finished(), stop(), initialState(), setRunning()
*/
void QStateMachine::start()
{
@@ -2145,7 +2161,7 @@ void QStateMachine::start()
Stops this state machine. The state machine will stop processing events and
then emit the stopped() signal.
- \sa stopped(), start()
+ \sa stopped(), start(), setRunning()
*/
void QStateMachine::stop()
{
@@ -2165,6 +2181,19 @@ void QStateMachine::stop()
}
/*!
+ Convenience functions to start/stop this state machine.
+
+ \sa start(), stop(), started(), finished(), stopped()
+*/
+void QStateMachine::setRunning(bool running)
+{
+ if (running)
+ start();
+ else
+ stop();
+}
+
+/*!
\threadsafe
Posts the given \a event of the given \a priority for processing by this
@@ -2712,6 +2741,15 @@ QStateMachine::WrappedEvent::~WrappedEvent()
Returns a clone of the original event.
*/
+/*!
+ \fn QStateMachine::runningChanged(bool running)
+ \since 5.4
+
+ This signal is emitted when the running property is changed.
+
+ \sa QStateMachine::running
+*/
+
QT_END_NAMESPACE
#include "qstatemachine.moc"
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index 9305676bb5..0092c4d0c5 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -62,6 +62,7 @@ class Q_CORE_EXPORT QStateMachine : public QState
Q_OBJECT
Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(QState::RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
#ifndef QT_NO_ANIMATION
Q_PROPERTY(bool animated READ isAnimated WRITE setAnimated)
#endif
@@ -149,6 +150,7 @@ public:
public Q_SLOTS:
void start();
void stop();
+ void setRunning(bool running);
Q_SIGNALS:
void started(
@@ -161,6 +163,8 @@ Q_SIGNALS:
QPrivateSignal
#endif
);
+ void runningChanged(bool running);
+
protected:
void onEntry(QEvent *event);
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index aeed199c97..3546becd77 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -294,9 +294,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndAnd on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand), &tmp))
return tmp;
}
}
@@ -327,9 +327,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndOr on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand), &tmp))
return tmp;
}
}
@@ -360,9 +360,9 @@ template <typename BaseClass> struct QGenericAtomicOps
T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndXor on top of testAndSet
+ T tmp = BaseClass::load(_q_value);
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
- if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand)))
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand), &tmp))
return tmp;
}
}
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index e2951b125f..aec553113b 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -65,11 +65,6 @@
#include <algorithm>
-
-#ifdef Q_OS_WINRT
-#include <thread>
-#endif
-
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
@@ -138,6 +133,10 @@ private:
#ifndef QT_NO_THREAD
+#ifdef Q_OS_WINRT
+namespace ABI { namespace Windows { namespace Foundation { struct IAsyncAction; } } }
+#endif
+
class QThreadPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QThread)
@@ -174,19 +173,23 @@ public:
#endif // Q_OS_UNIX
#ifdef Q_OS_WIN
+# ifndef Q_OS_WINRT
static unsigned int __stdcall start(void *);
static void finish(void *, bool lockAnyway=true);
+# else
+ HRESULT start(ABI::Windows::Foundation::IAsyncAction *);
+ void finish(bool lockAnyway = true);
+# endif
# ifndef Q_OS_WINRT
Qt::HANDLE handle;
- unsigned int id;
# else
- std::thread *handle;
- std::thread::id id;
+ ABI::Windows::Foundation::IAsyncAction *handle;
# endif
+ unsigned int id;
int waiters;
bool terminationEnabled, terminatePending;
-# endif
+#endif // Q_OS_WIN
QThreadData *data;
static void createEventDispatcher(QThreadData *data);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index bdc3463b9f..e950a02162 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,7 +40,7 @@
****************************************************************************/
//#define WINVER 0x0500
-#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT)
+#if (_WIN32_WINNT < 0x0400)
#define _WIN32_WINNT 0x0400
#endif
@@ -54,19 +54,10 @@
#include <qpointer.h>
#include <private/qcoreapplication_p.h>
-#ifdef Q_OS_WINRT
-#include <private/qeventdispatcher_winrt_p.h>
-#else
#include <private/qeventdispatcher_win_p.h>
-#endif
#include <qt_windows.h>
-#ifdef Q_OS_WINRT
-#include <qelapsedtimer.h>
-#include <thread>
-#endif
-
#ifndef Q_OS_WINCE
#ifndef _MT
#define _MT
@@ -79,7 +70,6 @@
#ifndef QT_NO_THREAD
QT_BEGIN_NAMESPACE
-#ifndef Q_OS_WINRT
void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread);
DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
@@ -101,38 +91,6 @@ static void qt_free_tls()
}
}
Q_DESTRUCTOR_FUNCTION(qt_free_tls)
-#else // !Q_OS_WINRT
-
-__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0;
-void qt_create_tls()
-{
-}
-
-static void qt_free_tls()
-{
- if (qt_current_thread_data_tls_index) {
- qt_current_thread_data_tls_index->deref();
- qt_current_thread_data_tls_index = 0;
- }
-}
-
-QThreadData* TlsGetValue(QThreadData*& tls)
-{
- Q_ASSERT(tls == qt_current_thread_data_tls_index);
- return tls;
-}
-
-void TlsSetValue(QThreadData*& tls, QThreadData* data)
-{
- Q_ASSERT(tls == qt_current_thread_data_tls_index);
- if (tls)
- tls->deref();
- tls = data;
- if (tls)
- tls->ref();
-}
-Q_DESTRUCTOR_FUNCTION(qt_free_tls)
-#endif // Q_OS_WINRT
/*
QThreadData
@@ -165,7 +123,6 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread;
-#ifndef Q_OS_WINRT
// TODO: is there a way to reflect the branch's behavior using
// WinRT API?
} else {
@@ -182,7 +139,6 @@ QThreadData *QThreadData::current(bool createIfNecessary)
realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId());
#endif
qt_watch_adopted_thread(realHandle, threadData->thread);
-#endif // !Q_OS_WINRT
}
}
return threadData;
@@ -190,16 +146,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
void QAdoptedThread::init()
{
-#ifndef Q_OS_WINRT
d_func()->handle = GetCurrentThread();
d_func()->id = GetCurrentThreadId();
-#else
- d_func()->handle = nullptr;
- d_func()->id = std::this_thread::get_id();
-#endif
}
-#ifndef Q_OS_WINRT
static QVector<HANDLE> qt_adopted_thread_handles;
static QVector<QThread *> qt_adopted_qthreads;
static QMutex qt_adopted_thread_watcher_mutex;
@@ -352,7 +302,6 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
}
}
#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE
-#endif // !Q_OS_WINRT
/**************************************************************************
** QThreadPrivate
@@ -362,11 +311,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
void QThreadPrivate::createEventDispatcher(QThreadData *data)
{
-#ifdef Q_OS_WINRT
- QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT;
-#else
QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32;
-#endif
data->eventDispatcher.storeRelease(theEventDispatcher);
theEventDispatcher->startingUp();
}
@@ -394,7 +339,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
else
createEventDispatcher(data);
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1,
@@ -440,21 +385,11 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
d->interruptionRequested = false;
if (!d->waiters) {
-#ifndef Q_OS_WINRT
CloseHandle(d->handle);
-#else
- d->handle->detach();
- delete d->handle;
-#endif
d->handle = 0;
}
-#ifndef Q_OS_WINRT
d->id = 0;
-#else
- d->id = std::thread::id();
-#endif
-
}
/**************************************************************************
@@ -469,15 +404,10 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
int QThread::idealThreadCount() Q_DECL_NOTHROW
{
SYSTEM_INFO sysinfo;
-#ifndef Q_OS_WINRT
GetSystemInfo(&sysinfo);
-#else
- GetNativeSystemInfo(&sysinfo);
-#endif
return sysinfo.dwNumberOfProcessors;
}
-#ifndef Q_OS_WINRT
void QThread::yieldCurrentThread()
{
#ifndef Q_OS_WINCE
@@ -501,28 +431,6 @@ void QThread::usleep(unsigned long usecs)
{
::Sleep((usecs / 1000) + 1);
}
-#else // !Q_OS_WINRT
-
-void QThread::yieldCurrentThread()
-{
- msleep(1);
-}
-
-void QThread::sleep(unsigned long secs)
-{
- msleep(secs * 1000);
-}
-
-void QThread::msleep(unsigned long msecs)
-{
- WaitForSingleObjectEx(GetCurrentThread(), msecs, FALSE);
-}
-
-void QThread::usleep(unsigned long usecs)
-{
- msleep((usecs / 1000) + 1);
-}
-#endif // Q_OS_WINRT
void QThread::start(Priority priority)
{
@@ -544,7 +452,6 @@ void QThread::start(Priority priority)
d->returnCode = 0;
d->interruptionRequested = false;
-#ifndef Q_OS_WINRT
/*
NOTE: we create the thread in the suspended state, set the
priority and then resume the thread.
@@ -609,23 +516,6 @@ void QThread::start(Priority priority)
if (ResumeThread(d->handle) == (DWORD) -1) {
qErrnoWarning("QThread::start: Failed to resume new thread");
}
-#else // !Q_OS_WINRT
- d->handle = new std::thread(QThreadPrivate::start, this);
-
- if (!d->handle) {
- qErrnoWarning(errno, "QThread::start: Failed to create thread");
- d->running = false;
- d->finished = true;
- return;
- }
-
- d->id = d->handle->get_id();
-
- if (priority != NormalPriority || priority != InheritPriority) {
- qWarning("QThread::start: Failed to set thread priority (not implemented)");
- d->priority = NormalPriority;
- }
-#endif // Q_OS_WINRT
}
void QThread::terminate()
@@ -639,11 +529,7 @@ void QThread::terminate()
return;
}
-#ifndef Q_OS_WINRT
TerminateThread(d->handle, 0);
-#else // !Q_OS_WINRT
- qWarning("QThread::terminate: Terminate is not supported on WinRT");
-#endif // Q_OS_WINRT
QThreadPrivate::finish(this, false);
}
@@ -652,11 +538,7 @@ bool QThread::wait(unsigned long time)
Q_D(QThread);
QMutexLocker locker(&d->mutex);
-#ifndef Q_OS_WINRT
if (d->id == GetCurrentThreadId()) {
-#else
- if (d->id == std::this_thread::get_id()) {
-#endif
qWarning("QThread::wait: Thread tried to wait on itself");
return false;
}
@@ -667,7 +549,6 @@ bool QThread::wait(unsigned long time)
locker.mutex()->unlock();
bool ret = false;
-#ifndef Q_OS_WINRT
switch (WaitForSingleObject(d->handle, time)) {
case WAIT_OBJECT_0:
ret = true;
@@ -680,14 +561,6 @@ bool QThread::wait(unsigned long time)
default:
break;
}
-#else // !Q_OS_WINRT
- if (!d->finished) {
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < time && !d->finished)
- yieldCurrentThread();
- }
-#endif // Q_OS_WINRT
locker.mutex()->lock();
--d->waiters;
@@ -699,12 +572,7 @@ bool QThread::wait(unsigned long time)
}
if (d->finished && !d->waiters) {
-#ifndef Q_OS_WINRT
CloseHandle(d->handle);
-#else
- d->handle->detach();
- delete d->handle;
-#endif
d->handle = 0;
}
@@ -722,16 +590,13 @@ void QThread::setTerminationEnabled(bool enabled)
if (enabled && d->terminatePending) {
QThreadPrivate::finish(thr, false);
locker.unlock(); // don't leave the mutex locked!
-#ifndef Q_OS_WINRT
_endthreadex(0);
-#endif
}
}
// Caller must hold the mutex
void QThreadPrivate::setPriority(QThread::Priority threadPriority)
{
-#ifndef Q_OS_WINRT
// copied from start() with a few modifications:
int prio;
@@ -774,12 +639,6 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
if (!SetThreadPriority(handle, prio)) {
qErrnoWarning("QThread::setPriority: Failed to set thread priority");
}
-#else // !Q_OS_WINRT
- if (priority != threadPriority) {
- qWarning("QThread::setPriority: Failed to set thread priority (not implemented)");
- return;
- }
-#endif // Q_OS_WINRT
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_winrt.cpp b/src/corelib/thread/qthread_winrt.cpp
new file mode 100644
index 0000000000..85860dc545
--- /dev/null
+++ b/src/corelib/thread/qthread_winrt.cpp
@@ -0,0 +1,458 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthread.h"
+#include "qthread_p.h"
+#include "qthreadstorage.h"
+
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QUuid>
+#include <QtCore/qt_windows.h>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qcoreapplication_p.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#include <wrl.h>
+#include <windows.system.threading.h>
+#include <windows.system.threading.core.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+using namespace ABI::Windows::System::Threading::Core;
+
+#ifndef QT_NO_THREAD
+QT_BEGIN_NAMESPACE
+
+static WorkItemPriority nativePriority(QThread::Priority priority)
+{
+ switch (priority) {
+ default:
+ case QThread::NormalPriority:
+ return WorkItemPriority_Normal;
+ case QThread::IdlePriority:
+ case QThread::LowestPriority:
+ case QThread::LowPriority:
+ return WorkItemPriority_Low;
+ case QThread::HighPriority:
+ case QThread::HighestPriority:
+ case QThread::TimeCriticalPriority:
+ return WorkItemPriority_High;
+ }
+}
+
+class QWinRTThreadGlobal
+{
+public:
+ QWinRTThreadGlobal()
+ {
+ HRESULT hr;
+
+ hr = RoGetActivationFactory(
+ HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_PreallocatedWorkItem).Get(),
+ IID_PPV_ARGS(&workItemFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = RoGetActivationFactory(
+ HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_SignalNotifier).Get(),
+ IID_PPV_ARGS(&notifierFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ QString eventName = QUuid::createUuid().toString();
+ dispatchEvent = CreateEventEx(NULL, reinterpret_cast<LPCWSTR>(eventName.utf16()), 0, EVENT_ALL_ACCESS);
+
+ hr = notifierFactory->AttachToEvent(
+ HStringReference(reinterpret_cast<LPCWSTR>(eventName.utf16())).Get(),
+ Callback<ISignalHandler>(this, &QWinRTThreadGlobal::dispatch).Get(), &notifier);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = notifier->Enable();
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ~QWinRTThreadGlobal()
+ {
+ CloseHandle(dispatchEvent);
+ }
+
+ void dispatch()
+ {
+ SetEvent(dispatchEvent);
+ }
+
+ void push(QThreadPrivate *d)
+ {
+ threads.append(d);
+ }
+
+private:
+ HRESULT dispatch(ISignalNotifier *notifier, boolean timedOut)
+ {
+ Q_UNUSED(timedOut);
+ notifier->Enable();
+ if (threads.isEmpty())
+ return S_OK;
+
+ QThreadPrivate *thread = threads.takeFirst();
+ ComPtr<IPreallocatedWorkItem> workItem;
+ HRESULT hr = workItemFactory->CreateWorkItemWithPriority(
+ Callback<IWorkItemHandler>(thread, &QThreadPrivate::start).Get(),
+ nativePriority(thread->priority), &workItem);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to create thread work item");
+ thread->finish();
+ return hr;
+ }
+
+ hr = workItem->RunAsync(&thread->handle);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to run work item");
+ thread->finish();
+ return hr;
+ }
+
+ return S_OK;
+ }
+
+ HANDLE dispatchEvent;
+ ComPtr<ISignalNotifier> notifier;
+ ComPtr<ISignalNotifierStatics> notifierFactory;
+ ComPtr<IPreallocatedWorkItemFactory> workItemFactory;
+
+ QList<QThreadPrivate *> threads;
+};
+Q_GLOBAL_STATIC(QWinRTThreadGlobal, g)
+
+/**************************************************************************
+ ** QThreadData
+ *************************************************************************/
+
+__declspec(thread) static QThreadData *qt_current_thread_data = 0;
+
+void QThreadData::clearCurrentThreadData()
+{
+ qt_current_thread_data = 0;
+}
+
+QThreadData *QThreadData::current(bool createIfNecessary)
+{
+ static bool winmainThread = true;
+ QThreadData *threadData = qt_current_thread_data;
+ if (!threadData && createIfNecessary) {
+ threadData = new QThreadData;
+ // This needs to be called prior to new AdoptedThread() to
+ // avoid recursion.
+ qt_current_thread_data = threadData;
+ QT_TRY {
+ threadData->thread = new QAdoptedThread(threadData);
+ } QT_CATCH(...) {
+ qt_current_thread_data = 0;
+ threadData->deref();
+ threadData = 0;
+ QT_RETHROW;
+ }
+ threadData->deref();
+ threadData->isAdopted = true;
+ threadData->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+
+ if (!QCoreApplicationPrivate::theMainThread && !winmainThread)
+ QCoreApplicationPrivate::theMainThread = threadData->thread;
+
+ if (winmainThread) {
+ g->dispatch();
+ threadData->thread->d_func()->createEventDispatcher(threadData);
+ winmainThread = false;
+ }
+ }
+
+ return threadData;
+}
+
+void QAdoptedThread::init()
+{
+ Q_D(QThread);
+
+ d->handle = Q_NULLPTR;
+ d->id = 0;
+}
+
+/**************************************************************************
+ ** QThreadPrivate
+ *************************************************************************/
+
+#endif // QT_NO_THREAD
+
+void QThreadPrivate::createEventDispatcher(QThreadData *data)
+{
+ QEventDispatcherWinRT *eventDispatcher = new QEventDispatcherWinRT;
+ data->eventDispatcher.storeRelease(eventDispatcher);
+ eventDispatcher->startingUp();
+}
+
+#ifndef QT_NO_THREAD
+
+HRESULT QThreadPrivate::start(IAsyncAction *)
+{
+ Q_Q(QThread);
+
+ qt_current_thread_data = data;
+ id = GetCurrentThreadId();
+ data->threadId = reinterpret_cast<Qt::HANDLE>(id);
+ QThread::setTerminationEnabled(false);
+
+ {
+ QMutexLocker locker(&mutex);
+ data->quitNow = exited;
+ }
+
+ if (data->eventDispatcher.load())
+ data->eventDispatcher.load()->startingUp();
+ else
+ createEventDispatcher(data);
+
+ running = true;
+ emit q->started(QThread::QPrivateSignal());
+
+ QThread::setTerminationEnabled(true);
+
+ q->run();
+
+ finish();
+
+ return S_OK;
+}
+
+void QThreadPrivate::finish(bool lockAnyway)
+{
+ Q_Q(QThread);
+
+ QMutexLocker locker(lockAnyway ? &mutex : 0);
+ isInFinish = true;
+ priority = QThread::InheritPriority;
+ void **tls_data = reinterpret_cast<void **>(&data->tls);
+ locker.unlock();
+ emit q->finished(QThread::QPrivateSignal());
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish(tls_data);
+ locker.relock();
+
+ QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load();
+ if (eventDispatcher) {
+ data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ running = false;
+ finished = true;
+ isInFinish = false;
+ interruptionRequested = false;
+
+ if (!waiters) {
+ if (handle)
+ handle->Release();
+ handle = Q_NULLPTR;
+ }
+
+ id = 0;
+}
+
+/**************************************************************************
+ ** QThread
+ *************************************************************************/
+
+Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+{
+ return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+}
+
+int QThread::idealThreadCount() Q_DECL_NOTHROW
+{
+ SYSTEM_INFO sysinfo;
+ GetNativeSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+}
+
+void QThread::yieldCurrentThread()
+{
+ msleep(1);
+}
+
+void QThread::sleep(unsigned long secs)
+{
+ msleep(secs * 1000);
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ WaitForSingleObjectEx(GetCurrentThread(), msecs, FALSE);
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ msleep((usecs / 1000) + 1);
+}
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->isInFinish) {
+ locker.unlock();
+ wait();
+ locker.relock();
+ }
+
+ if (d->running)
+ return;
+
+ d->finished = false;
+ d->exited = false;
+ d->returnCode = 0;
+ d->interruptionRequested = false;
+ d->priority = priority == QThread::InheritPriority ? currentThread()->priority() : priority;
+ g->push(d);
+ g->dispatch();
+
+ locker.unlock();
+ while (!d->running && !d->finished) {
+ QAbstractEventDispatcher *eventDispatcher = QThread::currentThread()->eventDispatcher();
+ if (eventDispatcher)
+ eventDispatcher->processEvents(QEventLoop::AllEvents);
+ else
+ yieldCurrentThread();
+ }
+}
+
+void QThread::terminate()
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+ if (!d->running)
+ return;
+ if (!d->terminationEnabled) {
+ d->terminatePending = true;
+ return;
+ }
+
+ if (d->handle) {
+ ComPtr<IAsyncInfo> info;
+ HRESULT hr = d->handle->QueryInterface(IID_PPV_ARGS(&info));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = info->Cancel();
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to cancel thread action");
+ }
+
+ d->finish(false);
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_D(QThread);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->id == GetCurrentThreadId()) {
+ qWarning("QThread::wait: Thread tried to wait on itself");
+ return false;
+ }
+ if (d->finished || !d->running)
+ return true;
+
+ ++d->waiters;
+ locker.mutex()->unlock();
+
+ // Alternatively, we could check the handle
+ bool ret = false;
+ if (!d->finished) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < time && !d->finished)
+ yieldCurrentThread();
+
+ ret = d->finished;
+ }
+
+ locker.mutex()->lock();
+ --d->waiters;
+
+ if (ret && !d->finished) {
+ // thread was terminated by someone else
+
+ d->finish(false);
+ }
+
+ if (d->finished && !d->waiters) {
+ if (d->handle)
+ d->handle->Release();
+ d->handle = Q_NULLPTR;
+ }
+
+ return ret;
+}
+
+void QThread::setTerminationEnabled(bool enabled)
+{
+ QThread *thr = currentThread();
+ Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
+ "Current thread was not started with QThread.");
+ QThreadPrivate *d = thr->d_func();
+ QMutexLocker locker(&d->mutex);
+ d->terminationEnabled = enabled;
+ if (enabled && d->terminatePending) {
+ d->finish(false);
+ locker.unlock(); // don't leave the mutex locked!
+ }
+}
+
+// Caller must hold the mutex
+void QThreadPrivate::setPriority(QThread::Priority threadPriority)
+{
+ if (running)
+ qWarning("WinRT threads can't change priority while running.");
+
+ priority = threadPriority;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 3c1ddd984a..2e027c8e21 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -50,6 +50,11 @@ win32:SOURCES += thread/qmutex_win.cpp \
thread/qthread_win.cpp \
thread/qwaitcondition_win.cpp
+winrt {
+ SOURCES -= thread/qthread_win.cpp
+ SOURCES += thread/qthread_winrt.cpp
+}
+
integrity:SOURCES += thread/qmutex_unix.cpp \
thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 12736d5c2e..4047bf611f 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -68,7 +68,7 @@ static const QArrayData &qt_array_empty = qt_array[0];
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options)
+ size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -114,7 +114,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
- size_t alignment)
+ size_t alignment) Q_DECL_NOTHROW
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -130,4 +130,33 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize,
::free(data);
}
+namespace QtPrivate {
+/*!
+ \internal
+*/
+QContainerImplHelper::CutResult QContainerImplHelper::mid(int originalLength, int *_position, int *_length)
+{
+ int &position = *_position;
+ int &length = *_length;
+ if (position > originalLength)
+ return Null;
+
+ if (position < 0) {
+ if (length < 0 || length + position >= originalLength)
+ return Full;
+ if (length + position <= 0)
+ return Null;
+ length += position;
+ position = 0;
+ } else if (uint(length) > uint(originalLength - position)) {
+ length = originalLength - position;
+ }
+
+ if (position == 0 && length == originalLength)
+ return Full;
+
+ return length > 0 ? Subset : Empty;
+}
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 10a9e35542..dd2b777ed7 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -101,10 +101,6 @@ struct Q_CORE_EXPORT QArrayData
AllocationOptions detachFlags() const
{
AllocationOptions result;
-#if QT_SUPPORTS(UNSHARABLE_CONTAINERS)
- if (!ref.isSharable())
- result |= Unsharable;
-#endif
if (capacityReserved)
result |= CapacityReserved;
return result;
@@ -120,9 +116,9 @@ struct Q_CORE_EXPORT QArrayData
static QArrayData *allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options = Default)
- Q_REQUIRED_RESULT;
+ Q_DECL_NOTHROW Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
- size_t alignment);
+ size_t alignment) Q_DECL_NOTHROW;
static const QArrayData shared_null[2];
static QArrayData *sharedNull() { return const_cast<QArrayData*>(shared_null); }
@@ -361,6 +357,14 @@ namespace QtPrivate {
QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
#endif // !defined(Q_ARRAY_LITERAL)
+namespace QtPrivate {
+struct Q_CORE_EXPORT QContainerImplHelper
+{
+ enum CutResult { Null, Empty, Full, Subset };
+ static CutResult mid(int originalLength, int *position, int *length);
+};
+}
+
QT_END_NAMESPACE
#endif // include guard
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index b94c6b50ea..c7ea6ebf86 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -57,6 +57,7 @@ struct QPodArrayOps
{
void appendInitialize(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize > uint(this->size));
Q_ASSERT(newSize <= this->alloc);
@@ -67,6 +68,7 @@ struct QPodArrayOps
void copyAppend(const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(b < e);
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
@@ -77,6 +79,7 @@ struct QPodArrayOps
void copyAppend(size_t n, const T &t)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(n <= this->alloc - uint(this->size));
@@ -89,6 +92,7 @@ struct QPodArrayOps
void truncate(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize < size_t(this->size));
@@ -97,6 +101,7 @@ struct QPodArrayOps
void destroyAll() // Call from destructors, ONLY!
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(this->ref.atomic.load() == 0);
// As this is to be called only from destructor, it doesn't need to be
@@ -105,6 +110,7 @@ struct QPodArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -118,6 +124,7 @@ struct QPodArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
@@ -133,6 +140,7 @@ struct QGenericArrayOps
{
void appendInitialize(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize > uint(this->size));
Q_ASSERT(newSize <= this->alloc);
@@ -145,6 +153,7 @@ struct QGenericArrayOps
void copyAppend(const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(b < e);
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
@@ -158,6 +167,7 @@ struct QGenericArrayOps
void copyAppend(size_t n, const T &t)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(n <= this->alloc - uint(this->size));
@@ -171,6 +181,7 @@ struct QGenericArrayOps
void truncate(size_t newSize)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(newSize < size_t(this->size));
@@ -182,6 +193,7 @@ struct QGenericArrayOps
void destroyAll() // Call from destructors, ONLY
{
+ Q_ASSERT(this->isMutable());
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -196,6 +208,7 @@ struct QGenericArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -261,6 +274,7 @@ struct QGenericArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
@@ -290,6 +304,7 @@ struct QMovableArrayOps
void insert(T *where, const T *b, const T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(!this->ref.isShared());
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
Q_ASSERT(b < e);
@@ -354,6 +369,7 @@ struct QMovableArrayOps
void erase(T *b, T *e)
{
+ Q_ASSERT(this->isMutable());
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index fb92d82f07..10fc3dea2d 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -48,6 +48,7 @@
#include "qlocale_p.h"
#include "qscopedpointer.h"
#include <qdatastream.h>
+#include <qmath.h>
#ifndef QT_NO_COMPRESS
#include <zlib.h>
@@ -67,24 +68,12 @@ int qFindByteArray(
const char *needle0, int needleLen);
-int qAllocMore(int alloc, int extra)
+int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
{
Q_ASSERT(alloc >= 0 && extra >= 0);
Q_ASSERT_X(alloc < (1 << 30) - extra, "qAllocMore", "Requested size is too large!");
- unsigned nalloc = alloc + extra;
-
- // Round up to next power of 2
-
- // Assuming container is growing, always overshoot
- //--nalloc;
-
- nalloc |= nalloc >> 1;
- nalloc |= nalloc >> 2;
- nalloc |= nalloc >> 4;
- nalloc |= nalloc >> 8;
- nalloc |= nalloc >> 16;
- ++nalloc;
+ unsigned nalloc = qNextPowerOfTwo(alloc + extra);
Q_ASSERT(nalloc > unsigned(alloc + extra));
@@ -2677,19 +2666,22 @@ QByteArray QByteArray::right(int len) const
QByteArray QByteArray::mid(int pos, int len) const
{
- if ((d->size == 0 && d->ref.isStatic()) || pos > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &pos, &len)) {
+ case QContainerImplHelper::Null:
return QByteArray();
- if (len < 0)
- len = d->size - pos;
- if (pos < 0) {
- len += pos;
- pos = 0;
+ case QContainerImplHelper::Empty:
+ {
+ QByteArrayDataPtr empty = { Data::allocate(0) };
+ return QByteArray(empty);
}
- if (len + pos > d->size)
- len = d->size - pos;
- if (pos == 0 && len == d->size)
+ case QContainerImplHelper::Full:
return *this;
- return QByteArray(d->data() + pos, len);
+ case QContainerImplHelper::Subset:
+ return QByteArray(d->data() + pos, len);
+ }
+ Q_UNREACHABLE();
+ return QByteArray();
}
/*!
@@ -2705,8 +2697,9 @@ QByteArray QByteArray::toLower() const
{
QByteArray s(*this);
uchar *p = reinterpret_cast<uchar *>(s.data());
+ uchar *e = reinterpret_cast<uchar *>(s.end());
if (p) {
- while (*p) {
+ while (p != e) {
*p = QChar::toLower((ushort)*p);
p++;
}
@@ -2728,8 +2721,9 @@ QByteArray QByteArray::toUpper() const
{
QByteArray s(*this);
uchar *p = reinterpret_cast<uchar *>(s.data());
+ uchar *e = reinterpret_cast<uchar *>(s.end());
if (p) {
- while (*p) {
+ while (p != e) {
*p = QChar::toUpper((ushort)*p);
p++;
}
@@ -3119,7 +3113,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
replaced with a single space.
Whitespace means any character for which the standard C++
- isspace() function returns \c true. This includes the ASCII
+ isspace() function returns \c true in the C locale. This includes the ASCII
characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
Example:
@@ -3137,9 +3131,9 @@ QByteArray QByteArray::simplified() const
int outc=0;
char *to = result.d->data();
for (;;) {
- while (from!=fromend && isspace(uchar(*from)))
+ while (from!=fromend && ascii_isspace(uchar(*from)))
from++;
- while (from!=fromend && !isspace(uchar(*from)))
+ while (from!=fromend && !ascii_isspace(uchar(*from)))
to[outc++] = *from++;
if (from!=fromend)
to[outc++] = ' ';
@@ -3157,7 +3151,7 @@ QByteArray QByteArray::simplified() const
and the end.
Whitespace means any character for which the standard C++
- isspace() function returns \c true. This includes the ASCII
+ isspace() function returns \c true in the C locale. This includes the ASCII
characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '.
Example:
@@ -3172,14 +3166,14 @@ QByteArray QByteArray::trimmed() const
if (d->size == 0)
return *this;
const char *s = d->data();
- if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
+ if (!ascii_isspace(uchar(*s)) && !ascii_isspace(uchar(s[d->size-1])))
return *this;
int start = 0;
int end = d->size - 1;
- while (start<=end && isspace(uchar(s[start]))) // skip white space from start
+ while (start<=end && ascii_isspace(uchar(s[start]))) // skip white space from start
start++;
if (start <= end) { // only white space
- while (end && isspace(uchar(s[end]))) // skip white space from end
+ while (end && ascii_isspace(uchar(s[end]))) // skip white space from end
end--;
}
int l = end - start + 1;
@@ -4186,6 +4180,27 @@ QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent
return tmp;
}
+/*! \fn QByteArray QByteArray::fromStdString(const std::string &str)
+ \since 5.4
+
+ Returns a copy of the \a str string as a QByteArray.
+
+ \sa toStdString(), QString::fromStdString()
+*/
+
+/*!
+ \fn std::string QByteArray::toStdString() const
+ \since 5.4
+
+ Returns a std::string object with the data contained in this
+ QByteArray.
+
+ This operator is mostly useful to pass a QByteArray to a function
+ that accepts a std::string object.
+
+ \sa fromStdString(), QString::toStdString()
+*/
+
/*! \fn QByteArray QByteArray::fromCFData(CFDataRef data)
\since 5.3
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 0a2f7a9e53..b5af305233 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -50,6 +50,8 @@
#include <string.h>
#include <stdarg.h>
+#include <string>
+
#ifdef truncate
#error qbytearray.h must be included before any header file that defines truncate
#endif
@@ -247,9 +249,9 @@ public:
int count(const char *a) const;
int count(const QByteArray &a) const;
- QByteArray left(int len) const;
- QByteArray right(int len) const;
- QByteArray mid(int index, int len = -1) const;
+ QByteArray left(int len) const Q_REQUIRED_RESULT;
+ QByteArray right(int len) const Q_REQUIRED_RESULT;
+ QByteArray mid(int index, int len = -1) const Q_REQUIRED_RESULT;
bool startsWith(const QByteArray &a) const;
bool startsWith(char c) const;
@@ -262,13 +264,13 @@ public:
void truncate(int pos);
void chop(int n);
- QByteArray toLower() const;
- QByteArray toUpper() const;
+ QByteArray toLower() const Q_REQUIRED_RESULT;
+ QByteArray toUpper() const Q_REQUIRED_RESULT;
- QByteArray trimmed() const;
- QByteArray simplified() const;
- QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const;
- QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
+ QByteArray trimmed() const Q_REQUIRED_RESULT;
+ QByteArray simplified() const Q_REQUIRED_RESULT;
+ QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT;
+ QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT;
QByteArray &prepend(char c);
QByteArray &prepend(const char *s);
@@ -300,7 +302,7 @@ public:
QList<QByteArray> split(char sep) const;
- QByteArray repeated(int times) const;
+ QByteArray repeated(int times) const Q_REQUIRED_RESULT;
#ifndef QT_NO_CAST_TO_ASCII
QT_ASCII_CAST_WARN QByteArray &append(const QString &s);
@@ -349,16 +351,16 @@ public:
QByteArray &setNum(double, char f = 'g', int prec = 6);
QByteArray &setRawData(const char *a, uint n); // ### Qt 6: use an int
- static QByteArray number(int, int base = 10);
- static QByteArray number(uint, int base = 10);
- static QByteArray number(qlonglong, int base = 10);
- static QByteArray number(qulonglong, int base = 10);
- static QByteArray number(double, char f = 'g', int prec = 6);
- static QByteArray fromRawData(const char *, int size);
- static QByteArray fromBase64(const QByteArray &base64, Base64Options options);
- static QByteArray fromBase64(const QByteArray &base64); // ### Qt6 merge with previous
- static QByteArray fromHex(const QByteArray &hexEncoded);
- static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%');
+ static QByteArray number(int, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(uint, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(qlonglong, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(qulonglong, int base = 10) Q_REQUIRED_RESULT;
+ static QByteArray number(double, char f = 'g', int prec = 6) Q_REQUIRED_RESULT;
+ static QByteArray fromRawData(const char *, int size) Q_REQUIRED_RESULT;
+ static QByteArray fromBase64(const QByteArray &base64, Base64Options options) Q_REQUIRED_RESULT;
+ static QByteArray fromBase64(const QByteArray &base64) Q_REQUIRED_RESULT; // ### Qt6 merge with previous
+ static QByteArray fromHex(const QByteArray &hexEncoded) Q_REQUIRED_RESULT;
+ static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%') Q_REQUIRED_RESULT;
#if defined(Q_OS_MAC) || defined(Q_QDOC)
static QByteArray fromCFData(CFDataRef data);
@@ -397,6 +399,9 @@ public:
void push_front(const char *c);
void push_front(const QByteArray &a);
+ static inline QByteArray fromStdString(const std::string &s);
+ inline std::string toStdString() const;
+
inline int count() const { return d->size; }
int length() const { return d->size; }
bool isNull() const;
@@ -620,6 +625,11 @@ inline QByteArray &QByteArray::setNum(uint n, int base)
inline QByteArray &QByteArray::setNum(float n, char f, int prec)
{ return setNum(double(n),f,prec); }
+inline std::string QByteArray::toStdString() const
+{ return std::string(constData(), length()); }
+
+inline QByteArray QByteArray::fromStdString(const std::string &s)
+{ return QByteArray(s.data(), int(s.size())); }
#if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE))
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index eb59cc719f..656e57391f 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -1398,7 +1398,7 @@ QChar::UnicodeVersion QChar::currentUnicodeVersion()
template <typename T>
-static inline T toLowerCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toLowerCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->lowerCaseSpecial) {
@@ -1409,7 +1409,7 @@ static inline T toLowerCase_helper(T uc)
}
template <typename T>
-static inline T toUpperCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toUpperCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->upperCaseSpecial) {
@@ -1420,7 +1420,7 @@ static inline T toUpperCase_helper(T uc)
}
template <typename T>
-static inline T toTitleCase_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toTitleCase_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->titleCaseSpecial) {
@@ -1431,7 +1431,7 @@ static inline T toTitleCase_helper(T uc)
}
template <typename T>
-static inline T toCaseFolded_helper(T uc)
+Q_DECL_CONST_FUNCTION static inline T toCaseFolded_helper(T uc)
{
const QUnicodeTables::Properties *p = qGetProp(uc);
if (p->caseFoldSpecial) {
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 24c757f9f4..5dfd7b30f9 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -388,7 +388,7 @@ public:
QT_DEPRECATED inline char toAscii() const { return toLatin1(); }
#endif
inline char toLatin1() const;
- inline ushort unicode() const { return ucs; }
+ Q_DECL_CONSTEXPR inline ushort unicode() const { return ucs; }
inline ushort &unicode() { return ucs; }
#if QT_DEPRECATED_SINCE(5, 0)
@@ -450,50 +450,50 @@ public:
return ushort(ucs4%0x400 + 0xdc00);
}
- static Category QT_FASTCALL category(uint ucs4);
- static Direction QT_FASTCALL direction(uint ucs4);
- static JoiningType QT_FASTCALL joiningType(uint ucs4);
+ static Category QT_FASTCALL category(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static Direction QT_FASTCALL direction(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static JoiningType QT_FASTCALL joiningType(uint ucs4) Q_DECL_CONST_FUNCTION;
#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4);
+ QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) Q_DECL_CONST_FUNCTION;
#endif
- static unsigned char QT_FASTCALL combiningClass(uint ucs4);
+ static unsigned char QT_FASTCALL combiningClass(uint ucs4) Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL mirroredChar(uint ucs4);
- static bool QT_FASTCALL hasMirrored(uint ucs4);
+ static uint QT_FASTCALL mirroredChar(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL hasMirrored(uint ucs4) Q_DECL_CONST_FUNCTION;
static QString QT_FASTCALL decomposition(uint ucs4);
- static Decomposition QT_FASTCALL decompositionTag(uint ucs4);
+ static Decomposition QT_FASTCALL decompositionTag(uint ucs4) Q_DECL_CONST_FUNCTION;
- static int QT_FASTCALL digitValue(uint ucs4);
- static uint QT_FASTCALL toLower(uint ucs4);
- static uint QT_FASTCALL toUpper(uint ucs4);
- static uint QT_FASTCALL toTitleCase(uint ucs4);
- static uint QT_FASTCALL toCaseFolded(uint ucs4);
+ static int QT_FASTCALL digitValue(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toLower(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toUpper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toCaseFolded(uint ucs4) Q_DECL_CONST_FUNCTION;
- static Script QT_FASTCALL script(uint ucs4);
+ static Script QT_FASTCALL script(uint ucs4) Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4);
+ static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL currentUnicodeVersion();
+ static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPrint(uint ucs4);
- static inline bool isSpace(uint ucs4);
- static bool QT_FASTCALL isMark(uint ucs4);
- static bool QT_FASTCALL isPunct(uint ucs4);
- static bool QT_FASTCALL isSymbol(uint ucs4);
- static inline bool isLetter(uint ucs4);
- static inline bool isNumber(uint ucs4);
- static inline bool isLetterOrNumber(uint ucs4);
- static inline bool isDigit(uint ucs4);
- static inline bool isLower(uint ucs4);
- static inline bool isUpper(uint ucs4);
- static inline bool isTitleCase(uint ucs4);
+ static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isSpace(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isMark(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isPunct(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isSymbol(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLetter(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isNumber(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLetterOrNumber(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isDigit(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isLower(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isUpper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static inline bool isTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION;
private:
- static bool QT_FASTCALL isSpace_helper(uint ucs4);
- static bool QT_FASTCALL isLetter_helper(uint ucs4);
- static bool QT_FASTCALL isNumber_helper(uint ucs4);
- static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4);
+ static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetter_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION;
#ifdef QT_NO_CAST_FROM_ASCII
QChar(char c);
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 505ab5f46d..168701d13c 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -495,10 +495,8 @@ void QCommandLineParser::process(const QStringList &arguments)
::exit(EXIT_FAILURE);
}
- if (d->builtinVersionOption && isSet(QStringLiteral("version"))) {
- printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
- ::exit(EXIT_SUCCESS);
- }
+ if (d->builtinVersionOption && isSet(QStringLiteral("version")))
+ showVersion();
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
showHelp(EXIT_SUCCESS);
@@ -888,6 +886,22 @@ QStringList QCommandLineParser::unknownOptionNames() const
}
/*!
+ Displays the version information from QCoreApplication::applicationVersion(),
+ and exits the application.
+ This is automatically triggered by the --version option, but can also
+ be used to display the version when not using process().
+ The exit code is set to EXIT_SUCCESS (0).
+
+ \sa addVersionOption()
+ \since 5.4
+*/
+Q_NORETURN void QCommandLineParser::showVersion()
+{
+ fprintf(stdout, "%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
+ ::exit(EXIT_SUCCESS);
+}
+
+/*!
Displays the help information, and exits the application.
This is automatically triggered by the --help option, but can also
be used to display the help when the user is not invoking the
diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h
index 5a7061f031..946d4dd238 100644
--- a/src/corelib/tools/qcommandlineparser.h
+++ b/src/corelib/tools/qcommandlineparser.h
@@ -92,6 +92,7 @@ public:
QStringList optionNames() const;
QStringList unknownOptionNames() const;
+ Q_NORETURN void showVersion();
Q_NORETURN void showHelp(int exitCode = 0);
QString helpText() const;
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index d6f1d6c942..3c01edc83e 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -3194,7 +3194,7 @@ QTimeZone QDateTime::timeZone() const
return d->m_timeZone;
case Qt::UTC:
if (!d->m_timeZone.isValid())
- d->m_timeZone = QTimeZone("UTC");
+ d->m_timeZone = QTimeZone(QTimeZonePrivate::utcQByteArray());
return d->m_timeZone;
case Qt::TimeZone :
return d->m_timeZone;
@@ -3254,9 +3254,9 @@ QString QDateTime::timeZoneAbbreviation() const
{
switch (d->m_spec) {
case Qt::UTC:
- return QStringLiteral("UTC");
+ return QTimeZonePrivate::utcQString();
case Qt::OffsetFromUTC:
- return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
+ return QTimeZonePrivate::utcQString() + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
case Qt::TimeZone:
#ifndef QT_BOOTSTRAPPED
return d->m_timeZone.d->abbreviation(d->toMSecsSinceEpoch());
@@ -4976,7 +4976,7 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
QDebug operator<<(QDebug dbg, const QDate &date)
{
- dbg.nospace() << "QDate(" << date.toString(QStringLiteral("yyyy-MM-dd")) << ')';
+ dbg.nospace() << "QDate(" << date.toString(Qt::ISODate) << ')';
return dbg.space();
}
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index b9f6995155..ac7296f742 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -94,9 +94,9 @@ QT_DEPRECATED inline bool setYMD(int y, int m, int d)
void getDate(int *year, int *month, int *day);
- QDate addDays(qint64 days) const;
- QDate addMonths(int months) const;
- QDate addYears(int years) const;
+ QDate addDays(qint64 days) const Q_REQUIRED_RESULT;
+ QDate addMonths(int months) const Q_REQUIRED_RESULT;
+ QDate addYears(int years) const Q_REQUIRED_RESULT;
qint64 daysTo(const QDate &) const;
bool operator==(const QDate &other) const { return jd == other.jd; }
@@ -157,9 +157,9 @@ public:
#endif
bool setHMS(int h, int m, int s, int ms = 0);
- QTime addSecs(int secs) const;
+ QTime addSecs(int secs) const Q_REQUIRED_RESULT;
int secsTo(const QTime &) const;
- QTime addMSecs(int ms) const;
+ QTime addMSecs(int ms) const Q_REQUIRED_RESULT;
int msecsTo(const QTime &) const;
bool operator==(const QTime &other) const { return mds == other.mds; }
@@ -251,11 +251,11 @@ public:
QString toString(Qt::DateFormat f = Qt::TextDate) const;
QString toString(const QString &format) const;
#endif
- QDateTime addDays(qint64 days) const;
- QDateTime addMonths(int months) const;
- QDateTime addYears(int years) const;
- QDateTime addSecs(qint64 secs) const;
- QDateTime addMSecs(qint64 msecs) const;
+ QDateTime addDays(qint64 days) const Q_REQUIRED_RESULT;
+ QDateTime addMonths(int months) const Q_REQUIRED_RESULT;
+ QDateTime addYears(int years) const Q_REQUIRED_RESULT;
+ QDateTime addSecs(qint64 secs) const Q_REQUIRED_RESULT;
+ QDateTime addMSecs(qint64 msecs) const Q_REQUIRED_RESULT;
QDateTime toTimeSpec(Qt::TimeSpec spec) const;
inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); }
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index ca946cbd8a..d6d3a3ad3d 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -191,7 +191,7 @@ class QFreeList
Q_DISABLE_COPY(QFreeList)
public:
- inline QFreeList();
+ Q_DECL_CONSTEXPR inline QFreeList();
inline ~QFreeList();
// returns the payload for the given index \a x
@@ -207,7 +207,7 @@ public:
};
template <typename T, typename ConstantsType>
-inline QFreeList<T, ConstantsType>::QFreeList()
+Q_DECL_CONSTEXPR inline QFreeList<T, ConstantsType>::QFreeList()
: _next(ConstantsType::InitialNextValue)
{ }
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 7200ea7993..c9271848ec 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -94,13 +94,14 @@ QT_BEGIN_NAMESPACE
(for instance, gcc 4.4 does that even at -O0).
*/
-#ifdef __SSE4_2__
+#if QT_COMPILER_SUPPORTS_HERE(SSE4_2)
static inline bool hasFastCrc32()
{
- return true;
+ return qCpuHasFeature(SSE4_2);
}
template <typename Char>
+QT_FUNCTION_TARGET(SSE4_2)
static uint crc32(const Char *ptr, size_t len, uint h)
{
// The CRC32 instructions from Nehalem calculate a 32-bit CRC32 checksum
@@ -163,6 +164,11 @@ static inline uint hash(const uchar *p, int len, uint seed) Q_DECL_NOTHROW
return h;
}
+uint qHashBits(const void *p, size_t len, uint seed) Q_DECL_NOTHROW
+{
+ return hash(static_cast<const uchar*>(p), int(len), seed);
+}
+
static inline uint hash(const QChar *p, int len, uint seed) Q_DECL_NOTHROW
{
uint h = seed;
@@ -669,6 +675,25 @@ void QHashData::checkSanity()
Types \c T1 and \c T2 must be supported by qHash().
*/
+/*! \fn uint qHashBits(const void *p, size_t len, uint seed = 0)
+ \relates QHash
+ \since 5.4
+
+ Returns the hash value for the memory block of size \a len pointed
+ to by \a p, using \a seed to seed the calculation.
+
+ Use this function only to implement qHash() for your own custom
+ types. E.g., here's how you could implement a qHash() overload for
+ std::vector<int>:
+
+ \snippet code/src_corelib_tools_qhash.cpp qhashbits
+
+ It bears repeating that the implementation of qHashBits() - like
+ the qHash() overloads offered by Qt - may change at any time. You
+ \b{must not} rely on the fact that qHashBits() will give the same
+ results (for the same inputs) across different Qt versions.
+*/
+
/*! \fn uint qHash(char key, uint seed = 0)
\relates QHash
\since 5.0
@@ -778,7 +803,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
}
#endif
-/*! \fn uint qHash(QChar key, uint seed = 0)
+/*! \fn uint qHash(const QChar key, uint seed = 0)
\relates QHash
\since 5.0
@@ -961,8 +986,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
A QHash's key type has additional requirements other than being an
assignable data type: it must provide operator==(), and there must also be
- a global qHash() function that returns a hash value for an argument of the
- key's type.
+ a qHash() function in the type's namespace that returns a hash value for an
+ argument of the key's type.
The qHash() function computes a numeric value based on a key. It
can use any algorithm imaginable, as long as it always returns
@@ -2127,8 +2152,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
QMultiHash's key and value data types must be \l{assignable data
types}. You cannot, for example, store a QWidget as a value;
instead, store a QWidget *. In addition, QMultiHash's key type
- must provide operator==(), and there must also be a global
- qHash() function that returns a hash value for an argument of the
+ must provide operator==(), and there must also be a qHash() function
+ in the type's namespace that returns a hash value for an argument of the
key's type. See the QHash documentation for details.
\sa QHash, QHashIterator, QMutableHashIterator, QMultiMap
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index f68b02be2c..db2d084035 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -66,44 +66,40 @@ class QString;
class QStringRef;
class QLatin1String;
-inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
-inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;
+
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(ulong) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return (sizeof(ulong) > sizeof(uint))
+ ? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed)
+ : (uint(key & (~0U)) ^ seed);
}
-inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
-inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
{
- if (sizeof(quint64) > sizeof(uint)) {
- return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
- } else {
- return uint(key & (~0U)) ^ seed;
- }
+ return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
}
-inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
-Q_CORE_EXPORT uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
#ifndef Q_OS_DARWIN
-Q_CORE_EXPORT uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
#endif
-inline uint qHash(QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
-Q_CORE_EXPORT uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
@@ -221,17 +217,23 @@ private:
Q_DISABLE_COPY(QHashNode)
};
-template <class Key, class T>
-struct QHashDummyNode
+// Specialize for QHashDummyValue in order to save some memory
+template <class Key>
+struct QHashNode<Key, QHashDummyValue>
{
- QHashNode<Key, T> *next;
+ union {
+ QHashNode *next;
+ QHashDummyValue value;
+ };
const uint h;
const Key key;
- inline QHashDummyNode(const Key &key0, uint hash, QHashNode<Key, T> *n) : next(n), h(hash), key(key0) {}
+ inline QHashNode(const Key &key0, const QHashDummyValue &, uint hash, QHashNode *n)
+ : next(n), h(hash), key(key0) {}
+ inline bool same_key(uint h0, const Key &key0) const { return h0 == h && key0 == key; }
private:
- Q_DISABLE_COPY(QHashDummyNode)
+ Q_DISABLE_COPY(QHashNode)
};
@@ -280,7 +282,6 @@ Q_HASH_DECLARE_INT_NODES(uint);
template <class Key, class T>
class QHash
{
- typedef QHashDummyNode<Key, T> DummyNode;
typedef QHashNode<Key, T> Node;
union {
@@ -293,7 +294,6 @@ class QHash
}
static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
- static inline int alignOfDummyNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(DummyNode)); }
public:
inline QHash() : d(const_cast<QHashData *>(&QHashData::shared_null)) { }
@@ -301,7 +301,7 @@ public:
inline QHash(std::initializer_list<std::pair<Key,T> > list)
: d(const_cast<QHashData *>(&QHashData::shared_null))
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
@@ -558,25 +558,14 @@ template <class Key, class T>
Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode)
{
Node *concreteNode = concrete(node);
- if (QTypeInfo<T>::isDummy) {
- (void) new (newNode) DummyNode(concreteNode->key, concreteNode->h, 0);
- } else {
- (void) new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, 0);
- }
+ new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, 0);
}
template <class Key, class T>
Q_INLINE_TEMPLATE typename QHash<Key, T>::Node *
QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode)
{
- Node *node;
-
- if (QTypeInfo<T>::isDummy) {
- node = reinterpret_cast<Node *>(new (d->allocateNode(alignOfDummyNode())) DummyNode(akey, ah, *anextNode));
- } else {
- node = new (d->allocateNode(alignOfNode())) Node(akey, avalue, ah, *anextNode);
- }
-
+ Node *node = new (d->allocateNode(alignOfNode())) Node(akey, avalue, ah, *anextNode);
*anextNode = node;
++d->size;
return node;
@@ -609,9 +598,7 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::clear()
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper()
{
- QHashData *x = d->detach_helper(duplicateNode, deleteNode2,
- QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node),
- QTypeInfo<T>::isDummy ? alignOfDummyNode() : alignOfNode());
+ QHashData *x = d->detach_helper(duplicateNode, deleteNode2, sizeof(Node), alignOfNode());
if (!d->ref.deref())
freeData(d);
d = x;
@@ -793,7 +780,7 @@ Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insert(const K
return iterator(createNode(h, akey, avalue, node));
}
- if (!QTypeInfo<T>::isDummy)
+ if (!QtPrivate::is_same<T, QHashDummyValue>::value)
(*node)->value = avalue;
return iterator(*node);
}
@@ -962,7 +949,7 @@ Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash<Key, T> &other)
do {
if (it2 == other.end() || !(it2.key() == akey))
return false;
- if (!QTypeInfo<T>::isDummy && !(it.value() == it2.value()))
+ if (!(it.value() == it2.value()))
return false;
++it;
++it2;
@@ -979,7 +966,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
{
- this->reserve(list.size());
+ this->reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 3b86edd750..86b78eb522 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -87,12 +87,9 @@ class QMutable##C##Iterator \
public: \
inline QMutable##C##Iterator(Q##C<T> &container) \
: c(&container) \
- { c->setSharable(false); i = c->begin(); n = c->end(); } \
- inline ~QMutable##C##Iterator() \
- { c->setSharable(true); } \
+ { i = c->begin(); n = c->end(); } \
inline QMutable##C##Iterator &operator=(Q##C<T> &container) \
- { c->setSharable(true); c = &container; c->setSharable(false); \
- i = c->begin(); n = c->end(); return *this; } \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = i; } \
inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
@@ -160,11 +157,9 @@ class QMutable##C##Iterator \
public: \
inline QMutable##C##Iterator(Q##C<Key,T> &container) \
: c(&container) \
- { c->setSharable(false); i = c->begin(); n = c->end(); } \
- inline ~QMutable##C##Iterator() \
- { c->setSharable(true); } \
+ { i = c->begin(); n = c->end(); } \
inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
- { c->setSharable(true); c = &container; c->setSharable(false); i = c->begin(); n = c->end(); return *this; } \
+ { c = &container; i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = c->end(); } \
inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 1ae9c58daa..f140af152d 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -501,17 +501,6 @@
\sa operator=()
*/
-/*!
- \fn QMutableListIterator::~QMutableListIterator()
- \fn QMutableLinkedListIterator::~QMutableLinkedListIterator()
- \fn QMutableVectorIterator::~QMutableVectorIterator()
- \fn QMutableSetIterator::~QMutableSetIterator()
-
- Destroys the iterator.
-
- \sa operator=()
-*/
-
/*! \fn QMutableListIterator &QMutableListIterator::operator=(QList<T> &list)
\fn QMutableLinkedListIterator &QMutableLinkedListIterator::operator=(QLinkedList<T> &list)
\fn QListIterator &QListIterator::operator=(const QList<T> &list)
@@ -1121,15 +1110,6 @@
\sa operator=()
*/
-/*!
- \fn QMutableMapIterator::~QMutableMapIterator()
- \fn QMutableHashIterator::~QMutableHashIterator()
-
- Destroys the iterator.
-
- \sa operator=()
-*/
-
/*! \fn QMapIterator &QMapIterator::operator=(const QMap<Key, T> &map)
\fn QMutableMapIterator &QMutableMapIterator::operator=(QMap<Key, T> &map)
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 990e6bef09..61c7899ef4 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -259,10 +259,11 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLine &p)
+QDebug operator<<(QDebug dbg, const QLine &p)
{
- d << "QLine(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLine(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
@@ -819,10 +820,11 @@ qreal QLineF::angle(const QLineF &l) const
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QLineF &p)
+QDebug operator<<(QDebug dbg, const QLineF &p)
{
- d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
- return d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QLineF(" << p.p1() << ',' << p.p2() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
index 69e8a8245a..9b41d7b83e 100644
--- a/src/corelib/tools/qline.h
+++ b/src/corelib/tools/qline.h
@@ -75,8 +75,8 @@ public:
inline void translate(const QPoint &p);
inline void translate(int dx, int dy);
- Q_DECL_CONSTEXPR inline QLine translated(const QPoint &p) const;
- Q_DECL_CONSTEXPR inline QLine translated(int dx, int dy) const;
+ Q_DECL_CONSTEXPR inline QLine translated(const QPoint &p) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLine translated(int dx, int dy) const Q_REQUIRED_RESULT;
inline void setP1(const QPoint &p1);
inline void setP2(const QPoint &p2);
@@ -216,7 +216,7 @@ public:
Q_DECL_CONSTEXPR inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2);
Q_DECL_CONSTEXPR inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { }
- static QLineF fromPolar(qreal length, qreal angle);
+ static QLineF fromPolar(qreal length, qreal angle) Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR bool isNull() const;
@@ -240,8 +240,8 @@ public:
qreal angleTo(const QLineF &l) const;
- QLineF unitVector() const;
- Q_DECL_CONSTEXPR inline QLineF normalVector() const;
+ QLineF unitVector() const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLineF normalVector() const Q_REQUIRED_RESULT;
// ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType
IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
@@ -252,8 +252,8 @@ public:
inline void translate(const QPointF &p);
inline void translate(qreal dx, qreal dy);
- Q_DECL_CONSTEXPR inline QLineF translated(const QPointF &p) const;
- Q_DECL_CONSTEXPR inline QLineF translated(qreal dx, qreal dy) const;
+ Q_DECL_CONSTEXPR inline QLineF translated(const QPointF &p) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QLineF translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT;
inline void setP1(const QPointF &p1);
inline void setP2(const QPointF &p2);
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 0811c3793e..db49fe9802 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -491,11 +491,11 @@ void **QListData::erase(void **xi)
/*!
\fn QList<T> QList<T>::mid(int pos, int length) const
- Returns a list whose elements are copied from this list,
+ Returns a sub-list which includes elements from this list,
starting at position \a pos. If \a length is -1 (the default), all
- elements from \a pos are copied; otherwise \a length elements (or
+ elements from \a pos are included; otherwise \a length elements (or
all remaining elements if there are less than \a length elements)
- are copied.
+ are included.
*/
/*! \fn QList::QList()
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 9e4ba70908..8cfd1a8f8b 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -45,6 +45,7 @@
#include <QtCore/qalgorithms.h>
#include <QtCore/qiterator.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qarraydata.h>
#include <iterator>
#include <list>
@@ -129,7 +130,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QList(std::initializer_list<T> args)
: d(const_cast<QListData::Data *>(&QListData::shared_null))
- { std::copy(args.begin(), args.end(), std::back_inserter(*this)); }
+ { reserve(args.size()); std::copy(args.begin(), args.end(), std::back_inserter(*this)); }
#endif
bool operator==(const QList<T> &l) const;
inline bool operator!=(const QList<T> &l) const { return !(*this == l); }
@@ -646,10 +647,17 @@ inline void QList<T>::move(int from, int to)
template<typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const
{
- if (alength < 0 || pos > size() - alength)
- alength = size() - pos;
- if (pos == 0 && alength == size())
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &pos, &alength)) {
+ case QContainerImplHelper::Null:
+ case QContainerImplHelper::Empty:
+ return QList<T>();
+ case QContainerImplHelper::Full:
return *this;
+ case QContainerImplHelper::Subset:
+ break;
+ }
+
QList<T> cpy;
if (alength <= 0)
return cpy;
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 98e38ca587..3754a1bfcf 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2404,6 +2404,13 @@ Qt::LayoutDirection QLocale::textDirection() const
\since 4.8
Returns an uppercase copy of \a str.
+
+ If Qt Core is using the ICU libraries, they will be used to perform
+ the transformation according to the rules of the current locale.
+ Otherwise the conversion may be done in a platform-dependent manner,
+ with QString::toUpper() as a generic fallback.
+
+ \sa QString::toUpper()
*/
QString QLocale::toUpper(const QString &str) const
{
@@ -2421,6 +2428,13 @@ QString QLocale::toUpper(const QString &str) const
\since 4.8
Returns a lowercase copy of \a str.
+
+ If Qt Core is using the ICU libraries, they will be used to perform
+ the transformation according to the rules of the current locale.
+ Otherwise the conversion may be done in a platform-dependent manner,
+ with QString::toLower() as a generic fallback.
+
+ \sa QString::toLower()
*/
QString QLocale::toLower(const QString &str) const
{
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 917e83834a..da8a820234 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -402,6 +402,33 @@ QString qt_readEscapedFormatString(const QString &format, int *idx);
bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry);
int qt_repeatCount(const QString &s, int i);
+enum { AsciiSpaceMask = (1 << (' ' - 1)) |
+ (1 << ('\t' - 1)) | // 9: HT - horizontal tab
+ (1 << ('\n' - 1)) | // 10: LF - line feed
+ (1 << ('\v' - 1)) | // 11: VT - vertical tab
+ (1 << ('\f' - 1)) | // 12: FF - form feed
+ (1 << ('\r' - 1)) }; // 13: CR - carriage return
+Q_DECL_CONSTEXPR inline bool ascii_isspace(uchar c)
+{
+ return c >= 1U && c <= 32U && (uint(AsciiSpaceMask) >> uint(c - 1)) & 1U;
+}
+
+#if defined(Q_COMPILER_CONSTEXPR)
+Q_STATIC_ASSERT(ascii_isspace(' '));
+Q_STATIC_ASSERT(ascii_isspace('\t'));
+Q_STATIC_ASSERT(ascii_isspace('\n'));
+Q_STATIC_ASSERT(ascii_isspace('\v'));
+Q_STATIC_ASSERT(ascii_isspace('\f'));
+Q_STATIC_ASSERT(ascii_isspace('\r'));
+Q_STATIC_ASSERT(!ascii_isspace('\0'));
+Q_STATIC_ASSERT(!ascii_isspace('\a'));
+Q_STATIC_ASSERT(!ascii_isspace('a'));
+Q_STATIC_ASSERT(!ascii_isspace('\177'));
+Q_STATIC_ASSERT(!ascii_isspace('\200'));
+Q_STATIC_ASSERT(!ascii_isspace('\xA0'));
+Q_STATIC_ASSERT(!ascii_isspace('\377'));
+#endif
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QStringRef)
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
index c2bae3df9d..f2d85b1985 100644
--- a/src/corelib/tools/qlocale_tools.cpp
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -243,7 +243,7 @@ qulonglong qstrtoull(const char *nptr, const char **endptr, int base, bool *ok)
s = nptr;
do {
c = *s++;
- } while (isspace(c));
+ } while (ascii_isspace(c));
if (c == '-') {
if (ok != 0)
*ok = false;
@@ -323,7 +323,7 @@ qlonglong qstrtoll(const char *nptr, const char **endptr, int base, bool *ok)
s = nptr;
do {
c = *s++;
- } while (isspace(c));
+ } while (ascii_isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
@@ -1468,7 +1468,7 @@ Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok)
rv = 0.;
- for(s = s00; isspace(uchar(*s)); s++)
+ for(s = s00; ascii_isspace(uchar(*s)); s++)
;
if (*s == '-') {
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index 1063cda52b..090e8d0ff2 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -452,15 +452,18 @@ QDataStream &operator>>(QDataStream &s, QPoint &p)
*/
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QPoint &p) {
+QDebug operator<<(QDebug dbg, const QPoint &p)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QPoint(" << p.x() << ',' << p.y() << ')';
- return dbg.space();
+ return dbg;
}
-QDebug operator<<(QDebug d, const QPointF &p)
+QDebug operator<<(QDebug dbg, const QPointF &p)
{
- d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
- return d.space();
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QPointF(" << p.x() << ',' << p.y() << ')';
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 382793f175..04269e485b 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -1286,10 +1286,12 @@ QDataStream &operator>>(QDataStream &s, QRect &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRect &r) {
+QDebug operator<<(QDebug dbg, const QRect &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRect(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -2493,10 +2495,12 @@ QDataStream &operator>>(QDataStream &s, QRectF &r)
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QRectF &r) {
+QDebug operator<<(QDebug dbg, const QRectF &r)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QRectF(" << r.x() << ',' << r.y() << ' '
<< r.width() << 'x' << r.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 2bb74e8221..8ee08877e8 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -68,7 +68,7 @@ public:
Q_DECL_CONSTEXPR inline int top() const;
Q_DECL_CONSTEXPR inline int right() const;
Q_DECL_CONSTEXPR inline int bottom() const;
- QRect normalized() const;
+ QRect normalized() const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline int x() const;
Q_DECL_CONSTEXPR inline int y() const;
@@ -102,8 +102,8 @@ public:
inline void translate(int dx, int dy);
inline void translate(const QPoint &p);
- Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const;
- Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const;
+ Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const Q_REQUIRED_RESULT;
inline void moveTo(int x, int t);
inline void moveTo(const QPoint &p);
@@ -115,7 +115,7 @@ public:
inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
inline void adjust(int x1, int y1, int x2, int y2);
- Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const;
+ Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline QSize size() const;
Q_DECL_CONSTEXPR inline int width() const;
@@ -133,8 +133,8 @@ public:
bool contains(const QPoint &p, bool proper=false) const;
inline bool contains(int x, int y) const;
inline bool contains(int x, int y, bool proper) const;
- inline QRect united(const QRect &other) const;
- inline QRect intersected(const QRect &other) const;
+ inline QRect united(const QRect &other) const Q_REQUIRED_RESULT;
+ inline QRect intersected(const QRect &other) const Q_REQUIRED_RESULT;
bool intersects(const QRect &r) const;
Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const;
@@ -143,8 +143,8 @@ public:
inline QRect &operator-=(const QMargins &margins);
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED QRect unite(const QRect &r) const { return united(r); }
- QT_DEPRECATED QRect intersect(const QRect &r) const { return intersected(r); }
+ QT_DEPRECATED QRect unite(const QRect &r) const Q_REQUIRED_RESULT { return united(r); }
+ QT_DEPRECATED QRect intersect(const QRect &r) const Q_REQUIRED_RESULT { return intersected(r); }
#endif
friend Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &);
@@ -510,7 +510,7 @@ public:
Q_DECL_CONSTEXPR inline bool isNull() const;
Q_DECL_CONSTEXPR inline bool isEmpty() const;
Q_DECL_CONSTEXPR inline bool isValid() const;
- QRectF normalized() const;
+ QRectF normalized() const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline qreal left() const { return xp; }
Q_DECL_CONSTEXPR inline qreal top() const { return yp; }
@@ -550,8 +550,8 @@ public:
inline void translate(qreal dx, qreal dy);
inline void translate(const QPointF &p);
- Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const;
- Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const;
+ Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT;
+ Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const Q_REQUIRED_RESULT;
inline void moveTo(qreal x, qreal y);
inline void moveTo(const QPointF &p);
@@ -563,7 +563,7 @@ public:
inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2);
- Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const;
+ Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const Q_REQUIRED_RESULT;
Q_DECL_CONSTEXPR inline QSizeF size() const;
Q_DECL_CONSTEXPR inline qreal width() const;
@@ -580,8 +580,8 @@ public:
bool contains(const QRectF &r) const;
bool contains(const QPointF &p) const;
inline bool contains(qreal x, qreal y) const;
- inline QRectF united(const QRectF &other) const;
- inline QRectF intersected(const QRectF &other) const;
+ inline QRectF united(const QRectF &other) const Q_REQUIRED_RESULT;
+ inline QRectF intersected(const QRectF &other) const Q_REQUIRED_RESULT;
bool intersects(const QRectF &r) const;
Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const;
@@ -590,15 +590,15 @@ public:
inline QRectF &operator-=(const QMarginsF &margins);
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED QRectF unite(const QRectF &r) const { return united(r); }
- QT_DEPRECATED QRectF intersect(const QRectF &r) const { return intersected(r); }
+ QT_DEPRECATED QRectF unite(const QRectF &r) const Q_REQUIRED_RESULT { return united(r); }
+ QT_DEPRECATED QRectF intersect(const QRectF &r) const Q_REQUIRED_RESULT { return intersected(r); }
#endif
friend Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &);
friend Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &);
- Q_DECL_CONSTEXPR inline QRect toRect() const;
- QRect toAlignedRect() const;
+ Q_DECL_CONSTEXPR inline QRect toRect() const Q_REQUIRED_RESULT;
+ QRect toAlignedRect() const Q_REQUIRED_RESULT;
private:
qreal xp;
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index e1cf82bb8c..88ce4caea3 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -699,6 +699,23 @@ QT_BEGIN_NAMESPACE
\c{\w} to match any character with either the Unicode L (letter) or N
(digit) property, plus underscore, and so on. This option corresponds
to the \c{/u} modifier in Perl regular expressions.
+
+ \value OptimizeOnFirstUsageOption
+ The regular expression will be optimized (and possibly
+ JIT-compiled) on its first usage, instead of after a certain (undefined)
+ number of usages. See also \l{QRegularExpression::}{optimize()}.
+ This enum value has been introduced in Qt 5.4.
+
+ \value DontAutomaticallyOptimizeOption
+ Regular expressions are automatically optimized after a
+ certain number of usages; setting this option prevents such
+ optimizations, therefore avoiding possible unpredictable spikes in
+ CPU and memory usage. If both this option and the
+ \c{OptimizeOnFirstUsageOption} option are set, then this option takes
+ precedence. Note: this option will still let the regular expression
+ to be optimized by manually calling
+ \l{QRegularExpression::}{optimize()}. This enum value has been
+ introduced in Qt 5.4.
*/
/*!
@@ -746,6 +763,13 @@ QT_BEGIN_NAMESPACE
The match is constrained to start exactly at the offset passed to
match() in order to be successful, even if the pattern string does not
contain any metacharacter that anchors the match at that point.
+
+ \value DontCheckSubjectStringMatchOption
+ The subject string is not checked for UTF-16 validity before
+ attempting a match. Use this option with extreme caution, as
+ attempting to match an invalid string may crash the program and/or
+ constitute a security issue. This enum value has been introduced in
+ Qt 5.4.
*/
// after how many usages we optimize the regexp
@@ -802,13 +826,24 @@ struct QRegularExpressionPrivate : QSharedData
void cleanCompiledPattern();
void compilePattern();
void getPatternInfo();
- void optimizePattern();
+
+ enum OptimizePatternOption {
+ LazyOptimizeOption,
+ ImmediateOptimizeOption
+ };
+
+ void optimizePattern(OptimizePatternOption option);
+
+ enum CheckSubjectStringOption {
+ CheckSubjectString,
+ DontCheckSubjectString
+ };
QRegularExpressionMatchPrivate *doMatch(const QString &subject,
int offset,
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
- bool checkSubjectString = true,
+ CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = 0) const;
int captureIndexForName(const QString &name) const;
@@ -1096,7 +1131,10 @@ static bool isJitEnabled()
setting the studyData member variable to the result of the study. It gets
called by doMatch() every time a match is performed. As of now, the
optimizations on the pattern are performed after a certain number of usages
- (i.e. the qt_qregularexpression_optimize_after_use_count constant).
+ (i.e. the qt_qregularexpression_optimize_after_use_count constant) unless
+ the DontAutomaticallyOptimizeOption option is set on the QRegularExpression
+ object, or anyhow by calling optimize() (which will pass
+ ImmediateOptimizeOption).
Notice that although the method is protected by a mutex, one thread may
invoke this function and return immediately (i.e. not study the pattern,
@@ -1107,20 +1145,23 @@ static bool isJitEnabled()
(localStudyData) before using storeRelease on studyData. In doMatch there's
the corresponding loadAcquire.
*/
-void QRegularExpressionPrivate::optimizePattern()
+void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
{
Q_ASSERT(compiledPattern);
QMutexLocker lock(&mutex);
- if (studyData.load() || (++usedCount != qt_qregularexpression_optimize_after_use_count))
+ if (studyData.load()) // already optimized
+ return;
+
+ if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count))
return;
static const bool enableJit = isJitEnabled();
int studyOptions = 0;
if (enableJit)
- studyOptions |= PCRE_STUDY_JIT_COMPILE;
+ studyOptions |= (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE);
const char *err;
pcre16_extra * const localStudyData = pcre16_study(compiledPattern, studyOptions, &err);
@@ -1187,7 +1228,9 @@ static int pcre16SafeExec(const pcre16 *code, const pcre16_extra *extra,
options \a matchOptions and returns the QRegularExpressionMatchPrivate of
the result. It also advances a match if a previous result is given as \a
previous. The \a subject string goes a Unicode validity check if
- \a checkSubjectString is true (PCRE doesn't like illegal UTF-16 sequences).
+ \a checkSubjectString is CheckSubjectString and the match options don't
+ include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal
+ UTF-16 sequences).
Advancing a match is a tricky algorithm. If the previous match matched a
non-empty string, we just do an ordinary match at the offset position.
@@ -1204,7 +1247,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
int offset,
QRegularExpression::MatchType matchType,
QRegularExpression::MatchOptions matchOptions,
- bool checkSubjectString,
+ CheckSubjectStringOption checkSubjectStringOption,
const QRegularExpressionMatchPrivate *previous) const
{
if (offset < 0)
@@ -1233,8 +1276,15 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
matchType, matchOptions,
capturingCount + 1);
- // this is mutex protected
- const_cast<QRegularExpressionPrivate *>(this)->optimizePattern();
+ if (!(patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)) {
+ const OptimizePatternOption optimizePatternOption =
+ (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ ? ImmediateOptimizeOption
+ : LazyOptimizeOption;
+
+ // this is mutex protected
+ const_cast<QRegularExpressionPrivate *>(this)->optimizePattern(optimizePatternOption);
+ }
// work with a local copy of the study data, as we are running pcre_exec
// potentially more than once, and we don't want to run call it
@@ -1248,8 +1298,10 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
else if (matchType == QRegularExpression::PartialPreferFirstMatch)
pcreOptions |= PCRE_PARTIAL_HARD;
- if (!checkSubjectString)
+ if (checkSubjectStringOption == DontCheckSubjectString
+ || matchOptions & QRegularExpression::DontCheckSubjectStringMatchOption) {
pcreOptions |= PCRE_NO_UTF16_CHECK;
+ }
bool previousMatchWasEmpty = false;
if (previous && previous->hasMatch &&
@@ -1360,7 +1412,7 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
Q_ASSERT(isValid);
Q_ASSERT(hasMatch || hasPartialMatch);
- // Note the "false" passed for the check of the subject string:
+ // Note the DontCheckSubjectString passed for the check of the subject string:
// if we're advancing a match on the same subject,
// then that subject was already checked at least once (when this object
// was created, or when the object that created this one was created, etc.)
@@ -1368,7 +1420,7 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
capturedOffsets.at(1),
matchType,
matchOptions,
- false,
+ QRegularExpressionPrivate::DontCheckSubjectString,
this);
return QRegularExpressionMatch(*nextPrivate);
}
@@ -1667,6 +1719,27 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s
}
/*!
+ \since 5.4
+
+ Forces an immediate optimization of the pattern, including
+ JIT-compiling it (if the JIT compiler is enabled).
+
+ Patterns are normally optimized only after a certain number of usages.
+ If you can predict that this QRegularExpression object is going to be
+ used for several matches, it may be convenient to optimize it in
+ advance by calling this function.
+
+ \sa QRegularExpression::OptimizeOnFirstUsageOption
+*/
+void QRegularExpression::optimize() const
+{
+ if (!isValid()) // will compile the pattern
+ return;
+
+ d->optimizePattern(QRegularExpressionPrivate::ImmediateOptimizeOption);
+}
+
+/*!
Returns \c true if the regular expression is equal to \a re, or false
otherwise. Two QRegularExpression objects are equal if they have
the same pattern string and the same pattern options.
@@ -2327,6 +2400,10 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
+ if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
+ flags.append("OptimizeOnFirstUsageOption|");
+ if (patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)
+ flags.append("DontAutomaticallyOptimizeOption|");
flags.chop(1);
}
@@ -2490,7 +2567,16 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-16 string"),
QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large")
+ QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-32 string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "setting UTF is disabled by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-hex character in \\x{} (closing brace missing?)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "group name must start with a non-digit"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)")
};
#endif // #if 0
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 5059ea6431..ce91eace5f 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -69,7 +69,9 @@ public:
ExtendedPatternSyntaxOption = 0x0008,
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
- UseUnicodePropertiesOption = 0x0040
+ UseUnicodePropertiesOption = 0x0040,
+ OptimizeOnFirstUsageOption = 0x0080,
+ DontAutomaticallyOptimizeOption = 0x0100
};
Q_DECLARE_FLAGS(PatternOptions, PatternOption)
@@ -108,7 +110,8 @@ public:
enum MatchOption {
NoMatchOption = 0x0000,
- AnchoredMatchOption = 0x0001
+ AnchoredMatchOption = 0x0001,
+ DontCheckSubjectStringMatchOption = 0x0002
};
Q_DECLARE_FLAGS(MatchOptions, MatchOption)
@@ -122,6 +125,8 @@ public:
MatchType matchType = NormalMatch,
MatchOptions matchOptions = NoMatchOption) const;
+ void optimize() const;
+
static QString escape(const QString &str);
bool operator==(const QRegularExpression &re) const;
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 5d25b0add1..5aa1f165be 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -61,9 +61,9 @@ QT_BEGIN_NAMESPACE
class QRingBuffer
{
public:
- explicit inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
- buffers << QByteArray();
- clear();
+ explicit inline QRingBuffer(int growth = 4096) :
+ head(0), tail(0), tailBuffer(0), basicBlockSize(growth), bufferSize(0) {
+ buffers.append(QByteArray());
}
inline int nextDataBlockSize() const {
@@ -78,115 +78,65 @@ public:
// the out-variable length will contain the amount of bytes readable
// from there, e.g. the amount still the same QByteArray
inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
- if (buffers.isEmpty()) {
- length = 0;
- return 0;
- }
-
- if (pos >= bufferSize) {
- length = 0;
- return 0;
- }
-
- // special case: it is in the first buffer
- int nextDataBlockSizeValue = nextDataBlockSize();
- if (pos < nextDataBlockSizeValue) {
- length = nextDataBlockSizeValue - pos;
- return buffers.at(0).constData() + head + pos;
- }
-
- // special case: we only had one buffer and tried to read over it
- if (buffers.length() == 1) {
- length = 0;
- return 0;
- }
-
- // skip the first
- pos -= nextDataBlockSizeValue;
-
- // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
- for (int i = 1; i < tailBuffer; i++) {
- if (pos >= buffers[i].size()) {
- pos -= buffers[i].size();
- continue;
+ if (pos >= 0) {
+ pos += head;
+ for (int i = 0; i < buffers.size(); ++i) {
+ length = (i == tailBuffer ? tail : buffers[i].size());
+ if (length > pos) {
+ length -= pos;
+ return buffers[i].constData() + pos;
+ }
+ pos -= length;
}
-
- length = buffers[i].length() - pos;
- return buffers[i].constData() + pos;
}
- // it is in the tail buffer
- length = tail - pos;
- return buffers[tailBuffer].constData() + pos;
+ length = 0;
+ return 0;
}
inline void free(int bytes) {
- bufferSize -= bytes;
- if (bufferSize < 0)
- bufferSize = 0;
-
- for (;;) {
- int nextBlockSize = nextDataBlockSize();
- if (bytes < nextBlockSize) {
- head += bytes;
- if (head == tail && tailBuffer == 0)
- head = tail = 0;
- break;
- }
-
- bytes -= nextBlockSize;
- if (buffers.count() == 1) {
- if (buffers.at(0).size() != basicBlockSize)
- buffers[0].resize(basicBlockSize);
- head = tail = 0;
- tailBuffer = 0;
- break;
+ while (bytes > 0) {
+ int blockSize = buffers.first().size() - head;
+
+ if (tailBuffer == 0 || blockSize > bytes) {
+ bufferSize -= bytes;
+ if (bufferSize <= 0)
+ clear(); // try to minify/squeeze us
+ else
+ head += bytes;
+ return;
}
- buffers.removeAt(0);
+ bufferSize -= blockSize;
+ bytes -= blockSize;
+ buffers.removeFirst();
--tailBuffer;
head = 0;
}
-
- if (isEmpty())
- clear(); // try to minify/squeeze us
}
inline char *reserve(int bytes) {
- // if this is a fresh empty QRingBuffer
- if (bufferSize == 0) {
- buffers[0].resize(qMax(basicBlockSize, bytes));
- bufferSize += bytes;
- tail = bytes;
- return buffers[tailBuffer].data();
- }
-
- bufferSize += bytes;
+ if (bytes <= 0)
+ return 0;
- // if there is already enough space, simply return.
- if (tail + bytes <= buffers.at(tailBuffer).size()) {
- char *writePtr = buffers[tailBuffer].data() + tail;
- tail += bytes;
- return writePtr;
- }
+ // if need buffer reallocation
+ if (tail + bytes > buffers.last().size()) {
+ if (tail >= basicBlockSize) {
+ // shrink this buffer to its current size
+ buffers.last().resize(tail);
- // if our buffer isn't half full yet, simply resize it.
- if (tail < buffers.at(tailBuffer).size() / 2) {
- buffers[tailBuffer].resize(tail + bytes);
- char *writePtr = buffers[tailBuffer].data() + tail;
- tail += bytes;
- return writePtr;
+ // create a new QByteArray
+ buffers.append(QByteArray());
+ ++tailBuffer;
+ tail = 0;
+ }
+ buffers.last().resize(qMax(basicBlockSize, tail + bytes));
}
- // shrink this buffer to its current size
- buffers[tailBuffer].resize(tail);
-
- // create a new QByteArray with the right size
- buffers << QByteArray();
- ++tailBuffer;
- buffers[tailBuffer].resize(qMax(basicBlockSize, bytes));
- tail = bytes;
- return buffers[tailBuffer].data();
+ char *writePtr = buffers.last().data() + tail;
+ bufferSize += bytes;
+ tail += bytes;
+ return writePtr;
}
inline void truncate(int pos) {
@@ -195,33 +145,22 @@ public:
}
inline void chop(int bytes) {
- bufferSize -= bytes;
- if (bufferSize < 0)
- bufferSize = 0;
-
- for (;;) {
- // special case: head and tail are in the same buffer
- if (tailBuffer == 0) {
- tail -= bytes;
- if (tail <= head)
- tail = head = 0;
- return;
- }
-
- if (bytes <= tail) {
- tail -= bytes;
+ while (bytes > 0) {
+ if (tailBuffer == 0 || tail > bytes) {
+ bufferSize -= bytes;
+ if (bufferSize <= 0)
+ clear(); // try to minify/squeeze us
+ else
+ tail -= bytes;
return;
}
+ bufferSize -= tail;
bytes -= tail;
- buffers.removeAt(tailBuffer);
-
+ buffers.removeLast();
--tailBuffer;
- tail = buffers.at(tailBuffer).size();
+ tail = buffers.last().size();
}
-
- if (isEmpty())
- clear(); // try to minify/squeeze us
}
inline bool isEmpty() const {
@@ -245,11 +184,11 @@ public:
--head;
if (head < 0) {
buffers.prepend(QByteArray());
- buffers[0].resize(basicBlockSize);
+ buffers.first().resize(basicBlockSize);
head = basicBlockSize - 1;
++tailBuffer;
}
- buffers[0][head] = c;
+ buffers.first()[head] = c;
++bufferSize;
}
@@ -259,8 +198,7 @@ public:
inline void clear() {
buffers.erase(buffers.begin() + 1, buffers.end());
- buffers[0].resize(0);
- buffers[0].squeeze();
+ buffers.first().clear();
head = tail = 0;
tailBuffer = 0;
@@ -269,47 +207,34 @@ public:
inline int indexOf(char c) const {
int index = 0;
+ int j = head;
for (int i = 0; i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
-
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- const char *ptr = buffers.at(i).data() + start;
- for (int j = start; j < end; ++j) {
+ const char *ptr = buffers[i].constData() + j;
+ j = index + (i == tailBuffer ? tail : buffers[i].size()) - j;
+
+ while (index < j) {
if (*ptr++ == c)
return index;
++index;
}
+ j = 0;
}
return -1;
}
inline int indexOf(char c, int maxLength) const {
int index = 0;
- int remain = qMin(size(), maxLength);
- for (int i = 0; remain && i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
-
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- if (remain < end - start) {
- end = start + remain;
- remain = 0;
- } else {
- remain -= end - start;
- }
- const char *ptr = buffers.at(i).data() + start;
- for (int j = start; j < end; ++j) {
+ int j = head;
+ for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
+ const char *ptr = buffers[i].constData() + j;
+ j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
+
+ while (index < j) {
if (*ptr++ == c)
return index;
++index;
}
+ j = 0;
}
return -1;
}
@@ -318,95 +243,47 @@ public:
int bytesToRead = qMin(size(), maxLength);
int readSoFar = 0;
while (readSoFar < bytesToRead) {
- const char *ptr = readPointer();
int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize());
if (data)
- memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
readSoFar += bytesToReadFromThisBlock;
free(bytesToReadFromThisBlock);
}
return readSoFar;
}
- inline QByteArray read(int maxLength) {
- QByteArray tmp;
- tmp.resize(qMin(maxLength, size()));
- read(tmp.data(), tmp.size());
- return tmp;
- }
-
- inline QByteArray readAll() {
- return read(size());
- }
-
// read an unspecified amount (will read the first buffer)
inline QByteArray read() {
if (bufferSize == 0)
return QByteArray();
- // multiple buffers, just take the first one
- if (head == 0 && tailBuffer != 0) {
- QByteArray qba = buffers.takeFirst();
- --tailBuffer;
- bufferSize -= qba.length();
- return qba;
- }
+ QByteArray qba(buffers.takeFirst());
- // one buffer with good value for head. Just take it.
- if (head == 0 && tailBuffer == 0) {
- QByteArray qba = buffers.takeFirst();
- qba.resize(tail);
- buffers << QByteArray();
- bufferSize = 0;
- tail = 0;
- return qba;
- }
-
- // Bad case: We have to memcpy.
- // We can avoid by initializing the QRingBuffer with basicBlockSize of 0
- // and only using this read() function.
- QByteArray qba(readPointer(), nextDataBlockSize());
- buffers.removeFirst();
- head = 0;
+ qba.reserve(0); // avoid that resizing needlessly reallocates
if (tailBuffer == 0) {
- buffers << QByteArray();
+ qba.resize(tail);
tail = 0;
+ buffers.append(QByteArray());
} else {
--tailBuffer;
}
- bufferSize -= qba.length();
+ qba.remove(0, head); // does nothing if head is 0
+ head = 0;
+ bufferSize -= qba.size();
return qba;
}
// append a new buffer to the end
inline void append(const QByteArray &qba) {
- buffers[tailBuffer].resize(tail);
- buffers << qba;
- ++tailBuffer;
- tail = qba.length();
- bufferSize += qba.length();
- }
-
- inline QByteArray peek(int maxLength) const {
- int bytesToRead = qMin(size(), maxLength);
- if(maxLength <= 0)
- return QByteArray();
- QByteArray ret;
- ret.resize(bytesToRead);
- int readSoFar = 0;
- for (int i = 0; readSoFar < bytesToRead && i < buffers.size(); ++i) {
- int start = 0;
- int end = buffers.at(i).size();
- if (i == 0)
- start = head;
- if (i == tailBuffer)
- end = tail;
- const int len = qMin(ret.size()-readSoFar, end-start);
- memcpy(ret.data()+readSoFar, buffers.at(i).constData()+start, len);
- readSoFar += len;
+ if (tail == 0) {
+ buffers.last() = qba;
+ } else {
+ buffers.last().resize(tail);
+ buffers.append(qba);
+ ++tailBuffer;
}
- Q_ASSERT(readSoFar == ret.size());
- return ret;
+ tail = qba.size();
+ bufferSize += tail;
}
inline int skip(int length) {
@@ -414,35 +291,26 @@ public:
}
inline int readLine(char *data, int maxLength) {
- int index = indexOf('\n');
- if (index == -1)
- return read(data, maxLength);
- if (maxLength <= 0)
+ if (!data || --maxLength <= 0)
return -1;
- int readSoFar = 0;
- while (readSoFar < index + 1 && readSoFar < maxLength - 1) {
- int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize());
- bytesToRead = qMin(bytesToRead, (maxLength - 1) - readSoFar);
- memcpy(data + readSoFar, readPointer(), bytesToRead);
- readSoFar += bytesToRead;
- free(bytesToRead);
- }
+ int i = indexOf('\n', maxLength);
+ i = read(data, i >= 0 ? (i + 1) : maxLength);
// Terminate it.
- data[readSoFar] = '\0';
- return readSoFar;
+ data[i] = '\0';
+ return i;
}
inline bool canReadLine() const {
- return indexOf('\n') != -1;
+ return indexOf('\n') >= 0;
}
private:
QList<QByteArray> buffers;
int head, tail;
int tailBuffer; // always buffers.size() - 1
- int basicBlockSize;
+ const int basicBlockSize;
int bufferSize;
};
diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp
index 2d61d2114e..bd3e03c464 100644
--- a/src/corelib/tools/qscopedvaluerollback.cpp
+++ b/src/corelib/tools/qscopedvaluerollback.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -70,6 +70,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QScopedValueRollback::QScopedValueRollback(T &var, T value)
+
+ Assigns \a value to \ var and stores the previous value of \a var
+ internally, for revert on destruction.
+
+ \since 5.4
+*/
+
+/*!
\fn QScopedValueRollback::~QScopedValueRollback()
Assigns the previous value to the managed variable.
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index dfaf1984be..2a5bd8c223 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -56,6 +56,13 @@ public:
oldValue = varRef;
}
+ explicit QScopedValueRollback(T &var, T value) :
+ varRef(var)
+ {
+ oldValue = varRef;
+ varRef = value;
+ }
+
~QScopedValueRollback()
{
varRef = oldValue;
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 0cc704b6cf..9682c97fec 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -60,7 +60,7 @@ public:
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QSet(std::initializer_list<T> list)
{
- reserve(list.size());
+ reserve(int(list.size()));
for (typename std::initializer_list<T>::const_iterator it = list.begin(); it != list.end(); ++it)
insert(*it);
}
@@ -356,12 +356,9 @@ class QMutableSetIterator
public:
inline QMutableSetIterator(QSet<T> &container)
: c(&container)
- { c->setSharable(false); i = c->begin(); n = c->end(); }
- inline ~QMutableSetIterator()
- { c->setSharable(true); }
+ { i = c->begin(); n = c->end(); }
inline QMutableSetIterator &operator=(QSet<T> &container)
- { c->setSharable(true); c = &container; c->setSharable(false);
- i = c->begin(); n = c->end(); return *this; }
+ { c = &container; i = c->begin(); n = c->end(); return *this; }
inline void toFront() { i = c->begin(); n = c->end(); }
inline void toBack() { i = c->end(); n = i; }
inline bool hasNext() const { return c->constEnd() != i; }
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index 941e58ee7c..b5eed0f504 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -538,10 +538,34 @@ QT_BEGIN_NAMESPACE
/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X>& other)
This copy constructor is different in that it allows \a other to be
a different type of explicitly shared data pointer but one that has
- a compatible shared data object. It performs a static cast of the
- \e{d pointer} in \a other and sets the \e {d pointer} of \e this to
- the converted \e{d pointer}. It increments the reference count of
- the shared data object.
+ a compatible shared data object.
+
+ By default, the \e{d pointer} of \a other (of type \c{X *}) gets
+ implicitly converted to the type \c{T *}; the result of this
+ conversion is set as the \e{d pointer} of \e{this}, and the
+ reference count of the shared data object is incremented.
+
+ However, if the macro
+ \c{QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST} is defined
+ before including the \c{QExplicitlySharedDataPointer} header, then
+ the \e{d pointer} of \a other undergoes a \c{static_cast} to the
+ type \c{T *}. The result of the cast is then set as the
+ \e{d pointer} of \e{this}, and the reference count of the shared data
+ object is incremented.
+
+ \warning relying on such \c{static_cast} is potentially dangerous,
+ because it allows code like this to compile:
+
+ \code
+ QExplicitlySharedDataPointer<Base> base(new Base);
+ QExplicitlySharedDataPointer<Derived> derived(base); // !!! DANGER !!!
+ \endcode
+
+ Starting from Qt 5.4 the cast is disabled by default. It is
+ possible to enable it back by defining the
+ \c{QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST} macro, and
+ therefore to allow old code (that relied on this feature) to
+ compile without modifications.
*/
/*! \fn QExplicitlySharedDataPointer<T>& QExplicitlySharedDataPointer::operator=(const QExplicitlySharedDataPointer<T>& other)
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 00bf4cba2a..d85184e995 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -44,6 +44,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
@@ -166,7 +167,12 @@ public:
inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
template<class X>
- inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data()))
+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
+#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
+ : d(static_cast<T *>(o.data()))
+#else
+ : d(o.data())
+#endif
{
if(d)
d->ref.ref();
@@ -274,6 +280,17 @@ namespace std {
}
QT_BEGIN_NAMESPACE
+template <class T>
+Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0)
+{
+ return qHash(ptr.data(), seed);
+}
+template <class T>
+Q_INLINE_TEMPLATE uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0)
+{
+ return qHash(ptr.data(), seed);
+}
+
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index a610fc46e5..e0cd54022e 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -372,6 +372,64 @@
*/
/*!
+ \class QEnableSharedFromThis
+ \inmodule QtCore
+ \brief A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer
+ \since 5.4
+
+ You can inherit this class when you need to create a QSharedPointer
+ from any instance of a class; for instance, from within the
+ object itself. The key point is that the technique of
+ just returning QSharedPointer<T>(this) can not be used, because
+ this winds up creating multiple distinct QSharedPointer objects
+ with separate reference counts. For this reason you must never
+ create more than one QSharedPointer from the same raw pointer.
+
+ QEnableSharedFromThis defines two member functions called
+ sharedFromThis() that return a QSharedPointer<T> and
+ QSharedPointer<const T>, depending on constness, to \c this:
+
+ \code
+ class Y: public QEnableSharedFromThis<Y>
+ {
+ public:
+ QSharedPointer<Y> f()
+ {
+ return sharedFromThis();
+ }
+ };
+
+ int main()
+ {
+ QSharedPointer<Y> p(new Y());
+ QSharedPointer<Y> y = p->f();
+ Q_ASSERT(p == y); // p and q must share ownership
+ }
+ \endcode
+
+ It is also possible to get a shared pointer from an object outside of
+ the class itself. This is especially useful in code that provides an
+ interface to scripts, where it is currently not possible to use shared
+ pointers. For example:
+
+ \code
+ class ScriptInterface : public QObject
+ {
+ Q_OBJECT
+
+ // ...
+
+ public slots:
+ void slotCalledByScript(Y *managedBySharedPointer)
+ {
+ QSharedPointer<Y> yPtr = managedBySharedPointer->sharedFromThis();
+ // Some other code unrelated to scripts that expects a QSharedPointer<Y> ...
+ }
+ };
+ \endcode
+*/
+
+/*!
\fn QSharedPointer::QSharedPointer()
Creates a QSharedPointer that points to null (0).
@@ -630,9 +688,15 @@
This function will attempt to call a constructor for type \tt T that can
accept all the arguments passed. Arguments will be perfectly-forwarded.
- \note This function is only available with a C++11 compiler that supports
- perfect forwarding of an arbitrary number of arguments. If the compiler
- does not support the necessary C++11 features, you must use the overload
+ \note This function is only fully available with a C++11 compiler that
+ supports perfect forwarding of an arbitrary number of arguments.
+
+ If the compiler does not support the necessary C++11 features,
+ then a restricted version is available since Qt 5.4: you may pass
+ one (but just one) argument, and it will always be passed by const
+ reference.
+
+ If you target Qt before version 5.4, you must use the overload
that calls the default constructor.
*/
@@ -771,6 +835,14 @@
*/
/*!
+ \fn void QWeakPointer::swap(QWeakPointer<T> &other)
+ \since 5.4
+
+ Swaps this weak pointer instance with \a other. This function is
+ very fast and never fails.
+*/
+
+/*!
\fn bool QWeakPointer::isNull() const
Returns \c true if this object is holding a reference to a null
@@ -894,6 +966,15 @@
*/
/*!
+ \fn QSharedPointer<T> QWeakPointer::lock() const
+ \since 5.4
+
+ Same as toStrongRef().
+
+ This function is provided for API compatibility with std::weak_ptr.
+*/
+
+/*!
\fn void QWeakPointer::clear()
Clears this QWeakPointer object, dropping the reference that it
@@ -901,6 +982,23 @@
*/
/*!
+ \fn QSharedPointer<T> QEnableSharedFromThis::sharedFromThis()
+ \since 5.4
+
+ If \c this (that is, the subclass instance invoking this method) is being
+ managed by a QSharedPointer, returns a shared pointer instance pointing to
+ \c this; otherwise returns a QSharedPointer holding a null pointer.
+*/
+
+/*!
+ \fn QSharedPointer<const T> QEnableSharedFromThis::sharedFromThis() const
+ \overload
+ \since 5.4
+
+ Const overload of sharedFromThis().
+*/
+
+/*!
\fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index 34b4bfbb12..431868ee08 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -122,10 +122,21 @@ public:
QWeakPointer(const QObject *other);
QWeakPointer<T> operator=(const QObject *other);
+ void swap(QWeakPointer<T> &other);
+
T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
+ QSharedPointer<T> lock() const;
+};
+
+template <class T>
+class QEnableSharedFromThis
+{
+public:
+ QSharedPointer<T> sharedFromThis();
+ QSharedPointer<const T> sharedFromThis() const;
};
template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2);
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 1423449a69..fe79aa1db1 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -91,6 +91,7 @@ template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
//
template <class T> class QWeakPointer;
template <class T> class QSharedPointer;
+template <class T> class QEnableSharedFromThis;
class QVariant;
@@ -318,16 +319,22 @@ public:
inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws
{ internalConstruct(ptr, deleter); }
- inline QSharedPointer(const QSharedPointer<T> &other) : value(other.value), d(other.d)
+ inline QSharedPointer(const QSharedPointer &other) : value(other.value), d(other.d)
{ if (d) ref(); }
- inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
+ inline QSharedPointer &operator=(const QSharedPointer &other)
{
QSharedPointer copy(other);
swap(copy);
return *this;
}
#ifdef Q_COMPILER_RVALUE_REFS
- inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
+ inline QSharedPointer(QSharedPointer &&other)
+ : value(other.value), d(other.d)
+ {
+ other.d = 0;
+ other.value = 0;
+ }
+ inline QSharedPointer &operator=(QSharedPointer &&other)
{
swap(other);
return *this;
@@ -339,7 +346,7 @@ public:
{ if (d) ref(); }
template <class X>
- inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
+ inline QSharedPointer &operator=(const QSharedPointer<X> &other)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalCopy(other);
@@ -355,7 +362,7 @@ public:
{ internalSet(other.d, other.value); return *this; }
inline void swap(QSharedPointer &other)
- { QSharedPointer<T>::internalSwap(other); }
+ { this->internalSwap(other); }
inline void reset() { clear(); }
inline void reset(T *t)
@@ -396,7 +403,7 @@ public:
#if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
template <typename... Args>
- static QSharedPointer<T> create(Args && ...arguments)
+ static QSharedPointer create(Args && ...arguments)
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -404,7 +411,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -416,7 +423,7 @@ public:
return result;
}
#else
- static inline QSharedPointer<T> create()
+ static inline QSharedPointer create()
{
typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
@@ -424,7 +431,7 @@ public:
# else
typename Private::DestroyerFn destroy = &Private::deleter;
# endif
- QSharedPointer<T> result(Qt::Uninitialized);
+ QSharedPointer result(Qt::Uninitialized);
result.d = Private::create(&result.value, destroy);
// now initialize the data
@@ -435,6 +442,27 @@ public:
result.d->setQObjectShared(result.value, true);
return result;
}
+
+ template <typename Arg>
+ static inline QSharedPointer create(const Arg &arg)
+ {
+ typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
+# else
+ typename Private::DestroyerFn destroy = &Private::deleter;
+# endif
+ QSharedPointer result(Qt::Uninitialized);
+ result.d = Private::create(&result.value, destroy);
+
+ // now initialize the data
+ new (result.data()) T(arg);
+# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
+ internalSafetyCheckAdd(result.d, result.value);
+# endif
+ result.d->setQObjectShared(result.value, true);
+ return result;
+ }
#endif
private:
@@ -452,6 +480,14 @@ private:
delete d;
}
+ template <class X>
+ inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
+ {
+ ptr->initializeFromSharedPointer(*this);
+ }
+
+ inline void enableSharedFromThis(...) {}
+
template <typename Deleter>
inline void internalConstruct(T *ptr, Deleter deleter)
{
@@ -472,6 +508,7 @@ private:
internalSafetyCheckAdd(d, ptr);
#endif
d->setQObjectShared(ptr, true);
+ enableSharedFromThis(ptr);
}
template <class X>
@@ -555,7 +592,7 @@ public:
inline bool operator !() const { return isNull(); }
inline T *data() const { return d == 0 || d->strongref.load() == 0 ? 0 : value; }
- inline QWeakPointer() : d(0), value(0) { }
+ Q_DECL_CONSTEXPR inline QWeakPointer() : d(0), value(0) { }
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
#ifndef QT_NO_QOBJECT
@@ -573,17 +610,23 @@ public:
{ return *this = QWeakPointer(ptr); }
#endif
- inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
+ inline QWeakPointer(const QWeakPointer &o) : d(o.d), value(o.value)
{ if (d) d->weakref.ref(); }
- inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
+ inline QWeakPointer &operator=(const QWeakPointer &o)
{
internalSet(o.d, o.value);
return *this;
}
+ inline void swap(QWeakPointer &other)
+ {
+ qSwap(this->d, other.d);
+ qSwap(this->value, other.value);
+ }
+
inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
{ if (d) d->weakref.ref();}
- inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<T> &o)
{
internalSet(o.d, o.value);
return *this;
@@ -594,7 +637,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
+ inline QWeakPointer &operator=(const QWeakPointer<X> &o)
{
// conversion between X and T could require access to the virtual table
// so force the operation to go through QSharedPointer
@@ -615,7 +658,7 @@ public:
{ *this = o; }
template <class X>
- inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
+ inline QWeakPointer &operator=(const QSharedPointer<X> &o)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalSet(o.d, o.data());
@@ -630,9 +673,11 @@ public:
inline bool operator!=(const QSharedPointer<X> &o) const
{ return !(*this == o); }
- inline void clear() { *this = QWeakPointer<T>(); }
+ inline void clear() { *this = QWeakPointer(); }
inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
+ // std::weak_ptr compatibility:
+ inline QSharedPointer<T> lock() const { return toStrongRef(); }
#if defined(QWEAKPOINTER_ENABLE_ARROW)
inline T *operator->() const { return data(); }
@@ -672,6 +717,37 @@ public:
T *value;
};
+template <class T>
+class QEnableSharedFromThis
+{
+protected:
+#ifdef Q_COMPILER_DEFAULT_MEMBERS
+ QEnableSharedFromThis() = default;
+#else
+ Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
+#endif
+ QEnableSharedFromThis(const QEnableSharedFromThis &) {}
+ QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
+
+public:
+ inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
+ inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
+
+#ifndef Q_NO_TEMPLATE_FRIENDS
+private:
+ template <class X> friend class QSharedPointer;
+#else
+public:
+#endif
+ template <class X>
+ inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
+ {
+ weakPointer = ptr;
+ }
+
+ mutable QWeakPointer<T> weakPointer;
+};
+
//
// operator== and operator!=
//
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 2d679e036e..a99c460b06 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -54,7 +54,7 @@
# include <intrin.h>
# endif
# endif
-#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(QT_COMPILER_SUPPORTS_IWMMXT))
+#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32) || defined(QT_COMPILER_SUPPORTS_IWMMXT))
#include "private/qcore_unix_p.h"
// the kernel header definitions for HWCAP_*
@@ -253,6 +253,22 @@ static void xgetbv(uint in, uint &eax, uint &edx)
static inline uint detectProcessorFeatures()
{
+ // Flags from the CR0 / XCR0 state register
+ enum XCR0Flags {
+ X87 = 1 << 0,
+ XMM0_15 = 1 << 1,
+ YMM0_15Hi128 = 1 << 2,
+ BNDRegs = 1 << 3,
+ BNDCSR = 1 << 4,
+ OpMask = 1 << 5,
+ ZMM0_15Hi256 = 1 << 6,
+ ZMM16_31 = 1 << 7,
+
+ SSEState = XMM0_15,
+ AVXState = XMM0_15 | YMM0_15Hi128,
+ AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
+ };
+
uint features = 0;
int cpuidLevel = maxBasicCpuidSupported();
if (cpuidLevel < 1)
@@ -264,6 +280,7 @@ static inline uint detectProcessorFeatures()
// x86 might not have SSE2 support
if (cpuid01EDX & (1u << 26))
features |= SSE2;
+ // we should verify that the OS enabled saving of the SSE state...
#else
// x86-64 or x32
features = SSE2;
@@ -291,7 +308,7 @@ static inline uint detectProcessorFeatures()
if (cpuidLevel >= 7)
cpuidFeatures07_00(cpuid0700EBX);
- if ((xgetbvA & 6) == 6) {
+ if ((xgetbvA & AVXState) == AVXState) {
// support for YMM and XMM registers is enabled
if (cpuid01ECX & (1u << 28))
features |= AVX;
@@ -308,6 +325,141 @@ static inline uint detectProcessorFeatures()
return features;
}
+#elif defined(Q_PROCESSOR_MIPS_32)
+
+#if defined(Q_OS_LINUX)
+//
+// Do not use QByteArray: it could use SIMD instructions itself at
+// some point, thus creating a recursive dependency. Instead, use a
+// QSimpleBuffer, which has the bare minimum needed to use memory
+// dynamically and read lines from /proc/cpuinfo of arbitrary sizes.
+//
+struct QSimpleBuffer {
+ static const int chunk_size = 256;
+ char *data;
+ unsigned alloc;
+ unsigned size;
+
+ QSimpleBuffer(): data(0), alloc(0), size(0) {}
+ ~QSimpleBuffer() { ::free(data); }
+
+ void resize(unsigned newsize) {
+ if (newsize > alloc) {
+ unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1);
+ if (newalloc < newsize) newalloc = newsize;
+ if (newalloc != alloc) {
+ data = static_cast<char*>(::realloc(data, newalloc));
+ alloc = newalloc;
+ }
+ }
+ size = newsize;
+ }
+ void append(const QSimpleBuffer &other, unsigned appendsize) {
+ unsigned oldsize = size;
+ resize(oldsize + appendsize);
+ ::memcpy(data + oldsize, other.data, appendsize);
+ }
+ void popleft(unsigned amount) {
+ if (amount >= size) return resize(0);
+ size -= amount;
+ ::memmove(data, data + amount, size);
+ }
+ char* cString() {
+ if (!alloc) resize(1);
+ return (data[size] = '\0', data);
+ }
+};
+
+//
+// Uses a scratch "buffer" (which must be used for all reads done in the
+// same file descriptor) to read chunks of data from a file, to read
+// one line at a time. Lines include the trailing newline character ('\n').
+// On EOF, line.size is zero.
+//
+static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer)
+{
+ for (;;) {
+ char *newline = static_cast<char*>(::memchr(buffer.data, '\n', buffer.size));
+ if (newline) {
+ unsigned piece_size = newline - buffer.data + 1;
+ line.append(buffer, piece_size);
+ buffer.popleft(piece_size);
+ line.resize(line.size - 1);
+ return;
+ }
+ if (buffer.size + QSimpleBuffer::chunk_size > buffer.alloc) {
+ int oldsize = buffer.size;
+ buffer.resize(buffer.size + QSimpleBuffer::chunk_size);
+ buffer.size = oldsize;
+ }
+ ssize_t read_bytes = ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size);
+ if (read_bytes > 0) buffer.size += read_bytes;
+ else return;
+ }
+}
+
+//
+// Checks if any line with a given prefix from /proc/cpuinfo contains
+// a certain string, surrounded by spaces.
+//
+static bool procCpuinfoContains(const char *prefix, const char *string)
+{
+ int cpuinfo_fd = ::qt_safe_open("/proc/cpuinfo", O_RDONLY);
+ if (cpuinfo_fd == -1)
+ return false;
+
+ unsigned string_len = ::strlen(string);
+ unsigned prefix_len = ::strlen(prefix);
+ QSimpleBuffer line, buffer;
+ bool present = false;
+ do {
+ line.resize(0);
+ bufReadLine(cpuinfo_fd, line, buffer);
+ char *colon = static_cast<char*>(::memchr(line.data, ':', line.size));
+ if (colon && line.size > prefix_len + string_len) {
+ if (!::strncmp(prefix, line.data, prefix_len)) {
+ // prefix matches, next character must be ':' or space
+ if (line.data[prefix_len] == ':' || ::isspace(line.data[prefix_len])) {
+ // Does it contain the string?
+ char *found = ::strstr(line.cString(), string);
+ if (found && ::isspace(found[-1]) &&
+ (::isspace(found[string_len]) || found[string_len] == '\0')) {
+ present = true;
+ break;
+ }
+ }
+ }
+ }
+ } while (line.size);
+
+ ::qt_safe_close(cpuinfo_fd);
+ return present;
+}
+#endif
+
+static inline uint detectProcessorFeatures()
+{
+ // NOTE: MIPS 74K cores are the only ones supporting DSPr2.
+ uint flags = 0;
+
+#if defined __mips_dsp
+ flags |= DSP;
+# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
+ flags |= DSPR2;
+# elif defined(Q_OS_LINUX)
+ if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
+ flags |= DSPR2;
+# endif
+#elif defined(Q_OS_LINUX)
+ if (procCpuinfoContains("ASEs implemented", "dsp")) {
+ flags |= DSP;
+ if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
+ flags |= DSPR2;
+ }
+#endif
+
+ return flags;
+}
#else
static inline uint detectProcessorFeatures()
@@ -330,6 +482,8 @@ static inline uint detectProcessorFeatures()
avx2
hle
rtm
+ dsp
+ dspr2
*/
// begin generated
@@ -345,11 +499,13 @@ static const char features_string[] =
" avx2\0"
" hle\0"
" rtm\0"
+ " dsp\0"
+ " dspr2\0"
"\0";
static const int features_indices[] = {
0, 8, 14, 20, 26, 33, 41, 49,
- 54, 60, 65, -1
+ 54, 60, 65, 70, 75, -1
};
// end generated
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index e1c22bac71..19a1943367 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -50,6 +50,7 @@
* They mean the compiler supports the necessary flags and the headers
* for the x86 and ARM intrinsics:
* - GCC: the -mXXX or march=YYY flag is necessary before #include
+ * up to 4.8; GCC >= 4.9 can include unconditionally
* - Intel CC: #include can happen unconditionally
* - MSVC: #include can happen unconditionally
* - RVCT: ???
@@ -60,25 +61,99 @@
* up do define __AVX__ if the -arch:AVX option is passed on the command-line.
*
* Supported XXX are:
- * Flag | Arch | GCC | Intel CC | MSVC |
- * NEON | ARM | I & C | None | ? |
- * IWMMXT | ARM | I & C | None | I & C |
- * SSE2 | x86 | I & C | I & C | I & C |
- * SSE3 | x86 | I & C | I & C | I only |
- * SSSE3 | x86 | I & C | I & C | I only |
- * SSE4_1 | x86 | I & C | I & C | I only |
- * SSE4_2 | x86 | I & C | I & C | I only |
- * AVX | x86 | I & C | I & C | I & C |
- * AVX2 | x86 | I & C | I & C | I only |
+ * Flag | Arch | GCC | Intel CC | MSVC |
+ * ARM_NEON | ARM | I & C | None | ? |
+ * IWMMXT | ARM | I & C | None | I & C |
+ * SSE2 | x86 | I & C | I & C | I & C |
+ * SSE3 | x86 | I & C | I & C | I only |
+ * SSSE3 | x86 | I & C | I & C | I only |
+ * SSE4_1 | x86 | I & C | I & C | I only |
+ * SSE4_2 | x86 | I & C | I & C | I only |
+ * AVX | x86 | I & C | I & C | I & C |
+ * AVX2 | x86 | I & C | I & C | I only |
* I = intrinsics; C = code generation
+ *
+ * Code can use the following constructs to determine compiler support & status:
+ * - #ifdef __XXX__ (e.g: #ifdef __AVX__ or #ifdef __ARM_NEON__)
+ * If this test passes, then the compiler is already generating code for that
+ * given sub-architecture. The intrinsics for that sub-architecture are
+ * #included and can be used without restriction or runtime check.
+ *
+ * - #if QT_COMPILER_SUPPORTS(XXX)
+ * If this test passes, then the compiler is able to generate code for that
+ * given sub-architecture in another translation unit, given the right set of
+ * flags. Use of the intrinsics is not guaranteed. This is useful with
+ * runtime detection (see below).
+ *
+ * - #if QT_COMPILER_SUPPORTS_HERE(XXX)
+ * If this test passes, then the compiler is able to generate code for that
+ * given sub-architecture in this translation unit, even if it is not doing
+ * that now (it might be). Individual functions may be tagged with
+ * QT_FUNCTION_TARGET(XXX) to cause the compiler to generate code for that
+ * sub-arch. Only inside such functions is the use of the intrisics
+ * guaranteed to work. This is useful with runtime detection (see below).
+ *
+ * Runtime detection of a CPU sub-architecture can be done with the
+ * qCpuHasFeature(XXX) function. There are two strategies for generating
+ * optimized code like that:
+ *
+ * 1) place the optimized code in a different translation unit (C or assembly
+ * sources) and pass the correct flags to the compiler to enable support. Those
+ * sources must not include qglobal.h, which means they cannot include this
+ * file either. The dispatcher function would look like this:
+ *
+ * void foo()
+ * {
+ * #if QT_COMPILER_SUPPORTS(XXX)
+ * if (qCpuHasFeature(XXX)) {
+ * foo_optimized_xxx();
+ * return;
+ * }
+ * #endif
+ * foo_plain();
+ * }
+ *
+ * 2) place the optimized code in a function tagged with QT_FUNCTION_TARGET and
+ * surrounded by #if QT_COMPILER_SUPPORTS_HERE(XXX). That code can freely use
+ * other Qt code. The dispatcher function would look like this:
+ *
+ * void foo()
+ * {
+ * #if QT_COMPILER_SUPPORTS_HERE(XXX)
+ * if (qCpuHasFeature(XXX)) {
+ * foo_optimized_xxx();
+ * return;
+ * }
+ * #endif
+ * foo_plain();
+ * }
*/
#if defined(__MINGW64_VERSION_MAJOR) || (defined(Q_CC_MSVC) && !defined(Q_OS_WINCE))
#include <intrin.h>
#endif
+#define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0)
+
+#if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \
+ || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \
+ && !defined(QT_BOOTSTRAPPED)
+# define QT_COMPILER_SUPPORTS_SIMD_ALWAYS
+# define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x)
+# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+ /* GCC requires attributes for a function */
+# define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x)))
+# else
+# define QT_FUNCTION_TARGET(x)
+# endif
+#else
+# define QT_COMPILER_SUPPORTS_HERE(x) defined(__ ## x ## __)
+# define QT_FUNCTION_TARGET(x)
+#endif
+
// SSE intrinsics
-#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
+#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#if defined(QT_LINUXBASE) || defined(Q_OS_ANDROID_NO_SDK)
/// this is an evil hack - the posix_memalign declaration in LSB
/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
@@ -95,27 +170,33 @@
#endif
// SSE3 intrinsics
-#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
+#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(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3"
+#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(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1"
+#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(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2"
+#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
#include <nmmintrin.h>
#endif
// AVX intrinsics
-#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(Q_CC_MSVC))
+#define QT_FUNCTION_TARGET_STRING_AVX "avx"
+#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2"
+#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>
@@ -149,8 +230,10 @@
#endif
// NEON intrinsics
+// note: as of GCC 4.9, does not support function targets for ARM
#if defined __ARM_NEON__
#include <arm_neon.h>
+#define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon"
#endif
@@ -171,12 +254,14 @@
#endif
#endif
+#undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS
+
QT_BEGIN_NAMESPACE
enum CPUFeatures {
IWMMXT = 0x1,
- NEON = 0x2,
+ NEON = 0x2, ARM_NEON = NEON,
SSE2 = 0x4,
SSE3 = 0x8,
SSSE3 = 0x10,
@@ -186,6 +271,8 @@ enum CPUFeatures {
AVX2 = 0x100,
HLE = 0x200,
RTM = 0x400,
+ DSP = 0x800,
+ DSPR2 = 0x1000,
// used only to indicate that the CPU detection was initialised
QSimdInitialized = 0x80000000
@@ -225,6 +312,12 @@ static const uint qCompilerCpuFeatures = 0
#if defined __IWMMXT__
| IWMMXT
#endif
+#if defined __mips_dsp
+ | DSP
+#endif
+#if defined __mips_dspr2
+ | DSPR2
+#endif
;
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index c9a6ffa03a..03966ab1d6 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -445,9 +445,11 @@ QDataStream &operator>>(QDataStream &s, QSize &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSize &s) {
+QDebug operator<<(QDebug dbg, const QSize &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSize(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
@@ -870,9 +872,11 @@ QDataStream &operator>>(QDataStream &s, QSizeF &sz)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSizeF &s) {
+QDebug operator<<(QDebug dbg, const QSizeF &s)
+{
+ QDebugStateSaver saver(dbg);
dbg.nospace() << "QSizeF(" << s.width() << ", " << s.height() << ')';
- return dbg.space();
+ return dbg;
}
#endif
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 83f1bac2ef..fdde0955dd 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -223,8 +223,15 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size)
// we're going to read str[offset..offset+15] (16 bytes)
for ( ; str + offset + 15 < e; offset += 16) {
- const __m128i nullMask = _mm_set1_epi32(0);
const __m128i chunk = _mm_loadu_si128((__m128i*)(str + offset)); // load
+#ifdef __AVX2__
+ // zero extend to an YMM register
+ const __m256i extended = _mm256_cvtepu8_epi16(chunk);
+
+ // store
+ _mm256_storeu_si256((__m256i*)(dst + offset), extended);
+#else
+ const __m128i nullMask = _mm_set1_epi32(0);
// unpack the first 8 bytes, padding with zeros
const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
@@ -233,6 +240,7 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size)
// unpack the last 8 bytes, padding with zeros
const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
_mm_storeu_si128((__m128i*)(dst + offset + 8), secondHalf); // store
+#endif
}
size = size % 16;
@@ -540,8 +548,20 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
// and c[offset..offset+15] (16 bytes)
for ( ; uc + offset + 15 < e; offset += 16) {
// similar to fromLatin1_helper:
- // load Latin 1 data and expand to UTF-16
+ // load 16 bytes of Latin 1 data
__m128i chunk = _mm_loadu_si128((__m128i*)(c + offset));
+
+# ifdef __AVX2__
+ // expand Latin 1 data via zero extension
+ __m256i ldata = _mm256_cvtepu8_epi16(chunk);
+
+ // load UTF-16 data and compare
+ __m256i ucdata = _mm256_loadu_si256((__m256i*)(uc + offset));
+ __m256i result = _mm256_cmpeq_epi16(ldata, ucdata);
+
+ uint mask = ~_mm256_movemask_epi8(result);
+# else
+ // expand via unpacking
__m128i firstHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i secondHalf = _mm_unpackhi_epi8(chunk, nullmask);
@@ -552,6 +572,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
__m128i result2 = _mm_cmpeq_epi16(secondHalf, ucdata2);
uint mask = ~(_mm_movemask_epi8(result1) | _mm_movemask_epi8(result2) << 16);
+# endif
if (mask) {
// found a different character
uint idx = uint(_bit_scan_forward(mask));
@@ -1309,7 +1330,7 @@ const QString::Null QString::null = { };
This constructor is only available if Qt is configured with STL
compatibility enabled.
- \sa fromLatin1(), fromLocal8Bit(), fromUtf8()
+ \sa fromLatin1(), fromLocal8Bit(), fromUtf8(), QByteArray::fromStdString()
*/
/*! \fn QString QString::fromStdWString(const std::wstring &str)
@@ -4090,21 +4111,22 @@ QString QString::right(int n) const
QString QString::mid(int position, int n) const
{
- if (position > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &position, &n)) {
+ case QContainerImplHelper::Null:
return QString();
- if (position < 0) {
- if (n < 0 || n + position >= d->size)
- return *this;
- if (n + position <= 0)
- return QString();
-
- n += position;
- position = 0;
- } else if (uint(n) > uint(d->size - position))
- n = d->size - position;
- if (position == 0 && n == d->size)
+ case QContainerImplHelper::Empty:
+ {
+ QStringDataPtr empty = { Data::allocate(0) };
+ return QString(empty);
+ }
+ case QContainerImplHelper::Full:
return *this;
- return QString((const QChar*) d->data() + position, n);
+ case QContainerImplHelper::Subset:
+ return QString((const QChar*)d->data() + position, n);
+ }
+ Q_UNREACHABLE();
+ return QString();
}
/*!
@@ -6602,6 +6624,27 @@ QString QString::number(double n, char f, int prec)
return s;
}
+namespace {
+template<class ResultList, typename MidMethod, typename Separator>
+static ResultList splitString(const QString &source, MidMethod mid, const Separator &sep,
+ QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize)
+{
+ ResultList list;
+ int start = 0;
+ int end;
+ int extra = 0;
+ while ((end = source.indexOf(sep, start + extra, cs)) != -1) {
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = end + separatorSize;
+ extra = (separatorSize == 0 ? 1 : 0);
+ }
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
+ return list;
+}
+} // namespace
+
/*!
Splits the string into substrings wherever \a sep occurs, and
returns the list of those strings. If \a sep does not match
@@ -6622,40 +6665,71 @@ QString QString::number(double n, char f, int prec)
*/
QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
- QStringList list;
- int start = 0;
- int extra = 0;
- int end;
- while ((end = indexOf(sep, start + extra, cs)) != -1) {
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + sep.size();
- extra = (sep.size() == 0 ? 1 : 0);
- }
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
- return list;
+ return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, sep.size());
}
/*!
+ Splits the string into substring references wherever \a sep occurs, and
+ returns the list of those strings. If \a sep does not match
+ anywhere in the string, splitRef() returns a single-element vector
+ containing this string reference.
+
+ \a cs specifies whether \a sep should be matched case
+ sensitively or case insensitively.
+
+ If \a behavior is QString::SkipEmptyParts, empty entries don't
+ appear in the result. By default, empty entries are kept.
+
+ \note All references are valid as long this string is alive. Destroying this
+ string will cause all references be dangling pointers.
+
+ \since 5.4
+ \sa QStringRef split()
+*/
+QVector<QStringRef> QString::splitRef(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{
+ return splitString<QVector<QStringRef> >(*this, &QString::midRef, sep, behavior, cs, sep.size());
+}
+/*!
\overload
*/
QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
- QStringList list;
+ return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, 1);
+}
+
+/*!
+ \overload
+ \since 5.4
+*/
+QVector<QStringRef> QString::splitRef(QChar sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{
+ return splitString<QVector<QStringRef> >(*this, &QString::midRef, sep, behavior, cs, 1);
+}
+
+#ifndef QT_NO_REGEXP
+namespace {
+template<class ResultList, typename MidMethod>
+static ResultList splitString(const QString &source, MidMethod mid, const QRegExp &rx, QString::SplitBehavior behavior)
+{
+ QRegExp rx2(rx);
+ ResultList list;
int start = 0;
+ int extra = 0;
int end;
- while ((end = indexOf(sep, start, cs)) != -1) {
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + 1;
+ while ((end = rx2.indexIn(source, start + extra)) != -1) {
+ int matchedLen = rx2.matchedLength();
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = end + matchedLen;
+ extra = (matchedLen == 0) ? 1 : 0;
}
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
return list;
}
+} // namespace
-#ifndef QT_NO_REGEXP
/*!
\overload
@@ -6684,26 +6758,60 @@ QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivit
*/
QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
{
- QRegExp rx2(rx);
- QStringList list;
- int start = 0;
- int extra = 0;
- int end;
- while ((end = rx2.indexIn(*this, start + extra)) != -1) {
- int matchedLen = rx2.matchedLength();
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = end + matchedLen;
- extra = (matchedLen == 0) ? 1 : 0;
- }
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
- return list;
+ return splitString<QStringList>(*this, &QString::mid, rx, behavior);
+}
+
+/*!
+ \overload
+ \since 5.4
+
+ Splits the string into substring references wherever the regular expression
+ \a rx matches, and returns the list of those strings. If \a rx
+ does not match anywhere in the string, splitRef() returns a
+ single-element vector containing this string reference.
+
+ \note All references are valid as long this string is alive. Destroying this
+ string will cause all references be dangling pointers.
+
+ \sa QStringRef split()
+*/
+QVector<QStringRef> QString::splitRef(const QRegExp &rx, SplitBehavior behavior) const
+{
+ return splitString<QVector<QStringRef> >(*this, &QString::midRef, rx, behavior);
}
#endif
#ifndef QT_NO_REGULAREXPRESSION
#ifndef QT_BOOTSTRAPPED
+namespace {
+template<class ResultList, typename MidMethod>
+static ResultList splitString(const QString &source, MidMethod mid, const QRegularExpression &re,
+ QString::SplitBehavior behavior)
+{
+ ResultList list;
+ if (!re.isValid()) {
+ qWarning("QString::split: invalid QRegularExpression object");
+ return list;
+ }
+
+ int start = 0;
+ int end = 0;
+ QRegularExpressionMatchIterator iterator = re.globalMatch(source);
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ end = match.capturedStart();
+ if (start != end || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, end - start));
+ start = match.capturedEnd();
+ }
+
+ if (start != source.size() || behavior == QString::KeepEmptyParts)
+ list.append((source.*mid)(start, -1));
+
+ return list;
+}
+} // namespace
+
/*!
\overload
\since 5.0
@@ -6733,27 +6841,26 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
*/
QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior) const
{
- QStringList list;
- if (!re.isValid()) {
- qWarning("QString::split: invalid QRegularExpression object");
- return list;
- }
+ return splitString<QStringList>(*this, &QString::mid, re, behavior);
+}
- int start = 0;
- int end = 0;
- QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
- while (iterator.hasNext()) {
- QRegularExpressionMatch match = iterator.next();
- end = match.capturedStart();
- if (start != end || behavior == KeepEmptyParts)
- list.append(mid(start, end - start));
- start = match.capturedEnd();
- }
+/*!
+ \overload
+ \since 5.4
- if (start != size() || behavior == KeepEmptyParts)
- list.append(mid(start));
+ Splits the string into substring references wherever the regular expression
+ \a re matches, and returns the list of those strings. If \a re
+ does not match anywhere in the string, splitRef() returns a
+ single-element vector containing this string reference.
- return list;
+ \note All references are valid as long this string is alive. Destroying this
+ string will cause all references be dangling pointers.
+
+ \sa split() QStringRef
+*/
+QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavior behavior) const
+{
+ return splitString<QVector<QStringRef> >(*this, &QString::midRef, re, behavior);
}
#endif // QT_BOOTSTRAPPED
#endif // QT_NO_REGULAREXPRESSION
@@ -6938,15 +7045,18 @@ static ArgEscapeData findArgEscapes(const QString &s)
break;
}
- if (c->digitValue() == -1)
+ int escape = c->digitValue();
+ if (escape == -1)
continue;
- int escape = c->digitValue();
++c;
- if (c != uc_end && c->digitValue() != -1) {
- escape = (10 * escape) + c->digitValue();
- ++c;
+ if (c != uc_end) {
+ int next_escape = c->digitValue();
+ if (next_escape != -1) {
+ escape = (10 * escape) + next_escape;
+ ++c;
+ }
}
if (escape > d.min_escape)
@@ -7726,7 +7836,7 @@ bool QString::isRightToLeft() const
If the QString contains non-Latin1 Unicode characters, using this
can lead to loss of information.
- \sa toLatin1(), toUtf8(), toLocal8Bit()
+ \sa toLatin1(), toUtf8(), toLocal8Bit(), QByteArray::toStdString()
*/
/*!
@@ -8794,19 +8904,19 @@ QStringRef QString::rightRef(int n) const
*/
QStringRef QStringRef::mid(int pos, int n) const
{
- if (pos > m_size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(m_size, &pos, &n)) {
+ case QContainerImplHelper::Null:
return QStringRef();
- if (pos < 0) {
- if (n < 0 || n + pos >= m_size)
- return QStringRef(m_string, m_position, m_size);
- if (n + pos <= 0)
- return QStringRef();
- n += pos;
- pos = 0;
- } else if (uint(n) > uint(m_size - pos)) {
- n = m_size - pos;
+ case QContainerImplHelper::Empty:
+ return QStringRef(m_string, 0, 0);
+ case QContainerImplHelper::Full:
+ return *this;
+ case QContainerImplHelper::Subset:
+ return QStringRef(m_string, pos + m_position, n);
}
- return QStringRef(m_string, pos + m_position, n);
+ Q_UNREACHABLE();
+ return QStringRef();
}
/*!
@@ -8831,19 +8941,19 @@ QStringRef QStringRef::mid(int pos, int n) const
*/
QStringRef QString::midRef(int position, int n) const
{
- if (position > d->size)
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &position, &n)) {
+ case QContainerImplHelper::Null:
return QStringRef();
- if (position < 0) {
- if (n < 0 || n + position >= d->size)
- return QStringRef(this, 0, d->size);
- if (n + position <= 0)
- return QStringRef();
-
- n += position;
- position = 0;
- } else if (uint(n) > uint(d->size - position))
- n = d->size - position;
- return QStringRef(this, position, n);
+ case QContainerImplHelper::Empty:
+ return QStringRef(this, 0, 0);
+ case QContainerImplHelper::Full:
+ return QStringRef(this, 0, d->size);
+ case QContainerImplHelper::Subset:
+ return QStringRef(this, position, n);
+ }
+ Q_UNREACHABLE();
+ return QStringRef();
}
/*!
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 3985bc76fe..21b64f5006 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -441,13 +441,19 @@ public:
QStringList split(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
+ QVector<QStringRef> splitRef(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QStringList split(QChar sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
+ QVector<QStringRef> splitRef(QChar sep, SplitBehavior behavior = KeepEmptyParts,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
#ifndef QT_NO_REGEXP
QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
+ QVector<QStringRef> splitRef(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
#endif
#ifndef QT_NO_REGULAREXPRESSION
QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
+ QVector<QStringRef> splitRef(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
#endif
enum NormalizationForm {
NormalizationForm_D,
@@ -724,7 +730,6 @@ private:
void reallocData(uint alloc, bool grow = false);
void expand(int i);
- void updateProperties() const;
QString multiArg(int numArgs, const QString **args) const;
static int compare_helper(const QChar *data1, int length1,
const QChar *data2, int length2,
@@ -1222,7 +1227,7 @@ inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteA
#endif // QT_USE_QSTRINGBUILDER
inline std::string QString::toStdString() const
-{ const QByteArray asc = toUtf8(); return std::string(asc.constData(), asc.length()); }
+{ return toUtf8().toStdString(); }
inline QString QString::fromStdString(const std::string &s)
{ return fromUtf8(s.data(), int(s.size())); }
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 6b0b39c7bb..0d37b6ea58 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -191,20 +191,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QStringList::QStringList(const QStringList &other)
-
- Constructs a copy of the \a other string list.
-
- This operation takes \l{constant time} because QStringList is
- \l{implicitly shared}, making the process of returning a
- QStringList from a function very fast. If a shared instance is
- modified, it will be copied (copy-on-write), and that takes
- \l{linear time}.
-
- \sa operator=()
-*/
-
-/*!
\fn QStringList::QStringList(const QList<QString> &other)
Constructs a copy of \a other.
@@ -218,6 +204,37 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QStringList::QStringList(QList<QString> &&other)
+ \overload
+ \since 5.4
+
+ Move-constructs from QList<QString>.
+
+ After a successful construction, \a other will be empty.
+*/
+
+/*!
+ \fn QStringList &QStringList::operator=(const QList<QString> &other)
+ \since 5.4
+
+ Copy assignment operator from QList<QString>. Assigns the \a other
+ list of strings to this string list.
+
+ After the operation, \a other and \c *this will be equal.
+*/
+
+/*!
+ \fn QStringList &QStringList::operator=(QList<QString> &&other)
+ \overload
+ \since 5.4
+
+ Move assignment operator from QList<QString>. Moves the \a other
+ list of strings to this string list.
+
+ After the operation, \a other will be empty.
+*/
+
+/*!
\fn void QStringList::sort(Qt::CaseSensitivity cs)
Sorts the list of strings in ascending order.
@@ -235,9 +252,14 @@ QT_BEGIN_NAMESPACE
integer index.
*/
-static inline bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
-{
- return s1.compare(s2, Qt::CaseInsensitive) < 0;
+namespace {
+struct CaseInsensitiveLessThan {
+ typedef bool result_type;
+ result_type operator()(const QString &s1, const QString &s2) const
+ {
+ return s1.compare(s2, Qt::CaseInsensitive) < 0;
+ }
+};
}
void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
@@ -245,7 +267,7 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
if (cs == Qt::CaseSensitive)
std::sort(that->begin(), that->end());
else
- std::sort(that->begin(), that->end(), caseInsensitiveLessThan);
+ std::sort(that->begin(), that->end(), CaseInsensitiveLessThan());
}
@@ -457,7 +479,7 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
if (totalLength == 0)
return res;
res.reserve(totalLength);
- for (int i = 0; i < that->size(); ++i) {
+ for (int i = 0; i < size; ++i) {
if (i)
res.append(sep, seplen);
res += that->at(i);
@@ -492,6 +514,16 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i
the latter string list.
*/
+/*!
+ \fn QStringList &QStringList::operator<<(const QList<QString> &other)
+ \since 5.4
+
+ \overload
+
+ Appends the \a other string list to the string list and returns a reference to
+ the latter string list.
+*/
+
#ifndef QT_NO_DATASTREAM
/*!
\fn QDataStream &operator>>(QDataStream &in, QStringList &list)
@@ -725,7 +757,7 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that)
continue;
seen.insert(s);
if (j != i)
- (*that)[j] = s;
+ that->swap(i, j);
++j;
}
if (n != j)
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index a962b7c528..7f06be3ca0 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -63,12 +63,21 @@ class QStringList : public QList<QString>
public:
inline QStringList() { }
inline explicit QStringList(const QString &i) { append(i); }
- inline QStringList(const QStringList &l) : QList<QString>(l) { }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QStringList(QList<QString> &&l) : QList<QString>(std::move(l)) { }
+#endif
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
#endif
+ QStringList &operator=(const QList<QString> &other)
+ { QList<QString>::operator=(other); return *this; }
+#ifdef Q_COMPILER_RVALUE_REFS
+ QStringList &operator=(QList<QString> &&other)
+ { QList<QString>::operator=(std::move(other)); return *this; }
+#endif
+
inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
inline int removeDuplicates();
@@ -86,6 +95,8 @@ public:
{ append(str); return *this; }
inline QStringList &operator<<(const QStringList &l)
{ *this += l; return *this; }
+ inline QStringList &operator<<(const QList<QString> &l)
+ { *this += l; return *this; }
#ifndef QT_NO_REGEXP
inline QStringList filter(const QRegExp &rx) const;
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
index 4286119586..0575b5c999 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/tools/qtimezoneprivate.cpp
@@ -446,32 +446,43 @@ QTimeZone::OffsetData QTimeZonePrivate::toOffsetData(const QTimeZonePrivate::Dat
bool QTimeZonePrivate::isValidId(const QByteArray &ianaId)
{
// Rules for defining TZ/IANA names as per ftp://ftp.iana.org/tz/code/Theory
- // * Use only valid POSIX file name components
- // * Within a file name component, use only ASCII letters, `.', `-' and `_'.
- // * Do not use digits
- // * A file name component must not exceed 14 characters or start with `-'
- // Aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid so we need to accept digits
- if (ianaId.contains(' '))
- return false;
- QList<QByteArray> parts = ianaId.split('/');
- foreach (const QByteArray &part, parts) {
- if (part.size() > 14 || part.size() < 1)
- return false;
- if (part.at(0) == '-')
- return false;
- for (int i = 0; i < part.size(); ++i) {
- QChar ch = part.at(i);
- if (!(ch >= 'a' && ch <= 'z')
+ // 1. Use only valid POSIX file name components
+ // 2. Within a file name component, use only ASCII letters, `.', `-' and `_'.
+ // 3. Do not use digits
+ // 4. A file name component must not exceed 14 characters or start with `-'
+ // Aliases such as "Etc/GMT+7" and "SystemV/EST5EDT" are valid so we need to accept digits, ':', and '+'.
+
+ // The following would be preferable if QRegExp would work on QByteArrays directly:
+ // const QRegExp rx(QStringLiteral("[a-z0-9:+._][a-z0-9:+._-]{,13}(?:/[a-z0-9:+._][a-z0-9:+._-]{,13})*"),
+ // Qt::CaseInsensitive);
+ // return rx.exactMatch(ianaId);
+
+ // hand-rolled version:
+ const int MinSectionLength = 1;
+ const int MaxSectionLength = 14;
+ int sectionLength = 0;
+ for (const char *it = ianaId.begin(), * const end = ianaId.end(); it != end; ++it, ++sectionLength) {
+ const char ch = *it;
+ if (ch == '/') {
+ if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
+ return false; // violates (4)
+ sectionLength = -1;
+ } else if (ch == '-') {
+ if (sectionLength == 0)
+ return false; // violates (4)
+ } else if (!(ch >= 'a' && ch <= 'z')
&& !(ch >= 'A' && ch <= 'Z')
&& !(ch == '_')
&& !(ch >= '0' && ch <= '9')
&& !(ch == '-')
&& !(ch == '+')
&& !(ch == ':')
- && !(ch == '.'))
- return false;
+ && !(ch == '.')) {
+ return false; // violates (2)
}
}
+ if (sectionLength < MinSectionLength || sectionLength > MaxSectionLength)
+ return false; // violates (4)
return true;
}
@@ -558,8 +569,8 @@ template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone()
// Create default UTC time zone
QUtcTimeZonePrivate::QUtcTimeZonePrivate()
{
- const QString name = QStringLiteral("UTC");
- init(QByteArrayLiteral("UTC"), 0, name, name, QLocale::AnyCountry, name);
+ const QString name = utcQString();
+ init(utcQByteArray(), 0, name, name, QLocale::AnyCountry, name);
}
// Create a named UTC time zone
@@ -583,7 +594,7 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
QString utcId;
if (offsetSeconds == 0)
- utcId = QStringLiteral("UTC");
+ utcId = utcQString();
else
utcId = isoOffsetFormat(offsetSeconds);
@@ -675,7 +686,7 @@ qint32 QUtcTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
{
- return QByteArrayLiteral("UTC");
+ return utcQByteArray();
}
QSet<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h
index 417ee2efbf..e8d250784a 100644
--- a/src/corelib/tools/qtimezoneprivate_p.h
+++ b/src/corelib/tools/qtimezoneprivate_p.h
@@ -154,6 +154,17 @@ public:
static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
QLocale::Country country);
+ // returns "UTC" QString and QByteArray
+ static inline QString utcQString() Q_REQUIRED_RESULT
+ {
+ return QStringLiteral("UTC");
+ }
+
+ static inline QByteArray utcQByteArray() Q_REQUIRED_RESULT
+ {
+ return QByteArrayLiteral("UTC");
+ }
+
protected:
QByteArray m_id;
};
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index b4ea91e626..2c7b00f653 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -958,7 +958,7 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
// Give up for now and return UTC
if (ianaId.isEmpty())
- ianaId = QByteArrayLiteral("UTC");
+ ianaId = utcQByteArray();
return ianaId;
}
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 052e584855..6e2c6b47b2 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -249,7 +249,7 @@ static QByteArray windowsSystemZoneId()
}
// If we can't determine the current ID use UTC
- return QByteArrayLiteral("UTC");
+ return QTimeZonePrivate::utcQByteArray();
}
static QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
@@ -635,7 +635,7 @@ QByteArray QWinTimeZonePrivate::systemTimeZoneId() const
ianaId = windowsIdToDefaultIanaId(windowsId);
// If no global default then probably an unknown Windows ID so return UTC
if (ianaId.isEmpty())
- return QByteArrayLiteral("UTC");
+ return utcQByteArray();
}
return ianaId;
}
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index b00343dd39..38073a6e30 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
// implemented in qbytearray.cpp
-int Q_CORE_EXPORT qAllocMore(int alloc, int extra);
+int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp
index 41a22a779a..a351533a98 100644
--- a/src/corelib/tools/qunicodetables.cpp
+++ b/src/corelib/tools/qunicodetables.cpp
@@ -6920,24 +6920,24 @@ static const Properties uc_properties[] = {
{ 12, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 12, 0 }
};
-static inline const Properties *qGetProp(uint ucs4)
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4)
{
const int index = GET_PROP_INDEX(ucs4);
return uc_properties + index;
}
-static inline const Properties *qGetProp(ushort ucs2)
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2)
{
const int index = GET_PROP_INDEX_UCS2(ucs2);
return uc_properties + index;
}
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4)
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4)
{
return qGetProp(ucs4);
}
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2)
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2)
{
return qGetProp(ucs2);
}
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 89396540e0..e1a451f953 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -180,11 +180,11 @@
/*!
\fn QVector<T> QVector::mid(int pos, int length = -1) const
- Returns a vector whose elements are copied from this vector,
+ Returns a sub-vector which contains elements from this vector,
starting at position \a pos. If \a length is -1 (the default), all
- elements after \a pos are copied; otherwise \a length elements (or
+ elements after \a pos are included; otherwise \a length elements (or
all remaining elements if there are less than \a length elements)
- are copied.
+ are included.
*/
@@ -576,6 +576,28 @@
\sa remove(), QList::removeAt()
*/
+/*! \fn int QVector::removeAll(const T &t)
+ \since 5.4
+
+ Removes all elements that compare equal to \a t from the
+ vector. Returns the number of elements removed, if any.
+
+ Provided for compatibility with QList.
+
+ \sa removeOne(), QList::removeAll()
+*/
+
+/*! \fn bool QVector::removeOne(const T &t)
+ \since 5.4
+
+ Removes the first element that compares equal to \a t from the
+ vector. Returns whether an element was, in fact, removed.
+
+ Provided for compatibility with QList.
+
+ \sa removeAll(), QList::removeOne()
+*/
+
/*! \fn int QVector::length() const
\since 5.2
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 6f7c534085..f09f1a3c41 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -156,6 +156,24 @@ public:
// QList compatibility
void removeAt(int i) { remove(i); }
+ int removeAll(const T &t)
+ {
+ const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
+ if (cit == ce)
+ return 0;
+ const iterator e = end(), it = std::remove(c2m(cit), e, t);
+ const int result = std::distance(it, e);
+ erase(it, e);
+ return result;
+ }
+ bool removeOne(const T &t)
+ {
+ const int i = indexOf(t);
+ if (i < 0)
+ return false;
+ remove(i);
+ return true;
+ }
int length() const { return size(); }
T takeAt(int i) { T t = at(i); remove(i); return t; }
@@ -252,6 +270,7 @@ private:
{
return (i <= d->end()) && (d->begin() <= i);
}
+ iterator c2m(const_iterator it) { return begin() + (it - cbegin()); }
class AlignmentDummy { Data header; T array[1]; };
};
@@ -791,29 +810,30 @@ bool QVector<T>::contains(const T &t) const
template <typename T>
int QVector<T>::count(const T &t) const
{
- int c = 0;
- T* b = d->begin();
- T* i = d->end();
- while (i != b)
- if (*--i == t)
- ++c;
- return c;
+ return int(std::count(cbegin(), cend(), t));
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
{
- if (len < 0)
- len = size() - pos;
- if (pos == 0 && len == size())
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d->size, &pos, &len)) {
+ case QContainerImplHelper::Null:
+ case QContainerImplHelper::Empty:
+ return QVector<T>();
+ case QContainerImplHelper::Full:
return *this;
- if (pos + len > size())
- len = size() - pos;
- QVector<T> copy;
- copy.reserve(len);
- for (int i = pos; i < pos + len; ++i)
- copy += at(i);
- return copy;
+ case QContainerImplHelper::Subset:
+ break;
+ }
+
+ QVector<T> midResult;
+ midResult.reallocData(0, len);
+ T *srcFrom = d->begin() + pos;
+ T *srcTo = d->begin() + pos + len;
+ midResult.copyConstruct(srcFrom, srcTo, midResult.data());
+ midResult.d->size = len;
+ return midResult;
}
template <typename T>
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 57a9591060..d1208a1fe6 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -43,7 +43,6 @@ HEADERS += \
tools/qqueue.h \
tools/qrect.h \
tools/qregexp.h \
- tools/qregularexpression.h \
tools/qringbuffer_p.h \
tools/qrefcount.h \
tools/qscopedpointer.h \
@@ -100,7 +99,6 @@ SOURCES += \
tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
- tools/qregularexpression.cpp \
tools/qrefcount.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
@@ -176,10 +174,15 @@ contains(QT_CONFIG,icu) {
SOURCES += tools/qcollator_posix.cpp
}
-pcre {
- include($$PWD/../../3rdparty/pcre.pri)
-} else {
- LIBS_PRIVATE += -lpcre16
+!contains(QT_DISABLED_FEATURES, regularexpression) {
+ HEADERS += tools/qregularexpression.h
+ SOURCES += tools/qregularexpression.cpp
+
+ pcre {
+ include($$PWD/../../3rdparty/pcre.pri)
+ } else {
+ LIBS_PRIVATE += -lpcre16
+ }
}
INCLUDEPATH += ../3rdparty/harfbuzz/src
@@ -207,3 +210,4 @@ TR_EXCLUDE += ../3rdparty/*
# MIPS DSP
MIPS_DSP_ASM += tools/qstring_mips_dsp_asm.S
MIPS_DSP_HEADERS += ../gui/painting/qt_mips_asm_dsp_p.h
+CONFIG += simd
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index 83d0c73ae1..4b726a2295 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -1631,7 +1631,7 @@ void QXmlStreamReaderPrivate::resolveTag()
if (attributes[j].name() == attribute.name()
&& attributes[j].namespaceUri() == attribute.namespaceUri()
&& (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
- raiseWellFormedError(QXmlStream::tr("Attribute redefined."));
+ raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName().toString()));
}
}
@@ -1711,9 +1711,9 @@ uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
uint s;
// ### add toXShort to QStringRef?
if (sym(symbolIndex).c == 'x')
- s = symString(symbolIndex, 1).toString().toUInt(&ok, 16);
+ s = symString(symbolIndex, 1).toUInt(&ok, 16);
else
- s = symString(symbolIndex).toString().toUInt(&ok, 10);
+ s = symString(symbolIndex).toUInt(&ok, 10);
ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
|| (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= QChar::LastValidCodePoint));
@@ -1773,7 +1773,7 @@ void QXmlStreamReaderPrivate::startDocument()
{
QString err;
if (documentVersion != QLatin1String("1.0")) {
- if (documentVersion.toString().contains(QLatin1Char(' ')))
+ if (documentVersion.contains(QLatin1Char(' ')))
err = QXmlStream::tr("Invalid XML version string.");
else
err = QXmlStream::tr("Unsupported XML version.");