summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure35
-rwxr-xr-xconfigure.exebin1320448 -> 1320960 bytes
-rw-r--r--dist/changes-4.7.1118
-rw-r--r--doc/src/getting-started/examples.qdoc4
-rw-r--r--doc/src/platforms/x11overlays.qdoc1
-rw-r--r--mkspecs/modules/README3
-rw-r--r--mkspecs/modules/qt_webkit_version.pri4
-rw-r--r--projects.pro4
-rw-r--r--qmake/generators/makefile.cpp37
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp3
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp3
-rw-r--r--qmake/generators/win32/msvc_vcxproj.cpp1
-rw-r--r--src/3rdparty/webkit/WebCore/WebCore.pro2
-rw-r--r--src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri2
-rw-r--r--src/corelib/global/global.pri2
-rw-r--r--src/corelib/global/qlibraryinfo.cpp11
-rw-r--r--src/corelib/plugin/qlibrary.cpp5
-rw-r--r--src/corelib/tools/qsimd.cpp191
-rw-r--r--src/corelib/tools/qsimd_p.h1
-rw-r--r--src/corelib/tools/qstring.cpp63
-rw-r--r--src/corelib/tools/qstring.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp9
-rw-r--r--src/gui/gui.pro2
-rw-r--r--src/gui/kernel/qgesturemanager.cpp5
-rw-r--r--src/network/bearer/qnetworkconfigmanager.cpp12
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp10
-rw-r--r--src/network/kernel/qhostinfo_unix.cpp5
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp9
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp1
-rw-r--r--src/script/api/qscriptengine.cpp28
-rw-r--r--src/testlib/qbenchmarkmeasurement_p.h4
-rw-r--r--tests/auto/gestures/tst_gestures.cpp5
-rw-r--r--tests/auto/headers/tst_headers.cpp3
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs/main.js91
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs/project.pro3
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs/project.ts.result195
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs2/expectedoutput.txt29
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs2/main.js56
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs2/project.pro3
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parsejs2/project.ts.result30
-rw-r--r--tests/auto/qmake/testdata/substitutes/test.pro6
-rw-r--r--tests/auto/qmake/testdata/substitutes/test3.txt1
-rw-r--r--tests/auto/qmake/tst_qmake.cpp2
-rw-r--r--tests/auto/qscriptengine/idtranslatable.js5
-rw-r--r--tests/auto/qscriptengine/qscriptengine.qrc1
-rw-r--r--tests/auto/qscriptengine/translations/idtranslatable_la.qmbin0 -> 342 bytes
-rw-r--r--tests/auto/qscriptengine/translations/idtranslatable_la.ts30
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp69
-rw-r--r--tests/auto/qtouchevent/tst_qtouchevent.cpp59
-rw-r--r--tests/benchmarks/corelib/tools/qstring/data.cpp1284
-rw-r--r--tests/benchmarks/corelib/tools/qstring/data.h53
-rw-r--r--tests/benchmarks/corelib/tools/qstring/generatelist.pl198
-rw-r--r--tests/benchmarks/corelib/tools/qstring/main.cpp1262
-rw-r--r--tests/benchmarks/corelib/tools/qstring/qstring.pro5
-rw-r--r--tools/configure/configureapp.cpp9
-rw-r--r--tools/linguist/lupdate/qscript.cpp234
-rw-r--r--tools/linguist/lupdate/qscript.g249
-rw-r--r--tools/qdoc3/test/qt-html-templates.qdocconf11
58 files changed, 4303 insertions, 166 deletions
diff --git a/configure b/configure
index bd69a0a..1221d62 100755
--- a/configure
+++ b/configure
@@ -7163,7 +7163,8 @@ if [ "$CFG_WEBKIT" = "auto" ]; then
fi
if [ "$CFG_WEBKIT" = "yes" ]; then
- QT_CONFIG="$QT_CONFIG webkit"
+ # This include takes care of adding "webkit" to QT_CONFIG.
+ cp -f "$relpath/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri" "$outpath/mkspecs/modules/qt_webkit_version.pri"
# The reason we set CFG_WEBKIT, is such that the printed overview of what will be enabled, shows correctly.
CFG_WEBKIT="yes"
else
@@ -7277,6 +7278,7 @@ fi
# some compilers generate binary incompatible code between different versions,
# so we need to generate a build key that is different between these compilers
+COMPAT_COMPILER=
case "$COMPILER" in
g++*)
# GNU C++
@@ -7310,6 +7312,22 @@ g++*)
esac
[ '!' -z "$COMPILER_VERSION" ] && COMPILER="g++-${COMPILER_VERSION}"
;;
+icc*)
+ # The Intel CC compiler on Unix systems matches the ABI of the g++
+ # that is found on PATH
+ COMPILER="icc"
+ COMPAT_COMPILER="g++-4"
+ case "`g++ -dumpversion` 2>/dev/null" in
+ 2.95.*)
+ COMPAT_COMPILER="g++-2.95.*"
+ ;;
+ 3.*)
+ COMPAT_COMPILER="g++-3.*"
+ ;;
+ *)
+ ;;
+ esac
+ ;;
*)
#
;;
@@ -7452,9 +7470,20 @@ if [ "$QT_CROSS_COMPILE" = "no" ]; then
QT_BUILD_KEY_COMPAT="$QT_BUILD_KEY_COMPAT $QT_NAMESPACE"
fi
fi
+
+# is this compiler compatible with some other "standard" build key
+QT_BUILD_KEY_COMPAT_COMPILER=
+if [ ! -z "$COMPAT_COMPILER" ]; then
+ QT_BUILD_KEY_COMPAT_COMPILER="$CFG_USER_BUILD_KEY $CFG_ARCH $TARGET_OPERATING_SYSTEM $COMPAT_COMPILER $BUILD_OPTIONS"
+ if [ -n "$QT_NAMESPACE" ]; then
+ QT_BUILD_KEY_COMPAT_COMPILER="$QT_BUILD_KEY_COMPAT_COMPILER $QT_NAMESPACE"
+ fi
+fi
+
# strip out leading/trailing/extra whitespace
QT_BUILD_KEY=`echo $QT_BUILD_KEY | sed -e "s, *, ,g" -e "s,^ *,," -e "s, *$,,"`
QT_BUILD_KEY_COMPAT=`echo $QT_BUILD_KEY_COMPAT | sed -e "s, *, ,g" -e "s,^ *,," -e "s, *$,,"`
+QT_BUILD_KEY_COMPAT_COMPILER=`echo $QT_BUILD_KEY_COMPAT_COMPILER | sed -e "s, *, ,g" -e "s,^ *,," -e "s, *$,,"`
#-------------------------------------------------------------------------------
# part of configuration information goes into qconfig.h
@@ -7503,6 +7532,10 @@ if [ -n "$QT_BUILD_KEY_COMPAT" ]; then
echo "#define QT_BUILD_KEY_COMPAT \"$QT_BUILD_KEY_COMPAT\"" \
>> "$outpath/src/corelib/global/qconfig.h.new"
fi
+if [ -n "$QT_BUILD_KEY_COMPAT_COMPILER" ]; then
+ echo "#define QT_BUILD_KEY_COMPAT2 \"$QT_BUILD_KEY_COMPAT_COMPILER\"" \
+ >> "$outpath/src/corelib/global/qconfig.h.new"
+fi
echo "" >>"$outpath/src/corelib/global/qconfig.h.new"
echo "#ifdef QT_BOOTSTRAPPED" >>"$outpath/src/corelib/global/qconfig.h.new"
diff --git a/configure.exe b/configure.exe
index c5bff85..982e038 100755
--- a/configure.exe
+++ b/configure.exe
Binary files differ
diff --git a/dist/changes-4.7.1 b/dist/changes-4.7.1
new file mode 100644
index 0000000..c8b26c2
--- /dev/null
+++ b/dist/changes-4.7.1
@@ -0,0 +1,118 @@
+Qt 4.7.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 4.7.0. For more details,
+refer to the online documentation included in this distribution. The
+documentation is also available online:
+
+ http://qt.nokia.com/doc/4.7
+
+The Qt version 4.7 series is binary compatible with the 4.6.x series.
+Applications compiled for 4.6 will continue to run with 4.7.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker, the (now obsolete) Task
+Tracker, or the Merge Request queue of the public source repository.
+
+Qt Bug Tracker: http://bugreports.qt.nokia.com
+Task Tracker: http://qt.nokia.com/developer/task-tracker
+Merge Request: http://qt.gitorious.org
+
+****************************************************************************
+* General *
+****************************************************************************
+
+Optimizations
+-------------
+
+ - Improved the benchmarking library's timing code
+ * Uses a faster access to the system clock
+
+ * See list of Important Behavior Changes below
+
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtCore
+------
+
+
+QtGui
+-----
+
+
+QtDBus
+------
+
+
+QtMultimedia
+------------
+
+
+QtNetwork
+---------
+
+
+QtOpenGL
+--------
+
+
+QtOpenVG
+--------
+
+
+QtWebKit
+--------
+
+
+QtSql
+-----
+
+
+QtSvg
+-----
+
+
+Qt Plugins
+----------
+
+
+
+****************************************************************************
+* Platform Specific Changes *
+****************************************************************************
+
+Qt for Unix (X11 and Mac OS X)
+------------------------------
+
+
+Qt for Linux/X11
+----------------
+
+
+Qt for Windows
+--------------
+
+
+Qt for Mac OS X
+---------------
+
+
+Qt for Symbian
+--------------
+
+
+
+****************************************************************************
+* Tools *
+****************************************************************************
+
+ - Designer
+
+ - uic
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+
diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc
index 708c44e..e8c85e6 100644
--- a/doc/src/getting-started/examples.qdoc
+++ b/doc/src/getting-started/examples.qdoc
@@ -255,6 +255,7 @@
\o \l{graphicsview/flowlayout}{Flow Layout}
\o \l{graphicsview/simpleanchorlayout}{Simple Anchor Layout}
\o \l{graphicsview/weatheranchorlayout}{Weather Anchor Layout}
+ \o \l{graphicsview/basicgraphicslayouts}{Basic Graphics Layouts}
\endlist
Some examples demonstrate the use of graphics effects with canvas items.
@@ -471,6 +472,7 @@
\o \l{network/googlesuggest}{Google Suggest}
\o \l{network/bearercloud}{Bearer Cloud}\raisedaster
\o \l{network/bearermonitor}{Bearer Monitor}
+ \o \l{network/securesocketclient}{Secure Socket Client}
\endlist
Examples marked with an asterisk (*) are fully documented.
@@ -609,6 +611,7 @@
\o \l{sql/querymodel}{Query Model}
\o \l{sql/relationaltablemodel}{Relational Table Model}
\o \l{sql/tablemodel}{Table Model}
+ \o \l{sql/masterdetail}{Master Detail}
\o \l{sql/sqlwidgetmapper}{SQL Widget Mapper}\raisedaster
\endlist
@@ -633,6 +636,7 @@
\o \l{xml/streambookmarks}{QXmlStream Bookmarks}\raisedaster
\o \l{xml/rsslisting}{RSS-Listing}
\o \l{xml/xmlstreamlint}{XML Stream Lint Example}\raisedaster
+ \o \l{xml/htmlinfo}{XML HTML Info}
\endlist
The XQuery/XPath and XML Schema engines in the QtXmlPatterns modules
diff --git a/doc/src/platforms/x11overlays.qdoc b/doc/src/platforms/x11overlays.qdoc
index 1a03ea6..949a500 100644
--- a/doc/src/platforms/x11overlays.qdoc
+++ b/doc/src/platforms/x11overlays.qdoc
@@ -28,6 +28,7 @@
/*!
\page x11overlays.html
\title How to Use X11 Overlays with Qt
+ \ingroup best-practices
X11 overlays are a powerful mechanism for drawing
annotations etc., on top of an image without destroying it, thus saving
diff --git a/mkspecs/modules/README b/mkspecs/modules/README
new file mode 100644
index 0000000..f095982
--- /dev/null
+++ b/mkspecs/modules/README
@@ -0,0 +1,3 @@
+Externally provided Qt modules may drop a qmake file here to become part of
+the current Qt configuration. The file name must follow the pattern
+"qt_<module>.pri". It must contain a "QT_CONFIG += <module>" statement.
diff --git a/mkspecs/modules/qt_webkit_version.pri b/mkspecs/modules/qt_webkit_version.pri
deleted file mode 100644
index ffd192c..0000000
--- a/mkspecs/modules/qt_webkit_version.pri
+++ /dev/null
@@ -1,4 +0,0 @@
-QT_WEBKIT_VERSION = 4.7.0
-QT_WEBKIT_MAJOR_VERSION = 4
-QT_WEBKIT_MINOR_VERSION = 7
-QT_WEBKIT_PATCH_VERSION = 0
diff --git a/projects.pro b/projects.pro
index 373b049..f94e1de 100644
--- a/projects.pro
+++ b/projects.pro
@@ -159,11 +159,13 @@ INSTALLS += qmake
#mkspecs
mkspecs.path=$$[QT_INSTALL_DATA]/mkspecs
-mkspecs.files=$$QT_BUILD_TREE/mkspecs/qconfig.pri $$QT_SOURCE_TREE/mkspecs/*
+mkspecs.files=$$QT_BUILD_TREE/mkspecs/qconfig.pri $$files($$QT_SOURCE_TREE/mkspecs/*)
+mkspecs.files -= $$QT_SOURCE_TREE/mkspecs/modules
unix {
DEFAULT_QMAKESPEC = $$QMAKESPEC
DEFAULT_QMAKESPEC ~= s,^.*mkspecs/,,g
mkspecs.commands += $(DEL_FILE) $(INSTALL_ROOT)$$mkspecs.path/default; $(SYMLINK) $$DEFAULT_QMAKESPEC $(INSTALL_ROOT)$$mkspecs.path/default
+ mkspecs.files -= $$QT_SOURCE_TREE/mkspecs/default
}
win32:!equals(QT_BUILD_TREE, $$QT_SOURCE_TREE) {
# When shadow building on Windows, the default mkspec only exists in the build tree.
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 852471d..03732ba 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -466,14 +466,37 @@ MakefileGenerator::init()
if(!project->isEmpty("QMAKE_SUBSTITUTES")) {
const QStringList &subs = v["QMAKE_SUBSTITUTES"];
for(int i = 0; i < subs.size(); ++i) {
- if(!subs.at(i).endsWith(".in")) {
- warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'",
- subs.at(i).toLatin1().constData());
- continue;
+ QString inn = subs.at(i) + ".input", outn = subs.at(i) + ".output";
+ if (v.contains(inn) || v.contains(outn)) {
+ if (!v.contains(inn) || !v.contains(outn)) {
+ warn_msg(WarnLogic, "Substitute '%s' has only one of .input and .output",
+ subs.at(i).toLatin1().constData());
+ continue;
+ }
+ const QStringList &tinn = v[inn], &toutn = v[outn];
+ if (tinn.length() != 1) {
+ warn_msg(WarnLogic, "Substitute '%s.input' does not have exactly one value",
+ subs.at(i).toLatin1().constData());
+ continue;
+ }
+ if (toutn.length() != 1) {
+ warn_msg(WarnLogic, "Substitute '%s.output' does not have exactly one value",
+ subs.at(i).toLatin1().constData());
+ continue;
+ }
+ inn = tinn.first();
+ outn = toutn.first();
+ } else {
+ inn = subs.at(i);
+ if(!inn.endsWith(".in")) {
+ warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'",
+ inn.toLatin1().constData());
+ continue;
+ }
+ outn = inn.left(inn.length()-3);
}
- QFile in(fileFixify(subs.at(i)));
- QFile out(fileFixify(subs.at(i).left(subs.at(i).length()-3),
- qmake_getpwd(), Option::output_dir));
+ QFile in(fileFixify(inn));
+ QFile out(fileFixify(outn, qmake_getpwd(), Option::output_dir));
if(in.open(QFile::ReadOnly)) {
QString contents;
QStack<int> state;
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 17c4d5a..2505056 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -1573,7 +1573,8 @@ bool VCXLinkerTool::parseOption(const char* option)
break;
case 0x0034160: // /MAP[:filename]
GenerateMapFile = _True;
- MapFileName = option+5;
+ if (option[4] == ':')
+ MapFileName = option+5;
break;
case 0x164e1ef: // /MAPINFO:{EXPORTS}
if(*(option+9) == 'E')
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 1e060a0..980e686 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -1430,7 +1430,8 @@ bool VCLinkerTool::parseOption(const char* option)
break;
case 0x0034160: // /MAP[:filename]
GenerateMapFile = _True;
- MapFileName = option+5;
+ if (option[4] == ':')
+ MapFileName = option+5;
break;
case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES}
if(*(option+9) == 'E')
diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp
index f68a435..271d9ae 100644
--- a/qmake/generators/win32/msvc_vcxproj.cpp
+++ b/qmake/generators/win32/msvc_vcxproj.cpp
@@ -202,7 +202,6 @@ void VcxprojGenerator::initConfiguration()
conf.CharacterSet = "NotSet";
break;
}
- conf.CharacterSet = charSet(temp.isEmpty() ? (short)charSetNotSet : temp.toShort());
}
conf.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean");
conf.ImportLibrary = conf.linker.ImportLibrary;
diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro
index 2047143..ac0c47c 100644
--- a/src/3rdparty/webkit/WebCore/WebCore.pro
+++ b/src/3rdparty/webkit/WebCore/WebCore.pro
@@ -82,7 +82,7 @@ CONFIG(QTDIR_build) {
symbian: TARGET =$$TARGET$${QT_LIBINFIX}
}
moduleFile=$$PWD/../WebKit/qt/qt_webkit_version.pri
-include($$moduleFile)
+isEmpty(QT_BUILD_TREE):include($$moduleFile)
VERSION = $${QT_WEBKIT_MAJOR_VERSION}.$${QT_WEBKIT_MINOR_VERSION}.$${QT_WEBKIT_PATCH_VERSION}
unix {
diff --git a/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri b/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri
index d8cf06c..4594d1e 100644
--- a/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri
+++ b/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri
@@ -2,4 +2,4 @@ QT_WEBKIT_VERSION = 4.7.0
QT_WEBKIT_MAJOR_VERSION = 4
QT_WEBKIT_MINOR_VERSION = 7
QT_WEBKIT_PATCH_VERSION = 0
-QT_CONFIG *= webkit
+QT_CONFIG += webkit
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index b916b4d..2505e72 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -19,7 +19,7 @@ INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
# Only used on platforms with CONFIG += precompile_header
PRECOMPILED_HEADER = global/qt_pch.h
-linux*-g++*:!static {
+linux*:!static {
QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate
prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
DEFINES += ELF_INTERPRETER=\\\"$$system(readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index ea7e2e4..b4f5d0f 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -508,6 +508,14 @@ void qt_core_boilerplate()
"Contact: Nokia Corporation (qt-info@nokia.com)\n"
"\n"
"Build key: " QT_BUILD_KEY "\n"
+ "Compat build key: "
+#ifdef QT_BUILD_KEY_COMPAT
+ "| " QT_BUILD_KEY_COMPAT " "
+#endif
+#ifdef QT_BUILD_KEY_COMPAT2
+ "| " QT_BUILD_KEY_COMPAT2 " "
+#endif
+ "|\n"
"Build date: %s\n"
"Installation prefix: %s\n"
"Library path: %s\n"
@@ -517,6 +525,9 @@ void qt_core_boilerplate()
qt_configure_libraries_path_str + 12,
qt_configure_headers_path_str + 12);
+ extern void qDumpCPUFeatures();
+ qDumpCPUFeatures();
+
#ifdef QT_EVAL
extern void qt_core_eval_init(uint);
qt_core_eval_init(1);
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 0f99948..a9ae2ab 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -790,10 +790,13 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
.arg(qt_version&0xff)
.arg(debug ? QLatin1String("debug") : QLatin1String("release"));
} else if (key != QT_BUILD_KEY
+ // we may have some compatibility keys, try them too:
#ifdef QT_BUILD_KEY_COMPAT
- // be sure to load plugins using an older but compatible build key
&& key != QT_BUILD_KEY_COMPAT
#endif
+#ifdef QT_BUILD_KEY_COMPAT2
+ && key != QT_BUILD_KEY_COMPAT2
+#endif
) {
if (qt_debug_component()) {
qWarning("In %s:\n"
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 8005d7d..68ab033 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -41,6 +41,7 @@
#include "qsimd_p.h"
#include <QByteArray>
+#include <stdio.h>
#if defined(Q_OS_WINCE)
#include <windows.h>
@@ -50,15 +51,20 @@
#include <intrin.h>
#endif
+#if defined(Q_OS_LINUX) && defined(__arm__)
+#include "private/qcore_unix_p.h"
+
+#include <asm/hwcap.h>
+#include <linux/auxvec.h>
+#endif
+
QT_BEGIN_NAMESPACE
-uint qDetectCPUFeatures()
+#if defined (Q_OS_WINCE)
+static inline uint detectProcessorFeatures()
{
- static uint features = 0xffffffff;
- if (features != 0xffffffff)
- return features;
+ uint features = 0;
-#if defined (Q_OS_WINCE)
#if defined (ARM)
if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX)) {
features = IWMMXT;
@@ -78,22 +84,57 @@ uint qDetectCPUFeatures()
#endif
features = 0;
return features;
-#elif defined(QT_HAVE_IWMMXT)
+}
+
+#elif defined(__arm__) || defined(__arm) || defined(QT_HAVE_IWMMXT) || defined(QT_HAVE_NEON)
+static inline uint detectProcessorFeatures()
+{
+ uint features = 0;
+
+#if defined(Q_OS_LINUX)
+ int auxv = ::qt_safe_open("/proc/self/auxv", O_RDONLY);
+ if (auxv != -1) {
+ unsigned long vector[64];
+ int nread;
+ while (features == 0) {
+ nread = ::qt_safe_read(auxv, (char *)vector, sizeof vector);
+ if (nread <= 0) {
+ // EOF or error
+ break;
+ }
+
+ int max = nread / (sizeof vector[0]);
+ for (int i = 0; i < max; i += 2)
+ if (vector[i] == AT_HWCAP) {
+ if (vector[i+1] & HWCAP_IWMMXT)
+ features |= IWMMXT;
+ if (vector[i+1] & HWCAP_NEON)
+ features |= NEON;
+ break;
+ }
+ }
+
+ ::qt_safe_close(auxv);
+ return features;
+ }
+ // fall back if /proc/self/auxv wasn't found
+#endif
+
+#if defined(QT_HAVE_IWMMXT)
// runtime detection only available when running as a previlegied process
- static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
- features = doIWMMXT ? IWMMXT : 0;
- return features;
+ features = IWMMXT;
#elif defined(QT_HAVE_NEON)
- static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
- features = doNEON ? NEON : 0;
+ features = NEON;
+#endif
+
return features;
-#else
- features = 0;
-#if defined(__x86_64__) || defined(Q_OS_WIN64)
- features = MMX|SSE|SSE2|CMOV;
-#elif defined(__ia64__)
- features = MMX|SSE|SSE2;
+}
+
#elif defined(__i386__) || defined(_M_IX86)
+static inline uint detectProcessorFeatures()
+{
+ uint features = 0;
+
unsigned int extended_result = 0;
unsigned int feature_result = 0;
uint result = 0;
@@ -149,6 +190,7 @@ uint qDetectCPUFeatures()
:
: "%eax", "%ecx", "%edx"
);
+
#elif defined (Q_OS_WIN)
_asm {
push eax
@@ -210,6 +252,7 @@ uint qDetectCPUFeatures()
}
#endif
+
// result now contains the standard feature bits
if (result & (1u << 15))
features |= CMOV;
@@ -236,9 +279,13 @@ uint qDetectCPUFeatures()
if (feature_result & (1u << 28))
features |= AVX;
-#endif // i386
+ return features;
+}
-#if defined(__x86_64__) || defined(Q_OS_WIN64)
+#elif defined(__x86_64) || defined(Q_OS_WIN64)
+static inline uint detectProcessorFeatures()
+{
+ uint features = MMX|SSE|SSE2|CMOV;
uint feature_result = 0;
#if defined(Q_CC_GNU)
@@ -282,33 +329,97 @@ uint qDetectCPUFeatures()
features |= SSE4_2;
if (feature_result & (1u << 28))
features |= AVX;
-#endif // x86_64
-#if defined(QT_HAVE_MMX)
- if (qgetenv("QT_NO_MMX").toInt())
- features ^= MMX;
-#endif
- if (qgetenv("QT_NO_MMXEXT").toInt())
- features ^= MMXEXT;
+ return features;
+}
-#if defined(QT_HAVE_3DNOW)
- if (qgetenv("QT_NO_3DNOW").toInt())
- features ^= MMX3DNOW;
-#endif
- if (qgetenv("QT_NO_3DNOWEXT").toInt())
- features ^= MMX3DNOWEXT;
+#elif defined(__ia64__)
+static inline uint detectProcessorFeatures()
+{
+ return MMX|SSE|SSE2;
+}
-#if defined(QT_HAVE_SSE)
- if (qgetenv("QT_NO_SSE").toInt())
- features ^= SSE;
-#endif
-#if defined(QT_HAVE_SSE2)
- if (qgetenv("QT_NO_SSE2").toInt())
- features ^= SSE2;
+#else
+static inline uint detectProcessorFeatures()
+{
+ return 0;
+}
#endif
+/*
+ * Use kdesdk/scripts/generate_string_table.pl to update the table below.
+ * Here's the data (don't forget the ONE leading space):
+ mmx
+ mmxext
+ mmx3dnow
+ mmx3dnowext
+ sse
+ sse2
+ cmov
+ iwmmxt
+ neon
+ sse3
+ ssse3
+ sse4.1
+ sse4.2
+ avx
+ */
+
+// begin generated
+static const char features_string[] =
+ " mmx\0"
+ " mmxext\0"
+ " mmx3dnow\0"
+ " mmx3dnowext\0"
+ " sse\0"
+ " sse2\0"
+ " cmov\0"
+ " iwmmxt\0"
+ " neon\0"
+ " sse3\0"
+ " ssse3\0"
+ " sse4.1\0"
+ " sse4.2\0"
+ " avx\0"
+ "\0";
+
+static const int features_indices[] = {
+ 0, 5, 13, 23, 36, 41, 47, 53,
+ 61, 67, 73, 80, 88, 96, -1
+};
+// end generated
+
+const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]);
+
+uint qDetectCPUFeatures()
+{
+ static QBasicAtomicInt features = Q_BASIC_ATOMIC_INITIALIZER(-1);
+ if (features != -1)
+ return features;
+
+ uint f = detectProcessorFeatures();
+ QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
+ if (!disable.isEmpty()) {
+ disable.prepend(' ');
+ for (int i = 0; i < features_count; ++i) {
+ if (disable.contains(features_string + features_indices[i]))
+ f &= ~(1 << i);
+ }
+ }
+
+ features = f;
return features;
-#endif
+}
+
+void qDumpCPUFeatures()
+{
+ uint features = qDetectCPUFeatures();
+ printf("Processor features: ");
+ for (int i = 0; i < features_count; ++i) {
+ if (features & (1 << i))
+ printf("%s", features_string + features_indices[i]);
+ }
+ puts("");
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index a3148fb..2626657 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -85,6 +85,7 @@ QT_BEGIN_HEADER
// SSE4.1 and SSE4.2 intrinsics
#if (defined(QT_HAVE_SSE4_1) || defined(QT_HAVE_SSE4_2)) && (defined(__SSE4_1__) || defined(Q_CC_MSVC))
#include <smmintrin.h>
+#include <nmmintrin.h>
#endif
// AVX intrinsics
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 2fd9a0b..d940bf8 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -173,7 +173,7 @@ static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b)
return 1;
}
-// Unicode case-insensitive comparison
+// Unicode case-sensitive comparison
static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen)
{
if (a == b && alen == blen)
@@ -202,22 +202,55 @@ static int ucstrnicmp(const ushort *a, const ushort *b, int l)
return ucstricmp(a, a + l, b, b + l);
}
+// Benchmarking indicates that doing memcmp is much slower than
+// executing the comparison ourselves.
+//
+// The profiling was done on a population of calls to qMemEquals, generated
+// during a run of the demo browser. The profile of the data (32-bit x86
+// Linux) was:
+//
+// total number of comparisons: 21353
+// longest string compared: 95
+// average comparison length: 14.8786
+// cache-line crosses: 5661 (13.3%)
+// alignment histogram:
+// 0xXXX0 = 512 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXX2 = 15087 (35.3%) strings, 5145 (34.1%) of which same-aligned
+// 0xXXX4 = 525 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXX6 = 557 (1.3%) strings, 6 (1.1%) of which same-aligned
+// 0xXXX8 = 509 (1.2%) strings, 0 (0.0%) of which same-aligned
+// 0xXXXa = 24358 (57.0%) strings, 9901 (40.6%) of which same-aligned
+// 0xXXXc = 557 (1.3%) strings, 0 (0.0%) of which same-aligned
+// 0xXXXe = 601 (1.4%) strings, 15 (2.5%) of which same-aligned
+// total = 42706 (100%) strings, 15067 (35.3%) of which same-aligned
+//
+// 92% of the strings have alignment of 2 or 10, which is due to malloc on
+// 32-bit Linux returning values aligned to 8 bytes, and offsetof(array, QString::Data) == 18.
+//
+// The profile on 64-bit will be different since offsetof(array, QString::Data) == 26.
+//
+// The benchmark results were, for a Core-i7 @ 2.67 GHz 32-bit, compiled with -O3 -funroll-loops:
+// 16-bit loads only: 872,301 CPU ticks [Qt 4.5 / memcmp]
+// 32- and 16-bit loads: 773,362 CPU ticks [Qt 4.6]
+// SSE2 "movdqu" 128-bit loads: 618,736 CPU ticks
+// SSE3 "lddqu" 128-bit loads: 619,954 CPU ticks
+// SSSE3 "palignr" corrections: 852,147 CPU ticks
+// SSE4.2 "pcmpestrm": 738,702 CPU ticks
+//
+// The same benchmark on an Atom N450 @ 1.66 GHz, is:
+// 16-bit loads only: 2,185,882 CPU ticks
+// 32- and 16-bit loads: 1,805,060 CPU ticks
+// SSE2 "movdqu" 128-bit loads: 2,529,843 CPU ticks
+// SSE3 "lddqu" 128-bit loads: 2,514,858 CPU ticks
+// SSSE3 "palignr" corrections: 2,160,325 CPU ticks
+// SSE4.2 not available
+//
+// The conclusion we reach is that alignment the SSE2 unaligned code can gain
+// 20% improvement in performance in some systems, but suffers a penalty due
+// to the unaligned loads on others.
+
static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
{
- // Benchmarking indicates that doing memcmp is much slower than
- // executing the comparison ourselves.
- // To make it even faster, we do a 32-bit comparison, comparing
- // twice the amount of data as a normal word-by-word comparison.
- //
- // Benchmarking results on a 2.33 GHz Core2 Duo, with a 64-QChar
- // block of data, with 4194304 iterations (per iteration):
- // operation usec cpu ticks
- // memcmp 330 710
- // 16-bit 79 167-171
- // 32-bit aligned 49 105-109
- //
- // Testing also indicates that unaligned 32-bit loads are as
- // performant as 32-bit aligned.
if (a == b || !length)
return true;
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index e52f59f..06e4d47 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -614,6 +614,7 @@ private:
ushort asciiCache : 1;
ushort capacity : 1;
ushort reserved : 11;
+ // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit
ushort array[1];
};
static Data shared_null;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 3c23884..4c03d33 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5742,16 +5742,11 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
}
if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
- // on touch-screens, combine this touch point with the closest one we find if it
- // is a a direct descendent or ancestor (
+ // on touch-screens, combine this touch point with the closest one we find
int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
- if (!item
- || (closestItem
- && (item->isAncestorOf(closestItem)
- || closestItem->isAncestorOf(item)))) {
+ if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
item = closestItem;
- }
}
if (!item)
continue;
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 3943e26..13d2c77 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -99,7 +99,7 @@ neon:*-g++* {
contains(QMAKE_MAC_XARCH, no) {
DEFINES += QT_NO_MAC_XARCH
} else {
- win32-g++*|!win32:!*-icc* {
+ win32-g++*|!win32:!win32-icc*:!macx-icc* {
mmx {
mmx_compiler.commands = $$QMAKE_CXX -c -Winline
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index e768a21..cb4061e 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -595,8 +595,9 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
if (gesture->hasHotSpot()) {
// guess the target widget using the hotspot of the gesture
QPoint pt = gesture->hotSpot().toPoint();
- if (QWidget *w = qApp->topLevelAt(pt)) {
- target = w->childAt(w->mapFromGlobal(pt));
+ if (QWidget *topLevel = qApp->topLevelAt(pt)) {
+ QWidget *child = topLevel->childAt(topLevel->mapFromGlobal(pt));
+ target = child ? child : topLevel;
}
} else {
// or use the context of the gesture
diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp
index 102b347..65014a6 100644
--- a/src/network/bearer/qnetworkconfigmanager.cpp
+++ b/src/network/bearer/qnetworkconfigmanager.cpp
@@ -54,7 +54,15 @@ Q_GLOBAL_STATIC(QNetworkConfigurationManagerPrivate, connManager);
QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate()
{
- return connManager();
+ static bool initialized = false;
+
+ QNetworkConfigurationManagerPrivate *m = connManager();
+ if (!initialized) {
+ initialized = true;
+ m->updateConfigurations();
+ }
+
+ return m;
}
/*!
@@ -178,7 +186,7 @@ QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate()
QNetworkConfigurationManager::QNetworkConfigurationManager( QObject* parent )
: QObject(parent)
{
- QNetworkConfigurationManagerPrivate *priv = connManager();
+ QNetworkConfigurationManagerPrivate *priv = qNetworkConfigurationManagerPrivate();
connect(priv, SIGNAL(configurationAdded(QNetworkConfiguration)),
this, SIGNAL(configurationAdded(QNetworkConfiguration)));
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index dd174bf..d388920 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -64,9 +64,6 @@ QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
{
qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
-
- moveToThread(QCoreApplicationPrivate::mainThread());
- updateConfigurations();
}
QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate()
@@ -359,6 +356,13 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
if (sender())
return;
+ if (thread() != QCoreApplicationPrivate::mainThread()) {
+ if (thread() != QThread::currentThread())
+ return;
+
+ moveToThread(QCoreApplicationPrivate::mainThread());
+ }
+
updating = false;
#ifndef QT_NO_LIBRARY
diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp
index 3112dd6..9e3da61 100644
--- a/src/network/kernel/qhostinfo_unix.cpp
+++ b/src/network/kernel/qhostinfo_unix.cpp
@@ -247,7 +247,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
#ifndef QT_NO_IPV6
else if (node->ai_family == AF_INET6) {
QHostAddress addr;
- addr.setAddress(((sockaddr_in6 *) node->ai_addr)->sin6_addr.s6_addr);
+ sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr;
+ addr.setAddress(sa6->sin6_addr.s6_addr);
+ if (sa6->sin6_scope_id)
+ addr.setScopeId(QString::number(sa6->sin6_scope_id));
if (!addresses.contains(addr))
addresses.append(addr);
}
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index fe28863..f6bfbac 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -352,10 +352,13 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
+
+ QString scopeid = addr.scopeId();
+ bool ok;
+ sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
#ifndef QT_NO_IPV6IFNAME
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(addr.scopeId().toLatin1().data());
-#else
- sockAddrIPv6.sin6_scope_id = addr.scopeId().toInt();
+ if (!ok)
+ sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
#endif
Q_IPV6ADDR ip6 = addr.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 8177b4f..477ef45 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -207,6 +207,7 @@ static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr
if (address.protocol() == QAbstractSocket::IPv6Protocol) {
memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
sockAddrIPv6->sin6_family = AF_INET6;
+ sockAddrIPv6->sin6_scope_id = address.scopeId().toInt();
WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
Q_IPV6ADDR tmp = address.toIPv6Address();
memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp));
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 8560214..8347626 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -782,6 +782,8 @@ static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSOb
static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
{
@@ -892,6 +894,28 @@ JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JS
return args.at(0);
}
+JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::throwError(exec, JSC::GeneralError, "qsTrId() requires at least one argument");
+ if (!args.at(0).isString())
+ return JSC::throwError(exec, JSC::TypeError, "qsTrId(): first argument (id) must be a string");
+ if ((args.size() > 1) && !args.at(1).isNumber())
+ return JSC::throwError(exec, JSC::TypeError, "qsTrId(): second argument (n) must be a number");
+ JSC::UString id = args.at(0).toString(exec);
+ int n = -1;
+ if (args.size() > 1)
+ n = args.at(1).toInt32(exec);
+ return JSC::jsString(exec, qtTrId(QScript::convertToLatin1(id).constData(), n));
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::jsUndefined();
+ return args.at(0);
+}
+
static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
@@ -3435,6 +3459,8 @@ void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
\row \o QT_TR_NOOP() \o QT_TR_NOOP()
\row \o qsTranslate() \o QCoreApplication::translate()
\row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
+ \row \o qsTrId() (since 4.7) \o qtTrId()
+ \row \o QT_TRID_NOOP() (since 4.7) \o QT_TRID_NOOP()
\endtable
\sa {Internationalization with Qt}
@@ -3453,6 +3479,8 @@ void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "qsTrId"), QScript::functionQsTrId));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TRID_NOOP"), QScript::functionQsTrIdNoOp));
glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
}
diff --git a/src/testlib/qbenchmarkmeasurement_p.h b/src/testlib/qbenchmarkmeasurement_p.h
index 932852c..20a3bc1 100644
--- a/src/testlib/qbenchmarkmeasurement_p.h
+++ b/src/testlib/qbenchmarkmeasurement_p.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include <QtCore/qdatetime.h>
+#include <QtCore/qelapsedtimer.h>
#include "3rdparty/cycle_p.h"
#include "qbenchmark.h"
@@ -87,7 +87,7 @@ public:
bool needsWarmupIteration();
QTest::QBenchmarkMetric metricType();
private:
- QTime time;
+ QElapsedTimer time;
};
#ifdef HAVE_TICK_COUNTER // defined in 3rdparty/cycle_p.h
diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp
index a968520..ddc3939 100644
--- a/tests/auto/gestures/tst_gestures.cpp
+++ b/tests/auto/gestures/tst_gestures.cpp
@@ -395,7 +395,12 @@ void tst_Gestures::customGesture()
{
GestureWidget widget;
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
CustomEvent event;
+ event.hotSpot = widget.mapToGlobal(QPoint(5,5));
+ event.hasHotSpot = true;
sendCustomGesture(&event, &widget);
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
diff --git a/tests/auto/headers/tst_headers.cpp b/tests/auto/headers/tst_headers.cpp
index 06c70f9..7ccf058 100644
--- a/tests/auto/headers/tst_headers.cpp
+++ b/tests/auto/headers/tst_headers.cpp
@@ -213,7 +213,8 @@ void tst_Headers::licenseCheck()
return;
if (content.first().contains("generated")) {
- content.takeFirst();
+ // don't scan generated files
+ return;
}
if (sourceFile.endsWith("/tests/auto/linguist/lupdate/testdata/good/merge_ordering/foo.cpp")
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs/main.js b/tests/auto/linguist/lupdate/testdata/good/parsejs/main.js
new file mode 100644
index 0000000..9f61cea
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs/main.js
@@ -0,0 +1,91 @@
+qsTr("One");
+qsTranslate("FooContext", "Two");
+
+var greeting_strings = [
+ QT_TR_NOOP("Hello"),
+ QT_TRANSLATE_NOOP("FooContext", "Goodbye")
+];
+
+qsTr("One", "not the same one");
+
+//: My first comment.
+qsTr("See comment");
+
+//: My second comment.
+qsTranslate("BarContext", "See other comment");
+
+//: My third comment
+//: spans two lines.
+qsTr("The comment explains it all");
+
+//: My fourth comment
+//: spans a whopping
+//: three lines.
+qsTranslate("BazContext", "It should be clear by now");
+
+/*: C-style comment. */
+qsTr("I love C++");
+
+/*: Another C-style comment. */
+qsTranslate("FooContext", "I really love C++");
+
+/*: C-style comment, followed by */
+/*: another one. */
+qsTr("Qt is the best");
+
+/*: Another C-style comment, followed by */
+/*: yet another one. */
+qsTranslate("BarContext", "Qt is the very best");
+
+// This comment doesn't have any effect.
+qsTr("The comment had no effect");
+
+// This comment doesn't have any effect either.
+qsTranslate("BazContext", "The comment had no effect, really");
+
+/* This C-style comment doesn't have any effect. */
+qsTr("No comment to your comment");
+
+/* This C-style comment doesn't have any effect either. */
+qsTranslate("FooContext", "I refuse to comment on that");
+
+//= id_foo
+qsTr("This string has an identifier");
+
+//= id_bar
+qsTranslate("BarContext", "This string also has an identifier");
+
+//~ loc-blank False
+qsTr("This string has meta-data");
+
+//~ loc-layout_id foo_dialog
+qsTranslate("BazContext", "This string also has meta-data");
+
+// This comment is to be ignored.
+//: This is a comment for the translator.
+//= id_baz
+//~ foo 123
+//~ magic-stuff This means something special.
+qsTr("This string has a lot of information");
+
+// This comment is also to be ignored.
+//: This is another comment for the translator.
+//= id_babar
+//~ foo-bar Important stuff
+//~ needle-in-haystack Found
+//~ overflow True
+qsTranslate("FooContext", "This string has even more information");
+
+qsTr("This string has disambiguation", "Disambiguation");
+
+qsTranslate("BarContext", "This string also has disambiguation", "Another disambiguation");
+
+qsTr("This string contains plurals", "", 10);
+
+qsTrId("qtn_foo_bar");
+
+var more_greeting_strings = [ QT_TRID_NOOP("qtn_needle"), QT_TRID_NOOP("qtn_haystack") ];
+
+//: qsTrId() with comment, meta-data and plurals.
+//~ well-tested True
+qsTrId("qtn_bar_baz", 10);
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs/project.pro b/tests/auto/linguist/lupdate/testdata/good/parsejs/project.pro
new file mode 100644
index 0000000..d549039
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs/project.pro
@@ -0,0 +1,3 @@
+SOURCES += main.js
+
+TRANSLATIONS = project.ts
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsejs/project.ts.result
new file mode 100644
index 0000000..d03c713
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs/project.ts.result
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0">
+<context>
+ <name></name>
+ <message id="qtn_foo_bar">
+ <location filename="main.js" line="85"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_needle">
+ <location filename="main.js" line="87"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_haystack">
+ <location filename="main.js" line="87"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_bar_baz" numerus="yes">
+ <location filename="main.js" line="91"/>
+ <source></source>
+ <extracomment>qsTrId() with comment, meta-data and plurals.</extracomment>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ </translation>
+ <extra-well-tested>True</extra-well-tested>
+ </message>
+</context>
+<context>
+ <name>BarContext</name>
+ <message>
+ <location filename="main.js" line="15"/>
+ <source>See other comment</source>
+ <extracomment>My second comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="38"/>
+ <source>Qt is the very best</source>
+ <extracomment>Another C-style comment, followed by yet another one.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_bar">
+ <location filename="main.js" line="56"/>
+ <source>This string also has an identifier</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="81"/>
+ <source>This string also has disambiguation</source>
+ <comment>Another disambiguation</comment>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>BazContext</name>
+ <message>
+ <location filename="main.js" line="24"/>
+ <source>It should be clear by now</source>
+ <extracomment>My fourth comment spans a whopping three lines.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="44"/>
+ <source>The comment had no effect, really</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="62"/>
+ <source>This string also has meta-data</source>
+ <translation type="unfinished"></translation>
+ <extra-loc-layout_id>foo_dialog</extra-loc-layout_id>
+ </message>
+</context>
+<context>
+ <name>FooContext</name>
+ <message>
+ <location filename="main.js" line="2"/>
+ <source>Two</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="6"/>
+ <source>Goodbye</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="30"/>
+ <source>I really love C++</source>
+ <extracomment>Another C-style comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="50"/>
+ <source>I refuse to comment on that</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_babar">
+ <location filename="main.js" line="77"/>
+ <source>This string has even more information</source>
+ <extracomment>This is another comment for the translator.</extracomment>
+ <translation type="unfinished"></translation>
+ <extra-needle-in-haystack>Found</extra-needle-in-haystack>
+ <extra-overflow>True</extra-overflow>
+ <extra-foo-bar>Important stuff</extra-foo-bar>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <location filename="main.js" line="1"/>
+ <source>One</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="5"/>
+ <source>Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="9"/>
+ <source>One</source>
+ <comment>not the same one</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="12"/>
+ <source>See comment</source>
+ <extracomment>My first comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="19"/>
+ <source>The comment explains it all</source>
+ <extracomment>My third comment spans two lines.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="27"/>
+ <source>I love C++</source>
+ <extracomment>C-style comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="34"/>
+ <source>Qt is the best</source>
+ <extracomment>C-style comment, followed by another one.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="41"/>
+ <source>The comment had no effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="47"/>
+ <source>No comment to your comment</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_foo">
+ <location filename="main.js" line="53"/>
+ <source>This string has an identifier</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="59"/>
+ <source>This string has meta-data</source>
+ <translation type="unfinished"></translation>
+ <extra-loc-blank>False</extra-loc-blank>
+ </message>
+ <message id="id_baz">
+ <location filename="main.js" line="69"/>
+ <source>This string has a lot of information</source>
+ <extracomment>This is a comment for the translator.</extracomment>
+ <translation type="unfinished"></translation>
+ <extra-foo>123</extra-foo>
+ <extra-magic-stuff>This means something special.</extra-magic-stuff>
+ </message>
+ <message>
+ <location filename="main.js" line="79"/>
+ <source>This string has disambiguation</source>
+ <comment>Disambiguation</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <location filename="main.js" line="83"/>
+ <source>This string contains plurals</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs2/expectedoutput.txt b/tests/auto/linguist/lupdate/testdata/good/parsejs2/expectedoutput.txt
new file mode 100644
index 0000000..d6c977f
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs2/expectedoutput.txt
@@ -0,0 +1,29 @@
+.*/lupdate/testdata/good/parsejs2/main.js:3: qsTranslate\(\) requires at least two arguments.
+.*/lupdate/testdata/good/parsejs2/main.js:4: qsTranslate\(\) requires at least two arguments.
+.*/lupdate/testdata/good/parsejs2/main.js:5: qsTranslate\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:6: qsTranslate\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:7: qsTranslate\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:9: QT_TRANSLATE_NOOP\(\) requires at least two arguments.
+.*/lupdate/testdata/good/parsejs2/main.js:10: QT_TRANSLATE_NOOP\(\) requires at least two arguments.
+.*/lupdate/testdata/good/parsejs2/main.js:11: QT_TRANSLATE_NOOP\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:12: QT_TRANSLATE_NOOP\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:13: QT_TRANSLATE_NOOP\(\): both arguments must be literal strings.
+.*/lupdate/testdata/good/parsejs2/main.js:15: qsTr\(\) requires at least one argument.
+.*/lupdate/testdata/good/parsejs2/main.js:16: qsTr\(\): text to translate must be a literal string.
+.*/lupdate/testdata/good/parsejs2/main.js:18: QT_TR_NOOP\(\) requires at least one argument.
+.*/lupdate/testdata/good/parsejs2/main.js:19: QT_TR_NOOP\(\): text to translate must be a literal string.
+.*/lupdate/testdata/good/parsejs2/main.js:21: qsTrId\(\) requires at least one argument.
+.*/lupdate/testdata/good/parsejs2/main.js:22: qsTrId\(\): identifier must be a literal string.
+.*/lupdate/testdata/good/parsejs2/main.js:24: QT_TRID_NOOP\(\) requires at least one argument.
+.*/lupdate/testdata/good/parsejs2/main.js:25: QT_TRID_NOOP\(\): identifier must be a literal string.
+.*/lupdate/testdata/good/parsejs2/main.js:27: Unexpected character in meta string
+.*/lupdate/testdata/good/parsejs2/main.js:28: Unexpected character in meta string
+.*/lupdate/testdata/good/parsejs2/main.js:29: Unterminated meta string
+.*/lupdate/testdata/good/parsejs2/main.js:30: Unterminated meta string
+.*/lupdate/testdata/good/parsejs2/main.js:33: //% cannot be used with qsTranslate\(\). Ignoring
+.*/lupdate/testdata/good/parsejs2/main.js:35: //% cannot be used with QT_TRANSLATE_NOOP\(\). Ignoring
+.*/lupdate/testdata/good/parsejs2/main.js:37: //% cannot be used with qsTr\(\). Ignoring
+.*/lupdate/testdata/good/parsejs2/main.js:39: //% cannot be used with QT_TR_NOOP\(\). Ignoring
+.*/lupdate/testdata/good/parsejs2/main.js:42: Discarding unconsumed meta data
+.*/lupdate/testdata/good/parsejs2/main.js:44: Discarding unconsumed meta data
+.*/lupdate/testdata/good/parsejs2/main.js:46: Discarding unconsumed meta data
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs2/main.js b/tests/auto/linguist/lupdate/testdata/good/parsejs2/main.js
new file mode 100644
index 0000000..ea02957
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs2/main.js
@@ -0,0 +1,56 @@
+// This script exercises lupdate errors and warnings.
+
+qsTranslate();
+qsTranslate(10);
+qsTranslate(10, 20);
+qsTranslate("10", 20);
+qsTranslate(10, "20");
+
+QT_TRANSLATE_NOOP();
+QT_TRANSLATE_NOOP(10);
+QT_TRANSLATE_NOOP(10, 20);
+QT_TRANSLATE_NOOP("10", 20);
+QT_TRANSLATE_NOOP(10, "20");
+
+qsTr();
+qsTr(10);
+
+QT_TR_NOOP();
+QT_TR_NOOP(10);
+
+qsTrId();
+qsTrId(10);
+
+QT_TRID_NOOP();
+QT_TRID_NOOP(10);
+
+//% This is wrong
+//% "This is not wrong" This is wrong
+//% "I forgot to close the meta string
+//% "Being evil \
+
+//% "Should cause a warning"
+qsTranslate("FooContext", "Hello");
+//% "Should cause a warning"
+QT_TRANSLATE_NOOP("FooContext", "World");
+//% "Should cause a warning"
+qsTr("Hello");
+//% "Should cause a warning"
+QT_TR_NOOP("World");
+
+//: This comment will be discarded.
+Math.sin(1);
+//= id_foobar
+Math.cos(2);
+//~ underflow False
+Math.tan(3);
+
+/*
+Not tested for now, because these should perhaps not cause
+translation entries to be generated at all; see QTBUG-11843.
+
+//= qtn_foo
+qsTrId("qtn_foo");
+//= qtn_bar
+QT_TRID_NOOP("qtn_bar");
+*/
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.pro b/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.pro
new file mode 100644
index 0000000..d549039
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.pro
@@ -0,0 +1,3 @@
+SOURCES += main.js
+
+TRANSLATIONS = project.ts
diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.ts.result
new file mode 100644
index 0000000..bfa1b3d
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parsejs2/project.ts.result
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0">
+<context>
+ <name>FooContext</name>
+ <message>
+ <location filename="main.js" line="33"/>
+ <source>Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="35"/>
+ <source>World</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <location filename="main.js" line="37"/>
+ <source>Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.js" line="39"/>
+ <source>World</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qmake/testdata/substitutes/test.pro b/tests/auto/qmake/testdata/substitutes/test.pro
index ddad93f..26b0272 100644
--- a/tests/auto/qmake/testdata/substitutes/test.pro
+++ b/tests/auto/qmake/testdata/substitutes/test.pro
@@ -1 +1,5 @@
-QMAKE_SUBSTITUTES += test.in sub/test2.in
+QMAKE_SUBSTITUTES += test.in sub/test2.in indirect
+
+indirect.input = $$PWD/test3.txt
+indirect.output = $$OUT_PWD/sub/indirect_test.txt
+
diff --git a/tests/auto/qmake/testdata/substitutes/test3.txt b/tests/auto/qmake/testdata/substitutes/test3.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/tests/auto/qmake/testdata/substitutes/test3.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/auto/qmake/tst_qmake.cpp b/tests/auto/qmake/tst_qmake.cpp
index 060fa01..277e9f8 100644
--- a/tests/auto/qmake/tst_qmake.cpp
+++ b/tests/auto/qmake/tst_qmake.cpp
@@ -484,12 +484,14 @@ void tst_qmake::substitutes()
QVERIFY( test_compiler.qmake( workDir, "test" ));
QVERIFY( test_compiler.exists( workDir, "test", Plain, "" ));
QVERIFY( test_compiler.exists( workDir, "sub/test2", Plain, "" ));
+ QVERIFY( test_compiler.exists( workDir, "sub/indirect_test.txt", Plain, "" ));
QVERIFY( test_compiler.makeDistClean( workDir ));
QString buildDir = base_path + "/testdata/substitutes_build";
QVERIFY( test_compiler.qmake( workDir, "test", buildDir ));
QVERIFY( test_compiler.exists( buildDir, "test", Plain, "" ));
QVERIFY( test_compiler.exists( buildDir, "sub/test2", Plain, "" ));
+ QVERIFY( test_compiler.exists( buildDir, "sub/indirect_test.txt", Plain, "" ));
QVERIFY( test_compiler.makeDistClean( buildDir ));
}
diff --git a/tests/auto/qscriptengine/idtranslatable.js b/tests/auto/qscriptengine/idtranslatable.js
new file mode 100644
index 0000000..554ca88
--- /dev/null
+++ b/tests/auto/qscriptengine/idtranslatable.js
@@ -0,0 +1,5 @@
+qsTrId("qtn_foo_bar");
+
+var more_greeting_strings = [ QT_TRID_NOOP("qtn_needle"), QT_TRID_NOOP("qtn_haystack") ];
+
+qsTrId("qtn_bar_baz", 10);
diff --git a/tests/auto/qscriptengine/qscriptengine.qrc b/tests/auto/qscriptengine/qscriptengine.qrc
index b87f985..fa55a5b 100644
--- a/tests/auto/qscriptengine/qscriptengine.qrc
+++ b/tests/auto/qscriptengine/qscriptengine.qrc
@@ -1,5 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>translations/translatable_la.qm</file>
+ <file>translations/idtranslatable_la.qm</file>
</qresource>
</RCC>
diff --git a/tests/auto/qscriptengine/translations/idtranslatable_la.qm b/tests/auto/qscriptengine/translations/idtranslatable_la.qm
new file mode 100644
index 0000000..c8c0b72
--- /dev/null
+++ b/tests/auto/qscriptengine/translations/idtranslatable_la.qm
Binary files differ
diff --git a/tests/auto/qscriptengine/translations/idtranslatable_la.ts b/tests/auto/qscriptengine/translations/idtranslatable_la.ts
new file mode 100644
index 0000000..b6d7053
--- /dev/null
+++ b/tests/auto/qscriptengine/translations/idtranslatable_la.ts
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="nb_NO">
+<context>
+ <name></name>
+ <message id="qtn_foo_bar">
+ <location filename="idtranslatable.js" line="1"/>
+ <source></source>
+ <translation>First string</translation>
+ </message>
+ <message id="qtn_needle">
+ <location filename="idtranslatable.js" line="3"/>
+ <source></source>
+ <translation>Second string</translation>
+ </message>
+ <message id="qtn_haystack">
+ <location filename="idtranslatable.js" line="3"/>
+ <source></source>
+ <translation>Third string</translation>
+ </message>
+ <message id="qtn_bar_baz" numerus="yes">
+ <location filename="idtranslatable.js" line="5"/>
+ <source></source>
+ <translation>
+ <numerusform>Fourth string</numerusform>
+ <numerusform>%n fooish bar(s) found</numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp
index 7a732cc..4cff043 100644
--- a/tests/auto/qscriptengine/tst_qscriptengine.cpp
+++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp
@@ -162,6 +162,7 @@ private slots:
void translateWithInvalidArgs();
void translationContext_data();
void translationContext();
+ void translateScriptIdBased();
void functionScopes();
void nativeFunctionScopes();
void evaluateProgram();
@@ -4386,6 +4387,8 @@ void tst_QScriptEngine::installTranslatorFunctions()
QVERIFY(!global.property("QT_TRANSLATE_NOOP").isValid());
QVERIFY(!global.property("qsTr").isValid());
QVERIFY(!global.property("QT_TR_NOOP").isValid());
+ QVERIFY(!global.property("qsTrId").isValid());
+ QVERIFY(!global.property("QT_TRID_NOOP").isValid());
QVERIFY(!globalOrig.property("String").property("prototype").property("arg").isValid());
eng.installTranslatorFunctions();
@@ -4393,6 +4396,8 @@ void tst_QScriptEngine::installTranslatorFunctions()
QVERIFY(global.property("QT_TRANSLATE_NOOP").isFunction());
QVERIFY(global.property("qsTr").isFunction());
QVERIFY(global.property("QT_TR_NOOP").isFunction());
+ QVERIFY(global.property("qsTrId").isFunction());
+ QVERIFY(global.property("QT_TRID_NOOP").isFunction());
QVERIFY(globalOrig.property("String").property("prototype").property("arg").isFunction());
if (useCustomGlobalObject) {
@@ -4400,6 +4405,8 @@ void tst_QScriptEngine::installTranslatorFunctions()
QVERIFY(!globalOrig.property("QT_TRANSLATE_NOOP").isValid());
QVERIFY(!globalOrig.property("qsTr").isValid());
QVERIFY(!globalOrig.property("QT_TR_NOOP").isValid());
+ QVERIFY(!globalOrig.property("qsTrId").isValid());
+ QVERIFY(!globalOrig.property("QT_TRID_NOOP").isValid());
}
{
@@ -4427,6 +4434,17 @@ void tst_QScriptEngine::installTranslatorFunctions()
QVERIFY(ret.isString());
QCOMPARE(ret.toString(), QString::fromLatin1("foobar"));
}
+
+ {
+ QScriptValue ret = eng.evaluate("qsTrId('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
+ {
+ QScriptValue ret = eng.evaluate("QT_TRID_NOOP('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
}
static QScriptValue callQsTr(QScriptContext *ctx, QScriptEngine *eng)
@@ -4537,6 +4555,10 @@ void tst_QScriptEngine::translateWithInvalidArgs_data()
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 123)") << "qsTranslate('foo', 'bar', 'baz', 123)" << "Error: qsTranslate(): fourth argument (encoding) must be a string";
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 'zab', 'rab')") << "qsTranslate('foo', 'bar', 'baz', 'zab', 'rab')" << "Error: qsTranslate(): fifth argument (n) must be a number";
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 'zab', 123)") << "qsTranslate('foo', 'bar', 'baz', 'zab', 123)" << "Error: qsTranslate(): invalid encoding 'zab'";
+
+ QTest::newRow("qsTrId()") << "qsTrId()" << "Error: qsTrId() requires at least one argument";
+ QTest::newRow("qsTrId(123)") << "qsTrId(123)" << "TypeError: qsTrId(): first argument (id) must be a string";
+ QTest::newRow("qsTrId('foo', 'bar')") << "qsTrId('foo', 'bar')" << "TypeError: qsTrId(): second argument (n) must be a number";
}
void tst_QScriptEngine::translateWithInvalidArgs()
@@ -4598,6 +4620,53 @@ void tst_QScriptEngine::translationContext()
QCoreApplication::instance()->removeTranslator(&translator);
}
+void tst_QScriptEngine::translateScriptIdBased()
+{
+ QScriptEngine engine;
+
+ QTranslator translator;
+ translator.load(":/translations/idtranslatable_la");
+ QCoreApplication::instance()->installTranslator(&translator);
+ engine.installTranslatorFunctions();
+
+ QString fileName = QString::fromLatin1("idtranslatable.js");
+
+ QHash<QString, QString> expectedTranslations;
+ expectedTranslations["qtn_foo_bar"] = "First string";
+ expectedTranslations["qtn_needle"] = "Second string";
+ expectedTranslations["qtn_haystack"] = "Third string";
+ expectedTranslations["qtn_bar_baz"] = "Fourth string";
+
+ QHash<QString, QString>::const_iterator it;
+ for (it = expectedTranslations.constBegin(); it != expectedTranslations.constEnd(); ++it) {
+ for (int x = 0; x < 2; ++x) {
+ QString fn;
+ if (x)
+ fn = fileName;
+ // Top-level
+ QCOMPARE(engine.evaluate(QString::fromLatin1("qsTrId('%0')")
+ .arg(it.key()), fn).toString(),
+ it.value());
+ QCOMPARE(engine.evaluate(QString::fromLatin1("QT_TRID_NOOP('%0')")
+ .arg(it.key()), fn).toString(),
+ it.key());
+ // From function
+ QCOMPARE(engine.evaluate(QString::fromLatin1("(function() { return qsTrId('%0'); })()")
+ .arg(it.key()), fn).toString(),
+ it.value());
+ QCOMPARE(engine.evaluate(QString::fromLatin1("(function() { return QT_TRID_NOOP('%0'); })()")
+ .arg(it.key()), fn).toString(),
+ it.key());
+ }
+ }
+
+ // Plural form
+ QCOMPARE(engine.evaluate("qsTrId('qtn_bar_baz', 10)").toString(),
+ QString::fromLatin1("10 fooish bar(s) found"));
+ QCOMPARE(engine.evaluate("qsTrId('qtn_foo_bar', 10)").toString(),
+ QString::fromLatin1("qtn_foo_bar")); // Doesn't have plural
+}
+
void tst_QScriptEngine::functionScopes()
{
QScriptEngine eng;
diff --git a/tests/auto/qtouchevent/tst_qtouchevent.cpp b/tests/auto/qtouchevent/tst_qtouchevent.cpp
index bb80fde..4219ef4 100644
--- a/tests/auto/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/qtouchevent/tst_qtouchevent.cpp
@@ -109,6 +109,7 @@ class tst_QTouchEventGraphicsItem : public QGraphicsItem
public:
QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints;
bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
+ int touchBeginCounter, touchUpdateCounter, touchEndCounter;
bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
tst_QTouchEventGraphicsItem **weakpointer;
@@ -131,6 +132,7 @@ public:
touchUpdatePoints.clear();
touchEndPoints.clear();
seenTouchBegin = seenTouchUpdate = seenTouchEnd = false;
+ touchBeginCounter = touchUpdateCounter = touchEndCounter = 0;
acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true;
deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
}
@@ -146,6 +148,7 @@ public:
if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
+ ++touchBeginCounter;
touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints();
event->setAccepted(acceptTouchBegin);
if (deleteInTouchBegin)
@@ -155,6 +158,7 @@ public:
if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
+ ++touchUpdateCounter;
touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints();
event->setAccepted(acceptTouchUpdate);
if (deleteInTouchUpdate)
@@ -164,6 +168,7 @@ public:
if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
seenTouchEnd = seenTouchBegin && !seenTouchEnd;
+ ++touchEndCounter;
touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints();
event->setAccepted(acceptTouchEnd);
if (deleteInTouchEnd)
@@ -194,6 +199,7 @@ private slots:
void deleteInEventHandler();
void deleteInRawEventTranslation();
void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
+ void touchBeginWithGraphicsWidget();
};
void tst_QTouchEvent::touchDisabledByDefault()
@@ -1334,6 +1340,59 @@ void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin()
QTest::touchEvent(view.viewport()).release(0, view.mapFromScene(QPoint(10, 10)));
}
+void tst_QTouchEvent::touchBeginWithGraphicsWidget()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ tst_QTouchEventGraphicsItem *root;
+ root = new tst_QTouchEventGraphicsItem;
+ root->setAcceptTouchEvents(true);
+ scene.addItem(root);
+
+ QGraphicsWidget *glassWidget = new QGraphicsWidget;
+ glassWidget->setMinimumSize(100, 100);
+ scene.addItem(glassWidget);
+
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.fitInView(scene.sceneRect());
+
+ QTest::touchEvent()
+ .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
+ QTest::touchEvent()
+ .stationary(0)
+ .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+ QTest::touchEvent()
+ .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
+ .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+
+ QCOMPARE(root->touchBeginCounter, 1);
+ QCOMPARE(root->touchUpdateCounter, 1);
+ QCOMPARE(root->touchEndCounter, 1);
+ QCOMPARE(root->touchUpdatePoints.size(), 2);
+
+ root->reset();
+ glassWidget->setWindowFlags(Qt::Window); // make the glassWidget a panel
+
+ QTest::touchEvent()
+ .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
+ QTest::touchEvent()
+ .stationary(0)
+ .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+ QTest::touchEvent()
+ .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
+ .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
+
+ QCOMPARE(root->touchBeginCounter, 0);
+ QCOMPARE(root->touchUpdateCounter, 0);
+ QCOMPARE(root->touchEndCounter, 0);
+
+
+ delete root;
+ delete glassWidget;
+}
+
QTEST_MAIN(tst_QTouchEvent)
#include "tst_qtouchevent.moc"
diff --git a/tests/benchmarks/corelib/tools/qstring/data.cpp b/tests/benchmarks/corelib/tools/qstring/data.cpp
new file mode 100644
index 0000000..6d1a069
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qstring/data.cpp
@@ -0,0 +1,1284 @@
+// This is a generated file - DO NOT EDIT
+static const ushort stringCollectionData[] __attribute__((aligned(16))) = {
+ // #0
+ 65535,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 118, 101, 114, 115, 105, 111, 110, 115, 47,
+ 65535,65534,65533,65532,65531, // 24
+ 65535,65534,65533,65532,65531,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 118, 101, 114, 115, 105, 111, 110, 115, 47,
+ 65535, // 48
+
+ // #1
+ 65535,65534,65533,65532,65531,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 118, 101, 114, 115, 105, 111, 110, 115, 47,
+ 65535, // 72
+ 65535,65534,65533,65532,65531,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 86, 101, 114, 115, 105, 111, 110, 115, 47,
+ 65535, // 96
+
+ // #2
+ 65535,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 116, 105, 109, 101, 115, 116, 97, 109, 112, 115, 47,
+ 65535,65534,65533, // 120
+ 65535,65534,65533,65532,65531,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 116, 105, 109, 101, 115, 116, 97, 109, 112, 115, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 152
+
+ // #3
+ 65535,65534,65533,65532,65531,
+ 99, 111, 109, 112, 105, 108, 101, 114, 32, 116, 105, 109, 101, 115, 116, 97, 109, 112, 115, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 184
+ 65535,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 47,
+ 65535,65534,65533, // 208
+
+ // #4
+ 65535,65534,65533,65532,65531,65530,65529,65528,65527,65526,65525,65524,65523,65522,65521,65520,65519,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532, // 280+
+
+
+ // #5
+ 65535,65534,65533,65532,65531,65530,65529,65528,65527,65526,65525,65524,65523,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 352+
+ 65535,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532, // 408+
+
+ // #6
+ 65535,65534,65533,65532,65531,65530,65529,65528,65527,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532, // 472+
+
+
+ // #7
+ 65535,
+ 97, 114, 99, 104, 105, 118, 101, 100, 32, 99, 111, 109, 112, 105, 108, 101, 114, 115, 47,
+ 65535,65534,65533,65532, // 496
+ 65535,65534,65533,65532,65531,
+ 97, 114, 99, 104, 105, 118, 101, 100, 32, 99, 111, 109, 112, 105, 108, 101, 114, 115, 47,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 528
+
+ // #8
+ 65535,65534,65533,65532,65531,
+ 97, 114, 99, 104, 105, 118, 101, 100, 32, 99, 111, 109, 112, 105, 108, 101, 114, 115, 47,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 560
+ 65535,65534,65533,65532,65531,
+ 65, 114, 99, 104, 105, 118, 101, 100, 32, 67, 111, 109, 112, 105, 108, 101, 114, 115, 47,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 592
+
+ // #9
+ 65535,65534,65533,65532,65531,65530,65529,65528,65527,65526,65525,65524,65523,65522,65521,65520,65519,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532, // 664+
+ 65535,65534,65533,65532,65531,65530,65529,65528,65527,65526,65525,65524,65523,
+ 47, 118, 97, 114, 47, 116, 109, 112, 47, 116, 101, 97, 109, 98, 117, 105, 108, 100, 101, 114, 45, 116, 109, 97, 99, 105, 101, 105, 114, 47, 99, 108, 105, 101, 110, 116, 47, 99, 111, 109, 112, 105, 108, 101, 114, 115, 46, 99, 111, 110, 102,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 736+
+
+ // #10
+ 65535,65534,65533,65532,65531,
+ 76, 105, 110, 117, 120,
+ 65535,65534,65533,65532,65531,65530, // 752
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 760
+
+ // #11
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 776
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 792
+
+ // #12
+ 65535,
+ 105, 99, 99,
+ 65535,65534,65533,65532, // 800
+ 65535,65534,65533,65532,65531,
+ 103, 43, 43,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 816
+
+ // #13
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 824
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 832
+
+ // #14
+ 65535,
+ 105, 51, 56, 54,
+ 65535,65534,65533, // 840
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 856
+
+ // #15
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 864
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 872
+
+ // #16
+ 65535,
+ 105, 51, 56, 54,
+ 65535,65534,65533, // 880
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 896
+
+ // #17
+ 65535,
+ 103, 99, 99,
+ 65535,65534,65533,65532, // 904
+ 65535,65534,65533,65532,65531,
+ 103, 43, 43,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 920
+
+ // #18
+ 65535,65534,65533,65532,65531,
+ 76, 105, 110, 117, 120,
+ 65535,65534,65533,65532,65531,65530, // 936
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 944
+
+ // #19
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 960
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 976
+
+ // #20
+ 65535,
+ 103, 43, 43,
+ 65535,65534,65533,65532, // 984
+ 65535,65534,65533,65532,65531,
+ 103, 43, 43,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 1000
+
+ // #21
+ 65535,65534,65533,65532,65531,
+ 52, 46, 52, 46, 51,
+ 65535,65534,65533,65532,65531,65530, // 1016
+ 65535,65534,65533,65532,65531,
+ 52, 46, 52, 46, 51,
+ 65535,65534,65533,65532,65531,65530, // 1032
+
+ // #22
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1040
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1048
+
+ // #23
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1064
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1080
+
+ // #24
+ 65535,
+ 47, 117, 115, 114, 47, 98, 105, 110, 47, 103, 43, 43,
+ 65535,65534,65533, // 1096
+ 65535,
+ 47, 117, 115, 114, 47, 98, 105, 110, 47, 103, 43, 43,
+ 65535,65534,65533, // 1112
+
+ // #25
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1120
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1128
+
+ // #26
+ 65535,
+ 105, 51, 56, 54,
+ 65535,65534,65533, // 1136
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1152
+
+ // #27
+ 65535,
+ 105, 99, 99,
+ 65535,65534,65533,65532, // 1160
+ 65535,65534,65533,65532,65531,
+ 103, 43, 43,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 1176
+
+ // #28
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1184
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1192
+
+ // #29
+ 65535,
+ 105, 51, 56, 54,
+ 65535,65534,65533, // 1200
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1216
+
+ // #30
+ 65535,65534,65533,65532,65531,
+ 76, 105, 110, 117, 120,
+ 65535,65534,65533,65532,65531,65530, // 1232
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1240
+
+ // #31
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1256
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1272
+
+ // #32
+ 65535,65534,65533,65532,65531,
+ 76, 105, 110, 117, 120,
+ 65535,65534,65533,65532,65531,65530, // 1288
+ 65535,
+ 76, 105, 110, 117, 120,
+ 65535,65534, // 1296
+
+ // #33
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1312
+ 65535,65534,65533,65532,65531,
+ 105, 51, 56, 54,
+ 65535,65534,65533,65532,65531,65530,65529, // 1328
+
+ // #34
+ 65535,
+ 45, 109, 97, 114, 99, 104, 61, 99, 111, 114, 101, 50,
+ 65535,65534,65533, // 1344
+ 65535,
+ 116, 98, 51, 54, 57, 54, 56, 95, 50, 46, 105, 105,
+ 65535,65534,65533, // 1360
+
+ // #35
+ 65535,65534,65533,65532,65531,
+ 45, 102, 108, 111, 111, 112, 45, 98, 108, 111, 99, 107,
+ 65535,65534,65533,65532,65531,65530,65529, // 1384
+ 65535,
+ 116, 98, 51, 54, 57, 54, 56, 95, 50, 46, 105, 105,
+ 65535,65534,65533, // 1400
+
+ // #36
+ 65535,65534,65533,65532,65531,
+ 116, 98, 51, 54, 57, 54, 56, 95, 50, 46, 105, 105,
+ 65535,65534,65533,65532,65531,65530,65529, // 1424
+ 65535,
+ 116, 98, 51, 54, 57, 54, 56, 95, 50, 46, 105, 105,
+ 65535,65534,65533, // 1440
+
+ // #37
+ 65535,65534,65533,65532,65531,
+ 45, 109, 115, 115, 101, 52,
+ 65535,65534,65533,65532,65531, // 1456
+ 65535,65534,65533,65532,65531,
+ 108, 101, 110, 103, 116, 104,
+ 65535,65534,65533,65532,65531, // 1472
+
+ // #38
+ 65535,65534,65533,65532,65531,
+ 116, 98, 51, 54, 57, 54, 56, 95, 49, 46, 111,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 1496
+ 65535,65534,65533,65532,65531,
+ 116, 98, 51, 54, 57, 54, 56, 95, 49, 46, 111,
+ 65535,65534,65533,65532,65531,65530,65529,65528, // 1520
+
+ // #39
+ 65535,65534,65533,65532,65531,
+ 68, 69, 83, 75, 84, 79, 80, 95, 83, 69, 83, 83,
+ 65535,65534,65533,65532,65531,65530,65529, // 1544
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1560
+
+ // #40
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 83, 79, 85, 82, 67, 69, 68, 61, 49,
+ 65535,65534,65533,65532,65531,65530,65529, // 1584
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1600
+
+ // #41
+ 65535,65534,65533,65532,65531,
+ 81, 84, 68, 73, 82, 61, 47, 104, 111, 109, 101, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 1624
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1640
+
+ // #42
+ 65535,
+ 76, 67, 95, 67, 84, 89, 80, 69, 61, 112, 116, 95,
+ 65535,65534,65533, // 1656
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1672
+
+ // #43
+ 65535,
+ 71, 84, 75, 95, 82, 67, 95, 70, 73, 76, 69, 83,
+ 65535,65534,65533, // 1688
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1704
+
+ // #44
+ 65535,
+ 88, 77, 79, 68, 73, 70, 73, 69, 82, 83, 61, 64,
+ 65535,65534,65533, // 1720
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1736
+
+ // #45
+ 65535,
+ 83, 72, 69, 76, 76, 61, 47, 98, 105, 110, 47, 122,
+ 65535,65534,65533, // 1752
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1768
+
+ // #46
+ 65535,65534,65533,65532,65531,
+ 85, 61, 64, 123, 117, 112, 115, 116, 114, 101, 97, 109,
+ 65535,65534,65533,65532,65531,65530,65529, // 1792
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1808
+
+ // #47
+ 65535,
+ 95, 61, 47, 117, 115, 114, 47, 98, 105, 110, 47, 105,
+ 65535,65534,65533, // 1824
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1840
+
+ // #48
+ 65535,
+ 88, 68, 71, 95, 67, 79, 78, 70, 73, 71, 95, 68,
+ 65535,65534,65533, // 1856
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1872
+
+ // #49
+ 65535,65534,65533,65532,65531,
+ 83, 65, 86, 69, 72, 73, 83, 84, 61, 49, 48, 48,
+ 65535,65534,65533,65532,65531,65530,65529, // 1896
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1912
+
+ // #50
+ 65535,
+ 75, 68, 69, 95, 77, 85, 76, 84, 73, 72, 69, 65,
+ 65535,65534,65533, // 1928
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1944
+
+ // #51
+ 65535,65534,65533,65532,65531,
+ 77, 65, 76, 76, 79, 67, 95, 67, 72, 69, 67, 75,
+ 65535,65534,65533,65532,65531,65530,65529, // 1968
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 1984
+
+ // #52
+ 65535,65534,65533,65532,65531,
+ 72, 73, 83, 84, 67, 79, 78, 84, 82, 79, 76, 61,
+ 65535,65534,65533,65532,65531,65530,65529, // 2008
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2024
+
+ // #53
+ 65535,65534,65533,65532,65531,
+ 88, 68, 71, 95, 68, 65, 84, 65, 95, 68, 73, 82,
+ 65535,65534,65533,65532,65531,65530,65529, // 2048
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2064
+
+ // #54
+ 65535,65534,65533,65532,65531,
+ 88, 68, 77, 95, 77, 65, 78, 65, 71, 69, 68, 61,
+ 65535,65534,65533,65532,65531,65530,65529, // 2088
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2104
+
+ // #55
+ 65535,
+ 76, 67, 95, 67, 79, 76, 76, 65, 84, 69, 61, 112,
+ 65535,65534,65533, // 2120
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2136
+
+ // #56
+ 65535,
+ 81, 84, 95, 80, 76, 85, 71, 73, 78, 95, 80, 65,
+ 65535,65534,65533, // 2152
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2168
+
+ // #57
+ 65535,
+ 83, 67, 82, 69, 69, 78, 68, 73, 82, 61, 47, 104,
+ 65535,65534,65533, // 2184
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2200
+
+ // #58
+ 65535,65534,65533,65532,65531,
+ 76, 69, 83, 83, 79, 80, 69, 78, 61, 124, 47, 117,
+ 65535,65534,65533,65532,65531,65530,65529, // 2224
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2240
+
+ // #59
+ 65535,
+ 76, 67, 95, 78, 65, 77, 69, 61, 110, 98, 95, 78,
+ 65535,65534,65533, // 2256
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2272
+
+ // #60
+ 65535,65534,65533,65532,65531,
+ 80, 52, 67, 76, 73, 69, 78, 84, 61, 116, 109, 97,
+ 65535,65534,65533,65532,65531,65530,65529, // 2296
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2312
+
+ // #61
+ 65535,
+ 80, 65, 84, 72, 61, 47, 104, 111, 109, 101, 47, 116,
+ 65535,65534,65533, // 2328
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2344
+
+ // #62
+ 65535,65534,65533,65532,65531,
+ 71, 80, 71, 95, 65, 71, 69, 78, 84, 95, 73, 78,
+ 65535,65534,65533,65532,65531,65530,65529, // 2368
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2384
+
+ // #63
+ 65535,65534,65533,65532,65531,
+ 88, 67, 85, 82, 83, 79, 82, 95, 84, 72, 69, 77,
+ 65535,65534,65533,65532,65531,65530,65529, // 2408
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2424
+
+ // #64
+ 65535,65534,65533,65532,65531,
+ 83, 69, 83, 83, 73, 79, 78, 95, 77, 65, 78, 65,
+ 65535,65534,65533,65532,65531,65530,65529, // 2448
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2464
+
+ // #65
+ 65535,
+ 81, 84, 83, 82, 67, 68, 73, 82, 61, 47, 104, 111,
+ 65535,65534,65533, // 2480
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2496
+
+ // #66
+ 65535,65534,65533,65532,65531,
+ 87, 73, 78, 68, 79, 87, 73, 68, 61, 52, 54, 49,
+ 65535,65534,65533,65532,65531,65530,65529, // 2520
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2536
+
+ // #67
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 77, 69, 83, 83, 65, 71, 69, 83, 61,
+ 65535,65534,65533,65532,65531,65530,65529, // 2560
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2576
+
+ // #68
+ 65535,
+ 76, 67, 95, 78, 85, 77, 69, 82, 73, 67, 61, 110,
+ 65535,65534,65533, // 2592
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2608
+
+ // #69
+ 65535,
+ 71, 84, 75, 50, 95, 82, 67, 95, 70, 73, 76, 69,
+ 65535,65534,65533, // 2624
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2640
+
+ // #70
+ 65535,
+ 80, 82, 79, 70, 73, 76, 69, 72, 79, 77, 69, 61,
+ 65535,65534,65533, // 2656
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2672
+
+ // #71
+ 65535,65534,65533,65532,65531,
+ 68, 77, 95, 67, 79, 78, 84, 82, 79, 76, 61, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 2696
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2712
+
+ // #72
+ 65535,
+ 76, 83, 95, 67, 79, 76, 79, 82, 83, 61, 114, 115,
+ 65535,65534,65533, // 2728
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2744
+
+ // #73
+ 65535,65534,65533,65532,65531,
+ 83, 83, 72, 95, 65, 85, 84, 72, 95, 83, 79, 67,
+ 65535,65534,65533,65532,65531,65530,65529, // 2768
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2784
+
+ // #74
+ 65535,65534,65533,65532,65531,
+ 75, 68, 69, 68, 73, 82, 83, 61, 47, 104, 111, 109,
+ 65535,65534,65533,65532,65531,65530,65529, // 2808
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2824
+
+ // #75
+ 65535,65534,65533,65532,65531,
+ 76, 68, 95, 80, 82, 69, 76, 79, 65, 68, 61, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 2848
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2864
+
+ // #76
+ 65535,65534,65533,65532,65531,
+ 88, 67, 85, 82, 83, 79, 82, 95, 80, 65, 84, 72,
+ 65535,65534,65533,65532,65531,65530,65529, // 2888
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2904
+
+ // #77
+ 65535,
+ 115, 114, 99, 100, 105, 114, 61, 47, 104, 111, 109, 101,
+ 65535,65534,65533, // 2920
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2936
+
+ // #78
+ 65535,65534,65533,65532,65531,
+ 72, 79, 77, 69, 61, 47, 104, 111, 109, 101, 47, 116,
+ 65535,65534,65533,65532,65531,65530,65529, // 2960
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 2976
+
+ // #79
+ 65535,
+ 81, 84, 52, 68, 79, 67, 68, 73, 82, 61, 47, 117,
+ 65535,65534,65533, // 2992
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3008
+
+ // #80
+ 65535,65534,65533,65532,65531,
+ 80, 87, 68, 61, 47, 104, 111, 109, 101, 47, 116, 109,
+ 65535,65534,65533,65532,65531,65530,65529, // 3032
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3048
+
+ // #81
+ 65535,65534,65533,65532,65531,
+ 75, 68, 69, 95, 83, 69, 83, 83, 73, 79, 78, 95,
+ 65535,65534,65533,65532,65531,65530,65529, // 3072
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3088
+
+ // #82
+ 65535,
+ 73, 78, 83, 73, 68, 69, 95, 83, 80, 69, 67, 73,
+ 65535,65534,65533, // 3104
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3120
+
+ // #83
+ 65535,
+ 83, 83, 72, 95, 65, 71, 69, 78, 84, 95, 80, 73,
+ 65535,65534,65533, // 3136
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3152
+
+ // #84
+ 65535,
+ 80, 75, 71, 95, 67, 79, 78, 70, 73, 71, 95, 80,
+ 65535,65534,65533, // 3168
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3184
+
+ // #85
+ 65535,65534,65533,65532,65531,
+ 68, 66, 85, 83, 95, 83, 69, 83, 83, 73, 79, 78,
+ 65535,65534,65533,65532,65531,65530,65529, // 3208
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3224
+
+ // #86
+ 65535,
+ 76, 68, 95, 76, 73, 66, 82, 65, 82, 89, 95, 80,
+ 65535,65534,65533, // 3240
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3256
+
+ // #87
+ 65535,65534,65533,65532,65531,
+ 80, 52, 85, 83, 69, 82, 61, 116, 106, 109, 97, 99,
+ 65535,65534,65533,65532,65531,65530,65529, // 3280
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3296
+
+ // #88
+ 65535,65534,65533,65532,65531,
+ 81, 84, 69, 83, 84, 95, 67, 79, 76, 79, 82, 69,
+ 65535,65534,65533,65532,65531,65530,65529, // 3320
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3336
+
+ // #89
+ 65535,65534,65533,65532,65531,
+ 88, 68, 71, 95, 83, 69, 83, 83, 73, 79, 78, 95,
+ 65535,65534,65533,65532,65531,65530,65529, // 3360
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3376
+
+ // #90
+ 65535,65534,65533,65532,65531,
+ 76, 69, 83, 83, 75, 69, 89, 61, 47, 101, 116, 99,
+ 65535,65534,65533,65532,65531,65530,65529, // 3400
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3416
+
+ // #91
+ 65535,
+ 76, 79, 71, 78, 65, 77, 69, 61, 116, 109, 97, 99,
+ 65535,65534,65533, // 3432
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3448
+
+ // #92
+ 65535,
+ 71, 95, 70, 73, 76, 69, 78, 65, 77, 69, 95, 69,
+ 65535,65534,65533, // 3464
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3480
+
+ // #93
+ 65535,
+ 75, 68, 69, 95, 70, 85, 76, 76, 95, 83, 69, 83,
+ 65535,65534,65533, // 3496
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3512
+
+ // #94
+ 65535,65534,65533,65532,65531,
+ 72, 79, 83, 84, 78, 65, 77, 69, 61, 108, 111, 116,
+ 65535,65534,65533,65532,65531,65530,65529, // 3536
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3552
+
+ // #95
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 84, 73, 77, 69, 61, 112, 116, 95, 66,
+ 65535,65534,65533,65532,65531,65530,65529, // 3576
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3592
+
+ // #96
+ 65535,
+ 83, 83, 72, 95, 65, 83, 75, 80, 65, 83, 83, 61,
+ 65535,65534,65533, // 3608
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3624
+
+ // #97
+ 65535,65534,65533,65532,65531,
+ 72, 73, 83, 84, 70, 73, 76, 69, 61, 47, 104, 111,
+ 65535,65534,65533,65532,65531,65530,65529, // 3648
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3664
+
+ // #98
+ 65535,
+ 75, 79, 78, 83, 79, 76, 69, 95, 68, 66, 85, 83,
+ 65535,65534,65533, // 3680
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3696
+
+ // #99
+ 65535,
+ 77, 65, 75, 69, 61, 47, 117, 115, 114, 47, 98, 105,
+ 65535,65534,65533, // 3712
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3728
+
+ // #100
+ 65535,
+ 67, 65, 78, 66, 69, 82, 82, 65, 95, 68, 82, 73,
+ 65535,65534,65533, // 3744
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3760
+
+ // #101
+ 65535,
+ 71, 67, 79, 78, 70, 95, 84, 77, 80, 68, 73, 82,
+ 65535,65534,65533, // 3776
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3792
+
+ // #102
+ 65535,65534,65533,65532,65531,
+ 85, 83, 69, 82, 61, 116, 109, 97, 99, 105, 101, 105,
+ 65535,65534,65533,65532,65531,65530,65529, // 3816
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3832
+
+ // #103
+ 65535,
+ 111, 98, 106, 100, 105, 114, 61, 47, 104, 111, 109, 101,
+ 65535,65534,65533, // 3848
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3864
+
+ // #104
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 77, 79, 78, 69, 84, 65, 82, 89, 61,
+ 65535,65534,65533,65532,65531,65530,65529, // 3888
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3904
+
+ // #105
+ 65535,65534,65533,65532,65531,
+ 81, 84, 76, 73, 66, 61, 47, 117, 115, 114, 47, 108,
+ 65535,65534,65533,65532,65531,65530,65529, // 3928
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3944
+
+ // #106
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 84, 69, 76, 69, 80, 72, 79, 78, 69,
+ 65535,65534,65533,65532,65531,65530,65529, // 3968
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 3984
+
+ // #107
+ 65535,
+ 80, 89, 84, 72, 79, 78, 68, 79, 78, 84, 87, 82,
+ 65535,65534,65533, // 4000
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4016
+
+ // #108
+ 65535,65534,65533,65532,65531,
+ 84, 77, 80, 68, 73, 82, 61, 47, 116, 109, 112, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 4040
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4056
+
+ // #109
+ 65535,65534,65533,65532,65531,
+ 65, 82, 77, 76, 77, 68, 95, 76, 73, 67, 69, 78,
+ 65535,65534,65533,65532,65531,65530,65529, // 4080
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4096
+
+ // #110
+ 65535,
+ 80, 89, 84, 72, 79, 78, 80, 65, 84, 72, 61, 47,
+ 65535,65534,65533, // 4112
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4128
+
+ // #111
+ 65535,65534,65533,65532,65531,
+ 77, 65, 75, 69, 70, 76, 65, 71, 83, 61, 119, 32,
+ 65535,65534,65533,65532,65531,65530,65529, // 4152
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4168
+
+ // #112
+ 65535,
+ 77, 70, 76, 65, 71, 83, 61, 45, 119, 32, 45, 45,
+ 65535,65534,65533, // 4184
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4200
+
+ // #113
+ 65535,
+ 77, 65, 73, 76, 61, 47, 118, 97, 114, 47, 115, 112,
+ 65535,65534,65533, // 4216
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4232
+
+ // #114
+ 65535,65534,65533,65532,65531,
+ 83, 72, 69, 76, 76, 95, 83, 69, 83, 83, 73, 79,
+ 65535,65534,65533,65532,65531,65530,65529, // 4256
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4272
+
+ // #115
+ 65535,
+ 75, 68, 69, 68, 73, 82, 61, 47, 104, 111, 109, 101,
+ 65535,65534,65533, // 4288
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4304
+
+ // #116
+ 65535,65534,65533,65532,65531,
+ 76, 69, 83, 83, 67, 72, 65, 82, 83, 69, 84, 61,
+ 65535,65534,65533,65532,65531,65530,65529, // 4328
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4344
+
+ // #117
+ 65535,65534,65533,65532,65531,
+ 76, 67, 95, 80, 65, 80, 69, 82, 61, 110, 98, 95,
+ 65535,65534,65533,65532,65531,65530,65529, // 4368
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4384
+
+ // #118
+ 65535,
+ 66, 82, 79, 87, 83, 69, 82, 61, 47, 117, 115, 114,
+ 65535,65534,65533, // 4400
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4416
+
+ // #119
+ 65535,
+ 77, 69, 84, 65, 95, 67, 76, 65, 83, 83, 61, 100,
+ 65535,65534,65533, // 4432
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4448
+
+ // #120
+ 65535,65534,65533,65532,65531,
+ 77, 68, 86, 95, 77, 69, 78, 85, 95, 83, 84, 89,
+ 65535,65534,65533,65532,65531,65530,65529, // 4472
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4488
+
+ // #121
+ 65535,65534,65533,65532,65531,
+ 67, 79, 76, 79, 82, 70, 71, 66, 71, 61, 49, 53,
+ 65535,65534,65533,65532,65531,65530,65529, // 4512
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4528
+
+ // #122
+ 65535,65534,65533,65532,65531,
+ 80, 89, 84, 72, 79, 78, 83, 84, 65, 82, 84, 85,
+ 65535,65534,65533,65532,65531,65530,65529, // 4552
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4568
+
+ // #123
+ 65535,
+ 76, 67, 95, 77, 69, 65, 83, 85, 82, 69, 77, 69,
+ 65535,65534,65533, // 4584
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4600
+
+ // #124
+ 65535,65534,65533,65532,65531,
+ 69, 68, 73, 84, 79, 82, 61, 47, 117, 115, 114, 47,
+ 65535,65534,65533,65532,65531,65530,65529, // 4624
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4640
+
+ // #125
+ 65535,65534,65533,65532,65531,
+ 69, 78, 95, 84, 66, 61, 109, 111, 99, 58, 117, 105,
+ 65535,65534,65533,65532,65531,65530,65529, // 4664
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4680
+
+ // #126
+ 65535,
+ 72, 73, 83, 84, 83, 73, 90, 69, 61, 49, 48, 48,
+ 65535,65534,65533, // 4696
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4712
+
+ // #127
+ 65535,65534,65533,65532,65531,
+ 71, 83, 95, 76, 73, 66, 61, 47, 104, 111, 109, 101,
+ 65535,65534,65533,65532,65531,65530,65529, // 4736
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4752
+
+ // #128
+ 65535,65534,65533,65532,65531,
+ 78, 76, 83, 80, 65, 84, 72, 61, 47, 117, 115, 114,
+ 65535,65534,65533,65532,65531,65530,65529, // 4776
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4792
+
+ // #129
+ 65535,65534,65533,65532,65531,
+ 87, 73, 78, 68, 79, 87, 80, 65, 84, 72, 61, 55,
+ 65535,65534,65533,65532,65531,65530,65529, // 4816
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4832
+
+ // #130
+ 65535,65534,65533,65532,65531,
+ 75, 79, 78, 83, 79, 76, 69, 95, 68, 66, 85, 83,
+ 65535,65534,65533,65532,65531,65530,65529, // 4856
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4872
+
+ // #131
+ 65535,
+ 76, 67, 95, 73, 68, 69, 78, 84, 73, 70, 73, 67,
+ 65535,65534,65533, // 4888
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4904
+
+ // #132
+ 65535,
+ 73, 78, 80, 85, 84, 82, 67, 61, 47, 101, 116, 99,
+ 65535,65534,65533, // 4920
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4936
+
+ // #133
+ 65535,65534,65533,65532,65531,
+ 81, 84, 73, 78, 67, 61, 47, 117, 115, 114, 47, 108,
+ 65535,65534,65533,65532,65531,65530,65529, // 4960
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 4976
+
+ // #134
+ 65535,
+ 76, 67, 95, 65, 68, 68, 82, 69, 83, 83, 61, 110,
+ 65535,65534,65533, // 4992
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5008
+
+ // #135
+ 65535,65534,65533,65532,65531,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 95,
+ 65535,65534,65533,65532,65531,65530,65529, // 5032
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5048
+
+ // #136
+ 65535,
+ 76, 65, 78, 71, 61, 112, 116, 95, 66, 82, 46, 85,
+ 65535,65534,65533, // 5064
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5080
+
+ // #137
+ 65535,
+ 80, 52, 80, 79, 82, 84, 61, 112, 52, 46, 116, 114,
+ 65535,65534,65533, // 5096
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5112
+
+ // #138
+ 65535,65534,65533,65532,65531,
+ 80, 73, 76, 79, 84, 80, 79, 82, 84, 61, 117, 115,
+ 65535,65534,65533,65532,65531,65530,65529, // 5136
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5152
+
+ // #139
+ 65535,
+ 75, 68, 69, 95, 83, 69, 83, 83, 73, 79, 78, 95,
+ 65535,65534,65533, // 5168
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5184
+
+ // #140
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5200
+ 65535,
+ 84, 69, 65, 77, 66, 85, 73, 76, 68, 69, 82, 61,
+ 65535,65534,65533, // 5216
+
+
+};
+static struct StringCollection
+{
+ int len;
+ int offset1, offset2;
+ ushort align1, align2;
+} stringCollection[] = {
+ {18, 1, 29, 3666, 106}, // #0
+ {18, 53, 77, 106, 1978}, // #1
+ {20, 97, 125, 2850, 3210}, // #2
+ {20, 157, 185, 3210, 3138}, // #3
+ {51, 225, 225, 3362, 3362}, // #4
+ {51, 293, 353, 1434, 3362}, // #5
+ {51, 417, 417, 3362, 3362}, // #6
+ {19, 473, 501, 2850, 10}, // #7
+ {19, 533, 565, 10, 442}, // #8
+ {51, 609, 677, 3362, 1434}, // #9
+ {5, 741, 753, 2666, 2066}, // #10
+ {4, 765, 781, 2362, 3930}, // #11
+ {3, 793, 805, 3330, 2138}, // #12
+ {5, 817, 825, 738, 2066}, // #13
+ {4, 833, 845, 434, 3930}, // #14
+ {5, 857, 865, 3842, 2066}, // #15
+ {4, 873, 885, 3538, 3930}, // #16
+ {3, 897, 909, 3330, 2138}, // #17
+ {5, 925, 937, 1898, 2066}, // #18
+ {4, 949, 965, 1594, 3930}, // #19
+ {3, 977, 989, 3330, 2138}, // #20
+ {5, 1005, 1021, 2218, 762}, // #21
+ {5, 1033, 1041, 3346, 2066}, // #22
+ {4, 1053, 1069, 3082, 3930}, // #23
+ {12, 1081, 1097, 2082, 962}, // #24
+ {5, 1113, 1121, 3362, 2066}, // #25
+ {4, 1129, 1141, 322, 3930}, // #26
+ {3, 1153, 1165, 2050, 2138}, // #27
+ {5, 1177, 1185, 1538, 2066}, // #28
+ {4, 1193, 1205, 1234, 3930}, // #29
+ {5, 1221, 1233, 554, 2066}, // #30
+ {4, 1245, 1261, 250, 3930}, // #31
+ {5, 1277, 1289, 2858, 2066}, // #32
+ {4, 1301, 1317, 2554, 3930}, // #33
+ {12, 1329, 1345, 2194, 1762}, // #34
+ {12, 1365, 1385, 2170, 1762}, // #35
+ {12, 1405, 1425, 2314, 1762}, // #36
+ {6, 1445, 1461, 3626, 666}, // #37
+ {11, 1477, 1501, 3882, 842}, // #38
+ {12, 1525, 1545, 1722, 2930}, // #39
+ {12, 1565, 1585, 1914, 2930}, // #40
+ {12, 1605, 1625, 442, 2930}, // #41
+ {12, 1641, 1657, 626, 2930}, // #42
+ {12, 1673, 1689, 946, 2930}, // #43
+ {12, 1705, 1721, 738, 2930}, // #44
+ {12, 1737, 1753, 2066, 2930}, // #45
+ {12, 1773, 1793, 1210, 2930}, // #46
+ {12, 1809, 1825, 1426, 2930}, // #47
+ {12, 1841, 1857, 1650, 2930}, // #48
+ {12, 1877, 1897, 1530, 2930}, // #49
+ {12, 1913, 1929, 1858, 2930}, // #50
+ {12, 1949, 1969, 2106, 2930}, // #51
+ {12, 1989, 2009, 2202, 2930}, // #52
+ {12, 2029, 2049, 2490, 2930}, // #53
+ {12, 2069, 2089, 2794, 2930}, // #54
+ {12, 2105, 2121, 2322, 2930}, // #55
+ {12, 2137, 2153, 2834, 2930}, // #56
+ {12, 2169, 2185, 1266, 2930}, // #57
+ {12, 2205, 2225, 2538, 2930}, // #58
+ {12, 2241, 2257, 2706, 2930}, // #59
+ {12, 2277, 2297, 3402, 2930}, // #60
+ {12, 2313, 2329, 146, 2930}, // #61
+ {12, 2349, 2369, 3690, 2930}, // #62
+ {12, 2389, 2409, 810, 2930}, // #63
+ {12, 2429, 2449, 1178, 2930}, // #64
+ {12, 2465, 2481, 1442, 2930}, // #65
+ {12, 2501, 2521, 3546, 2930}, // #66
+ {12, 2541, 2561, 1930, 2930}, // #67
+ {12, 2577, 2593, 1634, 2930}, // #68
+ {12, 2609, 2625, 1986, 2930}, // #69
+ {12, 2641, 2657, 1970, 2930}, // #70
+ {12, 2677, 2697, 1834, 2930}, // #71
+ {12, 2713, 2729, 1474, 2930}, // #72
+ {12, 2749, 2769, 2250, 2930}, // #73
+ {12, 2789, 2809, 2458, 2930}, // #74
+ {12, 2829, 2849, 2618, 2930}, // #75
+ {12, 2869, 2889, 3066, 2930}, // #76
+ {12, 2905, 2921, 3330, 2930}, // #77
+ {12, 2941, 2961, 1706, 2930}, // #78
+ {12, 2977, 2993, 2802, 2930}, // #79
+ {12, 3013, 3033, 3770, 2930}, // #80
+ {12, 3053, 3073, 3594, 2930}, // #81
+ {12, 3089, 3105, 2, 2930}, // #82
+ {12, 3121, 3137, 2962, 2930}, // #83
+ {12, 3153, 3169, 290, 2930}, // #84
+ {12, 3189, 3209, 794, 2930}, // #85
+ {12, 3225, 3241, 1058, 2930}, // #86
+ {12, 3261, 3281, 2394, 2930}, // #87
+ {12, 3301, 3321, 138, 2930}, // #88
+ {12, 3341, 3361, 1482, 2930}, // #89
+ {12, 3381, 3401, 570, 2930}, // #90
+ {12, 3417, 3433, 674, 2930}, // #91
+ {12, 3449, 3465, 1282, 2930}, // #92
+ {12, 3481, 3497, 1746, 2930}, // #93
+ {12, 3517, 3537, 1866, 2930}, // #94
+ {12, 3557, 3577, 1978, 2930}, // #95
+ {12, 3593, 3609, 3954, 2930}, // #96
+ {12, 3629, 3649, 2570, 2930}, // #97
+ {12, 3665, 3681, 2754, 2930}, // #98
+ {12, 3697, 3713, 3666, 2930}, // #99
+ {12, 3729, 3745, 34, 2930}, // #100
+ {12, 3761, 3777, 2914, 2930}, // #101
+ {12, 3797, 3817, 1194, 2930}, // #102
+ {12, 3833, 3849, 3202, 2930}, // #103
+ {12, 3869, 3889, 3018, 2930}, // #104
+ {12, 3909, 3929, 202, 2930}, // #105
+ {12, 3949, 3969, 3546, 2930}, // #106
+ {12, 3985, 4001, 3682, 2930}, // #107
+ {12, 4021, 4041, 3466, 2930}, // #108
+ {12, 4061, 4081, 4074, 2930}, // #109
+ {12, 4097, 4113, 306, 2930}, // #110
+ {12, 4133, 4153, 634, 2930}, // #111
+ {12, 4169, 4185, 802, 2930}, // #112
+ {12, 4201, 4217, 962, 2930}, // #113
+ {12, 4237, 4257, 1114, 2930}, // #114
+ {12, 4273, 4289, 1250, 2930}, // #115
+ {12, 4309, 4329, 3898, 2930}, // #116
+ {12, 4349, 4369, 1386, 2930}, // #117
+ {12, 4385, 4401, 1586, 2930}, // #118
+ {12, 4417, 4433, 1730, 2930}, // #119
+ {12, 4453, 4473, 1914, 2930}, // #120
+ {12, 4493, 4513, 1498, 2930}, // #121
+ {12, 4533, 4553, 2138, 2930}, // #122
+ {12, 4569, 4585, 2290, 2930}, // #123
+ {12, 4605, 4625, 2426, 2930}, // #124
+ {12, 4645, 4665, 2666, 2930}, // #125
+ {12, 4681, 4697, 2050, 2930}, // #126
+ {12, 4717, 4737, 2874, 2930}, // #127
+ {12, 4757, 4777, 3018, 2930}, // #128
+ {12, 4797, 4817, 1834, 2930}, // #129
+ {12, 4837, 4857, 3178, 2930}, // #130
+ {12, 4873, 4889, 3314, 2930}, // #131
+ {12, 4905, 4921, 2546, 2930}, // #132
+ {12, 4941, 4961, 3546, 2930}, // #133
+ {12, 4977, 4993, 3682, 2930}, // #134
+ {12, 5013, 5033, 3802, 2930}, // #135
+ {12, 5049, 5065, 3922, 2930}, // #136
+ {12, 5081, 5097, 4018, 2930}, // #137
+ {12, 5117, 5137, 42, 2930}, // #138
+ {12, 5153, 5169, 130, 2930}, // #139
+ {12, 5185, 5201, 242, 2930}, // #140
+};
+static const int stringCollectionCount = 141;
+static const int stringCollectionMaxLen = 51;
+// average comparison length: 12.0922
+// cache-line crosses: 6 (2.1%)
+// alignment histogram:
+// 0xXXX2 = 188 (66.7%) strings, 57 (30.3%) of which same-aligned
+// 0xXXXa = 94 (33.3%) strings, 10 (10.6%) of which same-aligned
+// total = 282 (100%) strings, 67 (23.8%) of which same-aligned
diff --git a/tests/benchmarks/corelib/tools/qstring/data.h b/tests/benchmarks/corelib/tools/qstring/data.h
new file mode 100644
index 0000000..c7a7467
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qstring/data.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+
+struct StringCollection
+{
+ int len;
+ int offset1, offset2;
+ ushort align1, align2;
+};
+
+extern const ushort stringCollectionData[];
+extern StringCollection stringCollection[];
+extern const int stringCollectionCount;
diff --git a/tests/benchmarks/corelib/tools/qstring/generatelist.pl b/tests/benchmarks/corelib/tools/qstring/generatelist.pl
new file mode 100644
index 0000000..d027adb
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qstring/generatelist.pl
@@ -0,0 +1,198 @@
+#!/usr/bin/perl
+## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is part of the QtCore module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## 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, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+#
+# Parses a file (passed as argument) that contains a dump of pairs of
+# strings and generates C source code including said data.
+#
+# The format of the file is:
+# LEN = <len> <keyword> <align1> <align2>\n<data1><data2>\n
+# where:
+# LEN the literal string "LEN"
+# <len> the length of the data, in 16-bit words
+# <keyword> the literal string "SAME" or "DIFF"
+# <align1> the alignment or pointer value of the first data
+# <align2> the alignment or pointer value of the second data
+# <data1> the first data
+# <data2> the second data
+# \n newline
+#
+# The code to write this data would be:
+# fprintf(out, "LEN = %d %s %d %d\n", len,
+# (p1 == p2) ? "SAME" : "DIFF",
+# uint(quintptr(p1)) & 0xfff, uint(quintptr(p2)) & 0xfff);
+# fwrite(p1, 2, len, out);
+# fwrite(p2, 2, len, out);
+# fwrite("\n", 1, 1, out);
+
+sub printUshortArray($$$) {
+ $str = $_[0];
+ $align = $_[1] & 0x1f;
+ $offset = $_[2];
+
+ die if ($align & 1) != 0;
+ $align /= 2;
+
+ $len = (length $str) / 2;
+ $headpadding = $align & 0x7;
+ $tailpadding = 8 - (($len + $headpadding) & 0x7);
+ $multiplecachelines = ($align + $len) > 0x20;
+
+ if ($multiplecachelines) {
+ # if this string crosses into a new cacheline, then
+ # replicate the result
+ $headpadding |= ($offset & ~0x1f);
+ $headpadding += 0x20
+ if ($headpadding < $offset);
+ $headpadding -= $offset;
+ ++$cachelinecrosses;
+ }
+ for $i (1..$headpadding) {
+ print 65536-$i,",";
+ }
+ print "\n " if ($headpadding > 0);
+ print " " if ($headpadding == 0);
+
+ for ($i = 0; $i < $len * 2; $i += 2) {
+ print " ", ord(substr($str, $i, 1)) +
+ ord(substr($str, $i + 1, 1)) * 256,
+ ",";
+ }
+ print "\n " if ($tailpadding > 0);
+
+ for $i (1..$tailpadding) {
+ print 65536-$i, ",";
+ }
+ print " // ", $offset + $headpadding + $len + $tailpadding;
+ print "+" if $multiplecachelines;
+
+ return ($offset + $headpadding, $offset + $headpadding + $len + $tailpadding);
+}
+
+print "#include \"data.h\"\n\n";
+
+print "// This is a generated file - DO NOT EDIT\n";
+print "const ushort stringCollectionData[] __attribute__((aligned(64))) = {\n";
+$count = 0;
+$offset = 0;
+$totalsize = 0;
+$maxlen = 0;
+$cachelinecrosses = 0;
+
+open IN, "<" . $ARGV[0];
+while (1) {
+ $line = readline(*IN);
+ last unless defined($line);
+ $line =~ /LEN = (\d+) (\w+) (\d+) (\d+)/;
+ $len = $1;
+ $data[$count]->{len} = $len;
+ $sameptr = $2;
+ $data[$count]->{align1} = $3 - 0;
+ $data[$count]->{align2} = $4 - 0;
+
+ # statistics
+ $alignhistogram{$3 & 0xf}++;
+ $alignhistogram{$4 & 0xf}++;
+ $samealignments{$3 & 0xf}++ if ($3 & 0xf) == ($4 & 0xf);
+
+ read IN, $a, $len * 2;
+ read IN, $b, $len * 2;
+
+ <IN>; # Eat the newline
+
+ if ($len == 0) {
+ $data[$count]->{offset1} = $offset;
+ $data[$count]->{offset2} = $data[$count]->{offset1};
+ ++$data[$count]->{offset2} if ($sameptr eq "DIFF");
+ } else {
+ print " // #$count\n";
+ print " ";
+ ($data[$count]->{offset1}, $offset) =
+ printUshortArray($a, $data[$count]->{align1}, $offset);
+ print "\n ";
+ die if ($offset & 0x7) != 0;
+
+ if ($sameptr eq "DIFF") {
+ ($data[$count]->{offset2}, $offset) =
+ printUshortArray($b, $data[$count]->{align2}, $offset);
+ print "\n\n";
+ } else {
+ $data[$count]->{offset2} = $data[$count]->{offset1};
+ print "\n\n";
+ }
+ }
+ ++$count;
+
+ $totalsize += $len;
+ $maxlen = $len if $len > $maxlen;
+}
+print "\n};\n";
+close IN;
+
+print "struct StringCollection stringCollection[] = {\n";
+
+for $i (0..$count-1) {
+ print " {",
+ $data[$i]->{len}, ", ",
+ $data[$i]->{offset1}, ", ",
+ $data[$i]->{offset2}, ", ",
+ $data[$i]->{align1}, ", ",
+ $data[$i]->{align2},
+ "}, // #$i\n";
+ next if $data[$i]->{len} == 0;
+ die if (($data[$i]->{offset1} & 0x7) != ($data[$i]->{align1} & 0xf)/2);
+ die if (($data[$i]->{offset2} & 0x7) != ($data[$i]->{align2} & 0xf)/2);
+}
+print "};\n";
+
+print "const int stringCollectionCount = $count;\n";
+print "const int stringCollectionMaxLen = $maxlen;\n";
+printf "// average comparison length: %.4f\n", ($totalsize * 1.0 / $count);
+printf "// cache-line crosses: %d (%.1f%%)\n",
+ $cachelinecrosses, ($cachelinecrosses * 100.0 / $count / 2);
+
+print "// alignment histogram:\n";
+for $key (sort { $a <=> $b } keys(%alignhistogram)) {
+ $value = $alignhistogram{$key};
+ $samealigned = $samealignments{$key};
+ printf "// 0xXXX%x = %d (%.1f%%) strings, %d (%.1f%%) of which same-aligned\n",
+ $key, $value, $value * 100.0 / ($count*2),
+ $samealigned, $samealigned * 100.0 / $value;
+ $samealignedtotal += $samealigned;
+}
+printf "// total = %d (100%) strings, %d (%.1f%%) of which same-aligned\n",
+ $count * 2, $samealignedtotal, $samealignedtotal * 100 / $count / 2;
diff --git a/tests/benchmarks/corelib/tools/qstring/main.cpp b/tests/benchmarks/corelib/tools/qstring/main.cpp
index 12826eb..9616052 100644
--- a/tests/benchmarks/corelib/tools/qstring/main.cpp
+++ b/tests/benchmarks/corelib/tools/qstring/main.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <QStringList>
#include <QFile>
-#include <qtest.h>
+#include <QtTest/QtTest>
#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
@@ -48,12 +48,27 @@
#define SRCDIR ""
#endif
+#ifdef Q_OS_UNIX
+#include <sys/mman.h>
+#include <unistd.h>
+#endif
+
+#include <private/qsimd_p.h>
+
+#include "data.h"
+
class tst_QString: public QObject
{
Q_OBJECT
+public:
+ tst_QString();
private slots:
void equals() const;
void equals_data() const;
+ void equals2_data() const;
+ void equals2() const;
+ void ucstrncmp_data() const;
+ void ucstrncmp() const;
void fromUtf8() const;
};
@@ -67,6 +82,10 @@ void tst_QString::equals() const
}
}
+tst_QString::tst_QString()
+{
+}
+
void tst_QString::equals_data() const
{
static const struct {
@@ -126,6 +145,1247 @@ void tst_QString::equals_data() const
<< QString::fromRawData(ptr + 1, 58) << QString::fromRawData(ptr + 3, 58);
}
+static bool equals2_memcmp_call(const ushort *p1, const ushort *p2, int len)
+{
+ return memcmp(p1, p2, len * 2) == 0;
+}
+
+static bool equals2_bytewise(const ushort *p1, const ushort *p2, int len)
+{
+ if (p1 == p2 || !len)
+ return true;
+ uchar *b1 = (uchar *)p1;
+ uchar *b2 = (uchar *)p2;
+ len *= 2;
+ while (len--)
+ if (*b1++ != *b2++)
+ return false;
+ return true;
+}
+
+static bool equals2_shortwise(const ushort *p1, const ushort *p2, int len)
+{
+ if (p1 == p2 || !len)
+ return true;
+// for (register int counter; counter < len; ++counter)
+// if (p1[counter] != p2[counter])
+// return false;
+ while (len--) {
+ if (p1[len] != p2[len])
+ return false;
+ }
+ return true;
+}
+
+static bool equals2_intwise(const ushort *p1, const ushort *p2, int length)
+{
+ if (p1 == p2 || !length)
+ return true;
+ register union {
+ const quint16 *w;
+ const quint32 *d;
+ quintptr value;
+ } sa, sb;
+ sa.w = p1;
+ sb.w = p2;
+
+ // check alignment
+ if ((sa.value & 2) == (sb.value & 2)) {
+ // both addresses have the same alignment
+ if (sa.value & 2) {
+ // both addresses are not aligned to 4-bytes boundaries
+ // compare the first character
+ if (*sa.w != *sb.w)
+ return false;
+ --length;
+ ++sa.w;
+ ++sb.w;
+
+ // now both addresses are 4-bytes aligned
+ }
+
+ // both addresses are 4-bytes aligned
+ // do a fast 32-bit comparison
+ register const quint32 *e = sa.d + (length >> 1);
+ for ( ; sa.d != e; ++sa.d, ++sb.d) {
+ if (*sa.d != *sb.d)
+ return false;
+ }
+
+ // do we have a tail?
+ return (length & 1) ? *sa.w == *sb.w : true;
+ } else {
+ // one of the addresses isn't 4-byte aligned but the other is
+ register const quint16 *e = sa.w + length;
+ for ( ; sa.w != e; ++sa.w, ++sb.w) {
+ if (*sa.w != *sb.w)
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline bool equals2_short_tail(const ushort *p1, const ushort *p2, int len)
+{
+ if (len) {
+ if (*p1 != *p2)
+ return false;
+ if (--len) {
+ if (p1[1] != p2[1])
+ return false;
+ if (--len) {
+ if (p1[2] != p2[2])
+ return false;
+ if (--len) {
+ if (p1[3] != p2[3])
+ return false;
+ if (--len) {
+ if (p1[4] != p2[4])
+ return false;
+ if (--len) {
+ if (p1[5] != p2[5])
+ return false;
+ if (--len) {
+ if (p1[6] != p2[6])
+ return false;
+ return p1[7] == p2[7];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+//#pragma GCC optimize("no-unroll-loops")
+#ifdef __SSE2__
+static bool equals2_sse2_aligned(const ushort *p1, const ushort *p2, int len)
+{
+ if (len >= 8) {
+ qptrdiff counter = 0;
+ while (len > 8) {
+ __m128i q1 = _mm_load_si128((__m128i *)(p1 + counter));
+ __m128i q2 = _mm_load_si128((__m128i *)(p2 + counter));
+ __m128i cmp = _mm_cmpeq_epi16(q1, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != ushort(0xffff))
+ return false;
+
+ len -= 8;
+ counter += 8;
+ }
+ p1 += counter;
+ p2 += counter;
+ }
+
+ return equals2_short_tail(p1, p2, len);
+}
+
+static bool __attribute__((optimize("no-unroll-loops"))) equals2_sse2(const ushort *p1, const ushort *p2, int len)
+{
+ if (p1 == p2 || !len)
+ return true;
+
+ if (len >= 8) {
+ qptrdiff counter = 0;
+ while (len >= 8) {
+ __m128i q1 = _mm_loadu_si128((__m128i *)(p1 + counter));
+ __m128i q2 = _mm_loadu_si128((__m128i *)(p2 + counter));
+ __m128i cmp = _mm_cmpeq_epi16(q1, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != 0xffff)
+ return false;
+
+ len -= 8;
+ counter += 8;
+ }
+ p1 += counter;
+ p2 += counter;
+ }
+
+ return equals2_short_tail(p1, p2, len);
+}
+
+//static bool equals2_sse2(const ushort *p1, const ushort *p2, int len)
+//{
+// register int val1 = quintptr(p1) & 0xf;
+// register int val2 = quintptr(p2) & 0xf;
+// if (false && val1 + val2 == 0)
+// return equals2_sse2_aligned(p1, p2, len);
+// else
+// return equals2_sse2_unaligned(p1, p2, len);
+//}
+
+static bool equals2_sse2_aligning(const ushort *p1, const ushort *p2, int len)
+{
+ if (len < 8)
+ return equals2_short_tail(p1, p2, len);
+
+ qptrdiff counter = 0;
+
+ // which one is easier to align, p1 or p2 ?
+ register int val1 = quintptr(p1) & 0xf;
+ register int val2 = quintptr(p2) & 0xf;
+ if (val1 && val2) {
+#if 0
+ // we'll align the one which requires the least number of steps
+ if (val1 > val2) {
+ qSwap(p1, p2);
+ val1 = val2;
+ }
+
+ // val1 contains the number of bytes past the 16-aligned mark
+ // we must read 16-val1 bytes to align
+ val1 = 16 - val1;
+ if (val1 & 0x2) {
+ if (*p1 != *p2)
+ return false;
+ --len;
+ ++counter;
+ }
+ while (val1 & 12) {
+ if (*(uint*)p1 != *(uint*)p2)
+ return false;
+ --len;
+ counter += 2;
+ val1 -= 4;
+ }
+#else
+ // we'll align the one closest to the 16-byte mark
+ if (val1 > val2) {
+ qSwap(p1, p2);
+ val1 = val2;
+ }
+
+ // we're reading val1 bytes too many
+ __m128i q2 = _mm_loadu_si128((__m128i *)(p2 - val1/2));
+ __m128i cmp = _mm_cmpeq_epi16(*(__m128i *)(p1 - val1/2), q2);
+ if (short(_mm_movemask_epi8(cmp)) >> val1 != short(-1))
+ return false;
+
+ counter = 8 - val1/2;
+ len -= 8 - val1/2;
+#endif
+ } else if (!val2) {
+ // p2 is already aligned
+ qSwap(p1, p2);
+ }
+
+ // p1 is aligned
+
+ while (len >= 8) {
+ __m128i q1 = _mm_load_si128((__m128i *)(p1 + counter));
+ __m128i q2 = _mm_loadu_si128((__m128i *)(p2 + counter));
+ __m128i cmp = _mm_cmpeq_epi16(q1, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != ushort(0xffff))
+ return false;
+
+ len -= 8;
+ counter += 8;
+ }
+
+ // tail
+ return equals2_short_tail(p1 + counter, p2 + counter, len);
+}
+
+#ifdef __SSE3__
+static bool __attribute__((optimize("no-unroll-loops"))) equals2_sse3(const ushort *p1, const ushort *p2, int len)
+{
+ if (p1 == p2 || !len)
+ return true;
+
+ if (len >= 8) {
+ qptrdiff counter = 0;
+ while (len >= 8) {
+ __m128i q1 = _mm_lddqu_si128((__m128i *)(p1 + counter));
+ __m128i q2 = _mm_lddqu_si128((__m128i *)(p2 + counter));
+ __m128i cmp = _mm_cmpeq_epi16(q1, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != 0xffff)
+ return false;
+
+ len -= 8;
+ counter += 8;
+ }
+ p1 += counter;
+ p2 += counter;
+ }
+
+ return equals2_short_tail(p1, p2, len);
+}
+
+#ifdef __SSSE3__
+template<int N> static __attribute__((optimize("unroll-loops"))) inline bool equals2_ssse3_alignr(__m128i *m1, __m128i *m2, int len)
+{
+ __m128i lower = _mm_load_si128(m1);
+ while (len >= 8) {
+ __m128i upper = _mm_load_si128(m1 + 1);
+ __m128i correct;
+ correct = _mm_alignr_epi8(upper, lower, N);
+
+ __m128i q2 = _mm_lddqu_si128(m2);
+ __m128i cmp = _mm_cmpeq_epi16(correct, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != 0xffff)
+ return false;
+
+ len -= 8;
+ ++m2;
+ ++m1;
+ lower = upper;
+ }
+
+ // tail
+ return len == 0 || equals2_short_tail((const ushort *)m1 + N / 2, (const ushort*)m2, len);
+}
+
+static inline __attribute__((optimize("unroll-loops"))) bool equals2_ssse3_aligned(__m128i *m1, __m128i *m2, int len)
+{
+ while (len >= 8) {
+ __m128i q2 = _mm_lddqu_si128(m2);
+ __m128i cmp = _mm_cmpeq_epi16(*m1, q2);
+ if (ushort(_mm_movemask_epi8(cmp)) != 0xffff)
+ return false;
+
+ len -= 8;
+ ++m1;
+ ++m2;
+ }
+ return len == 0 || equals2_short_tail((const ushort *)m1, (const ushort *)m2, len);
+}
+
+static bool equals2_ssse3(const ushort *p1, const ushort *p2, int len)
+{
+ // p1 & 0xf can be:
+ // 0, 2, 4, 6, 8, 10, 12, 14
+ // If it's 0, we're aligned
+ // If it's not, then we're interested in the 16 - (p1 & 0xf) bytes only
+
+ if (len >= 8) {
+ // find the last aligned position below the p1 memory
+ __m128i *m1 = (__m128i *)(quintptr(p1) & ~0xf);
+ __m128i *m2 = (__m128i *)p2;
+ qptrdiff diff = quintptr(p1) - quintptr(m1);
+
+ // diff contains the number of extra bytes
+ if (diff == 10)
+ return equals2_ssse3_alignr<10>(m1, m2, len);
+ else if (diff == 2)
+ return equals2_ssse3_alignr<2>(m1, m2, len);
+ if (diff < 8) {
+ if (diff < 4) {
+ return equals2_ssse3_aligned(m1, m2, len);
+ } else {
+ if (diff == 4)
+ return equals2_ssse3_alignr<4>(m1, m2, len);
+ else // diff == 6
+ return equals2_ssse3_alignr<6>(m1, m2, len);
+ }
+ } else {
+ if (diff < 12) {
+ return equals2_ssse3_alignr<8>(m1, m2, len);
+ } else {
+ if (diff == 12)
+ return equals2_ssse3_alignr<12>(m1, m2, len);
+ else // diff == 14
+ return equals2_ssse3_alignr<14>(m1, m2, len);
+ }
+ }
+ }
+
+ // tail
+ return equals2_short_tail(p1, p2, len);
+}
+
+template<int N> static inline bool equals2_ssse3_aligning_alignr(__m128i *m1, __m128i *m2, int len)
+{
+ __m128i lower = _mm_load_si128(m1);
+ while (len >= 8) {
+ __m128i upper = _mm_load_si128(m1 + 1);
+ __m128i correct;
+ correct = _mm_alignr_epi8(upper, lower, N);
+
+ __m128i cmp = _mm_cmpeq_epi16(correct, *m2);
+ if (ushort(_mm_movemask_epi8(cmp)) != 0xffff)
+ return false;
+
+ len -= 8;
+ ++m2;
+ ++m1;
+ lower = upper;
+ }
+
+ // tail
+ return len == 0 || equals2_short_tail((const ushort *)m1 + N / 2, (const ushort*)m2, len);
+}
+
+static bool equals2_ssse3_aligning(const ushort *p1, const ushort *p2, int len)
+{
+ if (len < 8)
+ return equals2_short_tail(p1, p2, len);
+ qptrdiff counter = 0;
+
+ // which one is easier to align, p1 or p2 ?
+ {
+ register int val1 = quintptr(p1) & 0xf;
+ register int val2 = quintptr(p2) & 0xf;
+ if (val1 && val2) {
+ // we'll align the one closest to the 16-byte mark
+ if (val1 < val2) {
+ qSwap(p1, p2);
+ val2 = val1;
+ }
+
+ // we're reading val1 bytes too many
+ __m128i q1 = _mm_lddqu_si128((__m128i *)(p1 - val2/2));
+ __m128i cmp = _mm_cmpeq_epi16(q1, *(__m128i *)(p2 - val2/2));
+ if (short(_mm_movemask_epi8(cmp)) >> val1 != short(-1))
+ return false;
+
+ counter = 8 - val2/2;
+ len -= 8 - val2/2;
+ } else if (!val1) {
+ // p1 is already aligned
+ qSwap(p1, p2);
+ }
+ }
+
+ // p2 is aligned now
+ // we want to use palignr in the mis-alignment of p1
+ __m128i *m1 = (__m128i *)(quintptr(p1 + counter) & ~0xf);
+ __m128i *m2 = (__m128i *)(p2 + counter);
+ register int val1 = quintptr(p1 + counter) - quintptr(m1);
+
+ // val1 contains the number of extra bytes
+ if (val1 == 8)
+ return equals2_ssse3_aligning_alignr<8>(m1, m2, len);
+ if (val1 == 0)
+ return equals2_sse2_aligned(p1 + counter, p2 + counter, len);
+ if (val1 < 8) {
+ if (val1 < 4) {
+ return equals2_ssse3_aligning_alignr<2>(m1, m2, len);
+ } else {
+ if (val1 == 4)
+ return equals2_ssse3_aligning_alignr<4>(m1, m2, len);
+ else // diff == 6
+ return equals2_ssse3_aligning_alignr<6>(m1, m2, len);
+ }
+ } else {
+ if (val1 < 12) {
+ return equals2_ssse3_aligning_alignr<10>(m1, m2, len);
+ } else {
+ if (val1 == 12)
+ return equals2_ssse3_aligning_alignr<12>(m1, m2, len);
+ else // diff == 14
+ return equals2_ssse3_aligning_alignr<14>(m1, m2, len);
+ }
+ }
+}
+
+#ifdef __SSE4_1__
+static bool equals2_sse4(const ushort *p1, const ushort *p2, int len)
+{
+ // We use the pcmpestrm instruction searching for differences (negative polarity)
+ // it will reset CF if it's all equal
+ // it will reset OF if the first char is equal
+ // it will set ZF & SF if the length is less than 8 (which means we've done the last operation)
+ // the three possible conditions are:
+ // difference found: CF = 1
+ // all equal, not finished: CF = ZF = SF = 0
+ // all equal, finished: CF = 0, ZF = SF = 1
+ // We use the JA instruction that jumps if ZF = 0 and CF = 0
+ if (p1 == p2 || !len)
+ return true;
+
+ // This function may read some bytes past the end of p1 or p2
+ // It is safe to do that, as long as those extra bytes (beyond p1+len and p2+len)
+ // are on the same page as the last valid byte.
+ // If len is a multiple of 8, we'll never load invalid bytes.
+ if (len & 7) {
+ // The last load would load (len & ~7) valid bytes and (8 - (len & ~7)) invalid bytes.
+ // So we can't do the last load if any of those bytes is in a different
+ // page. That is, if:
+ // pX + len is on a different page from pX + (len & ~7) + 8
+ //
+ // that is, if second-to-last load ended up less than 16 bytes from the page end:
+ // pX + (len & ~7) is the last ushort read in the second-to-last load
+ if (len < 8)
+ return equals2_short_tail(p1, p2, len);
+ if ((quintptr(p1 + (len & ~7)) & 0xfff) > 0xff0 ||
+ (quintptr(p2 + (len & ~7)) & 0xfff) > 0xff0) {
+
+ // yes, so we mustn't do the final 128-bit load
+ bool result;
+ asm (
+ "sub %[p1], %[p2]\n\t"
+ "sub $16, %[p1]\n\t"
+ "add $8, %[len]\n\t"
+
+ // main loop:
+ "0:\n\t"
+ "add $16, %[p1]\n\t"
+ "sub $8, %[len]\n\t"
+ "jz 1f\n\t"
+ "lddqu (%[p1]), %%xmm0\n\t"
+ "mov %[len], %%edx\n\t"
+ "pcmpestri %[mode], (%[p2],%[p1]), %%xmm0\n\t"
+
+ "jna 1f\n\t"
+ "add $16, %[p1]\n\t"
+ "sub $8, %[len]\n\t"
+ "jz 1f\n\t"
+ "lddqu (%[p1]), %%xmm0\n\t"
+ "mov %[len], %%edx\n\t"
+ "pcmpestri %[mode], (%[p2],%[p1]), %%xmm0\n\t"
+
+ "ja 0b\n\t"
+ "1:\n\t"
+ "setnc %[result]\n\t"
+ : [result] "=a" (result),
+ [p1] "+r" (p1),
+ [p2] "+r" (p2)
+ : [len] "0" (len & ~7),
+ [mode] "i" (_SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY)
+ : "%edx", "%ecx", "%xmm0"
+ );
+ return result && equals2_short_tail(p1, (const ushort *)(quintptr(p1) + quintptr(p2)), len & 7);
+ }
+ }
+
+// const qptrdiff disp = p2 - p1;
+// p1 -= 8;
+// len += 8;
+// while (true) {
+// enum { Mode = _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY };
+
+// p1 += 8;
+// len -= 8;
+// if (!len)
+// return true;
+
+// __m128i q1 = _mm_lddqu_si128((__m128i *)(p1 + disp));
+// __m128i *m2 = (__m128i *)p1;
+
+// bool cmp_a = _mm_cmpestra(q1, len, *m2, len, Mode);
+// if (cmp_a)
+// continue;
+// return !_mm_cmpestrc(q1, len, *m2, len, Mode);
+// }
+// return true;
+ bool result;
+ asm (
+ "sub %[p1], %[p2]\n\t"
+ "sub $16, %[p1]\n\t"
+ "add $8, %[len]\n\t"
+
+ "0:\n\t"
+ "add $16, %[p1]\n\t"
+ "sub $8, %[len]\n\t"
+ "jz 1f\n\t"
+ "lddqu (%[p2],%[p1]), %%xmm0\n\t"
+ "mov %[len], %%edx\n\t"
+ "pcmpestri %[mode], (%[p1]), %%xmm0\n\t"
+
+ "jna 1f\n\t"
+ "add $16, %[p1]\n\t"
+ "sub $8, %[len]\n\t"
+ "jz 1f\n\t"
+ "lddqu (%[p2],%[p1]), %%xmm0\n\t"
+ "mov %[len], %%edx\n\t"
+ "pcmpestri %[mode], (%[p1]), %%xmm0\n\t"
+
+ "ja 0b\n\t"
+
+ "1:\n\t"
+ "setnc %[result]\n\t"
+ : [result] "=a" (result)
+ : [len] "0" (len),
+ [p1] "r" (p1),
+ [p2] "r" (p2),
+ [mode] "i" (_SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY)
+ : "%edx", "%ecx", "%xmm0"
+ );
+ return result;
+}
+
+#endif
+#endif
+#endif
+#endif
+
+typedef bool (* FuncPtr)(const ushort *, const ushort *, int);
+static const FuncPtr func[] = {
+ equals2_memcmp_call, // 0
+ equals2_bytewise, // 1
+ equals2_shortwise, // 1
+ equals2_intwise, // 3
+#ifdef __SSE2__
+ equals2_sse2, // 4
+ equals2_sse2_aligning, // 5
+#ifdef __SSE3__
+ equals2_sse3, // 6
+#ifdef __SSSE3__
+ equals2_ssse3, // 7
+ equals2_ssse3, // 8
+#ifdef __SSE4_1__
+ equals2_sse4, // 9
+#endif
+#endif
+#endif
+#endif
+ 0
+};
+static const int functionCount = sizeof(func)/sizeof(func[0]) - 1;
+
+void tst_QString::equals2_data() const
+{
+ QTest::addColumn<int>("algorithm");
+ QTest::newRow("selftest") << -1;
+ QTest::newRow("memcmp_call") << 0;
+ QTest::newRow("bytewise") << 1;
+ QTest::newRow("shortwise") << 2;
+ QTest::newRow("intwise") << 3;
+#ifdef __SSE2__
+ QTest::newRow("sse2") << 4;
+ QTest::newRow("sse2_aligning") << 5;
+#ifdef __SSE3__
+ QTest::newRow("sse3") << 6;
+#ifdef __SSSE3__
+ QTest::newRow("ssse3") << 7;
+ QTest::newRow("ssse3_aligning") << 8;
+#ifdef __SSE4_1__
+ QTest::newRow("sse4.2") << 9;
+#endif
+#endif
+#endif
+#endif
+}
+
+static void __attribute__((noinline)) equals2_selftest()
+{
+#ifdef Q_OS_UNIX
+ const long pagesize = sysconf(_SC_PAGESIZE);
+ void *page1, *page3;
+ ushort *page2;
+ page1 = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ page2 = (ushort *)mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
+ page3 = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ Q_ASSERT(quintptr(page2) == quintptr(page1) + pagesize || quintptr(page2) == quintptr(page1) - pagesize);
+ Q_ASSERT(quintptr(page3) == quintptr(page2) + pagesize || quintptr(page3) == quintptr(page2) - pagesize);
+ munmap(page1, pagesize);
+ munmap(page3, pagesize);
+
+ // populate our page
+ for (uint i = 0; i < pagesize / sizeof(long long); ++i)
+ ((long long *)page2)[i] = Q_INT64_C(0x0041004100410041);
+
+ // the following should crash:
+ //page2[-1] = 0xdead;
+ //page2[pagesize / sizeof(ushort) + 1] = 0xbeef;
+
+ static const ushort needle[] = {
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x41
+ };
+
+ for (int algo = 0; algo < functionCount; ++algo) {
+ // boundary condition test:
+ for (int i = 0; i < 8; ++i) {
+ (func[algo])(page2 + i, needle, sizeof needle / 2);
+ (func[algo])(page2 - i - 1 - sizeof(needle)/2 + pagesize/2, needle, sizeof needle/2);
+ }
+ }
+
+ munmap(page2, pagesize);
+#endif
+
+ for (int algo = 0; algo < functionCount; ++algo) {
+ for (int i = 0; i < stringCollectionCount; ++i) {
+ const ushort *p1 = stringCollectionData + stringCollection[i].offset1;
+ const ushort *p2 = stringCollectionData + stringCollection[i].offset2;
+ bool expected = memcmp(p1, p2, stringCollection[i].len * 2) == 0;
+
+ bool result = (func[algo])(p1, p2, stringCollection[i].len);
+ if (expected != result)
+ qWarning().nospace()
+ << "algo=" << algo
+ << " i=" << i
+ << " failed (" << result << "!=" << expected
+ << "); strings were "
+ << QByteArray((char*)p1, stringCollection[i].len).toHex()
+ << " and "
+ << QByteArray((char*)p2, stringCollection[i].len).toHex();
+ }
+ }
+}
+
+void tst_QString::equals2() const
+{
+ QFETCH(int, algorithm);
+ if (algorithm == -1) {
+ equals2_selftest();
+ return;
+ }
+
+ QBENCHMARK {
+ for (int i = 0; i < stringCollectionCount; ++i) {
+ const ushort *p1 = stringCollectionData + stringCollection[i].offset1;
+ const ushort *p2 = stringCollectionData + stringCollection[i].offset2;
+ bool result = (func[algorithm])(p1, p2, stringCollection[i].len);
+ Q_UNUSED(result);
+ }
+ }
+}
+
+static int ucstrncmp_shortwise(const ushort *a, const ushort *b, int l)
+{
+ while (l-- && *a == *b)
+ a++,b++;
+ if (l==-1)
+ return 0;
+ return *a - *b;
+}
+
+static int ucstrncmp_intwise(const ushort *a, const ushort *b, int len)
+{
+ // do both strings have the same alignment?
+ if ((quintptr(a) & 2) == (quintptr(b) & 2)) {
+ // are we aligned to 4 bytes?
+ if (quintptr(a) & 2) {
+ if (*a != *b)
+ return *a - *b;
+ ++a;
+ ++b;
+ --len;
+ }
+
+ const uint *p1 = (const uint *)a;
+ const uint *p2 = (const uint *)b;
+ quintptr counter = 0;
+ for ( ; len > 1 ; len -= 2, ++counter) {
+ if (p1[counter] != p2[counter]) {
+ // which ushort isn't equal?
+ int diff = a[2*counter] - b[2*counter];
+ return diff ? diff : a[2*counter + 1] - b[2*counter + 1];
+ }
+ }
+
+ return len ? a[2*counter] - b[2*counter] : 0;
+ } else {
+ while (len-- && *a == *b)
+ a++,b++;
+ if (len==-1)
+ return 0;
+ return *a - *b;
+ }
+}
+
+#ifdef __SSE2__
+static inline int ucstrncmp_short_tail(const ushort *p1, const ushort *p2, int len)
+{
+ if (len) {
+ if (*p1 != *p2)
+ return *p1 - *p2;
+ if (--len) {
+ if (p1[1] != p2[1])
+ return p1[1] - p2[1];
+ if (--len) {
+ if (p1[2] != p2[2])
+ return p1[2] - p2[2];
+ if (--len) {
+ if (p1[3] != p2[3])
+ return p1[3] - p2[3];
+ if (--len) {
+ if (p1[4] != p2[4])
+ return p1[4] - p2[4];
+ if (--len) {
+ if (p1[5] != p2[5])
+ return p1[5] - p2[5];
+ if (--len) {
+ if (p1[6] != p2[6])
+ return p1[6] - p2[6];
+ return p1[7] - p2[7];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static inline int bsf_nonzero(register long val)
+{
+ int result;
+# ifdef Q_CC_GNU
+ // returns the first non-zero bit on a non-zero reg
+ asm ("bsf %1, %0" : "=r" (result) : "r" (val));
+ return result;
+# elif defined(Q_CC_MSVC)
+ _BitScanForward(&result, val);
+ return result;
+# endif
+}
+
+static __attribute__((optimize("no-unroll-loops"))) int ucstrncmp_sse2(const ushort *a, const ushort *b, int len)
+{
+ qptrdiff counter = 0;
+ while (len >= 8) {
+ __m128i m1 = _mm_loadu_si128((__m128i *)(a + counter));
+ __m128i m2 = _mm_loadu_si128((__m128i *)(b + counter));
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ }
+ return ucstrncmp_short_tail(a + counter, b + counter, len);
+}
+
+static __attribute__((optimize("no-unroll-loops"))) int ucstrncmp_sse2_aligning(const ushort *a, const ushort *b, int len)
+{
+ if (len >= 8) {
+ __m128i m1 = _mm_loadu_si128((__m128i *)a);
+ __m128i m2 = _mm_loadu_si128((__m128i *)b);
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ int counter = bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+
+ // now align to do 16-byte loads
+ int diff = 8 - (quintptr(a) & 0xf)/2;
+ len -= diff;
+ a += diff;
+ b += diff;
+ }
+
+ qptrdiff counter = 0;
+ while (len >= 8) {
+ __m128i m1 = _mm_load_si128((__m128i *)(a + counter));
+ __m128i m2 = _mm_loadu_si128((__m128i *)(b + counter));
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ }
+ return ucstrncmp_short_tail(a + counter, b + counter, len);
+}
+
+static inline __attribute__((optimize("no-unroll-loops"))) int ucstrncmp_sse2_aligned(const ushort *a, const ushort *b, int len)
+{
+ quintptr counter = 0;
+ while (len >= 8) {
+ __m128i m1 = _mm_load_si128((__m128i *)(a + counter));
+ __m128i m2 = _mm_load_si128((__m128i *)(b + counter));
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ }
+ return ucstrncmp_short_tail(a + counter, b + counter, len);
+}
+
+static inline __attribute__((optimize("no-unroll-loops"))) int ucstrncmp_ssse3_alignr_aligned(const ushort *a, const ushort *b, int len)
+{
+ quintptr counter = 0;
+ while (len >= 8) {
+ __m128i m1 = _mm_load_si128((__m128i *)(a + counter));
+ __m128i m2 = _mm_lddqu_si128((__m128i *)(b + counter));
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ }
+ return ucstrncmp_short_tail(a + counter, b + counter, len);
+}
+
+
+typedef __m128i (* MMLoadFunction)(const __m128i *);
+template<int N, MMLoadFunction LoadFunction>
+static inline __attribute__((optimize("no-unroll-loops"))) int ucstrncmp_ssse3_alignr(const ushort *a, const ushort *b, int len)
+{
+ qptrdiff counter = 0;
+ __m128i lower, upper;
+ upper = _mm_load_si128((__m128i *)a);
+
+ do {
+ lower = upper;
+ upper = _mm_load_si128((__m128i *)(a + counter) + 1);
+ __m128i merged = _mm_alignr_epi8(upper, lower, N);
+
+ __m128i m2 = LoadFunction((__m128i *)(b + counter));
+ __m128i cmp = _mm_cmpeq_epi16(merged, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter + N/2] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ } while (len >= 8);
+
+ return ucstrncmp_short_tail(a + counter + N/2, b + counter, len);
+}
+
+static int ucstrncmp_ssse3(const ushort *a, const ushort *b, int len)
+{
+ if (len >= 8) {
+ int val = quintptr(a) & 0xf;
+ a -= val/2;
+
+ if (val == 10)
+ return ucstrncmp_ssse3_alignr<10, _mm_lddqu_si128>(a, b, len);
+ else if (val == 2)
+ return ucstrncmp_ssse3_alignr<2, _mm_lddqu_si128>(a, b, len);
+ if (val < 8) {
+ if (val < 4)
+ return ucstrncmp_ssse3_alignr_aligned(a, b, len);
+ else if (val == 4)
+ return ucstrncmp_ssse3_alignr<4, _mm_lddqu_si128>(a, b, len);
+ else
+ return ucstrncmp_ssse3_alignr<6, _mm_lddqu_si128>(a, b, len);
+ } else {
+ if (val < 12)
+ return ucstrncmp_ssse3_alignr<8, _mm_lddqu_si128>(a, b, len);
+ else if (val == 12)
+ return ucstrncmp_ssse3_alignr<12, _mm_lddqu_si128>(a, b, len);
+ else
+ return ucstrncmp_ssse3_alignr<14, _mm_lddqu_si128>(a, b, len);
+ }
+ }
+ return ucstrncmp_short_tail(a, b, len);
+}
+
+static int ucstrncmp_ssse3_aligning(const ushort *a, const ushort *b, int len)
+{
+ if (len >= 8) {
+ __m128i m1 = _mm_loadu_si128((__m128i *)a);
+ __m128i m2 = _mm_loadu_si128((__m128i *)b);
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ int counter = bsf_nonzero(mask)/2;
+ return a[counter] - b[counter];
+ }
+
+
+ // now 'b' align to do 16-byte loads
+ int diff = 8 - (quintptr(b) & 0xf)/2;
+ len -= diff;
+ a += diff;
+ b += diff;
+ }
+
+ if (len < 8)
+ return ucstrncmp_short_tail(a, b, len);
+
+ // 'b' is aligned
+ int val = quintptr(a) & 0xf;
+ a -= val/2;
+
+ if (val == 8)
+ return ucstrncmp_ssse3_alignr<8, _mm_load_si128>(a, b, len);
+ else if (val == 0)
+ return ucstrncmp_sse2_aligned(a, b, len);
+ if (val < 8) {
+ if (val < 4)
+ return ucstrncmp_ssse3_alignr<2, _mm_load_si128>(a, b, len);
+ else if (val == 4)
+ return ucstrncmp_ssse3_alignr<4, _mm_load_si128>(a, b, len);
+ else
+ return ucstrncmp_ssse3_alignr<6, _mm_load_si128>(a, b, len);
+ } else {
+ if (val < 12)
+ return ucstrncmp_ssse3_alignr<10, _mm_load_si128>(a, b, len);
+ else if (val == 12)
+ return ucstrncmp_ssse3_alignr<12, _mm_load_si128>(a, b, len);
+ else
+ return ucstrncmp_ssse3_alignr<14, _mm_load_si128>(a, b, len);
+ }
+}
+
+static inline __attribute__((optimize("no-unroll-loops")))
+int ucstrncmp_ssse3_aligning2_aligned(const ushort *a, const ushort *b, int len, int garbage)
+{
+ // len >= 8
+ __m128i m1 = _mm_load_si128((const __m128i *)a);
+ __m128i m2 = _mm_load_si128((const __m128i *)b);
+ __m128i cmp = _mm_cmpeq_epi16(m1, m2);
+ int mask = short(_mm_movemask_epi8(cmp)); // force sign extension
+ mask >>= garbage;
+ if (~mask) {
+ // which ushort isn't equal?
+ uint counter = (garbage + bsf_nonzero(~mask));
+ return a[counter/2] - b[counter/2];
+ }
+
+ // the first 16-garbage bytes (8-garbage/2 ushorts) were equal
+ len -= 8 - garbage/2;
+ return ucstrncmp_sse2_aligned(a + 8, b + 8, len);
+}
+
+template<int N> static inline __attribute__((optimize("no-unroll-loops"),always_inline))
+int ucstrncmp_ssse3_aligning2_alignr(const ushort *a, const ushort *b, int len, int garbage)
+{
+ // len >= 8
+ __m128i lower, upper, merged;
+ lower = _mm_load_si128((const __m128i*)a);
+ upper = _mm_load_si128((const __m128i*)(a + 8));
+ merged = _mm_alignr_epi8(upper, lower, N);
+
+ __m128i m2 = _mm_load_si128((const __m128i*)b);
+ __m128i cmp = _mm_cmpeq_epi16(merged, m2);
+ int mask = short(_mm_movemask_epi8(cmp)); // force sign extension
+ mask >>= garbage;
+ if (~mask) {
+ // which ushort isn't equal?
+ uint counter = (garbage + bsf_nonzero(~mask));
+ return a[counter/2 + N/2] - b[counter/2];
+ }
+
+ // the first 16-garbage bytes (8-garbage/2 ushorts) were equal
+ quintptr counter = 8;
+ len -= 8 - garbage/2;
+ while (len >= 8) {
+ lower = upper;
+ upper = _mm_load_si128((__m128i *)(a + counter) + 1);
+ merged = _mm_alignr_epi8(upper, lower, N);
+
+ m2 = _mm_load_si128((__m128i *)(b + counter));
+ cmp = _mm_cmpeq_epi16(merged, m2);
+ ushort mask = ~uint(_mm_movemask_epi8(cmp));
+ if (mask) {
+ // which ushort isn't equal?
+ counter += bsf_nonzero(mask)/2;
+ return a[counter + N/2] - b[counter];
+ }
+
+ counter += 8;
+ len -= 8;
+ }
+
+ return ucstrncmp_short_tail(a + counter + N/2, b + counter, len);
+}
+
+static inline int conditional_invert(int result, bool invert)
+{
+ if (invert)
+ return -result;
+ return result;
+}
+
+static int ucstrncmp_ssse3_aligning2(const ushort *a, const ushort *b, int len)
+{
+ // Different strategy from above: instead of doing two unaligned loads
+ // when trying to align, we'll only do aligned loads and round down the
+ // addresses of a and b. This means the first load will contain garbage
+ // in the beginning of the string, which we'll shift out of the way
+ // (after _mm_movemask_epi8)
+
+ if (len < 8)
+ return ucstrncmp_intwise(a, b, len);
+
+ // both a and b are misaligned
+ // we'll call the alignr function with the alignment *difference* between the two
+ int offset = (quintptr(a) & 0xf) - (quintptr(b) & 0xf);
+ if (offset >= 0) {
+ // from this point on, b has the shortest alignment
+ // and align(a) = align(b) + offset
+ // round down the alignment so align(b) == align(a) == 0
+ int garbage = (quintptr(b) & 0xf);
+ a = (const ushort*)(quintptr(a) & ~0xf);
+ b = (const ushort*)(quintptr(b) & ~0xf);
+
+ // now the first load of b will load 'garbage' extra bytes
+ // and the first load of a will load 'garbage + offset' extra bytes
+ if (offset == 8)
+ return ucstrncmp_ssse3_aligning2_alignr<8>(a, b, len, garbage);
+ if (offset == 0)
+ return ucstrncmp_ssse3_aligning2_aligned(a, b, len, garbage);
+ if (offset < 8) {
+ if (offset < 4)
+ return ucstrncmp_ssse3_aligning2_alignr<2>(a, b, len, garbage);
+ else if (offset == 4)
+ return ucstrncmp_ssse3_aligning2_alignr<4>(a, b, len, garbage);
+ else
+ return ucstrncmp_ssse3_aligning2_alignr<6>(a, b, len, garbage);
+ } else {
+ if (offset < 12)
+ return ucstrncmp_ssse3_aligning2_alignr<10>(a, b, len, garbage);
+ else if (offset == 12)
+ return ucstrncmp_ssse3_aligning2_alignr<12>(a, b, len, garbage);
+ else
+ return ucstrncmp_ssse3_aligning2_alignr<14>(a, b, len, garbage);
+ }
+ } else {
+ // same as above but inverted
+ int garbage = (quintptr(a) & 0xf);
+ a = (const ushort*)(quintptr(a) & ~0xf);
+ b = (const ushort*)(quintptr(b) & ~0xf);
+
+ offset = -offset;
+ if (offset == 8)
+ return -ucstrncmp_ssse3_aligning2_alignr<8>(b, a, len, garbage);
+ if (offset < 8) {
+ if (offset < 4)
+ return -ucstrncmp_ssse3_aligning2_alignr<2>(b, a, len, garbage);
+ else if (offset == 4)
+ return -ucstrncmp_ssse3_aligning2_alignr<4>(b, a, len, garbage);
+ else
+ return -ucstrncmp_ssse3_aligning2_alignr<6>(b, a, len, garbage);
+ } else {
+ if (offset < 12)
+ return -ucstrncmp_ssse3_aligning2_alignr<10>(b, a, len, garbage);
+ else if (offset == 12)
+ return -ucstrncmp_ssse3_aligning2_alignr<12>(b, a, len, garbage);
+ else
+ return -ucstrncmp_ssse3_aligning2_alignr<14>(b, a, len, garbage);
+ }
+ }
+}
+
+#endif
+
+typedef int (* UcstrncmpFunction)(const ushort *, const ushort *, int);
+Q_DECLARE_METATYPE(UcstrncmpFunction)
+
+void tst_QString::ucstrncmp_data() const
+{
+ QTest::addColumn<UcstrncmpFunction>("function");
+ QTest::newRow("selftest") << UcstrncmpFunction(0);
+ QTest::newRow("shortwise") << &ucstrncmp_shortwise;
+ QTest::newRow("intwise") << &ucstrncmp_intwise;
+#ifdef __SSE2__
+ QTest::newRow("sse2") << &ucstrncmp_sse2;
+ QTest::newRow("sse2_aligning") << &ucstrncmp_sse2_aligning;
+#ifdef __SSSE3__
+ QTest::newRow("ssse3") << &ucstrncmp_ssse3;
+ QTest::newRow("ssse3_aligning") << &ucstrncmp_ssse3_aligning;
+ QTest::newRow("ssse3_aligning2") << &ucstrncmp_ssse3_aligning2;
+#endif
+#endif
+}
+
+void tst_QString::ucstrncmp() const
+{
+ QFETCH(UcstrncmpFunction, function);
+ if (!function) {
+ static const UcstrncmpFunction func[] = {
+ &ucstrncmp_shortwise,
+ &ucstrncmp_intwise,
+#ifdef __SSE2__
+ &ucstrncmp_sse2,
+ &ucstrncmp_sse2_aligning,
+#ifdef __SSSE3__
+ &ucstrncmp_ssse3,
+ &ucstrncmp_ssse3_aligning,
+ &ucstrncmp_ssse3_aligning2
+#endif
+#endif
+ };
+ static const int functionCount = sizeof func / sizeof func[0];
+
+#ifdef Q_OS_UNIX
+ const long pagesize = sysconf(_SC_PAGESIZE);
+ void *page1, *page3;
+ ushort *page2;
+ page1 = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ page2 = (ushort *)mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
+ page3 = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ Q_ASSERT(quintptr(page2) == quintptr(page1) + pagesize || quintptr(page2) == quintptr(page1) - pagesize);
+ Q_ASSERT(quintptr(page3) == quintptr(page2) + pagesize || quintptr(page3) == quintptr(page2) - pagesize);
+ munmap(page1, pagesize);
+ munmap(page3, pagesize);
+
+ // populate our page
+ for (uint i = 0; i < pagesize / sizeof(long long); ++i)
+ ((long long *)page2)[i] = Q_INT64_C(0x0041004100410041);
+
+ // the following should crash:
+ //page2[-1] = 0xdead;
+ //page2[pagesize / sizeof(ushort) + 1] = 0xbeef;
+
+ static const ushort needle[] = {
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x41
+ };
+
+ for (int algo = 0; algo < functionCount; ++algo) {
+ // boundary condition test:
+ for (int i = 0; i < 8; ++i) {
+ (func[algo])(page2 + i, needle, sizeof needle / 2);
+ (func[algo])(page2 - i - 1 - sizeof(needle)/2 + pagesize/2, needle, sizeof needle/2);
+ }
+ }
+
+ munmap(page2, pagesize);
+#endif
+
+ for (int algo = 0; algo < functionCount; ++algo) {
+ for (int i = 0; i < stringCollectionCount; ++i) {
+ const ushort *p1 = stringCollectionData + stringCollection[i].offset1;
+ const ushort *p2 = stringCollectionData + stringCollection[i].offset2;
+ int expected = ucstrncmp_shortwise(p1, p2, stringCollection[i].len);
+ expected = qBound(-1, expected, 1);
+
+ int result = (func[algo])(p1, p2, stringCollection[i].len);
+ result = qBound(-1, result, 1);
+ if (expected != result)
+ qWarning().nospace()
+ << "algo=" << algo
+ << " i=" << i
+ << " failed (" << result << "!=" << expected
+ << "); strings were "
+ << QByteArray((char*)p1, stringCollection[i].len).toHex()
+ << " and "
+ << QByteArray((char*)p2, stringCollection[i].len).toHex();
+ }
+ }
+ return;
+ }
+
+ QBENCHMARK {
+ for (int i = 0; i < stringCollectionCount; ++i) {
+ const ushort *p1 = stringCollectionData + stringCollection[i].offset1;
+ const ushort *p2 = stringCollectionData + stringCollection[i].offset2;
+ (function)(p1, p2, stringCollection[i].len);
+ }
+ }
+}
+
void tst_QString::fromUtf8() const
{
QFile file(SRCDIR "utf-8.txt");
diff --git a/tests/benchmarks/corelib/tools/qstring/qstring.pro b/tests/benchmarks/corelib/tools/qstring/qstring.pro
index fa4310e..e8720e1 100644
--- a/tests/benchmarks/corelib/tools/qstring/qstring.pro
+++ b/tests/benchmarks/corelib/tools/qstring/qstring.pro
@@ -1,7 +1,7 @@
load(qttest_p4)
TARGET = tst_bench_qstring
QT -= gui
-SOURCES += main.cpp
+SOURCES += main.cpp data.cpp
wince*:{
DEFINES += SRCDIR=\\\"\\\"
@@ -14,3 +14,6 @@ wince*:{
DEFINES += SRCDIR=\\\"$$PWD/\\\"
}
+sse4:QMAKE_CXXFLAGS += -msse4
+else:ssse3:QMAKE_FLAGS += -mssse3
+else:sse2:QMAKE_CXXFLAGS += -msse2
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 0c716d1..7049306 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -2667,8 +2667,13 @@ void Configure::generateOutputVars()
qtConfig += "audio-backend";
}
- if (dictionary["WEBKIT"] == "yes")
- qtConfig += "webkit";
+ if (dictionary["WEBKIT"] == "yes") {
+ // This include takes care of adding "webkit" to QT_CONFIG.
+ QString src = sourcePath + "/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri";
+ QString dst = buildPath + "/mkspecs/modules/qt_webkit_version.pri";
+ QFile::remove(dst);
+ QFile::copy(src, dst);
+ }
if (dictionary["DECLARATIVE"] == "yes") {
if (dictionary[ "SCRIPT" ] == "no") {
diff --git a/tools/linguist/lupdate/qscript.cpp b/tools/linguist/lupdate/qscript.cpp
index 188ac36..7ca0987 100644
--- a/tools/linguist/lupdate/qscript.cpp
+++ b/tools/linguist/lupdate/qscript.cpp
@@ -770,13 +770,16 @@ const int QScriptGrammar::action_check [] = {
static void recordMessage(
Translator *tor, const QString &context, const QString &text, const QString &comment,
- const QString &extracomment, bool plural, const QString &fileName, int lineNo)
+ const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
+ bool plural, const QString &fileName, int lineNo)
{
TranslatorMessage msg(
context, text, comment, QString(),
fileName, lineNo, QStringList(),
TranslatorMessage::Unfinished, plural);
msg.setExtraComment(extracomment.simplified());
+ msg.setId(msgid);
+ msg.setExtras(extra);
tor->extend(msg);
}
@@ -784,15 +787,23 @@ static void recordMessage(
namespace QScript
{
+class CommentProcessor
+{
+public:
+ virtual ~CommentProcessor() {}
+ virtual void processComment(const QChar *chars, int length) = 0;
+};
+
class Lexer
{
public:
- Lexer();
+ Lexer(CommentProcessor *);
~Lexer();
- void setCode(const QString &c, int lineno);
+ void setCode(const QString &c, const QString &fileName, int lineno);
int lex();
+ QString fileName() const { return yyfilename; }
int currentLineNo() const { return yylineno; }
int currentColumnNo() const { return yycolumn; }
@@ -872,6 +883,7 @@ public:
{ err = NoError; }
private:
+ QString yyfilename;
int yylineno;
bool done;
char *buffer8;
@@ -925,6 +937,8 @@ private:
void syncProhibitAutomaticSemicolon();
+ void processComment(const QChar *, int);
+
const QChar *code;
uint length;
int yycolumn;
@@ -951,6 +965,8 @@ private:
ParenthesesState parenthesesState;
int parenthesesCount;
bool prohibitAutomaticSemicolon;
+
+ CommentProcessor *commentProcessor;
};
} // namespace QScript
@@ -1027,7 +1043,7 @@ double integerFromString(const char *buf, int size, int radix)
} // namespace QScript
-QScript::Lexer::Lexer()
+QScript::Lexer::Lexer(QScript::CommentProcessor *proc)
:
yylineno(0),
size8(128), size16(128), restrKeyword(false),
@@ -1038,7 +1054,8 @@ QScript::Lexer::Lexer()
err(NoError),
check_reserved(true),
parenthesesState(IgnoreParentheses),
- prohibitAutomaticSemicolon(false)
+ prohibitAutomaticSemicolon(false),
+ commentProcessor(proc)
{
// allocate space for read buffers
buffer8 = new char[size8];
@@ -1053,9 +1070,10 @@ QScript::Lexer::~Lexer()
delete [] buffer16;
}
-void QScript::Lexer::setCode(const QString &c, int lineno)
+void QScript::Lexer::setCode(const QString &c, const QString &fileName, int lineno)
{
errmsg = QString();
+ yyfilename = fileName;
yylineno = lineno;
yycolumn = 1;
restrKeyword = false;
@@ -1404,10 +1422,12 @@ int QScript::Lexer::lex()
} else if (current == '/' && next1 == '/') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InSingleLineComment;
} else if (current == '/' && next1 == '*') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InMultiLineComment;
} else if (current == 0) {
syncProhibitAutomaticSemicolon();
@@ -1547,9 +1567,12 @@ int QScript::Lexer::lex()
break;
case InSingleLineComment:
if (isLineTerminator()) {
+ record16(current); // include newline
+ processComment(buffer16, pos16);
shiftWindowsLineBreak();
yylineno++;
yycolumn = 0;
+ pos16 = 0;
terminator = true;
bol = true;
if (restrKeyword) {
@@ -1559,6 +1582,8 @@ int QScript::Lexer::lex()
state = Start;
} else if (current == 0) {
setDone(Eof);
+ } else {
+ record16(current);
}
break;
case InMultiLineComment:
@@ -1570,8 +1595,12 @@ int QScript::Lexer::lex()
shiftWindowsLineBreak();
yylineno++;
} else if (current == '*' && next1 == '/') {
+ processComment(buffer16, pos16);
+ pos16 = 0;
state = Start;
shift(1);
+ } else {
+ record16(current);
}
break;
case InIdentifier:
@@ -2033,10 +2062,15 @@ void QScript::Lexer::syncProhibitAutomaticSemicolon()
}
}
+void QScript::Lexer::processComment(const QChar *chars, int length)
+{
+ commentProcessor->processComment(chars, length);
+}
+
class Translator;
-class QScriptParser: protected QScriptGrammar
+class QScriptParser: protected QScriptGrammar, public QScript::CommentProcessor
{
public:
QVariant val;
@@ -2052,10 +2086,12 @@ public:
QScriptParser();
~QScriptParser();
- bool parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator);
+ void setLexer(QScript::Lexer *);
+
+ bool parse(Translator *translator);
+ QString fileName() const
+ { return lexer->fileName(); }
inline QString errorMessage() const
{ return error_message; }
inline int errorLineNumber() const
@@ -2072,6 +2108,10 @@ protected:
inline Location &loc(int index)
{ return location_stack [tos + index - 2]; }
+ std::ostream &yyMsg(int line = 0);
+
+ virtual void processComment(const QChar *, int);
+
protected:
int tos;
int stack_size;
@@ -2081,6 +2121,13 @@ protected:
QString error_message;
int error_lineno;
int error_column;
+
+private:
+ QScript::Lexer *lexer;
+ QString extracomment;
+ QString msgid;
+ QString sourcetext;
+ TranslatorMessage::ExtraData extra;
};
inline void QScriptParser::reallocateStack()
@@ -2107,7 +2154,8 @@ QScriptParser::QScriptParser():
stack_size(0),
sym_stack(0),
state_stack(0),
- location_stack(0)
+ location_stack(0),
+ lexer(0)
{
}
@@ -2129,10 +2177,14 @@ static inline QScriptParser::Location location(QScript::Lexer *lexer)
return loc;
}
-bool QScriptParser::parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator)
+void QScriptParser::setLexer(QScript::Lexer *lex)
+{
+ lexer = lex;
+}
+
+bool QScriptParser::parse(Translator *translator)
{
+ Q_ASSERT(lexer != 0);
const int INITIAL_STATE = 0;
int yytoken = -1;
@@ -2214,44 +2266,70 @@ case 8: {
case 66: {
QString name = sym(1).toString();
if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << "//% cannot be used with " << qPrintable(name) << "(). Ignoring\n";
QVariantList args = sym(2).toList();
if (args.size() < 2) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "() requires at least two arguments.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least two arguments.\n";
} else {
if ((args.at(0).type() != QVariant::String)
|| (args.at(1).type() != QVariant::String)) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "(): both arguments must be literal strings.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "(): both arguments must be literal strings.\n";
} else {
QString context = args.at(0).toString();
QString text = args.at(1).toString();
QString comment = args.value(2).toString();
- QString extracomment;
bool plural = (args.size() > 4);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
} else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << "//% cannot be used with " << qPrintable(name) << "(). Ignoring\n";
QVariantList args = sym(2).toList();
if (args.size() < 1) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "() requires at least one argument.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least one argument.\n";
} else {
if (args.at(0).type() != QVariant::String) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "(): text to translate must be a literal string.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "(): text to translate must be a literal string.\n";
} else {
- QString context = QFileInfo(fileName).baseName();
+ QString context = QFileInfo(fileName()).baseName();
QString text = args.at(0).toString();
QString comment = args.value(1).toString();
- QString extracomment;
bool plural = (args.size() > 2);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ } else if ((name == QLatin1String("qsTrId")) || (name == QLatin1String("QT_TRID_NOOP"))) {
+ if (!msgid.isEmpty())
+ yyMsg(identLineNo) << "//= cannot be used with " << qPrintable(name) << "(). Ignoring\n";
+ QVariantList args = sym(2).toList();
+ if (args.size() < 1) {
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least one argument.\n";
+ } else {
+ if (args.at(0).type() != QVariant::String) {
+ yyMsg(identLineNo) << qPrintable(name) << "(): identifier must be a literal string.\n";
+ } else {
+ msgid = args.at(0).toString();
+ bool plural = (args.size() > 1);
+ recordMessage(translator, QString(), sourcetext, QString(), extracomment,
+ msgid, extra, plural, fileName(), identLineNo);
+ }
+ }
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
}
} break;
@@ -2278,6 +2356,44 @@ case 94: {
sym(1) = QVariant();
} break;
+ case 171:
+
+ case 172:
+
+ case 173:
+
+ case 174:
+
+ case 175:
+
+ case 176:
+
+ case 177:
+
+ case 178:
+
+ case 179:
+
+ case 180:
+
+ case 181:
+
+ case 182:
+
+ case 183:
+
+ case 184:
+
+ case 185:
+ if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
+ yyMsg() << "Discarding unconsumed meta data\n";
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ }
+ break;
+
} // switch
state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
@@ -2356,6 +2472,63 @@ case 94: {
return false;
}
+std::ostream &QScriptParser::yyMsg(int line)
+{
+ return std::cerr << qPrintable(fileName()) << ':' << (line ? line : lexer->startLineNo()) << ": ";
+}
+
+void QScriptParser::processComment(const QChar *chars, int length)
+{
+ if (!length)
+ return;
+ // Try to match the logic of the C++ parser.
+ if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
+ extracomment += QString(chars+2, length-2);
+ } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
+ msgid = QString(chars+2, length-2).simplified();
+ } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
+ QString text = QString(chars+2, length-2).trimmed();
+ int k = text.indexOf(QLatin1Char(' '));
+ if (k > -1)
+ extra.insert(text.left(k), text.mid(k + 1).trimmed());
+ } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
+ sourcetext.reserve(sourcetext.length() + length-2);
+ ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
+ int p = 2, c;
+ forever {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (isspace(c))
+ continue;
+ if (c != '"') {
+ yyMsg() << "Unexpected character in meta string\n";
+ break;
+ }
+ forever {
+ if (p >= length) {
+ whoops:
+ yyMsg() << "Unterminated meta string\n";
+ break;
+ }
+ c = chars[p++].unicode();
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (p >= length)
+ goto whoops;
+ c = chars[p++].unicode();
+ if (c == '\n')
+ goto whoops;
+ *ptr++ = '\\';
+ }
+ *ptr++ = c;
+ }
+ }
+ sourcetext.resize(ptr - (ushort *)sourcetext.data());
+ }
+}
+
bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd)
{
@@ -2375,10 +2548,11 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData
ts.setAutoDetectUnicode(true);
QString code = ts.readAll();
- QScript::Lexer lexer;
- lexer.setCode(code, /*lineNumber=*/1);
QScriptParser parser;
- if (!parser.parse(&lexer, filename, &translator)) {
+ QScript::Lexer lexer(&parser);
+ lexer.setCode(code, filename, /*lineNumber=*/1);
+ parser.setLexer(&lexer);
+ if (!parser.parse(&translator)) {
std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": "
<< qPrintable(parser.errorMessage()) << std::endl;
return false;
diff --git a/tools/linguist/lupdate/qscript.g b/tools/linguist/lupdate/qscript.g
index 857c58a..e4c2d22 100644
--- a/tools/linguist/lupdate/qscript.g
+++ b/tools/linguist/lupdate/qscript.g
@@ -101,13 +101,16 @@ QT_BEGIN_NAMESPACE
static void recordMessage(
Translator *tor, const QString &context, const QString &text, const QString &comment,
- const QString &extracomment, bool plural, const QString &fileName, int lineNo)
+ const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
+ bool plural, const QString &fileName, int lineNo)
{
TranslatorMessage msg(
context, text, comment, QString(),
fileName, lineNo, QStringList(),
TranslatorMessage::Unfinished, plural);
msg.setExtraComment(extracomment.simplified());
+ msg.setId(msgid);
+ msg.setExtras(extra);
tor->extend(msg);
}
@@ -115,15 +118,23 @@ static void recordMessage(
namespace QScript
{
+class CommentProcessor
+{
+public:
+ virtual ~CommentProcessor() {}
+ virtual void processComment(const QChar *chars, int length) = 0;
+};
+
class Lexer
{
public:
- Lexer();
+ Lexer(CommentProcessor *);
~Lexer();
- void setCode(const QString &c, int lineno);
+ void setCode(const QString &c, const QString &fileName, int lineno);
int lex();
+ QString fileName() const { return yyfilename; }
int currentLineNo() const { return yylineno; }
int currentColumnNo() const { return yycolumn; }
@@ -203,6 +214,7 @@ public:
{ err = NoError; }
private:
+ QString yyfilename;
int yylineno;
bool done;
char *buffer8;
@@ -256,6 +268,8 @@ private:
void syncProhibitAutomaticSemicolon();
+ void processComment(const QChar *, int);
+
const QChar *code;
uint length;
int yycolumn;
@@ -282,6 +296,8 @@ private:
ParenthesesState parenthesesState;
int parenthesesCount;
bool prohibitAutomaticSemicolon;
+
+ CommentProcessor *commentProcessor;
};
} // namespace QScript
@@ -358,7 +374,7 @@ double integerFromString(const char *buf, int size, int radix)
} // namespace QScript
-QScript::Lexer::Lexer()
+QScript::Lexer::Lexer(QScript::CommentProcessor *proc)
:
yylineno(0),
size8(128), size16(128), restrKeyword(false),
@@ -369,7 +385,8 @@ QScript::Lexer::Lexer()
err(NoError),
check_reserved(true),
parenthesesState(IgnoreParentheses),
- prohibitAutomaticSemicolon(false)
+ prohibitAutomaticSemicolon(false),
+ commentProcessor(proc)
{
// allocate space for read buffers
buffer8 = new char[size8];
@@ -384,9 +401,10 @@ QScript::Lexer::~Lexer()
delete [] buffer16;
}
-void QScript::Lexer::setCode(const QString &c, int lineno)
+void QScript::Lexer::setCode(const QString &c, const QString &fileName, int lineno)
{
errmsg = QString();
+ yyfilename = fileName;
yylineno = lineno;
yycolumn = 1;
restrKeyword = false;
@@ -735,10 +753,12 @@ int QScript::Lexer::lex()
} else if (current == '/' && next1 == '/') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InSingleLineComment;
} else if (current == '/' && next1 == '*') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InMultiLineComment;
} else if (current == 0) {
syncProhibitAutomaticSemicolon();
@@ -878,9 +898,12 @@ int QScript::Lexer::lex()
break;
case InSingleLineComment:
if (isLineTerminator()) {
+ record16(current); // include newline
+ processComment(buffer16, pos16);
shiftWindowsLineBreak();
yylineno++;
yycolumn = 0;
+ pos16 = 0;
terminator = true;
bol = true;
if (restrKeyword) {
@@ -890,6 +913,8 @@ int QScript::Lexer::lex()
state = Start;
} else if (current == 0) {
setDone(Eof);
+ } else {
+ record16(current);
}
break;
case InMultiLineComment:
@@ -901,8 +926,12 @@ int QScript::Lexer::lex()
shiftWindowsLineBreak();
yylineno++;
} else if (current == '*' && next1 == '/') {
+ processComment(buffer16, pos16);
+ pos16 = 0;
state = Start;
shift(1);
+ } else {
+ record16(current);
}
break;
case InIdentifier:
@@ -1364,10 +1393,15 @@ void QScript::Lexer::syncProhibitAutomaticSemicolon()
}
}
+void QScript::Lexer::processComment(const QChar *chars, int length)
+{
+ commentProcessor->processComment(chars, length);
+}
+
class Translator;
-class QScriptParser: protected $table
+class QScriptParser: protected $table, public QScript::CommentProcessor
{
public:
QVariant val;
@@ -1383,10 +1417,12 @@ public:
QScriptParser();
~QScriptParser();
- bool parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator);
+ void setLexer(QScript::Lexer *);
+ bool parse(Translator *translator);
+
+ QString fileName() const
+ { return lexer->fileName(); }
inline QString errorMessage() const
{ return error_message; }
inline int errorLineNumber() const
@@ -1403,6 +1439,10 @@ protected:
inline Location &loc(int index)
{ return location_stack [tos + index - 2]; }
+ std::ostream &yyMsg(int line = 0);
+
+ virtual void processComment(const QChar *, int);
+
protected:
int tos;
int stack_size;
@@ -1412,6 +1452,13 @@ protected:
QString error_message;
int error_lineno;
int error_column;
+
+private:
+ QScript::Lexer *lexer;
+ QString extracomment;
+ QString msgid;
+ QString sourcetext;
+ TranslatorMessage::ExtraData extra;
};
inline void QScriptParser::reallocateStack()
@@ -1438,7 +1485,8 @@ QScriptParser::QScriptParser():
stack_size(0),
sym_stack(0),
state_stack(0),
- location_stack(0)
+ location_stack(0),
+ lexer(0)
{
}
@@ -1460,10 +1508,14 @@ static inline QScriptParser::Location location(QScript::Lexer *lexer)
return loc;
}
-bool QScriptParser::parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator)
+void QScriptParser::setLexer(QScript::Lexer *lex)
{
+ lexer = lex;
+}
+
+bool QScriptParser::parse(Translator *translator)
+{
+ Q_ASSERT(lexer != 0);
const int INITIAL_STATE = 0;
int yytoken = -1;
@@ -1630,44 +1682,70 @@ CallExpression: MemberExpression Arguments ;
case $rule_number: {
QString name = sym(1).toString();
if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << "//% cannot be used with " << qPrintable(name) << "(). Ignoring\n";
QVariantList args = sym(2).toList();
if (args.size() < 2) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "() requires at least two arguments.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least two arguments.\n";
} else {
if ((args.at(0).type() != QVariant::String)
|| (args.at(1).type() != QVariant::String)) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "(): both arguments must be literal strings.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "(): both arguments must be literal strings.\n";
} else {
QString context = args.at(0).toString();
QString text = args.at(1).toString();
QString comment = args.value(2).toString();
- QString extracomment;
bool plural = (args.size() > 4);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
} else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << "//% cannot be used with " << qPrintable(name) << "(). Ignoring\n";
QVariantList args = sym(2).toList();
if (args.size() < 1) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "() requires at least one argument.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least one argument.\n";
} else {
if (args.at(0).type() != QVariant::String) {
- std::cerr << qPrintable(fileName) << ':' << identLineNo << ": "
- << qPrintable(name) << "(): text to translate must be a literal string.\n";
+ yyMsg(identLineNo) << qPrintable(name) << "(): text to translate must be a literal string.\n";
} else {
- QString context = QFileInfo(fileName).baseName();
+ QString context = QFileInfo(fileName()).baseName();
QString text = args.at(0).toString();
QString comment = args.value(1).toString();
- QString extracomment;
bool plural = (args.size() > 2);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
+ }
+ }
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ } else if ((name == QLatin1String("qsTrId")) || (name == QLatin1String("QT_TRID_NOOP"))) {
+ if (!msgid.isEmpty())
+ yyMsg(identLineNo) << "//= cannot be used with " << qPrintable(name) << "(). Ignoring\n";
+ QVariantList args = sym(2).toList();
+ if (args.size() < 1) {
+ yyMsg(identLineNo) << qPrintable(name) << "() requires at least one argument.\n";
+ } else {
+ if (args.at(0).type() != QVariant::String) {
+ yyMsg(identLineNo) << qPrintable(name) << "(): identifier must be a literal string.\n";
+ } else {
+ msgid = args.at(0).toString();
+ bool plural = (args.size() > 1);
+ recordMessage(translator, QString(), sourcetext, QString(), extracomment,
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
}
} break;
./
@@ -1813,20 +1891,73 @@ ExpressionNotInOpt: ;
ExpressionNotInOpt: ExpressionNotIn ;
Statement: Block ;
+/.
+ case $rule_number:
+./
Statement: VariableStatement ;
+/.
+ case $rule_number:
+./
Statement: EmptyStatement ;
+/.
+ case $rule_number:
+./
Statement: ExpressionStatement ;
+/.
+ case $rule_number:
+./
Statement: IfStatement ;
+/.
+ case $rule_number:
+./
Statement: IterationStatement ;
+/.
+ case $rule_number:
+./
Statement: ContinueStatement ;
+/.
+ case $rule_number:
+./
Statement: BreakStatement ;
+/.
+ case $rule_number:
+./
Statement: ReturnStatement ;
+/.
+ case $rule_number:
+./
Statement: WithStatement ;
+/.
+ case $rule_number:
+./
Statement: LabelledStatement ;
+/.
+ case $rule_number:
+./
Statement: SwitchStatement ;
+/.
+ case $rule_number:
+./
Statement: ThrowStatement ;
+/.
+ case $rule_number:
+./
Statement: TryStatement ;
+/.
+ case $rule_number:
+./
Statement: DebuggerStatement ;
+/.
+ case $rule_number:
+ if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
+ yyMsg() << "Discarding unconsumed meta data\n";
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ }
+ break;
+./
Block: T_LBRACE StatementListOpt T_RBRACE ;
StatementList: Statement ;
@@ -1988,6 +2119,63 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ;
return false;
}
+std::ostream &QScriptParser::yyMsg(int line)
+{
+ return std::cerr << qPrintable(fileName()) << ':' << (line ? line : lexer->startLineNo()) << ": ";
+}
+
+void QScriptParser::processComment(const QChar *chars, int length)
+{
+ if (!length)
+ return;
+ // Try to match the logic of the C++ parser.
+ if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
+ extracomment += QString(chars+2, length-2);
+ } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
+ msgid = QString(chars+2, length-2).simplified();
+ } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
+ QString text = QString(chars+2, length-2).trimmed();
+ int k = text.indexOf(QLatin1Char(' '));
+ if (k > -1)
+ extra.insert(text.left(k), text.mid(k + 1).trimmed());
+ } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
+ sourcetext.reserve(sourcetext.length() + length-2);
+ ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
+ int p = 2, c;
+ forever {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (isspace(c))
+ continue;
+ if (c != '"') {
+ yyMsg() << "Unexpected character in meta string\n";
+ break;
+ }
+ forever {
+ if (p >= length) {
+ whoops:
+ yyMsg() << "Unterminated meta string\n";
+ break;
+ }
+ c = chars[p++].unicode();
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (p >= length)
+ goto whoops;
+ c = chars[p++].unicode();
+ if (c == '\n')
+ goto whoops;
+ *ptr++ = '\\';
+ }
+ *ptr++ = c;
+ }
+ }
+ sourcetext.resize(ptr - (ushort *)sourcetext.data());
+ }
+}
+
bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd)
{
@@ -2007,10 +2195,11 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData
ts.setAutoDetectUnicode(true);
QString code = ts.readAll();
- QScript::Lexer lexer;
- lexer.setCode(code, /*lineNumber=*/1);
QScriptParser parser;
- if (!parser.parse(&lexer, filename, &translator)) {
+ QScript::Lexer lexer(&parser);
+ lexer.setCode(code, filename, /*lineNumber=*/1);
+ parser.setLexer(&lexer);
+ if (!parser.parse(&translator)) {
std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": "
<< qPrintable(parser.errorMessage()) << std::endl;
return false;
diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf
index c70bcaf..8d4d27f 100644
--- a/tools/qdoc3/test/qt-html-templates.qdocconf
+++ b/tools/qdoc3/test/qt-html-templates.qdocconf
@@ -98,10 +98,13 @@ HTML.postheader = " <div class=\"header\" id=\"qtdocheader\">\n" \
" Qt Topics</h2>\n" \
" <div id=\"list002\" class=\"list\">\n" \
" <ul id=\"ul002\" >\n" \
- " <li class=\"defaultLink\"><a href=\"qt-basic-concepts.html\">Basic Qt architecture</a></li>\n" \
- " <li class=\"defaultLink\"><a href=\"qtquick.html\">Device UI's &amp; Qt Quick</a></li>\n" \
- " <li class=\"defaultLink\"><a href=\"qt-gui-concepts.html\">Desktop UI components</a></li>\n" \
- " <li class=\"defaultLink\"><a href=\"platform-specific.html\">Platform-specific info</a></li>\n" \
+ " <li><a href=\"qt-basic-concepts.html\">Programming with Qt</a></li> \n" \
+ " <li><a href=\"qtquick.html\">Device UI's &amp; Qt Quick</a></li> \n" \
+ " <li><a href=\"qt-gui-concepts.html\">UI Design with Qt</a></li> \n" \
+ " <li><a href=\"developing-with-qt.html\">Cross-platform and Platform-specific</a></li> \n" \
+ " <li><a href=\"platform-specific.html\">Platform-specific info</a></li> \n" \
+ " <li><a href=\"technology-apis.html\">Qt and Key Technologies</a></li> \n" \
+ " <li><a href=\"best-practices.html\">How-To's and Best Practices</a></li> \n" \
" </ul> \n" \
" </div>\n" \
" </div>\n" \