summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.cpp22
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.h3
-rw-r--r--src/corelib/global/qglobal.cpp15
-rw-r--r--src/corelib/global/qglobal.h87
-rw-r--r--src/corelib/global/qlibraryinfo.cpp9
-rw-r--r--src/corelib/global/qlibraryinfo.h1
-rw-r--r--src/corelib/io/qtldurl.cpp34
-rw-r--r--src/corelib/io/qtldurl_p.h34
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp101
-rw-r--r--src/corelib/kernel/qeventloop.cpp66
-rw-r--r--src/corelib/kernel/qobject.cpp130
-rw-r--r--src/corelib/tools/qbytearray.h20
-rw-r--r--src/corelib/tools/qchar.cpp4
-rw-r--r--src/corelib/tools/qchar.h19
-rw-r--r--src/corelib/tools/qlist.cpp2
-rw-r--r--src/corelib/tools/qrefcount.cpp51
-rw-r--r--src/corelib/tools/qrefcount.h92
-rw-r--r--src/corelib/tools/qstring.cpp519
-rw-r--r--src/corelib/tools/qstring.h172
-rw-r--r--src/corelib/tools/qstringbuilder.cpp49
-rw-r--r--src/corelib/tools/qstringbuilder.h55
-rw-r--r--src/corelib/tools/qstringlist.h2
-rw-r--r--src/corelib/tools/tools.pri2
23 files changed, 797 insertions, 692 deletions
diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp
index 933ad3c264..237152c0d3 100644
--- a/src/corelib/concurrent/qtconcurrentexception.cpp
+++ b/src/corelib/concurrent/qtconcurrentexception.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qtconcurrentexception.h"
+#include "QtCore/qshareddata.h"
#ifndef QT_NO_QFUTURE
#ifndef QT_NO_EXCEPTIONS
@@ -141,15 +142,14 @@ Exception *UnhandledException::clone() const
namespace internal {
-class Base
+class Base : public QSharedData
{
public:
Base(Exception *exception)
- : exception(exception), refCount(1), hasThrown(false) { }
+ : exception(exception), hasThrown(false) { }
~Base() { delete exception; }
Exception *exception;
- QAtomicInt refCount;
bool hasThrown;
};
@@ -158,27 +158,15 @@ ExceptionHolder::ExceptionHolder(Exception *exception)
ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
: base(other.base)
-{
- base->refCount.ref();
-}
+{}
void ExceptionHolder::operator=(const ExceptionHolder &other)
{
- if (base == other.base)
- return;
-
- if (base->refCount.deref() == false)
- delete base;
-
base = other.base;
- base->refCount.ref();
}
ExceptionHolder::~ExceptionHolder()
-{
- if (base->refCount.deref() == 0)
- delete base;
-}
+{}
Exception *ExceptionHolder::exception() const
{
diff --git a/src/corelib/concurrent/qtconcurrentexception.h b/src/corelib/concurrent/qtconcurrentexception.h
index b58b3ba23a..1c100a5206 100644
--- a/src/corelib/concurrent/qtconcurrentexception.h
+++ b/src/corelib/concurrent/qtconcurrentexception.h
@@ -47,6 +47,7 @@
#ifndef QT_NO_QFUTURE
#include <QtCore/qatomic.h>
+#include <QtCore/qshareddata.h>
#ifndef QT_NO_EXCEPTIONS
# include <exception>
@@ -87,7 +88,7 @@ public:
void operator=(const ExceptionHolder &other);
~ExceptionHolder();
Exception *exception() const;
- Base *base;
+ QExplicitlySharedDataPointer<Base> base;
};
class Q_CORE_EXPORT ExceptionStore
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index ca8b30fc00..bbc9a15e74 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1642,6 +1642,21 @@ bool qSharedBuild()
\sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS
*/
+/*!
+ \macro QT_DISABLE_DEPRECATED_BEFORE
+ \relates <QtGlobal>
+
+ This macro can be defined in the project file to disable functions deprecated in
+ a specified version of Qt or any earlier version. The default version number is 5.0,
+ meaning that functions deprecated in or before Qt 5.0 will not be included.
+
+ Examples:
+ When using a future release of Qt 5, set QT_DISABLE_DEPRECATED_BEFORE=0x050100 to
+ disable functions deprecated in Qt 5.1 and earlier. In any release, set
+ QT_DISABLE_DEPRECATED_BEFORE=0x000000 to enable any functions, including the ones
+ deprecated in Qt 5.0
+ */
+
#if defined(QT_BUILD_QMAKE)
// needed to bootstrap qmake
static const unsigned int qt_one = 1;
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index af9d86c2ca..844fe0528e 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -54,6 +54,23 @@
*/
#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+#ifndef QT_DISABLE_DEPRECATED_BEFORE
+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0)
+#endif
+
+/*
+ QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than
+ the deprecation point specified.
+
+ Use it to specify from which version of Qt a function or class has been deprecated
+
+ Example:
+ #if QT_DEPRECATED_SINCE(5,1)
+ QT_DEPRECATED void deprecatedFunction(); //function deprecated sine Qt 5.1
+ #endif
+ */
+#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_BEFORE)
+
#define QT_PACKAGEDATE_STR "YYYY-MM-DD"
#define QT_PACKAGE_TAG ""
@@ -516,6 +533,7 @@ namespace QT_NAMESPACE {}
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
/* C++0x features supported in GCC 4.4: */
+# define Q_COMPILER_UNICODE_STRINGS
# define Q_COMPILER_VARIADIC_TEMPLATES
# define Q_COMPILER_AUTO_TYPE
# define Q_COMPILER_EXTERN_TEMPLATES
@@ -526,8 +544,12 @@ namespace QT_NAMESPACE {}
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
/* C++0x features supported in GCC 4.5: */
# define Q_COMPILER_LAMBDA
-# define Q_COMPILER_UNICODE_STRINGS
# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+ /* C++0x features supported in GCC 4.6: */
+# define Q_COMPILER_CONSTEXPR
+# endif
+
# endif
/* IBM compiler versions are a bit messy. There are actually two products:
@@ -961,6 +983,7 @@ QT_END_INCLUDE_NAMESPACE
#error "Compiler doesn't support the bool type"
#endif
+
/*
Constant bool values
*/
@@ -1091,6 +1114,12 @@ redefine to built-in booleans to make autotests work properly */
# define QT_FASTCALL
#endif
+#ifdef Q_COMPILER_CONSTEXPR
+# define Q_DECL_CONSTEXPR constexpr
+#else
+# define Q_DECL_CONSTEXPR
+#endif
+
//defines the type for the WNDPROC on windows
//the alignment needs to be forced for sse2 to not crash with mingw
#if defined(Q_OS_WIN)
@@ -1104,10 +1133,6 @@ redefine to built-in booleans to make autotests work properly */
typedef int QNoImplicitBoolCast;
-#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A)
-#define QT_NO_FPU
-#endif
-
// This logic must match the one in qmetatype.h
#if defined(QT_COORD_TYPE)
typedef QT_COORD_TYPE qreal;
@@ -1122,25 +1147,25 @@ typedef double qreal;
*/
template <typename T>
-inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
+Q_DECL_CONSTEXPR inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
-inline int qRound(qreal d)
+Q_DECL_CONSTEXPR inline int qRound(qreal d)
{ return d >= qreal(0.0) ? int(d + qreal(0.5)) : int(d - int(d-1) + qreal(0.5)) + int(d-1); }
#if defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
-inline qint64 qRound64(double d)
+Q_DECL_CONSTEXPR inline qint64 qRound64(double d)
{ return d >= 0.0 ? qint64(d + 0.5) : qint64(d - qreal(qint64(d-1)) + 0.5) + qint64(d-1); }
#else
-inline qint64 qRound64(qreal d)
+Q_DECL_CONSTEXPR inline qint64 qRound64(qreal d)
{ return d >= qreal(0.0) ? qint64(d + qreal(0.5)) : qint64(d - qreal(qint64(d-1)) + qreal(0.5)) + qint64(d-1); }
#endif
template <typename T>
-inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; }
+Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
-inline const T &qMax(const T &a, const T &b) { if (a < b) return b; return a; }
+Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
-inline const T &qBound(const T &min, const T &val, const T &max)
+Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max)
{ return qMax(min, qMin(max, val)); }
/*
@@ -1914,12 +1939,12 @@ inline bool operator!=(QBool b1, bool b2) { return !b1 != !b2; }
inline bool operator!=(bool b1, QBool b2) { return !b1 != !b2; }
inline bool operator!=(QBool b1, QBool b2) { return !b1 != !b2; }
-static inline bool qFuzzyCompare(double p1, double p2)
+Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(double p1, double p2)
{
return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2)));
}
-static inline bool qFuzzyCompare(float p1, float p2)
+Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(float p1, float p2)
{
return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
}
@@ -1927,7 +1952,7 @@ static inline bool qFuzzyCompare(float p1, float p2)
/*!
\internal
*/
-static inline bool qFuzzyIsNull(double d)
+Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(double d)
{
return qAbs(d) <= 0.000000000001;
}
@@ -1935,7 +1960,7 @@ static inline bool qFuzzyIsNull(double d)
/*!
\internal
*/
-static inline bool qFuzzyIsNull(float f)
+Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(float f)
{
return qAbs(f) <= 0.00001f;
}
@@ -2203,9 +2228,9 @@ class QFlags
int i;
public:
typedef Enum enum_type;
- inline QFlags(const QFlags &f) : i(f.i) {}
- inline QFlags(Enum f) : i(f) {}
- inline QFlags(Zero = 0) : i(0) {}
+ Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {}
+ Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {}
+ Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {}
inline QFlags(QFlag f) : i(f) {}
inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; }
@@ -2216,18 +2241,18 @@ public:
inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
- inline operator int() const { return i; }
+ Q_DECL_CONSTEXPR inline operator int() const { return i; }
- inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; }
- inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; }
- inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; }
- inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; }
- inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; }
- inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; }
- inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; }
- inline QFlags operator~() const { QFlags g; g.i = ~i; return g; }
+ Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); }
+ Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); }
- inline bool operator!() const { return !i; }
+ Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); }
};
@@ -2240,9 +2265,9 @@ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \
{ return QIncompatibleFlag(int(f1) | f2); }
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
-inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
-inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
{ return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags)
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 5333b71d7b..88f12ab1f7 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -297,11 +297,6 @@ QLibraryInfo::location(LibraryLocation loc)
path = QT_CONFIGURE_EXAMPLES_PATH;
break;
#endif
-#ifdef QT_CONFIGURE_DEMOS_PATH
- case DemosPath:
- path = QT_CONFIGURE_DEMOS_PATH;
- break;
-#endif
default:
break;
}
@@ -352,9 +347,6 @@ QLibraryInfo::location(LibraryLocation loc)
case ExamplesPath:
key = QLatin1String("Examples");
break;
- case DemosPath:
- key = QLatin1String("Demos");
- break;
default:
break;
}
@@ -500,7 +492,6 @@ QLibraryInfo::location(LibraryLocation loc)
\value TranslationsPath The location of translation information for Qt strings.
\value SettingsPath The location for Qt settings.
\value ExamplesPath The location for examples upon install.
- \value DemosPath The location for demos upon install.
\sa location()
*/
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
index 9af53c315c..a8fb90968c 100644
--- a/src/corelib/global/qlibraryinfo.h
+++ b/src/corelib/global/qlibraryinfo.h
@@ -75,7 +75,6 @@ public:
DataPath,
TranslationsPath,
SettingsPath,
- DemosPath,
ExamplesPath,
ImportsPath
};
diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp
index 7db4bbddd5..7d06ca4b17 100644
--- a/src/corelib/io/qtldurl.cpp
+++ b/src/corelib/io/qtldurl.cpp
@@ -7,29 +7,29 @@
** 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.
+** 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
+** 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.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/corelib/io/qtldurl_p.h b/src/corelib/io/qtldurl_p.h
index 152ffa0f63..77c0a15823 100644
--- a/src/corelib/io/qtldurl_p.h
+++ b/src/corelib/io/qtldurl_p.h
@@ -7,29 +7,29 @@
** 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.
+** 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
+** 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.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index c134881f31..d12391914b 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -805,7 +805,16 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
// call overhead.
QObjectPrivate *d = receiver->d_func();
QThreadData *threadData = d->threadData;
- ++threadData->loopLevel;
+
+ // Exception-safety without try/catch
+ struct Incrementer {
+ int &variable;
+ inline Incrementer(int &variable) : variable(variable)
+ { ++variable; }
+ inline ~Incrementer()
+ { --variable; }
+ };
+ Incrementer inc(threadData->loopLevel);
#ifdef QT_JAMBI_BUILD
int deleteWatch = 0;
@@ -816,12 +825,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
#endif
bool returnValue;
- QT_TRY {
- returnValue = notify(receiver, event);
- } QT_CATCH (...) {
- --threadData->loopLevel;
- QT_RETHROW;
- }
+ returnValue = notify(receiver, event);
#ifdef QT_JAMBI_BUILD
// Restore the previous state if the object was not deleted..
@@ -830,7 +834,6 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
}
QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
#endif
- --threadData->loopLevel;
return returnValue;
}
@@ -1373,6 +1376,40 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
data->postEventList.insertionOffset = data->postEventList.size();
+ // Exception-safe cleaning up without the need for a try/catch block
+ struct CleanUp {
+ QObject *receiver;
+ int event_type;
+ QThreadData *data;
+ bool exceptionCaught;
+
+ inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
+ receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
+ {}
+ inline ~CleanUp()
+ {
+ if (exceptionCaught) {
+ // since we were interrupted, we need another pass to make sure we clean everything up
+ data->canWait = false;
+ }
+
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+
+ // clear the global list, i.e. remove everything that was
+ // delivered.
+ if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
+ const QPostEventList::iterator it = data->postEventList.begin();
+ data->postEventList.erase(it, it + data->postEventList.startOffset);
+ data->postEventList.insertionOffset -= data->postEventList.startOffset;
+ Q_ASSERT(data->postEventList.insertionOffset >= 0);
+ data->postEventList.startOffset = 0;
+ }
+ }
+ };
+ CleanUp cleanup(receiver, event_type, data);
+
while (i < data->postEventList.size()) {
// avoid live-lock
if (i >= data->postEventList.insertionOffset)
@@ -1411,7 +1448,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// first, we diddle the event so that we can deliver
// it, and that no one will try to touch it later.
pe.event->posted = false;
- QEvent * e = pe.event;
+ QScopedPointer<QEvent> e(pe.event);
QObject * r = pe.receiver;
--r->d_func()->postedEvents;
@@ -1421,49 +1458,23 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// for the next event.
const_cast<QPostEvent &>(pe).event = 0;
- locker.unlock();
- // after all that work, it's time to deliver the event.
-#ifdef QT_NO_EXCEPTIONS
- QCoreApplication::sendEvent(r, e);
-#else
- try {
- QCoreApplication::sendEvent(r, e);
- } catch (...) {
- delete e;
- locker.relock();
-
- // since we were interrupted, we need another pass to make sure we clean everything up
- data->canWait = false;
-
- // uglehack: copied from below
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
- throw; // rethrow
- }
-#endif
+ struct MutexUnlocker
+ {
+ QMutexLocker &m;
+ MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); }
+ ~MutexUnlocker() { m.relock(); }
+ };
+ MutexUnlocker unlocker(locker);
- delete e;
- locker.relock();
+ // after all that work, it's time to deliver the event.
+ QCoreApplication::sendEvent(r, e.data());
// careful when adding anything below this point - the
// sendEvent() call might invalidate any invariants this
// function depends on.
}
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
-
- // clear the global list, i.e. remove everything that was
- // delivered.
- if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
- const QPostEventList::iterator it = data->postEventList.begin();
- data->postEventList.erase(it, it + data->postEventList.startOffset);
- data->postEventList.insertionOffset -= data->postEventList.startOffset;
- Q_ASSERT(data->postEventList.insertionOffset >= 0);
- data->postEventList.startOffset = 0;
- }
+ cleanup.exceptionCaught = false;
}
/*!
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index 5a4ce973bc..37c06a2093 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -184,49 +184,47 @@ int QEventLoop::exec(ProcessEventsFlags flags)
qWarning("QEventLoop::exec: instance %p has already called exec()", this);
return -1;
}
- d->inExec = true;
- d->exit = false;
- ++d->threadData->loopLevel;
- d->threadData->eventLoops.push(this);
- locker.unlock();
+
+ struct LoopReference {
+ QEventLoopPrivate *d;
+ QMutexLocker &locker;
+
+ bool exceptionCaught;
+ LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
+ {
+ d->inExec = true;
+ d->exit = false;
+ ++d->threadData->loopLevel;
+ d->threadData->eventLoops.push(d->q_func());
+ locker.unlock();
+ }
+
+ ~LoopReference()
+ {
+ if (exceptionCaught) {
+ qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
+ "exceptions from an event handler is not supported in Qt. You must\n"
+ "reimplement QApplication::notify() and catch all exceptions there.\n");
+ }
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+ }
+ };
+ LoopReference ref(d, locker);
// remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
-#if defined(QT_NO_EXCEPTIONS)
while (!d->exit)
processEvents(flags | WaitForMoreEvents | EventLoopExec);
-#else
- try {
- while (!d->exit)
- processEvents(flags | WaitForMoreEvents | EventLoopExec);
- } catch (...) {
- qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
- "exceptions from an event handler is not supported in Qt. You must\n"
- "reimplement QApplication::notify() and catch all exceptions there.\n");
-
- // copied from below
- locker.relock();
- QEventLoop *eventLoop = d->threadData->eventLoops.pop();
- Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
- Q_UNUSED(eventLoop); // --release warning
- d->inExec = false;
- --d->threadData->loopLevel;
-
- throw;
- }
-#endif
-
- // copied above
- locker.relock();
- QEventLoop *eventLoop = d->threadData->eventLoops.pop();
- Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
- Q_UNUSED(eventLoop); // --release warning
- d->inExec = false;
- --d->threadData->loopLevel;
+ ref.exceptionCaught = false;
return d->returnCode;
}
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index d573741654..08236a3fec 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -125,6 +125,39 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
}
}
+struct QConnectionSenderSwitcher {
+ QObject *receiver;
+ QObjectPrivate::Sender *previousSender;
+ QObjectPrivate::Sender currentSender;
+ bool switched;
+
+ inline QConnectionSenderSwitcher() : switched(false) {}
+
+ inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id)
+ {
+ switchSender(receiver, sender, signal_absolute_id);
+ }
+
+ inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id)
+ {
+ this->receiver = receiver;
+ currentSender.sender = sender;
+ currentSender.signal = signal_absolute_id;
+ currentSender.ref = 1;
+ previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ switched = true;
+ }
+
+ inline ~QConnectionSenderSwitcher()
+ {
+ if (switched)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+ }
+private:
+ Q_DISABLE_COPY(QConnectionSenderSwitcher)
+};
+
+
void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
@@ -1084,23 +1117,10 @@ bool QObject::event(QEvent *e)
d_func()->inEventHandler = false;
#endif
QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
- QObjectPrivate::Sender currentSender;
- currentSender.sender = const_cast<QObject*>(mce->sender());
- currentSender.signal = mce->signalId();
- currentSender.ref = 1;
- QObjectPrivate::Sender * const previousSender =
- QObjectPrivate::setCurrentSender(this, &currentSender);
-#if defined(QT_NO_EXCEPTIONS)
+
+ QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId());
+
mce->placeMetaCall(this);
-#else
- QT_TRY {
- mce->placeMetaCall(this);
- } QT_CATCH(...) {
- QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
- QT_RETHROW;
- }
-#endif
- QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
break;
}
@@ -2977,7 +2997,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
type &= Qt::UniqueConnection - 1;
}
- QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
c->sender = s;
c->receiver = r;
c->method_relative = method_index;
@@ -2987,16 +3007,11 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
c->nextConnectionList = 0;
c->callFunction = callFunction;
- QT_TRY {
- QObjectPrivate::get(s)->addConnection(signal_index, c);
- } QT_CATCH(...) {
- delete c;
- QT_RETHROW;
- }
+ QObjectPrivate::get(s)->addConnection(signal_index, c.data());
c->prev = &(QObjectPrivate::get(r)->senders);
c->next = *c->prev;
- *c->prev = c;
+ *c->prev = c.data();
if (c->next)
c->next->prev = &c->next;
@@ -3007,6 +3022,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
}
+ c.take(); // stop tracking
return true;
}
@@ -3265,16 +3281,37 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
Qt::HANDLE currentThreadId = QThread::currentThreadId();
+ {
QMutexLocker locker(signalSlotLock(sender));
- QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
- if (!connectionLists) {
+ struct ConnectionListsRef {
+ QObjectConnectionListVector *connectionLists;
+ ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists)
+ {
+ if (connectionLists)
+ ++connectionLists->inUse;
+ }
+ ~ConnectionListsRef()
+ {
+ if (!connectionLists)
+ return;
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned) {
+ if (!connectionLists->inUse)
+ delete connectionLists;
+ }
+ }
+
+ QObjectConnectionListVector *operator->() const { return connectionLists; }
+ };
+ ConnectionListsRef connectionLists = sender->d_func()->connectionLists;
+ if (!connectionLists.connectionLists) {
locker.unlock();
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
return;
}
- ++connectionLists->inUse;
-
const QObjectPrivate::ConnectionList *list;
if (signal_index < connectionLists->count())
@@ -3324,13 +3361,10 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
#endif
}
- QObjectPrivate::Sender currentSender;
- QObjectPrivate::Sender *previousSender = 0;
+ QConnectionSenderSwitcher sw;
+
if (receiverInSameThread) {
- currentSender.sender = sender;
- currentSender.signal = signal_absolute_index;
- currentSender.ref = 1;
- previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ sw.switchSender(receiver, sender, signal_absolute_index);
}
const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
const int method_relative = c->method_relative;
@@ -3355,23 +3389,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
argv ? argv : empty_argv);
}
-#if defined(QT_NO_EXCEPTIONS)
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
-#else
- QT_TRY {
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
- } QT_CATCH(...) {
- locker.relock();
- if (receiverInSameThread)
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
-
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned && !connectionLists->inUse)
- delete connectionLists;
- QT_RETHROW;
- }
-#endif
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, method);
@@ -3379,9 +3397,6 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
locker.relock();
}
- if (receiverInSameThread)
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
-
if (connectionLists->orphaned)
break;
} while (c != last && (c = c->nextConnectionList) != 0);
@@ -3392,17 +3407,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
//start over for all signals;
((list = &connectionLists->allsignals), true));
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned) {
- if (!connectionLists->inUse)
- delete connectionLists;
- } else if (connectionLists->dirty) {
- sender->d_func()->cleanConnectionLists();
}
- locker.unlock();
-
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 9f54f1a831..26cf2af59c 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -172,15 +172,9 @@ public:
inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
void clear();
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char at(int i) const;
- const char operator[](int i) const;
- const char operator[](uint i) const;
-#else
char at(int i) const;
char operator[](int i) const;
char operator[](uint i) const;
-#endif
QByteRef operator[](int i);
QByteRef operator[](uint i);
@@ -359,21 +353,12 @@ inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); }
inline int QByteArray::size() const
{ return d->size; }
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-inline const char QByteArray::at(int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
-inline const char QByteArray::operator[](int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
-inline const char QByteArray::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data[i]; }
-#else
inline char QByteArray::at(int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
inline char QByteArray::operator[](int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
inline char QByteArray::operator[](uint i) const
{ Q_ASSERT(i < uint(size())); return d->data[i]; }
-#endif
inline bool QByteArray::isEmpty() const
{ return d->size == 0; }
@@ -412,13 +397,8 @@ class Q_CORE_EXPORT QByteRef {
: a(array),i(idx) {}
friend class QByteArray;
public:
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- inline operator const char() const
- { return i < a.d->size ? a.d->data[i] : char(0); }
-#else
inline operator char() const
{ return i < a.d->size ? a.d->data[i] : char(0); }
-#endif
inline QByteRef &operator=(char c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
a.d->data[i] = c; return *this; }
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 9db7d1ae83..475bd55de4 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -1295,11 +1295,7 @@ ushort QChar::toCaseFolded(ushort ucs2)
\sa toLatin1(), unicode(), QTextCodec::codecForCStrings()
*/
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-const char QChar::toAscii() const
-#else
char QChar::toAscii() const
-#endif
{
#ifndef QT_NO_CODEC_FOR_C_STRINGS
if (QTextCodec::codecForCStrings())
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index b7793403bd..d6db72d5ac 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -56,13 +56,8 @@ struct QLatin1Char
{
public:
inline explicit QLatin1Char(char c) : ch(c) {}
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- inline const char toLatin1() const { return ch; }
- inline const ushort unicode() const { return ushort(uchar(ch)); }
-#else
inline char toLatin1() const { return ch; }
inline ushort unicode() const { return ushort(uchar(ch)); }
-#endif
private:
char ch;
@@ -230,20 +225,10 @@ public:
UnicodeVersion unicodeVersion() const;
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char toAscii() const;
- inline const char toLatin1() const;
- inline const ushort unicode() const { return ucs; }
-#else
char toAscii() const;
inline char toLatin1() const;
inline ushort unicode() const { return ucs; }
-#endif
-#ifdef Q_NO_PACKED_REFERENCE
- inline ushort &unicode() { return const_cast<ushort&>(ucs); }
-#else
inline ushort &unicode() { return ucs; }
-#endif
static QChar fromAscii(char c);
static QChar fromLatin1(char c);
@@ -339,11 +324,7 @@ Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE);
inline QChar::QChar() : ucs(0) {}
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
-inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
-#else
inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); }
-#endif
inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); }
inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){}
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 80c610be36..14dfc6a139 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -164,7 +164,7 @@ void **QListData::append(int n)
if (b - n >= 2 * d->alloc / 3) {
// we have enough space. Just not at the end -> move it.
e -= b;
- ::memcpy(d->array, d->array + b, e * sizeof(void *));
+ ::memmove(d->array, d->array + b, e * sizeof(void *));
d->begin = 0;
} else {
realloc(grow(d->alloc + n));
diff --git a/src/corelib/tools/qrefcount.cpp b/src/corelib/tools/qrefcount.cpp
new file mode 100644
index 0000000000..c40214b2ab
--- /dev/null
+++ b/src/corelib/tools/qrefcount.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QtPrivate::RefCount
+ \internal
+
+ QRefCount implements atomic ref counting for Qt's shared classes. It behaves very similar
+ to QAtomicInt, but ignores negative ref counts.
+
+ This can be used to allow to implement e.g. const read-only QStringData objects. QString::shared_null and
+ the qs(...) macro make use of this feature.
+*/
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
new file mode 100644
index 0000000000..9223cfe352
--- /dev/null
+++ b/src/corelib/tools/qrefcount.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREFCOUNT_H
+#define QREFCOUNT_H
+
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtPrivate
+{
+
+class RefCount
+{
+public:
+ inline void ref() {
+ if (atomic >= 0)
+ atomic.ref();
+ }
+
+ inline bool deref() {
+ if (atomic < 0)
+ return true;
+ return atomic.deref();
+ }
+
+ inline bool operator==(int value) const
+ { return atomic.operator ==(value); }
+ inline bool operator!=(int value) const
+ { return atomic.operator !=(value); }
+ inline bool operator!() const
+ { return atomic.operator !(); }
+ inline operator int() const
+ { return atomic.operator int(); }
+ inline RefCount &operator=(int value)
+ { atomic = value; return *this; }
+
+ QBasicAtomicInt atomic;
+};
+
+#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) }
+
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index afb396ce50..dab281cdf8 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -720,6 +720,18 @@ const QString::Null QString::null = { };
\section1 More Efficient String Construction
+ Many strings are known at compile time. But the trivial
+ constructor QString("Hello"), will convert the string literal
+ to a QString using the codecForCStrings(). To avoid this one
+ can use the QStringLiteral macro to directly create the required
+ data at compile time. Constructing a QString out of the literal
+ does then not cause any overhead at runtime.
+
+ A slightly less efficient way is to use QLatin1String. This class wraps
+ a C string literal, precalculates it length at compile time and can
+ then be used for faster comparison with QStrings and conversion to
+ QStrings than a regular C string literal.
+
Using the QString \c{'+'} operator, it is easy to construct a
complex string from multiple substrings. You will often write code
like this:
@@ -735,9 +747,6 @@ const QString::Null QString::null = { };
where \e{n > 2}, there can be as many as \e{n - 1} calls to the
memory allocator.
- Second, QLatin1String does not store its length internally but
- calls qstrlen() when it needs to know its length.
-
In 4.6, an internal template class \c{QStringBuilder} has been
added along with a few helper functions. This class is marked
internal and does not appear in the documentation, because you
@@ -755,12 +764,6 @@ const QString::Null QString::null = { };
then called \e{once} to get the required space, and the substrings
are copied into it one by one.
- \c{QLatin1Literal} is a second internal class that can replace
- QLatin1String, which can't be changed for compatibility reasons.
- \c{QLatin1Literal} stores its length, thereby saving time when
- \c{QStringBuilder} computes the amount of memory required for the
- final string.
-
Additional efficiency is gained by inlining and reduced reference
counting (the QString created from a \c{QStringBuilder} typically
has a ref count of 1, whereas QString::append() needs an extra
@@ -797,10 +800,8 @@ const QString::Null QString::null = { };
\sa split()
*/
-QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_null.array, 0, 0, 0, 0, 0, {0} };
-QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_empty.array, 0, 0, 0, 0, 0, {0} };
+const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
+const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
int QString::grow(int size)
{
@@ -1044,20 +1045,15 @@ int QString::toWCharArray(wchar_t *array) const
QString::QString(const QChar *unicode, int size)
{
if (!unicode) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size <= 0) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- memcpy(d->array, unicode, size * sizeof(QChar));
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ memcpy(d->data(), unicode, size * sizeof(QChar));
+ d->data()[size] = '\0';
}
}
@@ -1073,24 +1069,19 @@ QString::QString(const QChar *unicode, int size)
QString::QString(const QChar *unicode)
{
if (!unicode) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else {
int size = 0;
while (unicode[size] != 0)
++size;
if (!size) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- memcpy(d->array, unicode, size * sizeof(QChar));
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ memcpy(d->data(), unicode, size * sizeof(QChar));
+ d->data()[size] = '\0';
}
}
}
@@ -1105,18 +1096,14 @@ QString::QString(const QChar *unicode)
QString::QString(int size, QChar ch)
{
if (size <= 0) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
- ushort *i = d->array + size;
- ushort *b = d->array;
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[size] = '\0';
+ ushort *i = d->data() + size;
+ ushort *b = d->data();
const ushort value = ch.unicode();
while (i != b)
*--i = value;
@@ -1131,13 +1118,10 @@ QString::QString(int size, QChar ch)
*/
QString::QString(int size, Qt::Initialization)
{
- d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[size] = '\0';
}
/*! \fn QString::QString(const QLatin1String &str)
@@ -1152,15 +1136,11 @@ QString::QString(int size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
- void *buf = qMalloc(sizeof(Data) + sizeof(QChar));
- Q_CHECK_PTR(buf);
- d = reinterpret_cast<Data *>(buf);
- d->ref = 1;
- d->alloc = d->size = 1;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[0] = ch.unicode();
- d->array[1] = '\0';
+ d = (Data *) qMalloc(sizeof(Data) + 2*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ *d = (Data) { Q_REFCOUNT_INITIALIZER(1), 1, 1, false, { 0 } };
+ d->data()[0] = ch.unicode();
+ d->data()[1] = '\0';
}
/*! \fn QString::QString(const QByteArray &ba)
@@ -1256,21 +1236,23 @@ void QString::resize(int size)
if (size < 0)
size = 0;
- if (size == 0 && !d->capacity) {
- Data *x = &shared_empty;
- x->ref.ref();
+ if (d->offset && d->ref == 1 && size < d->size) {
+ d->size = size;
+ return;
+ }
+
+ if (size == 0 && !d->capacityReserved) {
+ Data *x = const_cast<Data *>(&shared_empty.str);
if (!d->ref.deref())
QString::free(d);
d = x;
} else {
if (d->ref != 1 || size > d->alloc ||
- (!d->capacity && size < d->size && size < d->alloc >> 1))
+ (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
realloc(grow(size));
if (d->alloc >= size) {
d->size = size;
- if (d->data == d->array) {
- d->array[size] = '\0';
- }
+ d->data()[size] = '\0';
}
}
}
@@ -1328,28 +1310,21 @@ void QString::resize(int size)
// ### Qt 5: rename reallocData() to avoid confusion. 197625
void QString::realloc(int alloc)
{
- if (d->ref != 1 || d->data != d->array) {
- Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
+ if (d->ref != 1 || d->offset) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(x);
- x->size = qMin(alloc, d->size);
- ::memcpy(x->array, d->data, x->size * sizeof(QChar));
- x->array[x->size] = 0;
- x->ref = 1;
- x->alloc = alloc;
- x->clean = d->clean;
- x->simpletext = d->simpletext;
- x->righttoleft = d->righttoleft;
- x->capacity = d->capacity;
- x->data = x->array;
+ *x = (Data){ Q_REFCOUNT_INITIALIZER(1), qMin(alloc, d->size), alloc, d->capacityReserved, { 0 } };
+ ::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
+ x->data()[x->size] = 0;
if (!d->ref.deref())
QString::free(d);
d = x;
} else {
- Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
+ Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(p);
d = p;
d->alloc = alloc;
- d->data = d->array;
+ d->offset = 0;
}
}
@@ -1363,8 +1338,8 @@ void QString::expand(int i)
int sz = d->size;
resize(qMax(i + 1, sz));
if (d->size - 1 > sz) {
- ushort *n = d->data + d->size - 1;
- ushort *e = d->data + sz;
+ ushort *n = d->data() + d->size - 1;
+ ushort *e = d->data() + sz;
while (n != e)
* --n = ' ';
}
@@ -1482,9 +1457,9 @@ QString &QString::insert(int i, const QLatin1String &str)
int len = qstrlen(str.latin1());
expand(qMax(d->size, i) + len - 1);
- ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar));
+ ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar));
for (int j = 0; j < len; ++j)
- d->data[i + j] = s[j];
+ d->data()[i + j] = s[j];
return *this;
}
@@ -1501,7 +1476,7 @@ QString& QString::insert(int i, const QChar *unicode, int size)
return *this;
const ushort *s = (const ushort *)unicode;
- if (s >= d->data && s < d->data + d->alloc) {
+ if (s >= d->data() && s < d->data() + d->alloc) {
// Part of me - take a copy
ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar)));
Q_CHECK_PTR(tmp);
@@ -1513,8 +1488,8 @@ QString& QString::insert(int i, const QChar *unicode, int size)
expand(qMax(d->size, i) + size - 1);
- ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar));
- memcpy(d->data + i, s, size * sizeof(QChar));
+ ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar));
+ memcpy(d->data() + i, s, size * sizeof(QChar));
return *this;
}
@@ -1532,8 +1507,8 @@ QString& QString::insert(int i, QChar ch)
if (i < 0)
return *this;
expand(qMax(i, d->size));
- ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar));
- d->data[i] = ch.unicode();
+ ::memmove(d->data() + i + 1, d->data() + i, (d->size - i) * sizeof(QChar));
+ d->data()[i] = ch.unicode();
return *this;
}
@@ -1557,15 +1532,15 @@ QString& QString::insert(int i, QChar ch)
*/
QString &QString::append(const QString &str)
{
- if (str.d != &shared_null) {
- if (d == &shared_null) {
+ if (str.d != &shared_null.str) {
+ if (d == &shared_null.str) {
operator=(str);
} else {
if (d->ref != 1 || d->size + str.d->size > d->alloc)
realloc(grow(d->size + str.d->size));
- memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar));
+ memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
d->size += str.d->size;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
}
}
return *this;
@@ -1583,7 +1558,7 @@ QString &QString::append(const QLatin1String &str)
int len = qstrlen((char *)s);
if (d->ref != 1 || d->size + len > d->alloc)
realloc(grow(d->size + len));
- ushort *i = d->data + d->size;
+ ushort *i = d->data() + d->size;
while ((*i++ = *s++))
;
d->size += len;
@@ -1626,8 +1601,8 @@ QString &QString::append(QChar ch)
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(grow(d->size + 1));
- d->data[d->size++] = ch.unicode();
- d->data[d->size] = '\0';
+ d->data()[d->size++] = ch.unicode();
+ d->data()[d->size] = '\0';
return *this;
}
@@ -1707,7 +1682,7 @@ QString &QString::remove(int pos, int len)
resize(pos); // truncate
} else if (len > 0) {
detach();
- memmove(d->data + pos, d->data + pos + len,
+ memmove(d->data() + pos, d->data() + pos + len,
(d->size - pos - len + 1) * sizeof(ushort));
d->size -= len;
}
@@ -1756,14 +1731,14 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
ushort c = ch.unicode();
if (cs == Qt::CaseSensitive) {
while (i < d->size)
- if (d->data[i] == ch)
+ if (d->data()[i] == ch)
remove(i, 1);
else
i++;
} else {
c = foldCase(c);
while (i < d->size)
- if (foldCase(d->data[i]) == c)
+ if (foldCase(d->data()[i]) == c)
remove(i, 1);
else
i++;
@@ -1859,10 +1834,10 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS
*/
void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen)
{
- // copy *after in case it lies inside our own d->data area
+ // copy *after in case it lies inside our own d->data() area
// (which we could possibly invalidate via a realloc or corrupt via memcpy operations.)
QChar *afterBuffer = const_cast<QChar *>(after);
- if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) {
+ if (after >= reinterpret_cast<QChar *>(d->data()) && after < reinterpret_cast<QChar *>(d->data()) + d->size) {
afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar)));
Q_CHECK_PTR(afterBuffer);
::memcpy(afterBuffer, after, alen*sizeof(QChar));
@@ -1873,30 +1848,30 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
// replace in place
detach();
for (int i = 0; i < nIndices; ++i)
- memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar));
+ memcpy(d->data() + indices[i], afterBuffer, alen * sizeof(QChar));
} else if (alen < blen) {
// replace from front
detach();
uint to = indices[0];
if (alen)
- memcpy(d->data+to, after, alen*sizeof(QChar));
+ memcpy(d->data()+to, after, alen*sizeof(QChar));
to += alen;
uint movestart = indices[0] + blen;
for (int i = 1; i < nIndices; ++i) {
int msize = indices[i] - movestart;
if (msize > 0) {
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
to += msize;
}
if (alen) {
- memcpy(d->data + to, afterBuffer, alen*sizeof(QChar));
+ memcpy(d->data() + to, afterBuffer, alen*sizeof(QChar));
to += alen;
}
movestart = indices[i] + blen;
}
int msize = d->size - movestart;
if (msize > 0)
- memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
+ memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar));
resize(d->size - nIndices*(blen-alen));
} else {
// replace from back
@@ -1910,9 +1885,9 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
int movestart = indices[nIndices] + blen;
int insertstart = indices[nIndices] + nIndices*(alen-blen);
int moveto = insertstart + alen;
- memmove(d->data + moveto, d->data + movestart,
+ memmove(d->data() + moveto, d->data() + movestart,
(moveend - movestart)*sizeof(QChar));
- memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar));
+ memcpy(d->data() + insertstart, afterBuffer, alen*sizeof(QChar));
moveend = movestart-blen;
}
}
@@ -1994,7 +1969,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
return remove(ch, cs);
if (after.d->size == 1)
- return replace(ch, after.d->data[0], cs);
+ return replace(ch, after.d->data()[0], cs);
if (d->size == 0)
return *this;
@@ -2007,13 +1982,13 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
uint pos = 0;
if (cs == Qt::CaseSensitive) {
while (pos < 1023 && index < d->size) {
- if (d->data[index] == cc)
+ if (d->data()[index] == cc)
indices[pos++] = index;
index++;
}
} else {
while (pos < 1023 && index < d->size) {
- if (QChar::toCaseFolded(d->data[index]) == cc)
+ if (QChar::toCaseFolded(d->data()[index]) == cc)
indices[pos++] = index;
index++;
}
@@ -2045,7 +2020,7 @@ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
ushort b = before.unicode();
if (d->size) {
detach();
- ushort *i = d->data;
+ ushort *i = d->data();
const ushort *e = i + d->size;
if (cs == Qt::CaseSensitive) {
for (; i != e; ++i)
@@ -2104,7 +2079,7 @@ QString &QString::replace(const QLatin1String &before,
const QString &after,
Qt::CaseSensitivity cs)
{
- int blen = qstrlen(before.latin1());
+ int blen = before.size();
QVarLengthArray<ushort> b(blen);
for (int i = 0; i < blen; ++i)
b[i] = (uchar)before.latin1()[i];
@@ -2127,7 +2102,7 @@ QString &QString::replace(const QString &before,
const QLatin1String &after,
Qt::CaseSensitivity cs)
{
- int alen = qstrlen(after.latin1());
+ int alen = after.size();
QVarLengthArray<ushort> a(alen);
for (int i = 0; i < alen; ++i)
a[i] = (uchar)after.latin1()[i];
@@ -2148,7 +2123,7 @@ QString &QString::replace(const QString &before,
*/
QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs)
{
- int alen = qstrlen(after.latin1());
+ int alen = after.size();
QVarLengthArray<ushort> a(alen);
for (int i = 0; i < alen; ++i)
a[i] = (uchar)after.latin1()[i];
@@ -2170,7 +2145,7 @@ bool QString::operator==(const QString &other) const
if (d->size != other.d->size)
return false;
- return qMemEquals(d->data, other.d->data, d->size);
+ return qMemEquals(d->data(), other.d->data(), d->size);
}
/*!
@@ -2178,20 +2153,23 @@ bool QString::operator==(const QString &other) const
*/
bool QString::operator==(const QLatin1String &other) const
{
- const ushort *uc = d->data;
- const ushort *e = uc + d->size;
- const uchar *c = (uchar *)other.latin1();
+ if (d->size != other.size())
+ return false;
- if (!c)
+ if (!other.size())
return isEmpty();
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();
+ const ushort *e = uc + d->size;
+ const uchar *c = (uchar *)other.latin1();
+
+ while (uc < e) {
+ if (*uc != *c)
return false;
++uc;
++c;
}
- return (uc == e);
+ return true;
}
/*! \fn bool QString::operator==(const QByteArray &other) const
@@ -2240,20 +2218,20 @@ bool QString::operator<(const QString &other) const
*/
bool QString::operator<(const QLatin1String &other) const
{
- const ushort *uc = d->data;
- const ushort *e = uc + d->size;
const uchar *c = (uchar *) other.latin1();
-
if (!c || *c == 0)
return false;
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();
+ const ushort *e = uc + qMin(d->size, other.size());
+
+ while (uc < e) {
+ if (*uc != *c)
break;
++uc;
++c;
}
- return (uc == e ? *c : *uc < *c);
+ return (uc == (d->data() + d->size) ? *c : *uc < *c);
}
/*! \fn bool QString::operator<(const QByteArray &other) const
@@ -2342,20 +2320,20 @@ bool QString::operator<(const QLatin1String &other) const
*/
bool QString::operator>(const QLatin1String &other) const
{
- const ushort *uc = d->data;;
- const ushort *e = uc + d->size;
const uchar *c = (uchar *) other.latin1();
-
if (!c || *c == '\0')
return !isEmpty();
- while (*c) {
- if (uc == e || *uc != *c)
+ const ushort *uc = d->data();;
+ const ushort *e = uc + qMin(d->size, other.size());
+
+ while (uc < e) {
+ if (*uc != *c)
break;
++uc;
++c;
}
- return (uc == e ? false : *uc > *c);
+ return (uc == (d->data() + d->size) ? false : *uc > *c);
}
/*! \fn bool QString::operator>(const QByteArray &other) const
@@ -2687,7 +2665,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c
{
const int sl = str.d->size;
if (sl == 1)
- return lastIndexOf(QChar(str.d->data[0]), from, cs);
+ return lastIndexOf(QChar(str.d->data()[0]), from, cs);
const int l = d->size;
if (from < 0)
@@ -2700,7 +2678,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c
if (from > delta)
from = delta;
- return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs);
+ return lastIndexOfHelper(d->data(), from, str.d->data(), str.d->size, cs);
}
/*!
@@ -2724,7 +2702,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c
*/
int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const
{
- const int sl = qstrlen(str.latin1());
+ const int sl = str.size();
if (sl == 1)
return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
@@ -2743,7 +2721,7 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity
for (int i = 0; i < sl; ++i)
s[i] = str.latin1()[i];
- return lastIndexOfHelper(d->data, from, s.data(), sl, cs);
+ return lastIndexOfHelper(d->data(), from, s.data(), sl, cs);
}
/*!
@@ -2789,7 +2767,7 @@ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs
if (from > delta)
from = delta;
- return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()),
+ return lastIndexOfHelper(d->data(), from, reinterpret_cast<const ushort*>(str.unicode()),
str.size(), cs);
}
@@ -2940,14 +2918,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
while (i < pos) {
int copyend = replacements[i].pos;
int size = copyend - copystart;
- memcpy(uc, d->data + copystart, size * sizeof(QChar));
+ memcpy(uc, d->data() + copystart, size * sizeof(QChar));
uc += size;
- memcpy(uc, after.d->data, al * sizeof(QChar));
+ memcpy(uc, after.d->data(), al * sizeof(QChar));
uc += al;
copystart = copyend + replacements[i].length;
i++;
}
- memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar));
+ memcpy(uc, d->data() + copystart, (d->size - copystart) * sizeof(QChar));
newstring.resize(newlen);
*this = newstring;
caretMode = QRegExp::CaretWontMatch;
@@ -3366,7 +3344,7 @@ QString QString::left(int n) const
{
if (n >= d->size || n < 0)
return *this;
- return QString((const QChar*) d->data, n);
+ return QString((const QChar*) d->data(), n);
}
/*!
@@ -3384,7 +3362,7 @@ QString QString::right(int n) const
{
if (n >= d->size || n < 0)
return *this;
- return QString((const QChar*) d->data + d->size - n, n);
+ return QString((const QChar*) d->data() + d->size - n, n);
}
/*!
@@ -3406,7 +3384,7 @@ QString QString::right(int n) const
QString QString::mid(int position, int n) const
{
- if (d == &shared_null || position >= d->size)
+ if (d == &shared_null.str || position >= d->size)
return QString();
if (n < 0)
n = d->size - position;
@@ -3418,7 +3396,7 @@ QString QString::mid(int position, int n) const
n = d->size - position;
if (position == 0 && n == d->size)
return *this;
- return QString((const QChar*) d->data + position, n);
+ return QString((const QChar*) d->data() + position, n);
}
/*!
@@ -3456,8 +3434,8 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const
{
return d->size
&& (cs == Qt::CaseSensitive
- ? d->data[0] == c
- : foldCase(d->data[0]) == foldCase(c.unicode()));
+ ? d->data()[0] == c
+ : foldCase(d->data()[0]) == foldCase(c.unicode()));
}
/*!
@@ -3530,8 +3508,8 @@ bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const
{
return d->size
&& (cs == Qt::CaseSensitive
- ? d->data[d->size - 1] == c
- : foldCase(d->data[d->size - 1]) == foldCase(c.unicode()));
+ ? d->data()[d->size - 1] == c
+ : foldCase(d->data()[d->size - 1]) == foldCase(c.unicode()));
}
/*! \fn const char *QString::ascii() const
@@ -3658,10 +3636,6 @@ QByteArray QString::toLatin1() const
return toLatin1_helper(unicode(), length());
}
-// ### Qt 5: Change the return type of at least toAscii(),
-// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE
-// isn't necessary in the header. See task 177402.
-
/*!
Returns an 8-bit representation of the string as a QByteArray.
@@ -3765,22 +3739,17 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
{
Data *d;
if (!str) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size == 0 || (!*str && size < 0)) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
if (size < 0)
size = qstrlen(str);
- d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + (size+1) * sizeof(QChar)));
Q_CHECK_PTR(d);
- d->ref = 1;
- d->alloc = d->size = size;
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
- d->data = d->array;
- d->array[size] = '\0';
- ushort *dst = d->data;
+ *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
+ d->data()[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.
@@ -3818,11 +3787,9 @@ QString::Data *QString::fromAscii_helper(const char *str, int size)
if (codecForCStrings) {
Data *d;
if (!str) {
- d = &shared_null;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_null.str);
} else if (size == 0 || (!*str && size < 0)) {
- d = &shared_empty;
- d->ref.ref();
+ d = const_cast<Data *>(&shared_empty.str);
} else {
if (size < 0)
size = qstrlen(str);
@@ -3867,7 +3834,7 @@ QString QString::fromLocal8Bit(const char *str, int size)
if (!str)
return QString();
if (size == 0 || (!*str && size < 0))
- return QLatin1String("");
+ return QString(shared_empty);
#if !defined(QT_NO_TEXTCODEC)
if (size < 0)
size = qstrlen(str);
@@ -3995,7 +3962,7 @@ QString& QString::setUnicode(const QChar *unicode, int size)
{
resize(size);
if (unicode && size)
- memcpy(d->data, unicode, size * sizeof(QChar));
+ memcpy(d->data(), unicode, size * sizeof(QChar));
return *this;
}
@@ -4034,7 +4001,7 @@ QString QString::simplified() const
if (d->size == 0)
return *this;
- const QChar * const start = reinterpret_cast<QChar *>(d->data);
+ const QChar * const start = reinterpret_cast<QChar *>(d->data());
const QChar *from = start;
const QChar *fromEnd = start + d->size;
forever {
@@ -4043,8 +4010,7 @@ QString QString::simplified() const
break;
if (++from == fromEnd) {
// All-whitespace string
- shared_empty.ref.ref();
- return QString(&shared_empty, 0);
+ return QString(shared_empty);
}
}
// This loop needs no underflow check, as we already determined that
@@ -4079,7 +4045,7 @@ QString QString::simplified() const
// of already simplified characters - at least one, obviously -
// without a trailing space.
QString result((fromEnd - from) + copyCount, Qt::Uninitialized);
- QChar *to = reinterpret_cast<QChar *>(result.d->data);
+ QChar *to = reinterpret_cast<QChar *>(result.d->data());
::memcpy(to, copyFrom, copyCount * 2);
to += copyCount;
fromEnd--;
@@ -4100,7 +4066,7 @@ QString QString::simplified() const
}
done:
*to++ = ch;
- result.truncate(to - reinterpret_cast<QChar *>(result.d->data));
+ result.truncate(to - reinterpret_cast<QChar *>(result.d->data()));
return result;
}
@@ -4124,7 +4090,7 @@ QString QString::trimmed() const
{
if (d->size == 0)
return *this;
- const QChar *s = (const QChar*)d->data;
+ const QChar *s = (const QChar*)d->data();
if (!s->isSpace() && !s[d->size-1].isSpace())
return *this;
int start = 0;
@@ -4137,8 +4103,7 @@ QString QString::trimmed() const
}
int l = end - start + 1;
if (l <= 0) {
- shared_empty.ref.ref();
- return QString(&shared_empty, 0);
+ return QString(shared_empty);
}
return QString(s + start, l);
}
@@ -4250,8 +4215,8 @@ QString& QString::fill(QChar ch, int size)
{
resize(size < 0 ? d->size : size);
if (d->size) {
- QChar *i = (QChar*)d->data + d->size;
- QChar *b = (QChar*)d->data;
+ QChar *i = (QChar*)d->data() + d->size;
+ QChar *b = (QChar*)d->data();
while (i != b)
*--i = ch;
}
@@ -4597,7 +4562,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const
{
if (cs == Qt::CaseSensitive)
return ucstrcmp(constData(), length(), other.constData(), other.length());
- return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size);
+ return ucstricmp(d->data(), d->data() + d->size, other.d->data(), other.d->data() + other.d->size);
}
/*!
@@ -4828,12 +4793,9 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
const ushort *QString::utf16() const
{
- if (d->data != d->array) {
- QString *that = const_cast<QString*>(this);
- that->realloc(); // ensure '\\0'-termination for ::fromRawData strings
- return that->d->data;
- }
- return d->array;
+ if (d->offset)
+ const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
+ return d->data();
}
/*!
@@ -4862,8 +4824,8 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data, d->data, sizeof(QChar)*len);
- QChar *uc = (QChar*)result.d->data + len;
+ memcpy(result.d->data(), d->data(), sizeof(QChar)*len);
+ QChar *uc = (QChar*)result.d->data() + len;
while (padlen--)
* uc++ = fill;
} else {
@@ -4900,11 +4862,11 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
int padlen = width - len;
if (padlen > 0) {
result.resize(len+padlen);
- QChar *uc = (QChar*)result.d->data;
+ QChar *uc = (QChar*)result.d->data();
while (padlen--)
* uc++ = fill;
if (len)
- memcpy(uc, d->data, sizeof(QChar)*len);
+ memcpy(uc, d->data(), sizeof(QChar)*len);
} else {
if (truncate)
result = left(width);
@@ -4924,7 +4886,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
QString QString::toLower() const
{
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
if (!d->size)
@@ -4939,7 +4901,7 @@ QString QString::toLower() const
}
#endif
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
// this avoids one out of bounds check in the loop
if (QChar(*p).isLowSurrogate())
@@ -4952,17 +4914,17 @@ QString QString::toLower() const
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->lowerCaseDiff || prop->lowerCaseSpecial) {
QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
- ushort *pp = s.d->data + (p - d->data);
+ memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
+ ushort *pp = s.d->data() + (p - d->data());
while (p < e) {
uint c = *p;
if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
c = QChar::surrogateToUcs4(*(p - 1), c);
prop = qGetProp(c);
if (prop->lowerCaseSpecial) {
- int pos = pp - s.d->data;
+ int pos = pp - s.d->data();
s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
- pp = s.d->data + pos;
+ pp = s.d->data() + pos;
const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff;
while (*specialCase)
*pp++ = *specialCase++;
@@ -4971,7 +4933,7 @@ QString QString::toLower() const
}
++p;
}
- s.truncate(pp - s.d->data);
+ s.truncate(pp - s.d->data());
return s;
}
++p;
@@ -4988,11 +4950,11 @@ QString QString::toCaseFolded() const
if (!d->size)
return *this;
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
uint last = 0;
while (p < e) {
@@ -5000,9 +4962,9 @@ QString QString::toCaseFolded() const
if (folded != *p) {
QString s(*this);
s.detach();
- ushort *pp = s.d->data + (p - d->data);
- const ushort *ppe = s.d->data + s.d->size;
- last = pp > s.d->data ? *(pp - 1) : 0;
+ ushort *pp = s.d->data() + (p - d->data());
+ const ushort *ppe = s.d->data() + s.d->size;
+ last = pp > s.d->data() ? *(pp - 1) : 0;
while (pp < ppe) {
*pp = foldCase(*pp, last);
++pp;
@@ -5024,7 +4986,7 @@ QString QString::toCaseFolded() const
QString QString::toUpper() const
{
- const ushort *p = d->data;
+ const ushort *p = d->data();
if (!p)
return *this;
if (!d->size)
@@ -5039,7 +5001,7 @@ QString QString::toUpper() const
}
#endif
- const ushort *e = d->data + d->size;
+ const ushort *e = d->data() + d->size;
// this avoids one out of bounds check in the loop
if (QChar(*p).isLowSurrogate())
@@ -5052,17 +5014,17 @@ QString QString::toUpper() const
const QUnicodeTables::Properties *prop = qGetProp(c);
if (prop->upperCaseDiff || prop->upperCaseSpecial) {
QString s(d->size, Qt::Uninitialized);
- memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort));
- ushort *pp = s.d->data + (p - d->data);
+ memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort));
+ ushort *pp = s.d->data() + (p - d->data());
while (p < e) {
uint c = *p;
if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate())
c = QChar::surrogateToUcs4(*(p - 1), c);
prop = qGetProp(c);
if (prop->upperCaseSpecial) {
- int pos = pp - s.d->data;
+ int pos = pp - s.d->data();
s.resize(s.d->size + SPECIAL_CASE_MAX_LEN);
- pp = s.d->data + pos;
+ pp = s.d->data() + pos;
const ushort *specialCase = specialCaseMap + prop->upperCaseDiff;
while (*specialCase)
*pp++ = *specialCase++;
@@ -5071,7 +5033,7 @@ QString QString::toUpper() const
}
++p;
}
- s.truncate(pp - s.d->data);
+ s.truncate(pp - s.d->data());
return s;
}
++p;
@@ -6196,19 +6158,19 @@ QString QString::repeated(int times) const
if (result.d->alloc != resultSize)
return QString(); // not enough memory
- memcpy(result.d->data, d->data, d->size * sizeof(ushort));
+ memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
int sizeSoFar = d->size;
- ushort *end = result.d->data + sizeSoFar;
+ ushort *end = result.d->data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
- memcpy(end, result.d->data, sizeSoFar * sizeof(ushort));
+ memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort));
end += sizeSoFar;
sizeSoFar <<= 1;
}
- memcpy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort));
- result.d->data[resultSize] = '\0';
+ memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort));
+ result.d->data()[resultSize] = '\0';
result.d->size = resultSize;
return result;
}
@@ -6902,7 +6864,7 @@ QString QString::multiArg(int numArgs, const QString **args) const
{
QString result;
QMap<int, int> numbersUsed;
- const QChar *uc = (const QChar *) d->data;
+ const QChar *uc = (const QChar *) d->data();
const int len = d->size;
const int end = len - 1;
int lastNumber = -1;
@@ -6951,62 +6913,50 @@ QString QString::multiArg(int numArgs, const QString **args) const
return result;
}
-static bool isStringRightToLeft(const ushort *p, const ushort *end)
-{
- bool righttoleft = false;
- while (p < end) {
- switch(QChar::direction(*p))
- {
- case QChar::DirL:
- goto end;
- case QChar::DirR:
- case QChar::DirAL:
- righttoleft = true;
- goto end;
- default:
- break;
- }
- ++p;
- }
- end:
- return righttoleft;
-}
-/*! \internal
- */
-void QString::updateProperties() const
+/*! \fn bool QString::isSimpleText() const
+
+ \internal
+*/
+bool QString::isSimpleText() const
{
- ushort *p = d->data;
- ushort *end = p + d->size;
- d->simpletext = true;
+ const ushort *p = d->data();
+ const ushort * const end = p + d->size;
while (p < end) {
ushort uc = *p;
// sort out regions of complex text formatting
if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
- d->simpletext = false;
+ return false;
}
p++;
}
- d->righttoleft = isStringRightToLeft(d->data, d->data + d->size);
- d->clean = true;
-}
-
-bool QString::isRightToLeft() const
-{
- return isStringRightToLeft(d->data, d->data + d->size);
+ return true;
}
-/*! \fn bool QString::isSimpleText() const
-
- \internal
-*/
-
/*! \fn bool QString::isRightToLeft() const
Returns true if the string is read right to left.
*/
-
+bool QString::isRightToLeft() const
+{
+ const ushort *p = d->data();
+ const ushort * const end = p + d->size;
+ while (p < end) {
+ switch(QChar::direction(*p))
+ {
+ case QChar::DirL:
+ return false;
+ case QChar::DirR:
+ case QChar::DirAL:
+ return true;
+ default:
+ break;
+ }
+ ++p;
+ }
+ return false;
+}
/*! \fn QChar *QString::data()
@@ -7122,17 +7072,13 @@ bool QString::isRightToLeft() const
QString QString::fromRawData(const QChar *unicode, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
+ *x = (Data){ Q_REFCOUNT_INITIALIZER(1), size, 0, false, { 0 } };
Q_CHECK_PTR(x);
if (unicode) {
- x->data = (ushort *)unicode;
+ x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
} else {
- x->data = x->array;
size = 0;
}
- x->ref = 1;
- x->alloc = x->size = size;
- *x->array = '\0';
- x->clean = x->simpletext = x->righttoleft = x->capacity = 0;
return QString(x, 0);
}
@@ -7152,18 +7098,16 @@ QString QString::fromRawData(const QChar *unicode, int size)
*/
QString &QString::setRawData(const QChar *unicode, int size)
{
- if (d->ref != 1 || (d->data == d->array && d->alloc)) {
+ if (d->ref != 1 || d->alloc) {
*this = fromRawData(unicode, size);
} else {
if (unicode) {
- d->data = (ushort *)unicode;
+ d->size = size;
+ d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort));
} else {
- d->data = d->array;
- size = 0;
+ d->offset = 0;
+ d->size = 0;
}
- d->alloc = d->size = size;
- *d->array = '\0';
- d->clean = d->simpletext = d->righttoleft = d->capacity = 0;
}
return *this;
}
@@ -7212,7 +7156,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
\snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6
- \sa QString, QLatin1Char
+ \sa QString, QLatin1Char, QStringLiteral
*/
/*! \fn QLatin1String::QLatin1String(const char *str)
@@ -7526,7 +7470,7 @@ QDataStream &operator>>(QDataStream &in, QString &str)
}
}
} else {
- str = QLatin1String("");
+ str = QString(QLatin1String(""));
}
}
return in;
@@ -8345,7 +8289,7 @@ QStringRef QString::rightRef(int n) const
QStringRef QString::midRef(int position, int n) const
{
- if (d == &shared_null || position >= d->size)
+ if (d == &shared_null.str || position >= d->size)
return QStringRef();
if (n < 0)
n = d->size - position;
@@ -8498,7 +8442,7 @@ int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
*/
int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- const int sl = qstrlen(str.latin1());
+ const int sl = str.size();
if (sl == 1)
return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs);
@@ -8851,7 +8795,7 @@ static inline int qt_find_latin1_string(const QChar *haystack, int size,
int from, Qt::CaseSensitivity cs)
{
const char *latin1 = needle.latin1();
- int len = qstrlen(latin1);
+ int len = needle.size();
QVarLengthArray<ushort> s(len);
for (int i = 0; i < len; ++i)
s[i] = latin1[i];
@@ -8892,7 +8836,7 @@ static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
return !needle.latin1();
if (haystackLen == 0)
return !needle.latin1() || *needle.latin1() == 0;
- const int slen = qstrlen(needle.latin1());
+ const int slen = needle.size();
if (slen > haystackLen)
return false;
const ushort *data = reinterpret_cast<const ushort*>(haystack);
@@ -8943,7 +8887,7 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
return !needle.latin1();
if (haystackLen == 0)
return !needle.latin1() || *needle.latin1() == 0;
- const int slen = qstrlen(needle.latin1());
+ const int slen = needle.size();
int pos = haystackLen - slen;
if (pos < 0)
return false;
@@ -9071,4 +9015,21 @@ QVector<uint> QStringRef::toUcs4() const
return v;
}
+/*!
+ \macro QStringLiteral(str)
+ \relates QString
+
+ The macro generates the data for a QString out of \a str at compile time if the compiler supports it.
+ Creating a QString from it is free in this case, and the generated string data is stored in
+ the read-only segment of the compiled object file.
+
+ Using QStringLiteral instead of a double quoted ascii literal can significantly speed up creation
+ of QString's from data known at compile time.
+
+ If the compiler is c++0x enabled the string \a str can actually contain unicode data.
+
+ For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to
+ QLatin1String.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 154012d132..27948e04ea 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -44,7 +44,7 @@
#include <QtCore/qchar.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qatomic.h>
+#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#ifndef QT_NO_STL
@@ -77,9 +77,86 @@ class QLatin1String;
class QStringRef;
template <typename T> class QVector;
+struct QStringData {
+ QtPrivate::RefCount ref;
+ int size;
+ uint alloc : 31;
+ uint capacityReserved : 1;
+ union {
+ qptrdiff offset; // will always work as we add/subtract from a ushort ptr
+ ushort d[sizeof(qptrdiff)/sizeof(ushort)];
+ };
+ inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
+ inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
+};
+
+template<int N> struct QConstStringData;
+template<int N> struct QConstStringDataPtr
+{
+ const QConstStringData<N> *ptr;
+};
+
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const char16_t data[n];
+};
+#define QT_QSTRING_UNICODE_MARKER u""
+
+#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)
+// wchar_t is 2 bytes
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const wchar_t data[n];
+};
+#define QT_QSTRING_UNICODE_MARKER L""
+
+#else
+template<int n> struct QConstStringData
+{
+ const QStringData str;
+ const ushort data[n];
+};
+#endif
+
+#if defined(QT_QSTRING_UNICODE_MARKER)
+# if defined(Q_COMPILER_LAMBDA)
+# define QStringLiteral(str) ([]() { \
+ enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+ static const QConstStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ return holder; }())
+
+# elif defined(Q_CC_GNU)
+// We need to create a QStringData in the .rodata section of memory
+// and the only way to do that is to create a "static const" variable.
+// To do that, we need the __extension__ {( )} trick which only GCC supports
+
+# define QStringLiteral(str) \
+ __extension__ ({ \
+ enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+ static const QConstStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ holder; })
+# endif
+#endif
+
+#ifndef QStringLiteral
+// no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t
+// fallback, uses QLatin1String as next best options
+
+# define QStringLiteral(str) QLatin1String(str)
+#endif
+
class Q_CORE_EXPORT QString
{
public:
+ typedef QStringData Data;
+
inline QString();
QString(const QChar *unicode, int size); // Qt5: don't cap size < 0
explicit QString(const QChar *unicode); // Qt5: merge with the above
@@ -108,7 +185,7 @@ public:
int capacity() const;
inline void reserve(int size);
- inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;}
+ inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;}
inline const QChar *unicode() const;
inline QChar *data();
@@ -262,8 +339,8 @@ public:
inline QString &operator+=(QChar c) {
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(grow(d->size + 1));
- d->data[d->size++] = c.unicode();
- d->data[d->size] = '\0';
+ d->data()[d->size++] = c.unicode();
+ d->data()[d->size] = '\0';
return *this;
}
@@ -491,15 +568,19 @@ public:
// compatibility
struct Null { };
static const Null null;
- inline QString(const Null &): d(&shared_null) { d->ref.ref(); }
+ inline QString(const Null &): d(const_cast<Data *>(&shared_null.str)) {}
inline QString &operator=(const Null &) { *this = QString(); return *this; }
- inline bool isNull() const { return d == &shared_null; }
+ inline bool isNull() const { return d == &shared_null.str; }
- bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
+ bool isSimpleText() const;
bool isRightToLeft() const;
QString(int size, Qt::Initialization);
+ template <int n>
+ inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
+ template <int N>
+ Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
@@ -511,22 +592,11 @@ private:
QString &operator=(const QByteArray &a);
#endif
- struct Data {
- QBasicAtomicInt ref;
- int alloc, size;
- ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then
- ushort clean : 1;
- ushort simpletext : 1;
- ushort righttoleft : 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;
- static Data shared_empty;
+ static const QConstStringData<1> shared_null;
+ static const QConstStringData<1> shared_empty;
Data *d;
- QString(Data *dd, int /*dummy*/) : d(dd) {}
+ inline QString(Data *dd, int /*dummy*/) : d(dd) {}
+
#ifndef QT_NO_TEXTCODEC
static QTextCodec *codecForCStrings;
#endif
@@ -563,11 +633,11 @@ public:
class Q_CORE_EXPORT QLatin1String
{
public:
- inline explicit QLatin1String(const char *s) : chars(s) {}
- inline QLatin1String &operator=(const QLatin1String &other)
- { chars = other.chars; return *this; }
+ inline explicit QLatin1String(const char *s) : m_size(s ? strlen(s) : 0), m_data(s) {}
- inline const char *latin1() const { return chars; }
+ inline const char *latin1() const { return m_data; }
+ inline int size() const { return m_size; }
+ inline const char *data() const { return m_data; }
inline bool operator==(const QString &s) const
{ return s == *this; }
@@ -595,9 +665,12 @@ public:
inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const
{ return QString::fromAscii(s) <= *this; }
private:
- const char *chars;
+ int m_size;
+ const char *m_data;
};
+// Qt 4.x compatibility
+typedef QLatin1String QLatin1Literal;
inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1()))
@@ -605,23 +678,23 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat
inline int QString::length() const
{ return d->size; }
inline const QChar QString::at(int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; }
inline const QChar QString::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+{ Q_ASSERT(i < uint(size())); return d->data()[i]; }
inline bool QString::isEmpty() const
{ return d->size == 0; }
inline const QChar *QString::unicode() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline const QChar *QString::data() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QChar *QString::data()
-{ detach(); return reinterpret_cast<QChar*>(d->data); }
+{ detach(); return reinterpret_cast<QChar*>(d->data()); }
inline const QChar *QString::constData() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline void QString::detach()
-{ if (d->ref != 1 || d->data != d->array) realloc(); }
+{ if (d->ref != 1 || d->offset) realloc(); }
inline bool QString::isDetached() const
{ return d->ref == 1; }
inline QString &QString::operator=(const QLatin1String &s)
@@ -703,10 +776,10 @@ public:
// all this is not documented: We just say "like QChar" and let it be.
inline operator QChar() const
- { return i < s.d->size ? s.d->data[i] : 0; }
+ { return i < s.d->size ? s.d->data()[i] : 0; }
inline QCharRef &operator=(const QChar &c)
{ if (i >= s.d->size) s.expand(i); else s.detach();
- s.d->data[i] = c.unicode(); return *this; }
+ s.d->data()[i] = c.unicode(); return *this; }
// An operator= for each QChar cast constructors
#ifndef QT_NO_CAST_FROM_ASCII
@@ -756,15 +829,9 @@ public:
inline void setCell(uchar cell);
inline void setRow(uchar row);
-#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
- const char toAscii() const { return QChar(*this).toAscii(); }
- const char toLatin1() const { return QChar(*this).toLatin1(); }
- const ushort unicode() const { return QChar(*this).unicode(); }
-#else
char toAscii() const { return QChar(*this).toAscii(); }
char toLatin1() const { return QChar(*this).toLatin1(); }
ushort unicode() const { return QChar(*this).unicode(); }
-#endif
ushort& unicode() { return s.data()[i].unicode(); }
};
@@ -773,9 +840,9 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); }
inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
-inline QString::QString() : d(&shared_null) { d->ref.ref(); }
+inline QString::QString() : d(const_cast<Data *>(&shared_null.str)) {}
inline QString::~QString() { if (!d->ref.deref()) free(d); }
-inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;}
+inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;}
inline QString &QString::setUtf16(const ushort *autf16, int asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
inline QCharRef QString::operator[](int i)
@@ -783,17 +850,17 @@ inline QCharRef QString::operator[](int i)
inline QCharRef QString::operator[](uint i)
{ return QCharRef(*this, i); }
inline QString::iterator QString::begin()
-{ detach(); return reinterpret_cast<QChar*>(d->data); }
+{ detach(); return reinterpret_cast<QChar*>(d->data()); }
inline QString::const_iterator QString::begin() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QString::const_iterator QString::constBegin() const
-{ return reinterpret_cast<const QChar*>(d->data); }
+{ return reinterpret_cast<const QChar*>(d->data()); }
inline QString::iterator QString::end()
-{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); }
+{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); }
inline QString::const_iterator QString::end() const
-{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
inline QString::const_iterator QString::constEnd() const
-{ return reinterpret_cast<const QChar*>(d->data + d->size); }
+{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return QBool(indexOf(s, 0, cs) != -1); }
inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
@@ -1024,7 +1091,7 @@ public:
inline const QChar *unicode() const {
if (!m_string)
- return reinterpret_cast<const QChar *>(QString::shared_null.data);
+ return reinterpret_cast<const QChar *>(QString::shared_null.str.data());
return m_string->unicode() + m_position;
}
inline const QChar *data() const { return unicode(); }
@@ -1154,7 +1221,6 @@ inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) c
{ return QBool(indexOf(s, 0, cs) != -1); }
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index 1cc7e5d2c3..4c6848498b 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -45,47 +45,6 @@
QT_BEGIN_NAMESPACE
/*!
- \class QLatin1Literal
- \internal
- \reentrant
- \since 4.6
-
- \brief The QLatin1Literal class provides a thin wrapper around string
- literals used in source code.
-
- \ingroup tools
- \ingroup shared
- \ingroup string-processing
-
-
- Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size
- without iterating over the literal.
-
- The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
- to reduce the number of reallocations needed to build up a string from
- smaller chunks.
-
- \sa QStringBuilder, QLatin1String, QString, QStringRef
-*/
-
-/*! \fn int QLatin1Literal::size() const
-
- Returns the number of characters in the literal \e{excluding} the trailing
- NULL char.
-*/
-
-/*! \fn QLatin1Literal::QLatin1Literal(const char str)
-
- Constructs a new literal from the string \a str.
-*/
-
-/*! \fn const char *QLatin1Literal::data() const
-
- Returns a pointer to the first character of the string literal.
- The string literal is terminated by a NUL character.
-*/
-
-/*!
\class QStringBuilder
\internal
\reentrant
@@ -110,7 +69,7 @@ QT_BEGIN_NAMESPACE
The QStringBuilder class is not to be used explicitly in user
code. Instances of the class are created as return values of the
operator%() function, acting on objects of type QString,
- QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef,
+ QLatin1String, QStringRef, QChar, QCharRef,
QLatin1Char, and \c char.
Concatenating strings with operator%() generally yields better
@@ -118,7 +77,7 @@ QT_BEGIN_NAMESPACE
if there are three or more of them, and performs equally well in other
cases.
- \sa QLatin1Literal, QString
+ \sa QLatin1String, QString
*/
/*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b)
@@ -132,7 +91,7 @@ QT_BEGIN_NAMESPACE
takes a QString parameter.
This function is usable with arguments of type \c QString,
- \c QLatin1String, \c QLatin1Literal, \c QStringRef,
+ \c QLatin1String, \c QStringRef,
\c QChar, \c QCharRef, \c QLatin1Char, and \c char.
*/
@@ -145,7 +104,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn operator QStringBuilder::QString() const
- Converts the \c QLatin1Literal into a \c QString object.
+ Converts the \c QLatin1String into a \c QString object.
*/
/*! \internal
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 594ab2f183..6d998b62aa 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -59,22 +59,6 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-// ### Qt 5: merge with QLatin1String
-class QLatin1Literal
-{
-public:
- int size() const { return m_size; }
- const char *data() const { return m_data; }
-
- template <int N>
- QLatin1Literal(const char (&str)[N])
- : m_size(N - 1), m_data(str) {}
-
-private:
- const int m_size;
- const char * const m_data;
-};
-
struct Q_CORE_EXPORT QAbstractConcatenable
{
protected:
@@ -234,31 +218,13 @@ template <> struct QConcatenable<QLatin1String>
typedef QLatin1String type;
typedef QString ConvertTo;
enum { ExactSize = true };
- static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
+ static int size(const QLatin1String &a) { return a.size(); }
static inline void appendTo(const QLatin1String &a, QChar *&out)
{
- for (const char *s = a.latin1(); *s; )
- *out++ = QLatin1Char(*s++);
- }
- static inline void appendTo(const QLatin1String &a, char *&out)
- {
- for (const char *s = a.latin1(); *s; )
- *out++ = *s++;
- }
-};
-
-template <> struct QConcatenable<QLatin1Literal>
-{
- typedef QLatin1Literal type;
- typedef QString ConvertTo;
- enum { ExactSize = true };
- static int size(const QLatin1Literal &a) { return a.size(); }
- static inline void appendTo(const QLatin1Literal &a, QChar *&out)
- {
for (const char *s = a.data(); *s; )
*out++ = QLatin1Char(*s++);
}
- static inline void appendTo(const QLatin1Literal &a, char *&out)
+ static inline void appendTo(const QLatin1String &a, char *&out)
{
for (const char *s = a.data(); *s; )
*out++ = *s++;
@@ -283,6 +249,23 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable
#endif
};
+template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
+{
+ typedef QConstStringDataPtr<N> type;
+ typedef QString ConvertTo;
+ enum { ExactSize = true };
+ static int size(const type &) { return N; }
+ static inline void appendTo(const type &a, QChar *&out)
+ {
+ memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
+ out += N;
+ }
+#ifndef QT_NO_CAST_TO_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out)
+ { convertToAscii(a.ptr->data, N, out); }
+#endif
+};
+
template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
{
typedef QStringRef type;
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index efb7f46c9b..bded94399d 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -68,7 +68,7 @@ public:
inline QStringList(const QStringList &l) : QList<QString>(l) { }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
#ifdef Q_COMPILER_INITIALIZER_LISTS
- inline QStringList(std::initializer_list<QString> args) : QList(args) { }
+ inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
#endif
inline void sort();
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 42cab84cc0..f5b38eb1c0 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -30,6 +30,7 @@ HEADERS += \
tools/qrect.h \
tools/qregexp.h \
tools/qringbuffer_p.h \
+ tools/qrefcount.h \
tools/qscopedpointer.h \
tools/qscopedpointer_p.h \
tools/qscopedvaluerollback.h \
@@ -72,6 +73,7 @@ SOURCES += \
tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
+ tools/qrefcount.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
tools/qsimd.cpp \