diff options
author | axis <qt-info@nokia.com> | 2010-03-01 14:06:02 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2010-03-01 14:06:02 (GMT) |
commit | 88a36e9e7e0e0bc09788c41ab6b968031dbc9154 (patch) | |
tree | 947663f695f54a0deb2724116f82d89fde761576 /src/corelib | |
parent | 4be1e01c6faebe11bfe205c1b910049747b5c335 (diff) | |
parent | ca82ee4ee55e52c75326949148455af1095df014 (diff) | |
download | Qt-88a36e9e7e0e0bc09788c41ab6b968031dbc9154.zip Qt-88a36e9e7e0e0bc09788c41ab6b968031dbc9154.tar.gz Qt-88a36e9e7e0e0bc09788c41ab6b968031dbc9154.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts:
configure
mkspecs/common/symbian/symbian.conf
qmake/generators/symbian/initprojectdeploy_symbian.cpp
qmake/generators/symbian/symmake_abld.cpp
qmake/generators/symbian/symmake_sbsv2.cpp
src/plugins/plugins.pro
Diffstat (limited to 'src/corelib')
32 files changed, 868 insertions, 68 deletions
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index 3065205..3b808b8 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -499,6 +499,13 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event) /*! \fn void QFutureWatcher::setFuture(const QFuture<T> &future) Starts watching the given \a future. + + One of the signals might be emitted for the current state of the + \a future. For example, if the future is already stopped, the + finished signal will be emitted. + + To avoid a race condition, it is important to call this function + \i after doing the connections. */ /*! \fn QFuture<T> QFutureWatcher::future() const diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index c4b4be2..500cde6 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -52,3 +52,25 @@ symbian: { partial_upgrade.path = c:/sys/bin DEPLOYMENT = partial_upgrade $$DEPLOYMENT } + +mmx { + DEFINES += QT_HAVE_MMX +} +3dnow { + DEFINES += QT_HAVE_3DNOW +} +sse { + DEFINES += QT_HAVE_SSE + DEFINES += QT_HAVE_MMXEXT +} +sse2 { + DEFINES += QT_HAVE_SSE2 +} +iwmmxt { + DEFINES += QT_HAVE_IWMMXT +} +neon { + DEFINES += QT_HAVE_NEON + QMAKE_CXXFLAGS *= -mfpu=neon +} + diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 7e7d7d8..4d48b60 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -814,7 +814,7 @@ namespace QT_NAMESPACE {} # define Q_WS_MAC32 # endif # elif defined(Q_OS_SYMBIAN) -# if (defined(__SERIES60_31__) || defined(__S60_32__) || defined(__S60_50__)) && !defined(QT_NO_S60) +# if !defined(QT_NO_S60) # define Q_WS_S60 # endif # elif !defined(Q_WS_QWS) @@ -2414,10 +2414,11 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #if defined(Q_OS_SYMBIAN) -#ifdef SYMBIAN_GRAPHICS_USE_GCE +#ifdef SYMBIAN_BUILD_GCE //RWsPointerCursor is fixed, so don't use low performance sprites #define Q_SYMBIAN_FIXED_POINTER_CURSORS #define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE +#define Q_SYMBIAN_WINDOW_SIZE_CACHE //enabling new graphics resources #define QT_SYMBIAN_SUPPORTS_SGIMAGE #define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index a9ea44a..9490225 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -266,6 +266,11 @@ QLibraryInfo::location(LibraryLocation loc) path = QT_CONFIGURE_PLUGINS_PATH; break; #endif +#ifdef QT_CONFIGURE_IMPORTS_PATH + case ImportsPath: + path = QT_CONFIGURE_IMPORTS_PATH; + break; +#endif #ifdef QT_CONFIGURE_DATA_PATH case DataPath: path = QT_CONFIGURE_DATA_PATH; @@ -439,7 +444,7 @@ QLibraryInfo::location(LibraryLocation loc) QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef); if (urlRef) { QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); - return QDir::cleanPath(path + QLatin1String("/Contents/") + ret); + return QDir::cleanPath(QString(path) + QLatin1String("/Contents/") + ret); } } #endif @@ -470,6 +475,7 @@ QLibraryInfo::location(LibraryLocation loc) \value LibrariesPath The location of installed librarires. \value BinariesPath The location of installed Qt binaries (tools and applications). \value PluginsPath The location of installed Qt plugins. + \value ImportsPath The location of installed QML extensions to import. \value DataPath The location of general Qt data. \value TranslationsPath The location of translation information for Qt strings. \value SettingsPath The location for Qt settings. diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index e64b760..4a7ba06 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -76,7 +76,8 @@ public: TranslationsPath, SettingsPath, DemosPath, - ExamplesPath + ExamplesPath, + ImportsPath }; static QString location(LibraryLocation); // ### Qt 5: consider renaming it to path() diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index fc35bfa..2731ae1 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -159,10 +159,9 @@ QT_BEGIN_NAMESPACE \section1 Reading and writing Qt collection classes - The Qt collection classes can also be serialized to a QDataStream. + The Qt container classes can also be serialized to a QDataStream. These include QList, QLinkedList, QVector, QSet, QHash, and QMap. - These classes have have stream operators declared as non-member of - the class. + The stream operators are declared as non-members of the classes. \target Serializing Qt Classes \section1 Reading and writing other Qt classes. diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 7cfdddf..505889e 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -960,13 +960,14 @@ void QDir::setNameFilters(const QStringList &nameFilters) /*! \obsolete + + Use QDir::addSearchPath() with a prefix instead. + Adds \a path to the search paths searched in to find resources that are not specified with an absolute path. The default search path is to search only in the root (\c{:/}). - Use QDir::addSearchPath() with a prefix instead. - - \sa {The Qt Resource System}, QResource::addSearchPath() + \sa {The Qt Resource System} */ void QDir::addResourceSearchPath(const QString &path) { diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 606941e..dced3e7 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -1270,7 +1270,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla int pageSize = getpagesize(); int extra = offset % pageSize; - if (size + extra > (size_t)-1) { + if (quint64(size + extra) > quint64((size_t)-1)) { q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); return 0; } diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 4e14ba8..662100a 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1003,8 +1003,8 @@ QByteArray QIODevice::readAll() to a maximum of \a maxSize - 1 bytes, stores the characters in \a data, and returns the number of bytes read. If a line could not be read but no error ocurred, this function returns 0. If an error - occurs, this function returns what it could the length of what - could be read, or -1 if nothing was read. + occurs, this function returns the length of what could be read, or + -1 if nothing was read. A terminating '\0' byte is always appended to \a data, so \a maxSize must be larger than 1. diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index adfbb15..6d33c8b 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -555,16 +555,15 @@ QStringList QResource::children() const /*! \obsolete + Use QDir::addSearchPath() with a prefix instead. + Adds \a path to the search paths searched in to find resources that are not specified with an absolute path. The \a path must be an absolute path (start with \c{/}). The default search path is to search only in the root (\c{:/}). The last path added will be consulted first upon next QResource creation. - - Use QDir::addSearchPath() with a prefix instead. */ - void QResource::addSearchPath(const QString &path) { @@ -578,6 +577,10 @@ QResource::addSearchPath(const QString &path) } /*! + \obsolete + + Use QDir::searchPaths() instead. + Returns the current search path list. This list is consulted when creating a relative resource. diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 076cc33..acb73fd 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -437,17 +437,19 @@ static bool QT_FASTCALL _unreserved(const char **ptr) } // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) -static void QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) +static bool QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) { bool first = true; + bool isSchemeValid = true; parseData->scheme = *ptr; for (;;) { char ch = **ptr; if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { ; - } else if (!first && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')) { - ; + } else if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.') { + if (first) + isSchemeValid = false; } else { break; } @@ -457,11 +459,14 @@ static void QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) } if (**ptr != ':') { + isSchemeValid = true; *ptr = parseData->scheme; } else { parseData->schemeLength = *ptr - parseData->scheme; ++(*ptr); // skip ':' } + + return isSchemeValid; } // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) @@ -3743,7 +3748,19 @@ void QUrlPrivate::parse(ParseOptions parseOptions) const #endif // optional scheme - _scheme(ptr, &parseData); + bool isSchemeValid = _scheme(ptr, &parseData); + + if (isSchemeValid == false) { + that->isValid = false; + char ch = *((*ptr)++); + that->errorInfo.setParams(*ptr, QT_TRANSLATE_NOOP(QUrl, "unexpected URL scheme"), + 0, ch); + QURL_SETFLAG(that->stateFlags, Validated | Parsed); +#if defined (QURL_DEBUG) + qDebug("QUrlPrivate::parse(), unrecognized: %c%s", ch, *ptr); +#endif + return; + } // hierpart _hierPart(ptr, &parseData); @@ -6348,7 +6365,7 @@ QUrl QUrl::fromUserInput(const QString &userInput) return QUrl::fromLocalFile(trimmedString); QUrl url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); - QUrl urlPrepended = QUrl::fromEncoded((QLatin1String("http://") + trimmedString).toUtf8(), QUrl::TolerantMode); + QUrl urlPrepended = QUrl::fromEncoded("http://" + trimmedString.toUtf8(), QUrl::TolerantMode); // Check the most common case of a valid url with scheme and host // We check if the port would be valid by adding the scheme to handle the case host:port diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 5990f86..566626d 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -1021,14 +1021,14 @@ QString decodeMSG(const MSG& msg) LPWINDOWPOS winPos = (LPWINDOWPOS)lParam; if (!winPos) break; - QString hwndAfter = valueCheck((uint)winPos->hwndInsertAfter, - FLAG_STRING((uint)HWND_BOTTOM, "HWND_BOTTOM"), - FLAG_STRING((int)HWND_NOTOPMOST, "HWND_NOTOPMOST"), - FLAG_STRING((uint)HWND_TOP, "HWND_TOP"), - FLAG_STRING((int)HWND_TOPMOST, "HWND_TOPMOST"), + QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter), + FLAG_STRING((quintptr)HWND_BOTTOM, "HWND_BOTTOM"), + FLAG_STRING((quintptr)HWND_NOTOPMOST, "HWND_NOTOPMOST"), + FLAG_STRING((quintptr)HWND_TOP, "HWND_TOP"), + FLAG_STRING((quintptr)HWND_TOPMOST, "HWND_TOPMOST"), FLAG_STRING()); if (hwndAfter.size() == 0) - hwndAfter = QString::number((uint)winPos->hwndInsertAfter, 16); + hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16); QString flags = flagCheck(winPos->flags, FLGSTR(SWP_DRAWFRAME), FLGSTR(SWP_FRAMECHANGED), diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 870baab..9e187d4 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -48,6 +48,7 @@ #include "qstringlist.h" #include "qvector.h" #include "qlocale.h" +#include "qeasingcurve.h" #ifdef QT_BOOTSTRAPPED # ifndef QT_NO_GEOM_VARIANT @@ -176,6 +177,7 @@ QT_BEGIN_NAMESPACE \value QVector3D QVector3D \value QVector4D QVector4D \value QQuaternion QQuaternion + \value QEasingCurve QEasingCurve \value User Base value for user types @@ -256,6 +258,7 @@ static const struct { const char * typeName; int type; } types[] = { {"QPointF", QMetaType::QPointF}, {"QRegExp", QMetaType::QRegExp}, {"QVariantHash", QMetaType::QVariantHash}, + {"QEasingCurve", QMetaType::QEasingCurve}, /* All GUI types */ {"QColorGroup", 63}, @@ -666,6 +669,11 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) stream << *static_cast<const NS(QRegExp)*>(data); break; #endif +#ifndef QT_BOOTSTRAPPED + case QMetaType::QEasingCurve: + stream << *static_cast<const NS(QEasingCurve)*>(data); + break; +#endif #ifdef QT3_SUPPORT case QMetaType::QColorGroup: #endif @@ -863,6 +871,11 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) stream >> *static_cast< NS(QRegExp)*>(data); break; #endif +#ifndef QT_BOOTSTRAPPED + case QMetaType::QEasingCurve: + stream >> *static_cast< NS(QEasingCurve)*>(data); + break; +#endif #ifdef QT3_SUPPORT case QMetaType::QColorGroup: #endif @@ -1007,6 +1020,10 @@ void *QMetaType::construct(int type, const void *copy) case QMetaType::QRegExp: return new NS(QRegExp)(*static_cast<const NS(QRegExp)*>(copy)); #endif +#ifndef QT_BOOTSTRAPPED + case QMetaType::QEasingCurve: + return new NS(QEasingCurve)(*static_cast<const NS(QEasingCurve)*>(copy)); +#endif case QMetaType::Void: return 0; default: @@ -1098,6 +1115,10 @@ void *QMetaType::construct(int type, const void *copy) case QMetaType::QRegExp: return new NS(QRegExp); #endif +#ifndef QT_BOOTSTRAPPED + case QMetaType::QEasingCurve: + return new NS(QEasingCurve); +#endif case QMetaType::Void: return 0; default: @@ -1253,6 +1274,11 @@ void QMetaType::destroy(int type, void *data) delete static_cast< NS(QRegExp)* >(data); break; #endif +#ifndef QT_BOOTSTRAPPED + case QMetaType::QEasingCurve: + delete static_cast< NS(QEasingCurve)* >(data); + break; +#endif case QMetaType::Void: break; default: { diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index c23caed..33126e8 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -69,7 +69,7 @@ public: QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17, QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22, QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27, - QVariantHash = 28, LastCoreType = 28 /* QVariantHash */, + QVariantHash = 28, QEasingCurve = 29, LastCoreType = QEasingCurve, FirstGuiType = 63 /* QColorGroup */, #ifdef QT3_SUPPORT @@ -81,12 +81,12 @@ public: QTextLength = 78, QTextFormat = 79, QMatrix = 80, QTransform = 81, QMatrix4x4 = 82, QVector2D = 83, QVector3D = 84, QVector4D = 85, QQuaternion = 86, - LastGuiType = 86 /* QQuaternion */, + LastGuiType = QQuaternion, FirstCoreExtType = 128 /* VoidStar */, VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132, UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137, - LastCoreExtType = 137 /* QWidgetStar */, + LastCoreExtType = QWidgetStar, // This logic must match the one in qglobal.h #if defined(QT_COORD_TYPE) @@ -290,6 +290,7 @@ class QPointF; #ifndef QT_NO_REGEXP class QRegExp; #endif +class QEasingCurve; class QWidget; class QObject; @@ -359,6 +360,7 @@ Q_DECLARE_BUILTIN_METATYPE(QPointF, QPointF) #ifndef QT_NO_REGEXP Q_DECLARE_BUILTIN_METATYPE(QRegExp, QRegExp) #endif +Q_DECLARE_BUILTIN_METATYPE(QEasingCurve, QEasingCurve) #ifdef QT3_SUPPORT Q_DECLARE_BUILTIN_METATYPE(QColorGroup, QColorGroup) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index e1b5825..227a60d 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -46,6 +46,7 @@ #include "qdebug.h" #include "qmap.h" #include "qdatetime.h" +#include "qeasingcurve.h" #include "qlist.h" #include "qstring.h" #include "qstringlist.h" @@ -146,6 +147,11 @@ static void construct(QVariant::Private *x, const void *copy) v_construct<QRegExp>(x, copy); break; #endif +#ifndef QT_BOOTSTRAPPED + case QVariant::EasingCurve: + v_construct<QEasingCurve>(x, copy); + break; +#endif case QVariant::Int: x->data.i = copy ? *static_cast<const int *>(copy) : 0; break; @@ -259,6 +265,11 @@ static void clear(QVariant::Private *d) v_clear<QRegExp>(d); break; #endif +#ifndef QT_BOOTSTRAPPED + case QVariant::EasingCurve: + v_clear<QEasingCurve>(d); + break; +#endif case QVariant::LongLong: case QVariant::ULongLong: case QVariant::Double: @@ -317,6 +328,9 @@ static bool isNull(const QVariant::Private *d) case QVariant::PointF: return v_cast<QPointF>(d)->isNull(); #endif +#ifndef QT_BOOTSTRAPPED + case QVariant::EasingCurve: +#endif case QVariant::Url: case QVariant::Locale: case QVariant::RegExp: @@ -435,6 +449,10 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) return *v_cast<QTime>(a) == *v_cast<QTime>(b); case QVariant::DateTime: return *v_cast<QDateTime>(a) == *v_cast<QDateTime>(b); +#ifndef QT_BOOTSTRAPPED + case QVariant::EasingCurve: + return *v_cast<QEasingCurve>(a) == *v_cast<QEasingCurve>(b); +#endif case QVariant::ByteArray: return *v_cast<QByteArray>(a) == *v_cast<QByteArray>(b); case QVariant::BitArray: @@ -1097,6 +1115,11 @@ static void streamDebug(QDebug dbg, const QVariant &v) case QVariant::DateTime: dbg.nospace() << v.toDateTime(); break; +#ifndef QT_BOOTSTRAPPED + case QVariant::EasingCurve: + dbg.nospace() << v.toEasingCurve(); + break; +#endif case QVariant::ByteArray: dbg.nospace() << v.toByteArray(); break; @@ -1265,6 +1288,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value Date a QDate \value DateTime a QDateTime \value Double a double + \value EasingCurve a QEasingCurve \value Font a QFont \value Hash a QVariantHash \value Icon a QIcon @@ -1483,6 +1507,12 @@ QVariant::QVariant(const char *val) */ /*! + \fn QVariant::QVariant(const QEasingCurve &val) + + Constructs a new variant with an easing curve value, \a val. +*/ + +/*! \fn QVariant::QVariant(const QByteArray &val) Constructs a new variant with a bytearray value, \a val. @@ -1681,6 +1711,10 @@ QVariant::QVariant(const QTime &val) { d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); } QVariant::QVariant(const QDateTime &val) { d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); } +#ifndef QT_BOOTSTRAPPED +QVariant::QVariant(const QEasingCurve &val) +{ d.is_null = false; d.type = EasingCurve; v_construct<QEasingCurve>(&d, val); } +#endif QVariant::QVariant(const QList<QVariant> &list) { d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); } QVariant::QVariant(const QMap<QString, QVariant> &map) @@ -1870,7 +1904,7 @@ QVariant::Type QVariant::nameToType(const char *name) } #ifndef QT_NO_DATASTREAM -enum { MapFromThreeCount = 35 }; +enum { MapFromThreeCount = 36 }; static const ushort map_from_three[MapFromThreeCount] = { QVariant::Invalid, @@ -1907,7 +1941,8 @@ static const ushort map_from_three[MapFromThreeCount] = QVariant::KeySequence, QVariant::Pen, QVariant::LongLong, - QVariant::ULongLong + QVariant::ULongLong, + QVariant::EasingCurve }; /*! @@ -2165,6 +2200,21 @@ QDateTime QVariant::toDateTime() const } /*! + \fn QEasingCurve QVariant::toEasingCurve() const + + Returns the variant as a QEasingCurve if the variant has type() \l + EasingCurve; otherwise returns a default easing curve. + + \sa canConvert(), convert() +*/ +#ifndef QT_BOOTSTRAPPED +QEasingCurve QVariant::toEasingCurve() const +{ + return qVariantToHelper<QEasingCurve>(d, EasingCurve, handler); +} +#endif + +/*! \fn QByteArray QVariant::toByteArray() const Returns the variant as a QByteArray if the variant has type() \l @@ -2605,8 +2655,9 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QRegExp*/ 0, -/*QHash*/ 0 +/*QHash*/ 0, +/*QEasingCurve*/ 0 }; /*! diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 1a9e43a..9628dbf 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -60,6 +60,7 @@ class QBitArray; class QDataStream; class QDate; class QDateTime; +class QEasingCurve; class QLine; class QLineF; class QLocale; @@ -128,9 +129,10 @@ class Q_CORE_EXPORT QVariant LineF = 24, Point = 25, PointF = 26, - RegExp = 27, + RegExp = 27, Hash = 28, - LastCoreType = Hash, + EasingCurve = 29, + LastCoreType = EasingCurve, // value 62 is internally reserved #ifdef QT3_SUPPORT @@ -219,6 +221,9 @@ class Q_CORE_EXPORT QVariant #ifndef QT_NO_REGEXP QVariant(const QRegExp ®Exp); #endif +#ifndef QT_BOOTSTRAPPED + QVariant(const QEasingCurve &easing); +#endif QVariant(Qt::GlobalColor color); QVariant& operator=(const QVariant &other); @@ -280,6 +285,9 @@ class Q_CORE_EXPORT QVariant #ifndef QT_NO_REGEXP QRegExp toRegExp() const; #endif +#ifndef QT_BOOTSTRAPPED + QEasingCurve toEasingCurve() const; +#endif #ifdef QT3_SUPPORT inline QT3_SUPPORT int &asInt(); diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index ec50ac8..43df13a 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -41,6 +41,7 @@ #include "qplatformdefs.h" #include "qmutex.h" +#include <qdebug.h> #ifndef QT_NO_THREAD #include "qatomic.h" @@ -159,8 +160,7 @@ void QMutex::lock() if (!isLocked) { #ifndef QT_NO_DEBUG if (d->owner == self) - qWarning("QMutex::lock: Deadlock detected in thread %ld", - long(d->owner)); + qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; #endif // didn't get the lock, wait for it @@ -197,8 +197,7 @@ void QMutex::lock() if (!isLocked) { #ifndef QT_NO_DEBUG if (d->owner == self) - qWarning("QMutex::lock: Deadlock detected in thread %ld", - long(d->owner)); + qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; #endif // didn't get the lock, wait for it diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index a27e488..3324796 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1804,7 +1804,20 @@ QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after) */ QByteArray &QByteArray::replace(int pos, int len, const char *after) { - int alen = qstrlen(after); + return replace(pos,len,after,qstrlen(after)); +} + +/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen) + + \overload + + Replaces \a len bytes from index position \a pos with \a alen bytes + from the string \a after. \a after is allowed to have '\0' characters. + + \since 4.7 +*/ +QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen) +{ if (len == alen && (pos + len <= d->size)) { detach(); memcpy(d->data + pos, after, len*sizeof(char)); diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index ec592f5f..0b77512 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -237,6 +237,7 @@ public: QByteArray &insert(int i, const QByteArray &a); QByteArray &remove(int index, int len); QByteArray &replace(int index, int len, const char *s); + QByteArray &replace(int index, int len, const char *s, int alen); QByteArray &replace(int index, int len, const QByteArray &s); QByteArray &replace(char before, const char *after); QByteArray &replace(char before, const QByteArray &after); diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index b6a2df4..d4b2c27 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -600,11 +600,11 @@ QEasingCurve::QEasingCurve(Type type) Construct a copy of \a other. */ QEasingCurve::QEasingCurve(const QEasingCurve &other) -: d_ptr(new QEasingCurvePrivate) + : d_ptr(new QEasingCurvePrivate) { // ### non-atomic, requires malloc on shallow copy *d_ptr = *other.d_ptr; - if(other.d_ptr->config) + if (other.d_ptr->config) d_ptr->config = other.d_ptr->config->copy(); } @@ -629,7 +629,7 @@ QEasingCurve &QEasingCurve::operator=(const QEasingCurve &other) } *d_ptr = *other.d_ptr; - if(other.d_ptr->config) + if (other.d_ptr->config) d_ptr->config = other.d_ptr->config->copy(); return *this; @@ -845,6 +845,67 @@ QDebug operator<<(QDebug debug, const QEasingCurve &item) } return debug; } -#endif +#endif // QT_NO_DEBUG_STREAM + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QEasingCurve &easing) + \relates QEasingCurve + + Writes the given \a easing curve to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QEasingCurve &easing) +{ + stream << quint8(easing.d_ptr->type); + stream << quint64(quintptr(easing.d_ptr->func)); + + bool hasConfig = easing.d_ptr->config; + stream << hasConfig; + if (hasConfig) { + stream << easing.d_ptr->config->_p; + stream << easing.d_ptr->config->_a; + stream << easing.d_ptr->config->_o; + } + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing) + \relates QQuaternion + + Reads an easing curve from the given \a stream into the given \a quaternion + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing) +{ + QEasingCurve::Type type; + quint8 int_type; + stream >> int_type; + type = static_cast<QEasingCurve::Type>(int_type); + easing.setType(type); + + quint64 ptr_func; + stream >> ptr_func; + easing.d_ptr->func = QEasingCurve::EasingFunction(quintptr(ptr_func)); + + bool hasConfig; + stream >> hasConfig; + if (hasConfig) { + QEasingCurveFunction *config = curveToFunctionObject(type); + stream >> config->_p; + stream >> config->_a; + stream >> config->_o; + easing.d_ptr->config = config; + } + return stream; +} +#endif // QT_NO_DATASTREAM QT_END_NAMESPACE diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index ae8822e..173fba4 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -100,13 +100,24 @@ public: qreal valueForProgress(qreal progress) const; private: QEasingCurvePrivate *d_ptr; +#ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item); +#endif +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&); + friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &); +#endif }; #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QEasingCurve&); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QEasingCurve &); +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index b4bfcaf..84bc154 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -465,7 +465,7 @@ static QString winToQtFormat(const QString &sys_fmt) if (text == QLatin1String("'")) result += QLatin1String("''"); else - result += QLatin1Char('\'') + text + QLatin1Char('\''); + result += QString(QLatin1Char('\'') + text + QLatin1Char('\'')); continue; } @@ -681,8 +681,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const case DateTimeFormatLong: case DateTimeFormatShort: - return query(type == DateTimeFormatLong ? DateFormatLong : DateFormatShort).toString() - + QLatin1Char(' ') + query(type == DateTimeFormatLong ? TimeFormatLong : TimeFormatShort).toString(); + return QString(query(type == DateTimeFormatLong ? DateFormatLong : DateFormatShort).toString() + + QLatin1Char(' ') + query(type == DateTimeFormatLong ? TimeFormatLong : TimeFormatShort).toString()); case DayNameLong: case DayNameShort: return winDayName(in.toInt(), (type == DayNameShort)); @@ -698,8 +698,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const case DateTimeToStringShort: case DateTimeToStringLong: { const QDateTime dt = in.toDateTime(); - return winDateToString(dt.date(), type == DateTimeToStringShort ? DATE_SHORTDATE : DATE_LONGDATE) - + QLatin1Char(' ') + winTimeToString(dt.time()); } + return QString(winDateToString(dt.date(), type == DateTimeToStringShort ? DATE_SHORTDATE : DATE_LONGDATE) + + QLatin1Char(' ') + winTimeToString(dt.time())); } case ZeroDigit: locale_info = LOCALE_SNATIVEDIGITS; diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp index b1a7caa..58e3ba8 100644 --- a/src/corelib/tools/qlocale_symbian.cpp +++ b/src/corelib/tools/qlocale_symbian.cpp @@ -841,7 +841,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const return symbianTimeFormat(); case DateTimeFormatLong: case DateTimeFormatShort: - return symbianDateFormat( (type == DateTimeFormatShort) ) + QLatin1Char(' ') + symbianTimeFormat(); + return QString(symbianDateFormat( (type == DateTimeFormatShort) ) + QLatin1Char(' ') + symbianTimeFormat()); case DateToStringShort: case DateToStringLong: return symbianDateToString(in.toDate(), (type == DateToStringShort) ); @@ -851,8 +851,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const case DateTimeToStringShort: case DateTimeToStringLong: { const QDateTime dt = in.toDateTime(); - return symbianDateToString(dt.date(), (type == DateTimeToStringShort) ) - + QLatin1Char(' ') + symbianTimeToString(dt.time()); + return QString(symbianDateToString(dt.date(), (type == DateTimeToStringShort) ) + + QLatin1Char(' ') + symbianTimeToString(dt.time())); } case MeasurementSystem: return static_cast<int>(symbianMeasurementSystem()); diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 25255f9..20ad444 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -1466,9 +1466,14 @@ void QRegExpMatchState::match(const QChar *str0, int len0, int pos0, #ifndef QT_NO_REGEXP_CAPTURE for (int i = 0; i < numCaptures; ++i) { int j = eng->captureForOfficialCapture.at(i); - int len = capEnd[j] - capBegin[j]; - *c++ = (len > 0) ? pos + capBegin[j] : 0; - *c++ = len; + if (capBegin[j] != EmptyCapture) { + int len = capEnd[j] - capBegin[j]; + *c++ = (len > 0) ? pos + capBegin[j] : 0; + *c++ = len; + } else { + *c++ = -1; + *c++ = -1; + } } #endif } else { diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp index 12badf0..e7dd769 100644 --- a/src/corelib/tools/qscopedpointer.cpp +++ b/src/corelib/tools/qscopedpointer.cpp @@ -225,4 +225,59 @@ QT_BEGIN_NAMESPACE Swap this pointer with \a other. */ +/*! + \class QScopedArrayPointer + + \brief The QScopedArrayPointer class stores a pointer to a + dynamically allocated array of objects, and deletes it upon + destruction. + + \since 4.6 + \reentrant + \ingroup misc + + A QScopedArrayPointer is a QScopedPointer that defaults to + deleting the object it is pointing to with the delete[] operator. It + also features operator[] for convenience, so we can write: + + \code + void foo() + { + QScopedArrayPointer<int> i(new int[10]); + i[2] = 42; + ... + return; // our integer array is now deleted using delete[] + } + \endcode +*/ + +/*! + \fn QScopedArrayPointer::QScopedArrayPointer(T *p = 0) + + Constructs this QScopedArrayPointer instance and sets its pointer + to \a p. +*/ + +/*! + \fn T *QScopedArrayPointer::operator[](int i) + + Provides access to entry \a i of the scoped pointer's array of + objects. + + If the contained pointer is \c null, behavior is undefined. + + \sa isNull() +*/ + +/*! + \fn T *QScopedArrayPointer::operator[](int i) const + + Provides access to entry \a i of the scoped pointer's array of + objects. + + If the contained pointer is \c null, behavior is undefined. + + \sa isNull() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index d85c248..bfc65bc 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -209,6 +209,7 @@ namespace QtSharedPointer { inline bool destroy() { destroyer(this); return true; } inline void operator delete(void *ptr) { ::operator delete(ptr); } + inline void operator delete(void *, void *) { } }; // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp new file mode 100644 index 0000000..52d2cea --- /dev/null +++ b/src/corelib/tools/qsimd.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qsimd_p.h" +#include <QByteArray> + +QT_BEGIN_NAMESPACE + +uint qDetectCPUFeatures() +{ + static uint features = 0xffffffff; + if (features != 0xffffffff) + return features; + +#if defined (Q_OS_WINCE) +#if defined (ARM) + if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX)) { + features = IWMMXT; + return features; + } +#elif defined(_X86_) + features = 0; +#if defined QT_HAVE_MMX + if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) + features |= MMX; +#endif +#if defined QT_HAVE_3DNOW + if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE)) + features |= MMX3DNOW; +#endif + return features; +#endif + features = 0; + return features; +#elif 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; +#elif defined(QT_HAVE_NEON) + static const bool doNEON = !qgetenv("QT_NO_NEON").toInt(); + features = doNEON ? NEON : 0; + 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) + unsigned int extended_result = 0; + uint result = 0; + /* see p. 118 of amd64 instruction set manual Vol3 */ +#if defined(Q_CC_GNU) + asm ("push %%ebx\n" + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%ebx\n" + "xor $0x00200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%edx\n" + "xor %%ebx, %%eax\n" + "jz 1f\n" + + "mov $0x00000001, %%eax\n" + "cpuid\n" + "1:\n" + "pop %%ebx\n" + "mov %%edx, %0\n" + : "=r" (result) + : + : "%eax", "%ecx", "%edx" + ); + + asm ("push %%ebx\n" + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%ebx\n" + "xor $0x00200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%edx\n" + "xor %%ebx, %%eax\n" + "jz 2f\n" + + "mov $0x80000000, %%eax\n" + "cpuid\n" + "cmp $0x80000000, %%eax\n" + "jbe 2f\n" + "mov $0x80000001, %%eax\n" + "cpuid\n" + "2:\n" + "pop %%ebx\n" + "mov %%edx, %0\n" + : "=r" (extended_result) + : + : "%eax", "%ecx", "%edx" + ); +#elif defined (Q_OS_WIN) + _asm { + push eax + push ebx + push ecx + push edx + pushfd + pop eax + mov ebx, eax + xor eax, 00200000h + push eax + popfd + pushfd + pop eax + mov edx, 0 + xor eax, ebx + jz skip + + mov eax, 1 + cpuid + mov result, edx + skip: + pop edx + pop ecx + pop ebx + pop eax + } + + _asm { + push eax + push ebx + push ecx + push edx + pushfd + pop eax + mov ebx, eax + xor eax, 00200000h + push eax + popfd + pushfd + pop eax + mov edx, 0 + xor eax, ebx + jz skip2 + + mov eax, 80000000h + cpuid + cmp eax, 80000000h + jbe skip2 + mov eax, 80000001h + cpuid + mov extended_result, edx + skip2: + pop edx + pop ecx + pop ebx + pop eax + } +#endif + + // result now contains the standard feature bits + if (result & (1u << 15)) + features |= CMOV; + if (result & (1u << 23)) + features |= MMX; + if (extended_result & (1u << 22)) + features |= MMXEXT; + if (extended_result & (1u << 31)) + features |= MMX3DNOW; + if (extended_result & (1u << 30)) + features |= MMX3DNOWEXT; + if (result & (1u << 25)) + features |= SSE; + if (result & (1u << 26)) + features |= SSE2; +#endif // i386 + +#if defined(QT_HAVE_MMX) + if (qgetenv("QT_NO_MMX").toInt()) + features ^= MMX; +#endif + if (qgetenv("QT_NO_MMXEXT").toInt()) + features ^= MMXEXT; + +#if defined(QT_HAVE_3DNOW) + if (qgetenv("QT_NO_3DNOW").toInt()) + features ^= MMX3DNOW; +#endif + if (qgetenv("QT_NO_3DNOWEXT").toInt()) + features ^= MMX3DNOWEXT; + +#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; +#endif + + return features; +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h new file mode 100644 index 0000000..556db14 --- /dev/null +++ b/src/corelib/tools/qsimd_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSIMD_P_H +#define QSIMD_P_H + +#include <qglobal.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__))) +// Disable MMX and SSE on Mac/PPC builds, or if the compiler +// does not support -Xarch argument passing +#undef QT_HAVE_SSE2 +#undef QT_HAVE_SSE +#undef QT_HAVE_3DNOW +#undef QT_HAVE_MMX +#endif + +// SSE intrinsics +#if defined(__SSE2__) +#if defined(QT_LINUXBASE) +/// this is an evil hack - the posix_memalign declaration in LSB +/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 +# define posix_memalign _lsb_hack_posix_memalign +# include <emmintrin.h> +# undef posix_memalign +#else +# include <emmintrin.h> +#endif + +#define QT_ALWAYS_HAVE_SSE2 +#endif + +// NEON intrinsics +#if defined(QT_HAVE_NEON) +#include <arm_neon.h> +#endif + + +// IWMMXT intrinsics +#if defined(QT_HAVE_IWMMXT) +#include <mmintrin.h> +#if defined(Q_OS_WINCE) +# include "qplatformdefs.h" +#endif +#endif + +#if defined(QT_HAVE_IWMMXT) +#if !defined(__IWMMXT__) && !defined(Q_OS_WINCE) +# include <xmmintrin.h> +#elif defined(Q_OS_WINCE_STD) && defined(_X86_) +# pragma warning(disable: 4391) +# include <xmmintrin.h> +#endif +#endif + +// 3D now intrinsics +#if defined(QT_HAVE_3DNOW) +#include <mm3dnow.h> +#endif + +enum CPUFeatures { + None = 0, + MMX = 0x1, + MMXEXT = 0x2, + MMX3DNOW = 0x4, + MMX3DNOWEXT = 0x8, + SSE = 0x10, + SSE2 = 0x20, + CMOV = 0x40, + IWMMXT = 0x80, + NEON = 0x100 +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +Q_CORE_EXPORT uint qDetectCPUFeatures(); + +#endif // QSIMD_P_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ac1bee7..e9b7b9a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -46,6 +46,7 @@ #include <qtextcodec.h> #endif #include <private/qutfcodec_p.h> +#include "qsimd_p.h" #include <qdatastream.h> #include <qlist.h> #include "qlocale.h" @@ -3479,12 +3480,82 @@ static QByteArray toLatin1_helper(const QChar *data, int length) QByteArray ba; if (length) { ba.resize(length); - const ushort *i = reinterpret_cast<const ushort *>(data); - const ushort *e = i + length; - uchar *s = (uchar*) ba.data(); - while (i != e) { - *s++ = (*i>0xff) ? '?' : (uchar) *i; - ++i; + const ushort *src = reinterpret_cast<const ushort *>(data); + uchar *dst = (uchar*) ba.data(); +#if defined(QT_ALWAYS_HAVE_SSE2) + if (length >= 16) { + const int chunkCount = length >> 4; // divided by 16 + const __m128i questionMark = _mm_set1_epi16('?'); + // SSE has no compare instruction for unsigned comparison. + // The variables must be shiffted + 0x8000 to be compared + const __m128i signedBitOffset = _mm_set1_epi16(0x8000); + const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000); + for (int i = 0; i < chunkCount; ++i) { + __m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load + src += 8; + { + // each 16 bit is equal to 0xFF if the source is outside latin 1 (>0xff) + const __m128i signedChunk = _mm_add_epi16(chunk1, signedBitOffset); + const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask); + + // offLimitQuestionMark contains '?' for each 16 bits that was off-limit + // the 16 bits that were correct contains zeros + const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark); + + // correctBytes contains the bytes that were in limit + // the 16 bits that were off limits contains zeros + const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk1); + + // merge offLimitQuestionMark and correctBytes to have the result + chunk1 = _mm_or_si128(correctBytes, offLimitQuestionMark); + } + + __m128i chunk2 = _mm_loadu_si128((__m128i*)src); // load + src += 8; + { + // exactly the same operations as for the previous chunk of data + const __m128i signedChunk = _mm_add_epi16(chunk2, signedBitOffset); + const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask); + const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark); + const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk2); + chunk2 = _mm_or_si128(correctBytes, offLimitQuestionMark); + } + + // pack the two vector to 16 x 8bits elements + const __m128i result = _mm_packus_epi16(chunk1, chunk2); + + _mm_storeu_si128((__m128i*)dst, result); // store + dst += 16; + } + length = length % 16; + } +#elif QT_HAVE_NEON + // Refer to the documentation of the SSE2 implementation + // this use eactly the same method as for SSE except: + // 1) neon has unsigned comparison + // 2) packing is done to 64 bits (8 x 8bits component). + if (length >= 16) { + const int chunkCount = length >> 3; // divided by 8 + const uint16x8_t questionMark = vdupq_n_u16('?'); // set + const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set + for (int i = 0; i < chunkCount; ++i) { + uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load + src += 8; + + const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask + const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark + const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk + chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark + const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing + vst1_u8(dst, result); // store + dst += 8; + } + length = length % 8; + } +#endif + while (length--) { + *dst++ = (*src>0xff) ? '?' : (uchar) *src; + ++src; } } return ba; @@ -3647,10 +3718,35 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size) d->alloc = d->size = size; d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; d->data = d->array; - ushort *i = d->data; d->array[size] = '\0'; + ushort *dst = d->data; + /* SIMD: + * Unpacking with SSE has been shown to improve performance on recent CPUs + * The same method gives no improvement with NEON. + */ +#if defined(QT_ALWAYS_HAVE_SSE2) + if (size >= 16) { + int chunkCount = size >> 4; // divided by 16 + const __m128i nullMask = _mm_set1_epi32(0); + for (int i = 0; i < chunkCount; ++i) { + const __m128i chunk = _mm_loadu_si128((__m128i*)str); // load + str += 16; + + // unpack the first 8 bytes, padding with zeros + const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask); + _mm_storeu_si128((__m128i*)dst, firstHalf); // store + dst += 8; + + // unpack the last 8 bytes, padding with zeros + const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask); + _mm_storeu_si128((__m128i*)dst, secondHalf); // store + dst += 8; + } + size = size % 16; + } +#endif while (size--) - *i++ = (uchar)*str++; + *dst++ = (uchar)*str++; } return d; } diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 8de3c7d..a59c0bd 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -73,6 +73,16 @@ typedef std::basic_string<wchar_t> QStdWString; #error qstring.h must be included before any header file that defines truncate #endif +#if defined(Q_CC_GNU) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0) +//There is a bug in GCC 4.0 that tries to instantiate template of annonymous enum +# ifdef QT_USE_FAST_OPERATOR_PLUS +# undef QT_USE_FAST_OPERATOR_PLUS +# endif +# ifdef QT_USE_FAST_CONCATENATION +# undef QT_USE_FAST_CONCATENATION +# endif +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 74661c2..0c3ba06 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -100,14 +100,18 @@ public: operator QString() const { - QString s(QConcatenable< QStringBuilder<A, B> >::size(*this), - Qt::Uninitialized); + const uint size = QConcatenable< QStringBuilder<A, B> >::size(*this); + QString s(size, Qt::Uninitialized); QChar *d = s.data(); + const QChar * const start = d; QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d); - // this resize is necessary since we allocate a bit too much - // when dealing with variable sized 8-bit encodings - s.resize(d - s.data()); + + if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(size) != d - start) { + // this resize is necessary since we allocate a bit too much + // when dealing with variable sized 8-bit encodings + s.resize(d - start); + } return s; } QByteArray toLatin1() const { return QString(*this).toLatin1(); } @@ -116,10 +120,24 @@ public: const B &b; }; +template <> +class QStringBuilder <QString, QString> +{ + public: + QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {} + + operator QString() const + { QString r(a); r += b; return r; } + QByteArray toLatin1() const { return QString(*this).toLatin1(); } + + const QString &a; + const QString &b; +}; template <> struct QConcatenable<char> : private QAbstractConcatenable { typedef char type; + enum { ExactSize = true }; static int size(const char) { return 1; } static inline void appendTo(const char c, QChar *&out) { @@ -130,6 +148,7 @@ template <> struct QConcatenable<char> : private QAbstractConcatenable template <> struct QConcatenable<QLatin1Char> { typedef QLatin1Char type; + enum { ExactSize = true }; static int size(const QLatin1Char) { return 1; } static inline void appendTo(const QLatin1Char c, QChar *&out) { @@ -140,6 +159,7 @@ template <> struct QConcatenable<QLatin1Char> template <> struct QConcatenable<QChar> { typedef QChar type; + enum { ExactSize = true }; static int size(const QChar) { return 1; } static inline void appendTo(const QChar c, QChar *&out) { @@ -150,6 +170,7 @@ template <> struct QConcatenable<QChar> template <> struct QConcatenable<QCharRef> { typedef QCharRef type; + enum { ExactSize = true }; static int size(const QCharRef &) { return 1; } static inline void appendTo(const QCharRef &c, QChar *&out) { @@ -160,6 +181,7 @@ template <> struct QConcatenable<QCharRef> template <> struct QConcatenable<QLatin1String> { typedef QLatin1String type; + enum { ExactSize = true }; static int size(const QLatin1String &a) { return qstrlen(a.latin1()); } static inline void appendTo(const QLatin1String &a, QChar *&out) { @@ -172,6 +194,7 @@ template <> struct QConcatenable<QLatin1String> template <> struct QConcatenable<QLatin1Literal> { typedef QLatin1Literal type; + enum { ExactSize = true }; static int size(const QLatin1Literal &a) { return a.size(); } static inline void appendTo(const QLatin1Literal &a, QChar *&out) { @@ -183,6 +206,7 @@ template <> struct QConcatenable<QLatin1Literal> template <> struct QConcatenable<QString> { typedef QString type; + enum { ExactSize = true }; static int size(const QString &a) { return a.size(); } static inline void appendTo(const QString &a, QChar *&out) { @@ -195,6 +219,7 @@ template <> struct QConcatenable<QString> template <> struct QConcatenable<QStringRef> { typedef QStringRef type; + enum { ExactSize = true }; static int size(const QStringRef &a) { return a.size(); } static inline void appendTo(QStringRef a, QChar *&out) { @@ -208,6 +233,7 @@ template <> struct QConcatenable<QStringRef> template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable { typedef char type[N]; + enum { ExactSize = false }; static int size(const char[N]) { return N - 1; @@ -221,6 +247,7 @@ template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable { typedef const char type[N]; + enum { ExactSize = false }; static int size(const char[N]) { return N - 1; } static inline void appendTo(const char a[N], QChar *&out) { @@ -231,6 +258,7 @@ template <int N> struct QConcatenable<const char[N]> : private QAbstractConcaten template <> struct QConcatenable<const char *> : private QAbstractConcatenable { typedef char const *type; + enum { ExactSize = false }; static int size(const char *a) { return qstrlen(a); } static inline void appendTo(const char *a, QChar *&out) { @@ -241,6 +269,7 @@ template <> struct QConcatenable<const char *> : private QAbstractConcatenable template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable { typedef QByteArray type; + enum { ExactSize = false }; static int size(const QByteArray &ba) { return qstrnlen(ba.constData(), ba.size()); } static inline void appendTo(const QByteArray &ba, QChar *&out) { @@ -253,6 +282,7 @@ template <typename A, typename B> struct QConcatenable< QStringBuilder<A, B> > { typedef QStringBuilder<A, B> type; + enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize }; static int size(const type &p) { return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b); diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 3406e41..6d64915 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -33,6 +33,7 @@ HEADERS += \ tools/qsharedpointer.h \ tools/qsharedpointer_impl.h \ tools/qset.h \ + tools/qsimd_p.h \ tools/qsize.h \ tools/qstack.h \ tools/qstring.h \ @@ -68,6 +69,7 @@ SOURCES += \ tools/qregexp.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ + tools/qsimd.cpp \ tools/qsize.cpp \ tools/qstring.cpp \ tools/qstringbuilder.cpp \ |