summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/corelib.pro14
-rw-r--r--src/corelib/global/qcompilerdetection.h6
-rw-r--r--src/corelib/global/qglobal.h12
-rw-r--r--src/corelib/global/qlogging.cpp2
-rw-r--r--src/corelib/io/io.pri2
-rw-r--r--src/corelib/io/qdir.cpp4
-rw-r--r--src/corelib/io/qfile.cpp5
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp1
-rw-r--r--src/corelib/io/qstandardpaths_android.cpp331
-rw-r--r--src/corelib/io/qurl.cpp2
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp28
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp21
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h1
-rw-r--r--src/corelib/kernel/qobject.cpp9
-rw-r--r--src/corelib/kernel/qobject_p.h6
-rw-r--r--src/corelib/thread/qthread_p.h2
-rw-r--r--src/corelib/thread/qthread_unix.cpp4
-rw-r--r--src/corelib/thread/qthread_win.cpp4
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp3
-rw-r--r--src/corelib/tools/qdatetime.cpp56
-rw-r--r--src/corelib/tools/qlocale_win.cpp3
-rw-r--r--src/corelib/tools/qstring.cpp35
-rw-r--r--src/corelib/tools/qstring_mips_dsp_asm.S449
-rw-r--r--src/corelib/tools/qvector.h14
-rw-r--r--src/corelib/tools/tools.pri4
25 files changed, 976 insertions, 42 deletions
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 406e0fd396..373b3f148d 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -111,3 +111,17 @@ 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/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 908800b317..2c2e1295c5 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -256,7 +256,7 @@
# if defined(__EDG__)
# define Q_CC_EDG
# endif
-/* Compaq have disabled EDG's _BOOL macro and use _BOOL_EXISTS instead
+/* Compaq has disabled EDG's _BOOL macro and uses _BOOL_EXISTS instead
- observed on Compaq C++ V6.3-002.
In any case versions prior to Compaq C++ V6.0-005 do not have bool. */
# if !defined(_BOOL_EXISTS)
@@ -794,13 +794,13 @@
# define Q_COMPILER_DECLTYPE
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_STATIC_ASSERT
-// MSVC's library has std::initilizer_list, but the compiler does not support the braces initialization
+// MSVC's library has std::initializer_list, but the compiler does not support the braces initialization
//# define Q_COMPILER_INITIALIZER_LISTS
//# define Q_COMPILER_UNIFORM_INIT
# endif
# if _MSC_VER >= 1700
/* C++11 features supported in VC11 = VC2012: */
-# undef Q_DECL_OVERRIDE /* undo 2005/2098 settings... */
+# 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
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 8a86dc158e..f68f6af920 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -829,18 +829,18 @@ Q_CORE_EXPORT void qFreeAligned(void *ptr);
#endif
#if defined(QT_NO_WARNINGS)
# if defined(Q_CC_MSVC)
-# pragma warning(disable: 4251) /* class 'A' needs to have dll interface for to be used by clients of class 'B'. */
-# pragma warning(disable: 4244) /* 'conversion' conversion from 'type1' to 'type2', possible loss of data */
+# pragma warning(disable: 4251) /* class 'type' needs to have dll-interface to be used by clients of class 'type2' */
+# pragma warning(disable: 4244) /* conversion from 'type1' to 'type2', possible loss of data */
# pragma warning(disable: 4275) /* non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' */
-# pragma warning(disable: 4514) /* unreferenced inline/local function has been removed */
+# pragma warning(disable: 4514) /* unreferenced inline function has been removed */
# pragma warning(disable: 4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */
# pragma warning(disable: 4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */
# pragma warning(disable: 4706) /* assignment within conditional expression */
-# pragma warning(disable: 4786) /* truncating debug info after 255 characters */
+# pragma warning(disable: 4786) /* 'identifier' : identifier was truncated to 'number' characters in the debug information */
# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
-# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */
+# pragma warning(disable: 4231) /* nonstandard extension used : 'identifier' before template explicit instantiation */
# pragma warning(disable: 4710) /* function not inlined */
-# pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify -GX */
+# pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
# elif defined(Q_CC_BOR)
# pragma option -w-inl
# pragma option -w-aus
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 076582373e..28493311fb 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -102,7 +102,7 @@ static inline bool hasStdErr()
}
# endif // !Q_OS_WINCE && !Q_OS_WINRT
-bool qWinLogToStderr()
+Q_CORE_EXPORT bool qWinLogToStderr()
{
# if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
static const bool result = hasStdErr();
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 0ec3d949b9..3f2f025aeb 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -144,6 +144,8 @@ win32 {
}
} else:blackberry {
SOURCES += io/qstandardpaths_blackberry.cpp
+ } else:android {
+ SOURCES += io/qstandardpaths_android.cpp
} else {
SOURCES += io/qstandardpaths_unix.cpp
}
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index a60bcde30d..3075e0fb12 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -855,7 +855,7 @@ QString QDir::fromNativeSeparators(const QString &pathName)
/*!
Changes the QDir's directory to \a dirName.
- Returns \c true if the new directory exists and is readable;
+ Returns \c true if the new directory exists;
otherwise returns \c false. Note that the logical cd() operation is
not performed if the new directory does not exist.
@@ -923,7 +923,7 @@ bool QDir::cd(const QString &dirName)
Changes directory by moving one directory up from the QDir's
current directory.
- Returns \c true if the new directory exists and is readable;
+ Returns \c true if the new directory exists;
otherwise returns \c false. Note that the logical cdUp() operation is
not performed if the new directory does not exist.
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 519ac009aa..82aee331c5 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -571,6 +571,8 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, tr("Destination file exists"));
return false;
}
+#ifndef QT_NO_TEMPORARYFILE
+ // This #ifndef disables the workaround it encloses. Therefore, this configuration is not recommended.
#ifdef Q_OS_LINUX
// rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
// FS, such as FAT32. Move the file away and rename in 2 steps to work around.
@@ -598,7 +600,8 @@ QFile::rename(const QString &newName)
arg(QDir::toNativeSeparators(tempFile.fileName()), tempFile.errorString()));
}
return false;
-#endif
+#endif // Q_OS_LINUX
+#endif // QT_NO_TEMPORARYFILE
}
unsetError();
close();
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 44bbe55719..d1deae2d7b 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -77,6 +77,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
return QKqueueFileSystemWatcherEngine::create(parent);
#else
+ Q_UNUSED(parent);
return 0;
#endif
}
diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp
new file mode 100644
index 0000000000..60b285a3d6
--- /dev/null
+++ b/src/corelib/io/qstandardpaths_android.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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 "qstandardpaths.h"
+
+#ifndef QT_NO_STANDARDPATHS
+
+#include <QtCore/private/qjni_p.h>
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qmap.h>
+#include <QDir>
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QString, QString> AndroidDirCache;
+Q_GLOBAL_STATIC(AndroidDirCache, androidDirCache)
+
+static QString testDir()
+{
+ return QStandardPaths::isTestModeEnabled() ? QLatin1String("/qttest")
+ : QLatin1String("");
+}
+
+static QJNIObjectPrivate applicationContext()
+{
+ static QJNIObjectPrivate appCtx;
+ if (appCtx.isValid())
+ return appCtx;
+
+ QJNIObjectPrivate activity = QtAndroidPrivate::activity();
+ if (!activity.isValid())
+ return appCtx;
+
+ appCtx = activity.callObjectMethod("getApplicationContext",
+ "()Landroid/content/Context;");
+ return appCtx;
+}
+
+static inline QString getAbsolutePath(const QJNIObjectPrivate &file)
+{
+ QJNIObjectPrivate path = file.callObjectMethod("getAbsolutePath",
+ "()Ljava/lang/String;");
+ if (!path.isValid())
+ return QString();
+
+ return path.toString();
+}
+
+/*
+ * The root of the external storage
+ *
+ */
+static QString getExternalStorageDirectory()
+{
+ QString &path = (*androidDirCache)[QStringLiteral("EXT_ROOT")];
+ if (!path.isEmpty())
+ return path;
+
+ QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment",
+ "getExternalStorageDirectory",
+ "()Ljava/io/File;");
+ if (!file.isValid())
+ return QString();
+
+ return (path = getAbsolutePath(file));
+}
+
+/*
+ * Locations where applications can place user files (public).
+ * E.g., /storage/Music
+ */
+static QString getExternalStoragePublicDirectory(const char *directoryField)
+{
+ QString &path = (*androidDirCache)[QLatin1String(directoryField)];
+ if (!path.isEmpty())
+ return path;
+
+ QJNIObjectPrivate dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment",
+ directoryField,
+ "Ljava/lang/String;");
+ if (!dirField.isValid())
+ return QString();
+
+ QJNIObjectPrivate file = QJNIObjectPrivate::callStaticObjectMethod("android/os/Environment",
+ "getExternalStoragePublicDirectory",
+ "(Ljava/lang/String;)Ljava/io/File;",
+ dirField.object());
+ if (!file.isValid())
+ return QString();
+
+ return (path = getAbsolutePath(file));
+}
+
+/*
+ * Locations where applications can place persistent files it owns.
+ * E.g., /storage/org.app/Music
+ */
+static QString getExternalFilesDir(const char *directoryField = 0)
+{
+ QString &path = (*androidDirCache)[QString(QLatin1String("APPNAME_%1")).arg(QLatin1String(directoryField))];
+ if (!path.isEmpty())
+ return path;
+
+ QJNIObjectPrivate activity = QtAndroidPrivate::activity();
+ if (!activity.isValid())
+ return QString();
+
+ QJNIObjectPrivate appCtx = applicationContext();
+ if (!appCtx.isValid())
+ return QString();
+
+ QJNIObjectPrivate dirField = QJNIObjectPrivate::fromString(QLatin1String(""));
+ if (directoryField) {
+ dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment",
+ directoryField,
+ "Ljava/lang/String;");
+ if (!dirField.isValid())
+ return QString();
+ }
+
+ QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalFilesDir",
+ "(Ljava/lang/String;)Ljava/io/File;",
+ dirField.object());
+
+ if (!file.isValid())
+ return QString();
+
+ return (path = getAbsolutePath(file));
+}
+
+/*
+ * Directory where applications can store cache files it owns (public).
+ * E.g., /storage/org.app/
+ */
+static QString getExternalCacheDir()
+{
+ QString &path = (*androidDirCache)[QStringLiteral("APPNAME_CACHE")];
+ if (!path.isEmpty())
+ return path;
+
+ QJNIObjectPrivate appCtx = applicationContext();
+ if (!appCtx.isValid())
+ return QString();
+
+ QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalCacheDir",
+ "()Ljava/io/File;");
+
+ if (!file.isValid())
+ return QString();
+
+ return (path = getAbsolutePath(file));
+}
+
+/*
+ * Directory where applications can store cache files it owns (private).
+ */
+static QString getCacheDir()
+{
+ QString &path = (*androidDirCache)[QStringLiteral("APPROOT_CACHE")];
+ if (!path.isEmpty())
+ return path;
+
+ QJNIObjectPrivate appCtx = applicationContext();
+ if (!appCtx.isValid())
+ return QString();
+
+ QJNIObjectPrivate file = appCtx.callObjectMethod("getCacheDir",
+ "()Ljava/io/File;");
+ if (!file.isValid())
+ return QString();
+
+ return (path = getAbsolutePath(file));
+}
+
+/*
+ * Directory where applications can store files it owns (private).
+ * (Same location as $HOME)
+ */
+static QString getFilesDir()
+{
+ QString &path = (*androidDirCache)[QStringLiteral("APPROOT_FILES")];
+ if (!path.isEmpty())
+ return path;
+
+ return (path = QDir::homePath());
+}
+
+QString QStandardPaths::writableLocation(StandardLocation type)
+{
+ switch (type) {
+ case QStandardPaths::MusicLocation:
+ return getExternalStoragePublicDirectory("DIRECTORY_MUSIC");
+ case QStandardPaths::MoviesLocation:
+ return getExternalStoragePublicDirectory("DIRECTORY_MOVIES");
+ case QStandardPaths::PicturesLocation:
+ return getExternalStoragePublicDirectory("DIRECTORY_PICTURES");
+ case QStandardPaths::DocumentsLocation:
+ if (QtAndroidPrivate::androidSdkVersion() > 18)
+ return getExternalStoragePublicDirectory("DIRECTORY_DOCUMENTS");
+ else
+ return getExternalStorageDirectory() + QLatin1String("/Documents");
+ case QStandardPaths::DownloadLocation:
+ return getExternalStoragePublicDirectory("DIRECTORY_DOWNLOADS");
+ case QStandardPaths::GenericConfigLocation:
+ case QStandardPaths::ConfigLocation:
+ return getFilesDir() + testDir() + QLatin1String("/settings");
+ case QStandardPaths::GenericDataLocation:
+ return getExternalStorageDirectory() + testDir();
+ case QStandardPaths::DataLocation:
+ return getFilesDir() + testDir();
+ case QStandardPaths::GenericCacheLocation:
+ case QStandardPaths::RuntimeLocation:
+ case QStandardPaths::TempLocation:
+ case QStandardPaths::CacheLocation:
+ return getCacheDir() + testDir();
+ case QStandardPaths::DesktopLocation:
+ case QStandardPaths::HomeLocation:
+ return getFilesDir();
+ case QStandardPaths::ApplicationsLocation:
+ case QStandardPaths::FontsLocation:
+ default:
+ break;
+ }
+
+ return QString();
+}
+
+QStringList QStandardPaths::standardLocations(StandardLocation type)
+{
+ if (type == MusicLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_MUSIC")
+ << getExternalStoragePublicDirectory("DIRECTORY_PODCASTS")
+ << getExternalFilesDir("DIRECTORY_PODCASTS")
+ << getExternalStoragePublicDirectory("DIRECTORY_NOTIFICATIONS")
+ << getExternalFilesDir("DIRECTORY_NOTIFICATIONS")
+ << getExternalStoragePublicDirectory("DIRECTORY_ALARMS")
+ << getExternalFilesDir("DIRECTORY_ALARMS");
+ }
+
+ if (type == MoviesLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_MOVIES");
+ }
+
+ if (type == PicturesLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_PICTURES");
+ }
+
+ if (type == DocumentsLocation) {
+ if (QtAndroidPrivate::androidSdkVersion() > 18) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_DOCUMENTS");
+ } else {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir() + QLatin1String("/Documents");
+ }
+ }
+
+ if (type == DownloadLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_DOWNLOADS");
+ }
+
+ if (type == DataLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir();
+ }
+
+ if (type == CacheLocation) {
+ return QStringList() << writableLocation(type)
+ << getExternalCacheDir();
+ }
+
+ if (type == FontsLocation) {
+ QString &fontLocation = (*androidDirCache)[QStringLiteral("FONT_LOCATION")];
+ if (!fontLocation.isEmpty())
+ return QStringList(fontLocation);
+
+ const QByteArray ba = qgetenv("QT_ANDROID_FONT_LOCATION");
+ if (!ba.isEmpty())
+ return QStringList((fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba))));
+
+ return QStringList((fontLocation = QLatin1String("/system/fonts")));
+ }
+
+ return QStringList(writableLocation(type));
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STANDARDPATHS
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 77aa3c4821..eac5a0b738 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -3437,7 +3437,7 @@ QString QUrl::fromAce(const QByteArray &domain)
(like \c "example.com") to be written using international
characters.
- This function return an empty QByteArra if \a domain is not a valid
+ This function returns an empty QByteArray if \a domain is not a valid
hostname. Note, in particular, that IPv6 literals are not valid domain
names.
*/
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index ab257a996d..4241fe08ca 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -2334,6 +2334,31 @@ void QAbstractItemModel::doSetRoleNames(const QHash<int,QByteArray> &roleNames)
Returns the model's role names.
+ The default role names set by Qt are:
+
+ \table
+ \header
+ \li Qt Role
+ \li QML Role Name
+ \row
+ \li Qt::DisplayRole
+ \li display
+ \row
+ \li Qt::DecorationRole
+ \li decoration
+ \row
+ \li Qt::EditRole
+ \li edit
+ \row
+ \li Qt::ToolTipRole
+ \li toolTip
+ \row
+ \li Qt::StatusTipRole
+ \li statusTip
+ \row
+ \li Qt::WhatsThisRole
+ \li whatsThis
+ \endtable
*/
QHash<int,QByteArray> QAbstractItemModel::roleNames() const
{
@@ -3378,6 +3403,9 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
of the rowCount() and data() functions. Well behaved models also provide
a headerData() implementation.
+ If your model is used within QML and requires roles other than the
+ default ones provided by the roleNames() function, you must override it.
+
For editable list models, you must also provide an implementation of
setData(), implement the flags() function so that it returns a value
containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index 9ec491f6a9..74eb6f5b27 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
static JavaVM *g_javaVM = Q_NULLPTR;
static jobject g_jActivity = Q_NULLPTR;
static jobject g_jClassLoader = Q_NULLPTR;
+static jint g_androidSdkVersion = 0;
static inline bool exceptionCheck(JNIEnv *env)
{
@@ -60,6 +61,19 @@ static inline bool exceptionCheck(JNIEnv *env)
return false;
}
+static void setAndroidSdkVersion(JNIEnv *env)
+{
+ jclass androidVersionClass = env->FindClass("android/os/Build$VERSION");
+ if (exceptionCheck(env))
+ return;
+
+ jfieldID androidSDKFieldID = env->GetStaticFieldID(androidVersionClass, "SDK_INT", "I");
+ if (exceptionCheck(env))
+ return;
+
+ g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID);
+}
+
jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
{
jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative");
@@ -93,6 +107,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
if (exceptionCheck(env))
return JNI_ERR;
+ setAndroidSdkVersion(env);
+
g_jClassLoader = env->NewGlobalRef(classLoader);
env->DeleteLocalRef(classLoader);
g_jActivity = env->NewGlobalRef(activity);
@@ -118,4 +134,9 @@ jobject QtAndroidPrivate::classLoader()
return g_jClassLoader;
}
+jint QtAndroidPrivate::androidSdkVersion()
+{
+ return g_androidSdkVersion;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h
index 39059db215..c92dbdde7f 100644
--- a/src/corelib/kernel/qjnihelpers_p.h
+++ b/src/corelib/kernel/qjnihelpers_p.h
@@ -64,6 +64,7 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT JavaVM *javaVM();
Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env);
jobject classLoader();
+ jint androidSdkVersion();
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 40e1e8bcc5..876ed8f27b 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -2180,7 +2180,9 @@ void QObject::deleteLater()
const char *qFlagLocation(const char *method)
{
- QThreadData::current()->flaggedSignatures.store(method);
+ QThreadData *currentThreadData = QThreadData::current(false);
+ if (currentThreadData != 0)
+ currentThreadData->flaggedSignatures.store(method);
return method;
}
@@ -3553,8 +3555,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
{
int signal_index = signalOffset + local_signal_index;
- if (!sender->d_func()->isSignalConnected(signal_index))
+ if (!sender->d_func()->isSignalConnected(signal_index)
+ && !qt_signal_spy_callback_set.signal_begin_callback
+ && !qt_signal_spy_callback_set.signal_end_callback) {
return; // nothing connected to these signals, and no spy
+ }
if (sender->d_func()->blockSig)
return;
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 193fa78403..9df438b518 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -247,7 +247,7 @@ public:
Returns \c true if the signal with index \a signal_index from object \a sender is connected.
Signals with indices above a certain range are always considered connected (see connectedSignals
- in QObjectPrivate). If a signal spy is installed, all signals are considered connected.
+ in QObjectPrivate).
\a signal_index must be the index returned by QObjectPrivate::signalIndex;
*/
@@ -256,9 +256,7 @@ inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
return signal_index >= sizeof(connectedSignals) * 8
|| (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
|| (declarativeData && QAbstractDeclarativeData::isSignalConnected
- && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index))
- || qt_signal_spy_callback_set.signal_begin_callback
- || qt_signal_spy_callback_set.signal_end_callback);
+ && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index)));
}
inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index c9b98ac5c0..e2951b125f 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -232,7 +232,7 @@ public:
QThreadData(int initialRefCount = 1);
~QThreadData();
- static QThreadData *current();
+ static QThreadData *current(bool createIfNecessary = true);
static void clearCurrentThreadData();
static QThreadData *get2(QThread *thread)
{ Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 15558cb148..b838cb4b28 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -215,10 +215,10 @@ void QThreadData::clearCurrentThreadData()
clear_thread_data();
}
-QThreadData *QThreadData::current()
+QThreadData *QThreadData::current(bool createIfNecessary)
{
QThreadData *data = get_thread_data();
- if (!data) {
+ if (!data && createIfNecessary) {
data = new QThreadData;
QT_TRY {
set_thread_data(data);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 2c3ff879e4..03c5b943d6 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -141,11 +141,11 @@ void QThreadData::clearCurrentThreadData()
TlsSetValue(qt_current_thread_data_tls_index, 0);
}
-QThreadData *QThreadData::current()
+QThreadData *QThreadData::current(bool createIfNecessary)
{
qt_create_tls();
QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
- if (!threadData) {
+ if (!threadData && createIfNecessary) {
threadData = new QThreadData;
// This needs to be called prior to new AdoptedThread() to
// avoid recursion.
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index db4c2961f0..c860b4d155 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -720,7 +720,8 @@ QStringList QCommandLineParser::values(const QString &optionName) const
*/
bool QCommandLineParser::isSet(const QCommandLineOption &option) const
{
- return isSet(option.names().first());
+ // option.names() might be empty if the constructor failed
+ return !option.names().isEmpty() && isSet(option.names().first());
}
/*!
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index a95c7f53f7..e7a53c0790 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -1284,6 +1284,11 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format)
}
#endif // QT_NO_TEXTDATE
case Qt::ISODate: {
+ // Semi-strict parsing, must be long enough and have non-numeric separators
+ if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
+ || (string.size() > 10 && string.at(10).isDigit())) {
+ return QDate();
+ }
const int year = string.mid(0, 4).toInt();
if (year <= 0 || year > 9999)
return QDate();
@@ -1900,7 +1905,7 @@ int QTime::msecsTo(const QTime &t) const
#ifndef QT_NO_DATESTRING
-static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, bool *isMidnight24)
+static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
{
if (isMidnight24)
*isMidnight24 = false;
@@ -1933,9 +1938,13 @@ static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, boo
// the maximum amount of millisecond digits it will expand to once converted to
// seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
// will then be rounded up AND clamped to 999.
- const float minuteFraction = QString::fromUtf8("0.%1").arg(string.mid(6, 5)).toFloat(&ok);
+
+ const QStringRef minuteFractionStr = string.mid(6, 5);
+ const long minuteFractionInt = minuteFractionStr.toLong(&ok);
if (!ok)
return QTime();
+ const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
+
const float secondWithMs = minuteFraction * 60;
const float secondNoMs = std::floor(secondWithMs);
const float secondFraction = secondWithMs - secondNoMs;
@@ -1947,9 +1956,11 @@ static QTime fromIsoTimeString(const QString &string, Qt::DateFormat format, boo
if (!ok)
return QTime();
if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
- const double secondFraction = QString::fromUtf8("0.%1").arg(string.mid(9, 4)).toDouble(&ok);
+ const QStringRef msecStr(string.mid(9, 4));
+ int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
if (!ok)
return QTime();
+ const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
msec = qMin(qRound(secondFraction * 1000.0), 999);
}
}
@@ -1999,7 +2010,7 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format)
case Qt::ISODate:
case Qt::TextDate:
default:
- return fromIsoTimeString(string, format, 0);
+ return fromIsoTimeString(&string, format, 0);
}
}
@@ -2767,6 +2778,15 @@ void QDateTimePrivate::refreshDateTime()
return;
}
+#ifndef QT_BOOTSTRAPPED
+ // If not valid time zone then is invalid
+ if (m_spec == Qt::TimeZone && !m_timeZone.isValid()) {
+ clearValidDateTime();
+ m_offsetFromUtc = 0;
+ return;
+ }
+#endif // QT_BOOTSTRAPPED
+
// We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
// LocalTime and TimeZone might fall into "missing" DaylightTime transition hour
// Calling toEpochMSecs will adjust the returned date/time if it does
@@ -4372,26 +4392,40 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (size < 10)
return QDateTime();
- QString isoString = string;
+ QStringRef isoString(&string);
Qt::TimeSpec spec = Qt::LocalTime;
- QDate date = QDate::fromString(isoString.left(10), Qt::ISODate);
+ QDate date = QDate::fromString(string.left(10), Qt::ISODate);
if (!date.isValid())
return QDateTime();
if (size == 10)
return QDateTime(date);
- isoString.remove(0, 11);
+ isoString = isoString.right(11);
int offset = 0;
// Check end of string for Time Zone definition, either Z for UTC or [+-]HH:MM for Offset
if (isoString.endsWith(QLatin1Char('Z'))) {
spec = Qt::UTC;
- isoString.chop(1);
+ isoString = isoString.left(isoString.size() - 1);
} else {
- const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
- if (signIndex >= 0) {
+ // the loop below is faster but functionally equal to:
+ // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
+ const int sizeOfTimeZoneString = 4;
+ int signIndex = isoString.size() - sizeOfTimeZoneString - 1;
+ bool found = false;
+ {
+ const QChar plus = QLatin1Char('+');
+ const QChar minus = QLatin1Char('-');
+ do {
+ QChar character(isoString.at(signIndex));
+ found = character == plus || character == minus;
+ } while (--signIndex >= 0 && !found);
+ ++signIndex;
+ }
+
+ if (found) {
bool ok;
- offset = fromOffsetString(isoString.mid(signIndex), &ok);
+ offset = fromOffsetString(isoString.mid(signIndex).toString(), &ok);
if (!ok)
return QDateTime();
isoString = isoString.left(signIndex);
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index 885c77c46d..b03866681e 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -348,6 +348,9 @@ QVariant QSystemLocalePrivate::dateTimeFormat(QLocale::FormatType type)
QVariant QSystemLocalePrivate::dayName(int day, QLocale::FormatType type)
{
+ if (day < 1 || day > 7)
+ return QString();
+
static const LCTYPE short_day_map[]
= { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 9544062dd9..555f8a8c97 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -189,9 +189,23 @@ static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b, const uc
return 1;
}
+#if defined(__mips_dsp)
+// From qstring_mips_dsp_asm.S
+extern "C" int qt_ucstrncmp_mips_dsp_asm(const ushort *a,
+ const ushort *b,
+ unsigned len);
+#endif
+
// Unicode case-sensitive compare two same-sized strings
static int ucstrncmp(const QChar *a, const QChar *b, int l)
{
+#if defined(__mips_dsp)
+ if (l >= 8) {
+ return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const ushort*>(a),
+ reinterpret_cast<const ushort*>(b),
+ l);
+ }
+#endif // __mips_dsp
while (l-- && *a == *b)
a++,b++;
if (l==-1)
@@ -3947,6 +3961,10 @@ static inline __m128i mergeQuestionMarks(__m128i chunk)
}
#endif
+#if defined(__mips_dsp)
+extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int length);
+#endif
+
static void toLatin1_helper(uchar *dst, const ushort *src, int length)
{
if (length) {
@@ -3995,10 +4013,14 @@ static void toLatin1_helper(uchar *dst, const ushort *src, int length)
length = length % 8;
}
#endif
+#if defined(__mips_dsp)
+ qt_toLatin1_mips_dsp_asm(dst, src, length);
+#else
while (length--) {
*dst++ = (*src>0xff) ? '?' : (uchar) *src;
++src;
}
+#endif
}
}
@@ -4151,6 +4173,12 @@ QVector<uint> QString::toUcs4() const
return v;
}
+#if defined(__mips_dsp)
+// From qstring_mips_dsp_asm.S
+extern "C" void qt_fromlatin1_mips_asm_unroll4 (ushort*, const char*, uint);
+extern "C" void qt_fromlatin1_mips_asm_unroll8 (ushort*, const char*, uint);
+#endif
+
QString::Data *QString::fromLatin1_helper(const char *str, int size)
{
Data *d;
@@ -4191,8 +4219,15 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
size = size % 16;
}
#endif
+#if defined(__mips_dsp)
+ if (size > 20)
+ qt_fromlatin1_mips_asm_unroll8(dst, str, size);
+ else
+ qt_fromlatin1_mips_asm_unroll4(dst, str, size);
+#else
while (size--)
*dst++ = (uchar)*str++;
+#endif
}
return d;
}
diff --git a/src/corelib/tools/qstring_mips_dsp_asm.S b/src/corelib/tools/qstring_mips_dsp_asm.S
new file mode 100644
index 0000000000..aee162c290
--- /dev/null
+++ b/src/corelib/tools/qstring_mips_dsp_asm.S
@@ -0,0 +1,449 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui 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 "../../gui/painting/qt_mips_asm_dsp_p.h"
+
+.macro EXTRACT_HALVES_x2 src1, src2, hi_1, hi_2
+#if defined(__MIPSEL) && __MIPSEL
+ srl \hi_1, \src1, 16
+ ext \src1, \src1, 0, 16
+ srl \hi_2, \src2, 16
+ ext \src2, \src2, 0, 16
+#else
+ ext \hi_1, \src1, 0, 16
+ srl \src1, \src1, 16
+ ext \hi_2, \src2, 0, 16
+ srl \src2, \src2, 16
+#endif
+.endm
+
+
+LEAF_MIPS_DSP(qt_ucstrncmp_mips_dsp_asm)
+/*
+ * Arguments:
+ * a0 - string_a (uint16_t*)
+ * a1 - string_b (uint16_t*)
+ * a2 - length (uint32_t)
+ *
+ * Register usage:
+ * t0 - batches
+ */
+
+ move v0, zero /* result = 0 */
+ andi t0, a0, 0x3 /* t1 = string_a % 4 */
+ andi t1, a1, 0x3 /* t0 = string_b % 4 */
+ or t2, t0, t1 /* t2 = t0 | t1 */
+
+ beqz t2, 5f /* both aligned */
+ and t2, t0 ,t1
+ beqz t2, 6f /* one aligned */
+ nop
+
+ /*
+ * Both strings are unaligned: read 1 halfword from each,
+ * then fall-off to continue with the both-aligned case.
+ */
+ lhu t0, 0 (a0)
+ lhu t1, 0 (a1)
+ addiu a2, a2, -1 /* len-- */
+ sub v0, t0, t1 /* v0 = t0-t1 */
+ addiu a0, a0, 2 /* string_a++ */
+ bnez v0, 0f /* if (t0-t1): return */
+ addiu a1, a1, 2 /* string_b++ */
+ beqz a2, 0f /* if !len: return */
+ /* next instruction (srl) fills delay branch slot */
+
+5: /* Both string pointers are aligned */
+ srl t0, a2, 3 /* batches = length / 8 */
+ beqz t0, 9f /* if !batches: tail */
+ andi a2, a2, 0x7 /* length = length % 8 */
+
+ SAVE_REGS_ON_STACK 0, s0, s1, s2, s3
+
+1: lw t1, 0 (a0) /* [a0 a1] */
+ lw t3, 4 (a0) /* [a2 a3] */
+ lw t5, 8 (a0) /* [a4 a5] */
+ lw t7, 12 (a0) /* [a6 a7] */
+
+ lw t2, 0 (a1) /* [b0 b1] */
+ lw t4, 4 (a1) /* [b2 b3] */
+ lw t6, 8 (a1) /* [b4 b5] */
+ lw t8, 12 (a1) /* [b6 b7] */
+
+ /*
+ * Subtract elements one by one, if the result is zero
+ * both halves of the registers (shorts) are equal.
+ */
+ subq.ph s0, t1, t2 /* [a0-b0 a1-b1] */
+ subq.ph s1, t3, t4 /* [a2-b2 a3-b3] */
+
+ bnez s0, 1f
+ subq.ph s2, t5, t6 /* [a4-b4 a5-b5] */
+ bnez s1, 2f
+ subq.ph s3, t7, t8 /* [a6-b6 a7-b7] */
+ bnez s2, 3f
+ addiu t0, t0, -1 /* batches-- */
+ bnez s3, 4f
+ addiu a0, a0, 8*2 /* string_a += 8 */
+
+ bnez t0, 1b /* if batches: loop */
+ addiu a1, a1, 8*2 /* string_b += 8 */
+
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+
+ bnez a2, 9f /* if length: tail */
+ nop
+ jr ra
+ nop
+
+
+ 1: /* Check t1 [a0 a1] vs. t2 [b0 b1] */
+ EXTRACT_HALVES_x2 t1, t2, t3, t4 /* a0, b0, a1, b1 */
+ sub v0, t1, t2
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+ bnez v0, 0f /* if (a0-b0): return */
+ nop
+ jr ra
+ sub v0, t3, t4 /* return a1-b1 */
+
+ 2: /* Check t3 [a2 a3] vs. t4 [b2 b3] */
+ EXTRACT_HALVES_x2 t3, t4, t1, t2 /* a2, b2, a3, b3 */
+ sub v0, t3, t4
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+ bnez v0, 0f /* if (a2-b2): return */
+ nop
+ jr ra
+ sub v0, t1, t2 /* return a3-b3 */
+
+ 3: /* Check t5 [a4 a5] vs. t6 [b4 b5] */
+ EXTRACT_HALVES_x2 t5, t6, t1, t2 /* a4, b4, a5, b5 */
+ sub v0, t5, t6
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+ bnez v0, 0f /* if (a4-b4): return */
+ nop
+ jr ra
+ sub v0, t1, t2 /* return a5-b5 */
+
+ 4: /* Check t7 [a6 a7] vs. t8 [b6 b7] */
+ EXTRACT_HALVES_x2 t7, t8, t1, t2 /* a6, b6, a7, b7 */
+ sub v0, t7, t8
+ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+ bnez v0, 0f /* if (a6-b6): return */
+ nop
+ jr ra
+ sub v0, t1, t2
+
+
+ /* Process remaining tail items. */
+9: lhu t1, 0 (a0) /* a */
+ lhu t2, 0 (a1) /* b */
+ addiu a2, a2, -1 /* length-- */
+ sub v0, t1, t2 /* result = (a - b) */
+
+ bnez v0, 0f /* if (a - b): return */
+ addiu a0, a0, 2 /* string_a++ */
+
+ bnez a2, 9b /* if length: loop */
+ addiu a1, a1, 2 /* string_b++ */
+
+0: jr ra
+ nop
+
+
+ /* One of the inputs is unaligned, do unrolled half-word loads */
+6: srl t0, a2, 3 /* batches = length / 8 */
+ andi a2, a2, 0x7 /* length = length % 8 */
+
+1: lhu t1, 0 (a0)
+ lhu t2, 0 (a1)
+ lhu t3, 2 (a0)
+ lhu t4, 2 (a1)
+ lhu t5, 4 (a0)
+ lhu t6, 4 (a1)
+ lhu t7, 6 (a0)
+ lhu t8, 6 (a1)
+
+ sub v0, t1, t2
+ sub t1, t3, t4
+
+ bnez v0, 0f
+ sub t2, t5, t6
+ bnez t1, 2f
+ sub t3, t7, t8
+ bnez t2, 3f
+ lhu t1, 8 (a0)
+ bnez t3, 4f
+ lhu t2, 8 (a1)
+
+ lhu t3, 10 (a0)
+ lhu t4, 10 (a1)
+ lhu t5, 12 (a0)
+ lhu t6, 12 (a1)
+ lhu t7, 14 (a0)
+ lhu t8, 14 (a1)
+
+ sub v0, t1, t2
+ sub t1, t3, t4
+
+ bnez v0, 0f
+ sub t2, t5, t6
+ bnez t1, 2f
+ sub t3, t7, t8
+ bnez t2, 3f
+ addiu t0, t0, -1 /* batches-- */
+ bnez t3, 4f
+ addiu a0, a0, 8*2 /* string_a += 8 */
+
+ bnez t0, 1b
+ addiu a1, a1, 8*2 /* string_b += 8 */
+
+ bnez a2, 9b /* if length: tail */
+ nop
+
+0: jr ra
+ nop
+2: jr ra
+ move v0, t1
+3: jr ra
+ move v0, t2
+4: jr ra
+ move v0, t3
+
+END(qt_ucstrncmp_mips_dsp_asm)
+
+
+#if defined(__mips_dspr2)
+LEAF_MIPS_DSPR2(qt_fromlatin1_mips_asm_unroll8)
+#else
+LEAF_MIPS_DSP(qt_fromlatin1_mips_asm_unroll8)
+#endif
+
+ andi t0, a1, 0x3
+ beqz t0, 9f /* check that src is aligned */
+ nop
+
+1: lbu t1, 0 (a1)
+ addiu a1, a1, 1
+ addiu a2, a2, -1
+ sh t1, 0 (a0)
+ beqz a2, 0f
+ andi t0, a1, 0x3
+ bnez t0, 1b
+ addiu a0, a0, 2
+
+9: /* source pointer is aligned: do batches of 8 elements */
+ andi t0, a0, 3 /* check if dst is aligned */
+ bnez t0, 6f
+ srl t0, a2, 3 /* batches = len / 8 */
+ andi a2, a2, 0x7 /* tail = len % 8 */
+
+ beqz t0, 8f /* if !batches: tail */
+ nop
+
+1: lw t1, 0 (a1)
+ lw t2, 4 (a1)
+
+ addiu a1, a1, 8*1
+ addiu t0, t0, -1
+
+ preceu.ph.qbl t3, t1
+ preceu.ph.qbr t1, t1
+ preceu.ph.qbl t4, t2
+ preceu.ph.qbr t2, t2
+
+#if defined(__MIPSEL) && __MIPSEL
+ sw t1, 0 (a0)
+ sw t3, 4 (a0)
+ sw t2, 8 (a0)
+ sw t4, 12 (a0)
+#else
+ sw t3, 0 (a0)
+ sw t1, 4 (a0)
+ sw t4, 8 (a0)
+ sw t2, 12 (a0)
+#endif
+
+ bnez t0, 1b
+ addiu a0, a0, 8*2
+
+8: /* process tail items */
+ beqz a2, 0f
+ nop
+
+1: lbu t1, 0 (a1)
+ addiu a2, a2, -1
+ sh t1, 0 (a0)
+ addiu a1, a1, 1
+ bnez a2, 1b
+ addiu a0, a0, 2
+
+0: jr ra
+ nop
+
+6: beqz t0, 8b
+ andi a2, a2, 7
+7: lw t1, 0(a1)
+ lw t2, 4(a1)
+ addiu t0, t0, -1
+ addiu a1, a1, 8
+ andi t3, t1, 0xff
+#if defined(__mips_dspr2)
+ prepend t1, t2, 8
+#else
+ sll t4, t4, 24
+ srl t1, t1, 8
+ or t1, t1, t4
+#endif
+ srl t2, t2, 8
+ preceu.ph.qbr t4, t1
+ preceu.ph.qbl t1, t1
+ preceu.ph.qbr t5, t2
+ srl t2, t2, 16
+ sh t3, 0(a0)
+ sw t4, 2(a0)
+ sw t1, 6(a0)
+ sw t5, 10(a0)
+ sh t2, 14(a0)
+ bnez t0, 7b
+ addiu a0, a0, 16
+ bnez a2, 1b
+ nop
+
+ jr ra
+ nop
+
+END(qt_fromlatin1_mips_asm_unroll8)
+
+
+LEAF_MIPS_DSP(qt_fromlatin1_mips_asm_unroll4)
+/*
+ * Arguments:
+ * a0 - dst (uint16_t*)
+ * a1 - src (const char*)
+ * a2 - len (unsigned int)
+ */
+
+ /*
+ * QString::fromLatin1_helper() already handles the len==0
+ * case: assume that len is never zero.
+ */
+ srl t0, a2, 2
+ beqz t0, 9f
+ andi a2, a2, 0x3
+
+1: lbu t1, 0(a1)
+ lbu t2, 1(a1)
+ lbu t3, 2(a1)
+ lbu t4, 3(a1)
+ sh t1, 0(a0)
+ sh t2, 2(a0)
+ sh t3, 4(a0)
+ sh t4, 6(a0)
+ addiu t0, t0, -1
+ addiu a1, a1, 4
+ bnez t0, 1b
+ addiu a0, a0, 8
+
+8: beqz a2, 0f
+ nop
+
+9: lbu t1, 0(a1)
+ addiu a2, a2, -1
+ addiu a1, a1, 1
+ sh t1, 0(a0)
+ bnez a2, 9b
+ addiu a0, a0, 2
+
+0: jr ra
+ nop
+
+END(qt_fromlatin1_mips_asm_unroll4)
+
+
+LEAF_MIPS_DSP(qt_toLatin1_mips_dsp_asm)
+ /*
+ * a0 - dst
+ * a1 - src
+ * a2 - length
+ */
+
+ addiu t9, zero, 0x3f
+ srl t8, a2, 2
+ beqz t8, 2f
+ andi a2, a2, 3
+1:
+ lhu t0, 0(a1)
+ lhu t1, 2(a1)
+ lhu t2, 4(a1)
+ lhu t3, 6(a1)
+ srl t4, t0, 8
+ srl t5, t1, 8
+ srl t6, t2, 8
+ srl t7, t3, 8
+ movn t0, t9, t4
+ movn t1, t9, t5
+ movn t2, t9, t6
+ movn t3, t9, t7
+ addiu a1, a1, 8
+ addiu t8, t8, -1
+ sb t0, 0(a0)
+ sb t1, 1(a0)
+ sb t2, 2(a0)
+ sb t3, 3(a0)
+ bgtz t8, 1b
+ addiu a0, a0, 4
+2: beqz a2, 4f
+ nop
+3:
+ lhu t0, 0(a1)
+ addiu a1, a1, 2
+ addiu a2, a2, -1
+ srl t1, t0, 8
+ movn t0, t9, t1
+ sb t0, 0(a0)
+ bgtz a2, 3b
+ addiu a0, a0, 1
+4:
+ jr ra
+ nop
+
+END(qt_toLatin1_mips_dsp_asm)
+
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index f56511edbf..505e1a32e4 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -438,11 +438,15 @@ QVector<T>::QVector(int asize, const T &t)
template <typename T>
QVector<T>::QVector(std::initializer_list<T> args)
{
- d = Data::allocate(args.size());
- // std::initializer_list<T>::iterator is guaranteed to be
- // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
- copyConstruct(args.begin(), args.end(), d->begin());
- d->size = int(args.size());
+ if (args.size() > 0) {
+ d = Data::allocate(args.size());
+ // std::initializer_list<T>::iterator is guaranteed to be
+ // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
+ copyConstruct(args.begin(), args.end(), d->begin());
+ d->size = int(args.size());
+ } else {
+ d = Data::sharedNull();
+ }
}
#endif
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index ce3a6f9e8c..a727315700 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -198,3 +198,7 @@ INCLUDEPATH += ../3rdparty/md5 \
!macx-icc:!vxworks:unix:LIBS_PRIVATE += -lm
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