summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/codecs/qtextcodec.cpp77
-rw-r--r--src/corelib/codecs/qtextcodec.h3
-rw-r--r--src/corelib/codecs/qtsciicodec_p.h2
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp2
-rw-r--r--src/corelib/global/qfeatures.h5
-rw-r--r--src/corelib/global/qfeatures.txt7
-rw-r--r--src/corelib/global/qglobal.cpp7
-rw-r--r--src/corelib/global/qglobal.h46
-rw-r--r--src/corelib/global/qnamespace.h8
-rw-r--r--src/corelib/io/io.pri3
-rw-r--r--src/corelib/io/qdatastream.h7
-rw-r--r--src/corelib/io/qdebug.h19
-rw-r--r--src/corelib/io/qdir.cpp12
-rw-r--r--src/corelib/io/qdiriterator.cpp4
-rw-r--r--src/corelib/io/qfile.cpp3
-rw-r--r--src/corelib/io/qfileinfo.cpp11
-rw-r--r--src/corelib/io/qfileinfo_p.h145
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp2
-rw-r--r--src/corelib/io/qiodevice.cpp15
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp542
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h189
-rw-r--r--src/corelib/io/qprocess.cpp107
-rw-r--r--src/corelib/io/qprocess.h5
-rw-r--r--src/corelib/io/qprocess_p.h2
-rw-r--r--src/corelib/io/qprocess_unix.cpp48
-rw-r--r--src/corelib/io/qprocess_win.cpp75
-rw-r--r--src/corelib/io/qresource.cpp80
-rw-r--r--src/corelib/io/qsettings.cpp2
-rw-r--r--src/corelib/io/qsettings_p.h2
-rw-r--r--src/corelib/io/qtextstream.cpp18
-rw-r--r--src/corelib/io/qurl.cpp6
-rw-r--r--src/corelib/kernel/kernel.pri9
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp33
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp5
-rw-r--r--src/corelib/kernel/qfunctions_wince.h5
-rw-r--r--src/corelib/kernel/qobject.cpp316
-rw-r--r--src/corelib/kernel/qobject_p.h13
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp4
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp7
-rw-r--r--src/corelib/kernel/qtimer.cpp2
-rw-r--r--src/corelib/kernel/qvariant.cpp168
-rw-r--r--src/corelib/kernel/qvariant.h15
-rw-r--r--src/corelib/kernel/qvariant_p.h43
-rw-r--r--src/corelib/plugin/qplugin.h19
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp2
-rw-r--r--src/corelib/tools/qbytearraymatcher.h2
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp435
-rw-r--r--src/corelib/tools/qcontiguouscache.h424
-rw-r--r--src/corelib/tools/qdumper.cpp1157
-rw-r--r--src/corelib/tools/qeasingcurve.cpp2
-rw-r--r--src/corelib/tools/qhash.cpp7
-rw-r--r--src/corelib/tools/qhash.h5
-rw-r--r--src/corelib/tools/qlocale.cpp13
-rw-r--r--src/corelib/tools/qmap.h2
-rw-r--r--src/corelib/tools/qpoint.cpp13
-rw-r--r--src/corelib/tools/qpoint.h2
-rw-r--r--src/corelib/tools/qrect.cpp2
-rw-r--r--src/corelib/tools/qringbuffer_p.h48
-rw-r--r--src/corelib/tools/qset.h14
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h21
-rw-r--r--src/corelib/tools/qsize.cpp2
-rw-r--r--src/corelib/tools/qsize.h8
-rw-r--r--src/corelib/tools/qstringlist.cpp2
-rw-r--r--src/corelib/tools/qtimeline.cpp4
-rw-r--r--src/corelib/tools/qvector.h170
-rw-r--r--src/corelib/tools/tools.pri3
-rwxr-xr-xsrc/corelib/xml/make-parser.sh4
-rw-r--r--src/corelib/xml/qxmlstream.g4
-rw-r--r--src/corelib/xml/qxmlstream_p.h1
70 files changed, 2563 insertions, 1879 deletions
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 6e8ffa1..51ca43e 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -1508,9 +1508,14 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
/*!
\since 4.4
- Tries to detect the encoding of the provided snippet of HTML in the given byte array, \a ba,
- and returns a QTextCodec instance that is capable of decoding the html to unicode.
- If the codec cannot be detected from the content provided, \a defaultCodec is returned.
+ Tries to detect the encoding of the provided snippet of HTML in
+ the given byte array, \a ba, by checking the BOM (Byte Order Mark)
+ and the content-type meta header and returns a QTextCodec instance
+ that is capable of decoding the html to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForUtfText
*/
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
@@ -1518,15 +1523,8 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
int pos;
QTextCodec *c = 0;
- if (ba.size() > 1 && (((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
- || ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe))) {
- c = QTextCodec::codecForMib(1015); // utf16
- } else if (ba.size() > 2
- && (uchar)ba[0] == 0xef
- && (uchar)ba[1] == 0xbb
- && (uchar)ba[2] == 0xbf) {
- c = QTextCodec::codecForMib(106); // utf-8
- } else {
+ c = QTextCodec::codecForUtfText(ba, c);
+ if (!c) {
QByteArray header = ba.left(512).toLower();
if ((pos = header.indexOf("http-equiv=")) != -1) {
pos = header.indexOf("charset=", pos) + int(strlen("charset="));
@@ -1554,6 +1552,61 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
return codecForHtml(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
}
+/*!
+ \since 4.6
+
+ Tries to detect the encoding of the provided snippet \a ba by
+ using the BOM (Byte Order Mark) and returns a QTextCodec instance
+ that is capable of decoding the text to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForHtml
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec)
+{
+ const uint arraySize = ba.size();
+
+ if (arraySize > 3) {
+ if ((uchar)ba[0] == 0x00
+ && (uchar)ba[1] == 0x00
+ && (uchar)ba[2] == 0xFE
+ && (uchar)ba[3] == 0xFF)
+ return QTextCodec::codecForMib(1018); // utf-32 be
+ else if ((uchar)ba[0] == 0xFF
+ && (uchar)ba[1] == 0xFE
+ && (uchar)ba[2] == 0x00
+ && (uchar)ba[3] == 0x00)
+ return QTextCodec::codecForMib(1019); // utf-32 le
+ }
+
+ if (arraySize < 2)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
+ return QTextCodec::codecForMib(1013); // utf16 be
+ else if ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe)
+ return QTextCodec::codecForMib(1014); // utf16 le
+
+ if (arraySize < 3)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xef
+ && (uchar)ba[1] == 0xbb
+ && (uchar)ba[2] == 0xbf)
+ return QTextCodec::codecForMib(106); // utf-8
+
+ return defaultCodec;
+}
+
+/*!
+ \overload
+
+ If the codec cannot be detected, this overload returns a Latin-1 QTextCodec.
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
+{
+ return codecForUtfText(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+}
+
/*! \internal
\since 4.3
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index e32650f..83097a5 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -82,6 +82,9 @@ public:
static QTextCodec *codecForHtml(const QByteArray &ba);
static QTextCodec *codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec);
+ static QTextCodec *codecForUtfText(const QByteArray &ba);
+ static QTextCodec *codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec);
+
QTextDecoder* makeDecoder() const;
QTextEncoder* makeEncoder() const;
diff --git a/src/corelib/codecs/qtsciicodec_p.h b/src/corelib/codecs/qtsciicodec_p.h
index 8f11e48..425e7fd 100644
--- a/src/corelib/codecs/qtsciicodec_p.h
+++ b/src/corelib/codecs/qtsciicodec_p.h
@@ -88,7 +88,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_CODECS
-class Q_CORE_EXPORT QTsciiCodec : public QTextCodec {
+class QTsciiCodec : public QTextCodec {
public:
~QTsciiCodec();
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp
index ea35e9e..39d7698 100644
--- a/src/corelib/concurrent/qfuturewatcher.cpp
+++ b/src/corelib/concurrent/qfuturewatcher.cpp
@@ -465,7 +465,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
break;
emit q->progressValueChanged(event->index1);
- if (event->text != QString()) // ###
+ if (!event->text.isNull()) // ###
q->progressTextChanged(event->text);
break;
case QFutureCallOutEvent::ProgressRange:
diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h
index 2189723..f11c9df 100644
--- a/src/corelib/global/qfeatures.h
+++ b/src/corelib/global/qfeatures.h
@@ -361,6 +361,11 @@
#define QT_NO_MENU
#endif
+// QNetworkDiskCache
+#if !defined(QT_NO_NETWORKDISKCACHE) && (defined(QT_NO_TEMPORARYFILE))
+#define QT_NO_NETWORKDISKCACHE
+#endif
+
// Phonon::SeekSlider
#if !defined(QT_NO_PHONON_SEEKSLIDER) && (defined(QT_NO_SLIDER))
#define QT_NO_PHONON_SEEKSLIDER
diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt
index 40ccb15..5d63e46 100644
--- a/src/corelib/global/qfeatures.txt
+++ b/src/corelib/global/qfeatures.txt
@@ -1085,6 +1085,13 @@ Requires:
Name: QNetworkInterface
SeeAlso: ???
+Feature: NETWORKDISKCACHE
+Description: Supports a disk cache for network resources
+Section: Networking
+Requires: TEMPORARYFILE
+Name: QNetworkDiskCache
+SeeAlso: ???
+
# Utilities
Feature: COMPLETER
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 8324d05..ce98ec4 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2959,7 +2959,12 @@ bool QInternal::callFunction(InternalFunction func, void **args)
\relates <QtGlobal>
\since 4.4
\threadsafe
- \overload
+
+ Compares the floating point value \a p1 and \a p2 and
+ returns \c true if they are considered equal, otherwise \c false.
+
+ The two numbers are compared in a relative way, where the
+ exactness is stronger the smaller the numbers are.
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 36d87e2..3990c7d 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -44,11 +44,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "4.5.2"
+#define QT_VERSION_STR "4.6.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x040502
+#define QT_VERSION 0x040600
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -747,6 +747,10 @@ namespace QT_NAMESPACE {}
# endif
#elif defined(Q_OS_WINCE)
# define Q_WS_WIN32
+# define Q_WS_WINCE
+# if defined(Q_OS_WINCE_WM)
+# define Q_WS_WINCE_WM
+# endif
#elif defined(Q_OS_OS2)
# define Q_WS_PM
# error "Qt does not work with OS/2 Presentation Manager or Workplace Shell"
@@ -764,10 +768,11 @@ namespace QT_NAMESPACE {}
# endif
#endif
-#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32)
+#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32) || defined(Q_WS_WINCE)
# define Q_WS_WIN
#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -821,17 +826,12 @@ typedef quint64 qulonglong;
sizeof(void *) == sizeof(quintptr)
&& sizeof(void *) == sizeof(qptrdiff)
*/
-template <int> class QUintForSize { private: typedef void Type; };
-template <> class QUintForSize<4> { public: typedef quint32 Type; };
-template <> class QUintForSize<8> { public: typedef quint64 Type; };
-template <typename T> class QUintForType : public QUintForSize<sizeof(T)> { };
-typedef QUintForType<void *>::Type quintptr;
-
-template <int> class QIntForSize { private: typedef void Type; };
-template <> class QIntForSize<4> { public: typedef qint32 Type; };
-template <> class QIntForSize<8> { public: typedef qint64 Type; };
-template <typename T> class QIntForType : public QIntForSize<sizeof(T)> { };
-typedef QIntForType<void *>::Type qptrdiff;
+template <int> struct QIntegerForSize;
+template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
+template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
+template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
+typedef QIntegerForSizeof<void*>::Unsigned quintptr;
+typedef QIntegerForSizeof<void*>::Signed qptrdiff;
/*
Useful type definitions for Qt
@@ -1706,6 +1706,22 @@ static inline bool qFuzzyCompare(float p1, float p2)
return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
}
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(double d)
+{
+ return qAbs(d) <= 0.000000000001;
+}
+
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(float f)
+{
+ return qAbs(f) <= 0.00001f;
+}
+
/*
This function tests a double for a null value. It doesn't
check whether the actual value is 0 or close to 0, but whether
@@ -1837,7 +1853,7 @@ enum { /* TYPEINFO flags */
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
template <> \
-class QTypeInfo<TYPE> \
+class QTypeInfo<TYPE > \
{ \
public: \
enum { \
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index a519f4a..3367581 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -188,6 +188,12 @@ public:
#endif
};
+ enum TileRule {
+ Stretch,
+ Repeat,
+ Round
+ };
+
// Text formatting flags for QPainter::drawText and QLabel.
// The following two enums can be combined to one integer which
// is passed as 'flags' to drawText and qt_format_text.
@@ -497,6 +503,8 @@ public:
AA_NativeWindows = 3,
AA_DontCreateNativeWidgetSiblings = 4,
AA_MacPluginApplication = 5,
+ AA_DontUseNativeMenuBar = 6,
+ AA_MacDontSwapCtrlAndMeta = 7,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 3690d4b..8f37e25 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -10,9 +10,9 @@ HEADERS += \
io/qdiriterator.h \
io/qfile.h \
io/qfileinfo.h \
- io/qfileinfo_p.h \
io/qiodevice.h \
io/qiodevice_p.h \
+ io/qnoncontiguousbytedevice_p.h \
io/qprocess.h \
io/qprocess_p.h \
io/qtextstream.h \
@@ -38,6 +38,7 @@ SOURCES += \
io/qfile.cpp \
io/qfileinfo.cpp \
io/qiodevice.cpp \
+ io/qnoncontiguousbytedevice.cpp \
io/qprocess.cpp \
io/qtextstream.cpp \
io/qtemporaryfile.cpp \
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 4c8295e..ec5780c 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -83,10 +83,11 @@ public:
Qt_4_2 = 8,
Qt_4_3 = 9,
Qt_4_4 = 10,
- Qt_4_5 = 11
-#if QT_VERSION >= 0x040600
+ Qt_4_5 = 11,
+ Qt_4_6 = Qt_4_5
+#if QT_VERSION >= 0x040700
#error Add the datastream version for this Qt version
- , Qt_4_6 = Qt_4_5
+ Qt_4_7 = Qt_4_6
#endif
};
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 8334146..9b0fbe5 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -51,6 +51,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qvector.h>
#include <QtCore/qset.h>
+#include <QtCore/qcontiguouscache.h>
QT_BEGIN_HEADER
@@ -232,6 +233,24 @@ inline QDebug operator<<(QDebug debug, const QSet<T> &set)
return operator<<(debug, set.toList());
}
+#if defined(FORCE_UREF)
+template <class T>
+inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#else
+template <class T>
+inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#endif
+{
+ debug.nospace() << "QContiguousCache(";
+ for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
+ debug << cache[i];
+ if (i != cache.lastIndex())
+ debug << ", ";
+ }
+ debug << ")";
+ return debug.space();
+}
+
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index b7861ba..0dc8a63 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -55,6 +55,8 @@
# include "qresource.h"
#endif
+#include "qvarlengtharray.h"
+
#include "../kernel/qcoreglobaldata_p.h"
#include <stdlib.h>
@@ -2054,11 +2056,13 @@ QString QDir::cleanPath(const QString &path)
QString name = path;
QChar dir_separator = separator();
if(dir_separator != QLatin1Char('/'))
- name.replace(dir_separator, QLatin1Char('/'));
+ name.replace(dir_separator, QLatin1Char('/'));
int used = 0, levels = 0;
const int len = name.length();
- QVector<QChar> out(len);
+ QVarLengthArray<QChar> outVector(len);
+ QChar *out = outVector.data();
+
const QChar *p = name.unicode();
for(int i = 0, last = -1, iwrite = 0; i < len; i++) {
if(p[i] == QLatin1Char('/')) {
@@ -2158,7 +2162,7 @@ QString QDir::cleanPath(const QString &path)
if(used == len)
ret = name;
else
- ret = QString(out.data(), used);
+ ret = QString(out, used);
// Strip away last slash except for root directories
if (ret.endsWith(QLatin1Char('/'))
@@ -2221,7 +2225,7 @@ QStringList QDir::nameFiltersFromString(const QString &nameFilter)
\snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 13
- If the file name contains characters that cannot be part of a valid C++ function name
+ If the file name contains characters that cannot be part of a valid C++ function name
(such as '-'), they have to be replaced by the underscore character ('_').
Note: This macro cannot be used in a namespace. It should be called from
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index b14f436..81bfb27 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -201,8 +201,8 @@ void QDirIteratorPrivate::advance()
QString subDir = it->currentFilePath();
#ifdef Q_OS_WIN
- if (currentFileInfo.isSymLink())
- subDir = currentFileInfo.canonicalFilePath();
+ if (nextFileInfo.isSymLink())
+ subDir = nextFileInfo.canonicalFilePath();
#endif
pushSubDirectory(subDir, it->nameFilters(), it->filters());
}
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index d7da800..04750b0 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -708,6 +708,7 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, tr("Destination file exists"));
return false;
}
+ unsetError();
close();
if(error() == QFile::NoError) {
if (fileEngine()->rename(newName)) {
@@ -849,6 +850,7 @@ QFile::copy(const QString &newName)
d->setError(QFile::CopyError, tr("Destination file exists"));
return false;
}
+ unsetError();
close();
if(error() == QFile::NoError) {
if(fileEngine()->copy(newName)) {
@@ -908,6 +910,7 @@ QFile::copy(const QString &newName)
out.setAutoRemove(false);
#endif
}
+ close();
}
if(!error) {
QFile::setPermissions(newName, permissions());
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 96e0f82..36b1ed8 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -537,8 +537,7 @@ QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
void QFileInfo::setFile(const QString &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(file);
+ *this = QFileInfo(file);
}
/*!
@@ -555,8 +554,7 @@ void QFileInfo::setFile(const QString &file)
void QFileInfo::setFile(const QFile &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(file.fileName());
+ *this = QFileInfo(file.fileName());
}
/*!
@@ -573,8 +571,7 @@ void QFileInfo::setFile(const QFile &file)
void QFileInfo::setFile(const QDir &dir, const QString &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(dir.filePath(file));
+ *this = QFileInfo(dir.filePath(file));
}
/*!
@@ -921,7 +918,7 @@ QString QFileInfo::suffix() const
\bold{Note:} The QDir returned always corresponds to the object's
parent directory, even if the QFileInfo represents a directory.
-
+
For each of the follwing, dir() returns a QDir for
\c{"~/examples/191697"}.
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
deleted file mode 100644
index 7d66581..0000000
--- a/src/corelib/io/qfileinfo_p.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, 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.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFILEINFO_P_H
-#define QFILEINFO_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of QIODevice. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qfileinfo.h"
-
-QT_BEGIN_NAMESPACE
-
-class QFileInfoPrivate
-{
-public:
- QFileInfoPrivate(const QFileInfo *copy=0);
- ~QFileInfoPrivate();
-
- void initFileEngine(const QString &);
-
- enum Access {
- ReadAccess,
- WriteAccess,
- ExecuteAccess
- };
- bool hasAccess(Access access) const;
-
- uint getFileFlags(QAbstractFileEngine::FileFlags) const;
- QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
- QString getFileName(QAbstractFileEngine::FileName) const;
-
- enum {
- CachedFileFlags = 0x01,
- CachedLinkTypeFlag = 0x02,
- CachedBundleTypeFlag= 0x04,
- CachedMTime = 0x10,
- CachedCTime = 0x20,
- CachedATime = 0x40,
- CachedSize = 0x08
- };
-
- struct Data
- {
- inline Data()
- : ref(1), fileEngine(0), cache_enabled(1)
- {
- clear();
- }
-
- inline Data(const Data &copy)
- : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
- fileName(copy.fileName), cache_enabled(copy.cache_enabled)
- {
- clear();
- }
-
- inline ~Data()
- {
- delete fileEngine;
- }
-
- inline void clear()
- {
- fileNames.clear();
- fileFlags = 0;
- cachedFlags = 0;
- }
-
- mutable QAtomicInt ref;
-
- QAbstractFileEngine *fileEngine;
- mutable QString fileName;
- mutable QHash<int, QString> fileNames;
- mutable uint cachedFlags : 31;
- mutable uint cache_enabled : 1;
- mutable uint fileFlags;
- mutable qint64 fileSize;
- mutable QDateTime fileTimes[3];
-
- inline bool getCachedFlag(uint c) const
- { return cache_enabled ? (cachedFlags & c) : 0; }
-
- inline void setCachedFlag(uint c)
- { if (cache_enabled) cachedFlags |= c; }
- } *data;
-
- inline void reset() {
- detach();
- data->clear();
- }
-
- void detach();
-};
-
-
-QT_END_NAMESPACE
-#endif
-
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 18b92e2..7a6a85b 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -935,6 +935,8 @@ bool QFSFileEngine::setSize(qint64 size)
Q_D(QFSFileEngine);
if (d->fd != -1)
return !QT_FTRUNCATE(d->fd, size);
+ if (d->fh)
+ return !QT_FTRUNCATE(QT_FILENO(d->fh), size);
return !QT_TRUNCATE(d->nativeFilePath.constData(), size);
}
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 63506c2..c5b54b4 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -1392,8 +1392,6 @@ bool QFSFileEnginePrivate::doStat() const
if (tmpAttributes != -1) {
fileAttrib = tmpAttributes;
could_stat = true;
- } else {
- return false;
}
#endif
} else {
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index c739054..2ccc6ea 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -48,6 +48,10 @@
#include "qstringlist.h"
#include <limits.h>
+#ifdef QIODEVICE_DEBUG
+# include <ctype.h>
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef QIODEVICE_DEBUG
@@ -362,7 +366,7 @@ QIODevice::QIODevice()
{
#if defined QIODEVICE_DEBUG
QFile *file = qobject_cast<QFile *>(this);
- printf("%p QIODevice::QIODevice(\"%s\") %s\n", this, className(),
+ printf("%p QIODevice::QIODevice(\"%s\") %s\n", this, metaObject()->className(),
qPrintable(file ? file->fileName() : QString()));
#endif
}
@@ -375,7 +379,7 @@ QIODevice::QIODevice(QObject *parent)
: QObject(*new QIODevicePrivate, parent)
{
#if defined QIODEVICE_DEBUG
- printf("%p QIODevice::QIODevice(%p \"%s\")\n", this, parent, className());
+ printf("%p QIODevice::QIODevice(%p \"%s\")\n", this, parent, metaObject()->className());
#endif
}
@@ -945,9 +949,9 @@ QByteArray QIODevice::readAll()
QByteArray tmp;
if (d->isSequential() || size() == 0) {
- // Read it in chunks, bytesAvailable() is unreliable for sequential
- // devices.
- const int chunkSize = 4096;
+ // Read it in chunks. Use bytesAvailable() as an unreliable hint for
+ // sequential devices, but try to read 4K as a minimum.
+ int chunkSize = qMax(qint64(4096), bytesAvailable());
qint64 totalRead = 0;
forever {
tmp.resize(tmp.size() + chunkSize);
@@ -956,6 +960,7 @@ QByteArray QIODevice::readAll()
if (readBytes <= 0)
return tmp;
totalRead += readBytes;
+ chunkSize = qMax(qint64(4096), bytesAvailable());
}
} else {
// Read it all in one go.
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
new file mode 100644
index 0000000..6233fde
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -0,0 +1,542 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnoncontiguousbytedevice_p.h"
+#include <QObject>
+#include <QBuffer>
+#include <QDebug>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNonContiguousByteDevice
+ \brief A QNonContiguousByteDevice is a representation of a
+ file, array or buffer that allows access with a read pointer.
+ \since 4.6
+
+ \inmodule QtCore
+
+ The goal of this class is to have a data representation that
+ allows us to avoid doing a memcpy as we have to do with QIODevice.
+
+ \sa QNonContiguousByteDeviceFactory
+
+ \internal
+*/
+/*!
+ \fn virtual const char* QNonContiguousByteDevice::readPointer(qint64 maximumLength, qint64 &len)
+
+ Return a byte pointer for at most \a maximumLength bytes of that device.
+ if \a maximumLength is -1, the caller does not care about the length and
+ the device may return what it desires to.
+ The actual number of bytes the pointer is valid for is returned in
+ the \a len variable.
+ \a len will be -1 if EOF or an error occurs.
+ If it was really EOF can then afterwards be checked with atEnd()
+ Returns 0 if it is not possible to read at that position.
+
+ \sa atEnd()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::advanceReadPointer(qint64 amount)
+
+ will advance the internal read pointer by \a amount bytes.
+ The old readPointer is invalid after this call.
+
+ \sa readPointer()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::atEnd()
+
+ Returns true if everything has been read and the read
+ pointer cannot be advanced anymore.
+
+ \sa readPointer(), advanceReadPointer(), reset()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::reset()
+
+ Moves the internal read pointer back to the beginning.
+ Returns false if this was not possible.
+
+ \sa atEnd(), disableReset()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::disableReset()
+
+ Disable the reset() call, e.g. it will always
+ do nothing and return false.
+
+ \sa reset()
+
+ \internal
+*/
+/*!
+ \fn virtual qint64 QNonContiguousByteDevice::size()
+
+ Returns the size of the complete device or -1 if unknown.
+ May also return less/more than what can be actually read with readPointer()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readyRead()
+
+ Emitted when there is data available
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readProgress(qint64 current, qint64 total)
+
+ Emitted when data has been "read" by advancing the read pointer
+
+ \internal
+*/
+
+QNonContiguousByteDevice::QNonContiguousByteDevice() : QObject((QObject*)0), resetDisabled(false)
+{
+};
+
+QNonContiguousByteDevice::~QNonContiguousByteDevice()
+{
+};
+
+void QNonContiguousByteDevice::disableReset()
+{
+ resetDisabled = true;
+}
+
+QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b) : QNonContiguousByteDevice()
+{
+ buffer = b;
+ byteArray = QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(), buffer->size() - buffer->pos());
+ arrayImpl = new QNonContiguousByteDeviceByteArrayImpl(&byteArray);
+ arrayImpl->setParent(this);
+ connect(arrayImpl, SIGNAL(readyRead()), SIGNAL(readyRead()));
+ connect(arrayImpl, SIGNAL(readProgress(qint64,qint64)), SIGNAL(readProgress(qint64,qint64)));
+}
+
+QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ return arrayImpl->readPointer(maximumLength, len);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::advanceReadPointer(qint64 amount)
+{
+ return arrayImpl->advanceReadPointer(amount);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::atEnd()
+{
+ return arrayImpl->atEnd();
+}
+
+bool QNonContiguousByteDeviceBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+ return arrayImpl->reset();
+}
+
+qint64 QNonContiguousByteDeviceBufferImpl::size()
+{
+ return arrayImpl->size();
+}
+
+QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0)
+{
+ byteArray = ba;
+}
+
+QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceByteArrayImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ if (maximumLength != -1)
+ len = qMin(maximumLength, size() - currentPosition);
+ else
+ len = size() - currentPosition;
+
+ return byteArray->constData() + currentPosition;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::atEnd()
+{
+ return currentPosition >= size();
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+}
+
+qint64 QNonContiguousByteDeviceByteArrayImpl::size()
+{
+ return byteArray->size();
+}
+
+QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb)
+ : QNonContiguousByteDevice(), currentPosition(0)
+{
+ ringBuffer = rb;
+}
+
+QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl()
+{
+};
+
+const char* QNonContiguousByteDeviceRingBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ const char *returnValue = ringBuffer->readPointerAtPosition(currentPosition, len);
+
+ if (maximumLength != -1)
+ len = qMin(len, maximumLength);
+
+ return returnValue;
+};
+
+bool QNonContiguousByteDeviceRingBufferImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+};
+
+bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
+{
+ return currentPosition >= size();
+};
+
+bool QNonContiguousByteDeviceRingBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+};
+
+qint64 QNonContiguousByteDeviceRingBufferImpl::size()
+{
+ return ringBuffer->size();
+};
+
+QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d)
+ : QNonContiguousByteDevice(),
+ currentReadBuffer(0), currentReadBufferSize(16*1024),
+ currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0),
+ eof(false)
+{
+ device = d;
+ initialPosition = d->pos();
+ connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+ connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+};
+
+QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl()
+{
+ delete currentReadBuffer;
+};
+
+const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (eof == true) {
+ len = -1;
+ return 0;
+ }
+
+ if (currentReadBuffer == 0)
+ currentReadBuffer = new QByteArray(currentReadBufferSize, '\0'); // lazy alloc
+
+ if (maximumLength == -1)
+ maximumLength = currentReadBufferSize;
+
+ if (currentReadBufferAmount - currentReadBufferPosition > 0) {
+ len = currentReadBufferAmount - currentReadBufferPosition;
+ return currentReadBuffer->data() + currentReadBufferPosition;
+ }
+
+ qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize));
+
+ if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) {
+ eof = true;
+ len = -1;
+ // size was unknown before, emit a readProgress with the final size
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ return 0;
+ }
+
+ currentReadBufferAmount = haveRead;
+ currentReadBufferPosition = 0;
+
+ len = haveRead;
+ return currentReadBuffer->data();
+};
+
+bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount)
+{
+ totalAdvancements += amount;
+
+ // normal advancement
+ currentReadBufferPosition += amount;
+
+ // advancing over that what has actually been read before
+ if (currentReadBufferPosition > currentReadBufferAmount) {
+ qint64 i = currentReadBufferPosition - currentReadBufferAmount;
+ while (i > 0) {
+ if (device->getChar(0) == false) {
+ emit readProgress(totalAdvancements - i, size());
+ return false; // ### FIXME handle eof
+ }
+ i--;
+ }
+
+ currentReadBufferPosition = 0;
+ currentReadBufferAmount = 0;
+ }
+
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ else
+ emit readProgress(totalAdvancements, size());
+
+ return true;
+};
+
+bool QNonContiguousByteDeviceIoDeviceImpl::atEnd()
+{
+ return eof == true;
+};
+
+bool QNonContiguousByteDeviceIoDeviceImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ if (device->seek(initialPosition)) {
+ eof = false; // assume eof is false, it will be true after a read has been attempted
+ return true;
+ }
+
+ return false;
+};
+
+qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
+{
+ // note that this is different from the size() implementation of QIODevice!
+
+ if (device->isSequential())
+ return -1;
+
+ return device->size() - initialPosition;
+};
+
+QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
+{
+ byteDevice = bd;
+ connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead()));
+
+ open(ReadOnly);
+}
+
+QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice()
+{
+
+}
+
+bool QByteDeviceWrappingIoDevice::isSequential() const
+{
+ return (byteDevice->size() == -1);
+}
+
+bool QByteDeviceWrappingIoDevice::atEnd() const
+{
+ return byteDevice->atEnd();
+}
+
+bool QByteDeviceWrappingIoDevice::reset()
+{
+ return byteDevice->reset();
+}
+
+qint64 QByteDeviceWrappingIoDevice::size() const
+{
+ if (isSequential())
+ return 0;
+
+ return byteDevice->size();
+}
+
+
+qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize)
+{
+ qint64 len;
+ const char *readPointer = byteDevice->readPointer(maxSize, len);
+ if (len == -1)
+ return -1;
+
+ memcpy(data, readPointer, len);
+ byteDevice->advanceReadPointer(len);
+ return len;
+}
+
+qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize)
+{
+ return -1;
+}
+
+/*!
+ \class QNonContiguousByteDeviceFactory
+ \since 4.6
+
+ \inmodule QtCore
+
+ Creates a QNonContiguousByteDevice out of a QIODevice,
+ QByteArray etc.
+
+ \sa QNonContiguousByteDevice
+
+ \internal
+*/
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device);
+
+ Create a QNonContiguousByteDevice out of a QIODevice.
+ For QFile, QBuffer and all other QIoDevice, sequential or not.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) {
+ return new QNonContiguousByteDeviceBufferImpl(buffer);
+ }
+
+ // ### FIXME special case if device is a QFile that supports map()
+ // then we can actually deal with the file without using read/peek
+
+ // generic QIODevice
+ return new QNonContiguousByteDeviceIoDeviceImpl(device); // FIXME
+};
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer);
+
+ Create a QNonContiguousByteDevice out of a QRingBuffer.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer)
+{
+ return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer);
+};
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray);
+
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
+{
+ return new QNonContiguousByteDeviceByteArrayImpl(byteArray);
+};
+
+/*!
+ \fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice);
+
+ Wrap the \a byteDevice (possibly again) into a QIODevice.
+
+ \internal
+*/
+QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
+{
+ // ### FIXME if it already has been based on QIoDevice, we could that one out again
+ // and save some calling
+
+ // needed for FTP backend
+
+ return new QByteDeviceWrappingIoDevice(byteDevice);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
new file mode 100644
index 0000000..2a7e40b
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNONCONTIGUOUSBYTEDEVICE_H
+#define QNONCONTIGUOUSBYTEDEVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qbuffer.h>
+#include <QtCore/qiodevice.h>
+#include "private/qringbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject
+{
+ Q_OBJECT
+public:
+ virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
+ virtual bool advanceReadPointer(qint64 amount) = 0;
+ virtual bool atEnd() = 0;
+ virtual bool reset() = 0;
+ void disableReset();
+ virtual qint64 size() = 0;
+
+protected:
+ QNonContiguousByteDevice();
+ virtual ~QNonContiguousByteDevice();
+
+ bool resetDisabled;
+signals:
+ void readyRead();
+ void readProgress(qint64 current, qint64 total);
+};
+
+class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
+{
+public:
+ static QNonContiguousByteDevice* create(QIODevice *device);
+ static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QNonContiguousByteDevice* create(QRingBuffer *ringBuffer);
+ static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
+};
+
+// the actual implementations
+//
+
+class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba);
+ ~QNonContiguousByteDeviceByteArrayImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QByteArray* byteArray;
+ qint64 currentPosition;
+};
+
+class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb);
+ ~QNonContiguousByteDeviceRingBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QRingBuffer* ringBuffer;
+ qint64 currentPosition;
+};
+
+
+class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d);
+ ~QNonContiguousByteDeviceIoDeviceImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QIODevice* device;
+ QByteArray* currentReadBuffer;
+ qint64 currentReadBufferSize;
+ qint64 currentReadBufferAmount;
+ qint64 currentReadBufferPosition;
+ qint64 totalAdvancements;
+ bool eof;
+ qint64 initialPosition;
+};
+
+class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice
+{
+ Q_OBJECT
+public:
+ QNonContiguousByteDeviceBufferImpl(QBuffer *b);
+ ~QNonContiguousByteDeviceBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QBuffer* buffer;
+ QByteArray byteArray;
+ QNonContiguousByteDeviceByteArrayImpl* arrayImpl;
+};
+
+// ... and the reverse thing
+class QByteDeviceWrappingIoDevice : public QIODevice
+{
+ Q_OBJECT
+public:
+ QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd);
+ ~QByteDeviceWrappingIoDevice ();
+ virtual bool isSequential () const;
+ virtual bool atEnd () const;
+ virtual bool reset ();
+ virtual qint64 size () const;
+protected:
+ virtual qint64 readData ( char * data, qint64 maxSize );
+ virtual qint64 writeData ( const char * data, qint64 maxSize );
+
+ QNonContiguousByteDevice *byteDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index a128482..30f4291 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -101,6 +101,29 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
+static QHash<QString, QString> environmentHashFromList(const QStringList &environment)
+{
+ QHash<QString, QString> result;
+ QStringList::ConstIterator it = environment.constBegin(),
+ end = environment.constEnd();
+ for ( ; it != end; ++it) {
+ int equals = it->indexOf(QLatin1Char('='));
+
+ QString name = *it;
+ QString value;
+ if (equals != -1) {
+ name.truncate(equals);
+#ifdef Q_OS_WIN
+ name = name.toUpper();
+#endif
+ value = it->mid(equals + 1);
+ }
+ result.insert(name, value);
+ }
+
+ return result;
+}
+
void QProcessPrivate::Channel::clear()
{
switch (type) {
@@ -416,6 +439,7 @@ QProcessPrivate::QProcessPrivate()
sequenceNumber = 0;
exitCode = 0;
exitStatus = QProcess::NormalExit;
+ environment = 0;
startupSocketNotifier = 0;
deathNotifier = 0;
notifier = 0;
@@ -442,6 +466,7 @@ QProcessPrivate::QProcessPrivate()
*/
QProcessPrivate::~QProcessPrivate()
{
+ delete environment;
if (stdinChannel.process)
stdinChannel.process->stdoutChannel.clear();
if (stdoutChannel.process)
@@ -1191,29 +1216,83 @@ QProcess::ProcessState QProcess::state() const
\snippet doc/src/snippets/qprocess-environment/main.cpp 0
- \sa environment(), systemEnvironment()
+ \sa environment(), systemEnvironment(), setEnvironmentHash()
*/
void QProcess::setEnvironment(const QStringList &environment)
{
- Q_D(QProcess);
- d->environment = environment;
+ setEnvironmentHash(environmentHashFromList(environment));
}
/*!
Returns the environment that QProcess will use when starting a
process, or an empty QStringList if no environment has been set
- using setEnvironment(). If no environment has been set, the
- environment of the calling process will be used.
+ using setEnvironment() or setEnvironmentHash(). If no environment
+ has been set, the environment of the calling process will be used.
\note The environment settings are ignored on Windows CE,
as there is no concept of an environment.
- \sa setEnvironment(), systemEnvironment()
+ \sa environmentHash(), setEnvironment(), systemEnvironment()
*/
QStringList QProcess::environment() const
{
Q_D(const QProcess);
- return d->environment;
+
+ QStringList result;
+ if (!d->environment)
+ return result;
+
+ QHash<QString, QString>::ConstIterator it = d->environment->constBegin(),
+ end = d->environment->constEnd();
+ for ( ; it != end; ++it) {
+ QString data = it.key();
+ data.reserve(data.length() + it.value().length() + 1);
+ data.append(QLatin1Char('='));
+ data.append(it.value());
+ result << data;
+ }
+ return result;
+}
+
+/*!
+ \since 4.5
+ Sets the environment that QProcess will use when starting a process to the
+ \a environment hash map.
+
+ For example, the following code adds the \c{C:\\BIN} directory to the list of
+ executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}:
+
+ \snippet doc/src/snippets/qprocess-environment/main.cpp 1
+
+ \sa environment(), systemEnvironmentHash(), setEnvironment()
+*/
+void QProcess::setEnvironmentHash(const QHash<QString, QString> &environment)
+{
+ Q_D(QProcess);
+ if (!d->environment)
+ d->environment = new QHash<QString, QString>(environment);
+ else
+ *d->environment = environment;
+}
+
+/*!
+ \since 4.5
+ Returns the environment that QProcess will use when starting a
+ process, or an empty QHash if no environment has been set using
+ setEnvironment() or setEnvironmentHash(). If no environment has
+ been set, the environment of the calling process will be used.
+
+ \note The environment settings are ignored on Windows CE,
+ as there is no concept of an environment.
+
+ \sa setEnvironmentHash(), setEnvironment(), systemEnvironmentHash()
+*/
+QHash<QString, QString> QProcess::environmentHash() const
+{
+ Q_D(const QProcess);
+ if (d->environment)
+ return *d->environment;
+ return QHash<QString, QString>();
}
/*!
@@ -1812,7 +1891,7 @@ QT_END_INCLUDE_NAMESPACE
\snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
- \sa environment(), setEnvironment()
+ \sa systemEnvironmentHash(), environment(), setEnvironment()
*/
QStringList QProcess::systemEnvironment()
{
@@ -1825,6 +1904,18 @@ QStringList QProcess::systemEnvironment()
}
/*!
+ \since 4.5
+
+ Returns the environment of the calling process as a QHash.
+
+ \sa systemEnvironment(), environmentHash(), setEnvironmentHash()
+*/
+QHash<QString, QString> QProcess::systemEnvironmentHash()
+{
+ return environmentHashFromList(systemEnvironment());
+}
+
+/*!
\typedef Q_PID
\relates QProcess
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 54a96c7..bf9a5a6 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -53,6 +53,8 @@ QT_MODULE(Core)
#ifndef QT_NO_PROCESS
+template <class Key, class T> class QHash;
+
#if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)) || defined(qdoc)
typedef qint64 Q_PID;
#else
@@ -121,6 +123,8 @@ public:
void setEnvironment(const QStringList &environment);
QStringList environment() const;
+ void setEnvironmentHash(const QHash<QString, QString> &environment);
+ QHash<QString, QString> environmentHash() const;
QProcess::ProcessError error() const;
QProcess::ProcessState state() const;
@@ -156,6 +160,7 @@ public:
static bool startDetached(const QString &program);
static QStringList systemEnvironment();
+ static QHash<QString, QString> systemEnvironmentHash();
public Q_SLOTS:
void terminate();
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 33059dd..f67fd2d 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -161,7 +161,7 @@ public:
QString program;
QStringList arguments;
- QStringList environment;
+ QHash<QString, QString> *environment;
QRingBuffer outputReadBuffer;
QRingBuffer errorReadBuffer;
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 33d4a47..2f05f6e 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -531,8 +531,12 @@ bool QProcessPrivate::createChannel(Channel &channel)
}
}
-static char **_q_dupEnvironment(const QStringList &environment, int *envc)
+static char **_q_dupEnvironment(const QHash<QString, QString> *environment, int *envc)
{
+ *envc = 0;
+ if (!environment)
+ return 0; // use the default environment
+
// if LD_LIBRARY_PATH exists in the current environment, but
// not in the environment list passed by the programmer, then
// copy it over.
@@ -541,27 +545,29 @@ static char **_q_dupEnvironment(const QStringList &environment, int *envc)
#else
static const char libraryPath[] = "LD_LIBRARY_PATH";
#endif
- const QString libraryPathString = QLatin1String(libraryPath);
- QStringList env = environment;
- QStringList matches = env.filter(
- QRegExp(QLatin1Char('^') + libraryPathString + QLatin1Char('=')));
- const QString envLibraryPath = QString::fromLocal8Bit(::getenv(libraryPath));
- if (matches.isEmpty() && !envLibraryPath.isEmpty()) {
- QString entry = libraryPathString;
- entry += QLatin1Char('=');
- entry += envLibraryPath;
- env << libraryPathString + QLatin1Char('=') + envLibraryPath;
- }
-
- char **envp = new char *[env.count() + 1];
- envp[env.count()] = 0;
-
- for (int j = 0; j < env.count(); ++j) {
- QString item = env.at(j);
- envp[j] = ::strdup(item.toLocal8Bit().constData());
+ const QByteArray envLibraryPath = qgetenv(libraryPath);
+ bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
+ !environment->contains(QLatin1String(libraryPath));
+
+ char **envp = new char *[environment->count() + 2];
+ envp[environment->count()] = 0;
+ envp[environment->count() + 1] = 0;
+
+ QHash<QString, QString>::ConstIterator it = environment->constBegin();
+ const QHash<QString, QString>::ConstIterator end = environment->constEnd();
+ for ( ; it != end; ++it) {
+ QByteArray key = it.key().toLocal8Bit();
+ QByteArray value = it.value().toLocal8Bit();
+ key.reserve(key.length() + 1 + value.length());
+ key.append('=');
+ key.append(value);
+
+ envp[(*envc)++] = ::strdup(key.constData());
}
- *envc = env.count();
+ if (needToAddLibraryPath)
+ envp[(*envc)++] = ::strdup(QByteArray(libraryPath) + '=' +
+ envLibraryPath);
return envp;
}
@@ -800,7 +806,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
q->setupChildProcess();
// execute the process
- if (environment.isEmpty()) {
+ if (!envp) {
qt_native_execvp(argv[0], argv);
} else {
if (path) {
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 0e36760..5d862e5 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -304,44 +304,69 @@ static QString qt_create_commandline(const QString &program, const QStringList &
return args;
}
-static QByteArray qt_create_environment(const QStringList &environment)
+static QByteArray qt_create_environment(const QHash<QString, QString> *environment)
{
QByteArray envlist;
- if (!environment.isEmpty()) {
- QStringList envStrings = environment;
- int pos = 0;
- // add PATH if necessary (for DLL loading)
- if (envStrings.filter(QRegExp(QLatin1String("^PATH="),Qt::CaseInsensitive)).isEmpty()) {
+ if (environment) {
+ QHash<QString, QString> copy = *environment;
+
+ // add PATH if necessary (for DLL loading)
+ if (!copy.contains(QLatin1String("PATH"))) {
QByteArray path = qgetenv("PATH");
if (!path.isEmpty())
- envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)));
+ copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path));
}
+
// add systemroot if needed
- if (envStrings.filter(QRegExp(QLatin1String("^SystemRoot="),Qt::CaseInsensitive)).isEmpty()) {
- QByteArray systemRoot = qgetenv("SystemRoot");
+ if (!copy.contains(QLatin1String("SYSTEMROOT"))) {
+ QByteArray systemRoot = qgetenv("SYSTEMROOT");
if (!systemRoot.isEmpty())
- envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot)));
+ copy.insert(QLatin1String("SYSTEMROOT"), QString::fromLocal8Bit(systemRoot));
}
+
+ int pos = 0;
+ QHash<QString, QString>::ConstIterator it = copy.constBegin(),
+ end = copy.constEnd();
#ifdef UNICODE
if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
- for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); ++it) {
- QString tmp = *it;
- uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
+ static const TCHAR equal = L'=';
+ static const TCHAR nul = L'\0';
+
+ for ( ; it != end; ++it) {
+ uint tmpSize = sizeof(TCHAR) * (it.key().length() + it.value().length() + 2);
+ // ignore empty strings
+ if (tmpSize == sizeof(TCHAR)*2)
+ continue;
envlist.resize(envlist.size() + tmpSize);
- memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
+
+ tmpSize = it.key().length() * sizeof(TCHAR);
+ memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data()+pos, &equal, sizeof(TCHAR));
+ pos += sizeof(TCHAR);
+
+ tmpSize = it.value().length() * sizeof(TCHAR);
+ memcpy(envlist.data()+pos, it.value().utf16(), tmpSize);
pos += tmpSize;
- }
- // add the 2 terminating 0 (actually 4, just to be on the safe side)
- envlist.resize( envlist.size()+4 );
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
+
+ memcpy(envlist.data()+pos, &nul, sizeof(TCHAR));
+ pos += sizeof(TCHAR);
+ }
+ // add the 2 terminating 0 (actually 4, just to be on the safe side)
+ envlist.resize( envlist.size()+4 );
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
} else
#endif // UNICODE
{
- for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++) {
- QByteArray tmp = (*it).toLocal8Bit();
+ for ( ; it != end; it++) {
+ QByteArray tmp = it.key().toLocal8Bit();
+ tmp.append('=');
+ tmp.append(it.value().toLocal8Bit());
+
uint tmpSize = tmp.length() + 1;
envlist.resize(envlist.size() + tmpSize);
memcpy(envlist.data()+pos, tmp.data(), tmpSize);
@@ -418,7 +443,7 @@ void QProcessPrivate::startProcess()
};
success = CreateProcessW(0, (WCHAR*)args.utf16(),
0, 0, TRUE, dwCreationFlags,
- environment.isEmpty() ? 0 : envlist.data(),
+ environment ? envlist.data() : 0,
workingDirectory.isEmpty() ? 0
: (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(),
&startupInfo, pid);
@@ -437,7 +462,7 @@ void QProcessPrivate::startProcess()
};
success = CreateProcessA(0, args.toLocal8Bit().data(),
- 0, 0, TRUE, dwCreationFlags, environment.isEmpty() ? 0 : envlist.data(),
+ 0, 0, TRUE, dwCreationFlags, environment ? envlist.data() : 0,
workingDirectory.isEmpty() ? 0
: QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(),
&startupInfo, pid);
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index a1f921e..3b704f6 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -60,6 +60,37 @@
QT_BEGIN_NAMESPACE
+
+class QStringSplitter
+{
+public:
+ QStringSplitter(const QString &s)
+ : m_string(s), m_data(m_string.constData()), m_len(s.length()), m_pos(0)
+ {
+ m_splitChar = QLatin1Char('/');
+ }
+
+ inline bool hasNext() {
+ while (m_pos < m_len && m_data[m_pos] == m_splitChar)
+ ++m_pos;
+ return m_pos < m_len;
+ }
+
+ inline QStringRef next() {
+ int start = m_pos;
+ while (m_pos < m_len && m_data[m_pos] != m_splitChar)
+ ++m_pos;
+ return QStringRef(&m_string, start, m_pos - start);
+ }
+
+ QString m_string;
+ const QChar *m_data;
+ QChar m_splitChar;
+ int m_len;
+ int m_pos;
+};
+
+
//resource glue
class QResourceRoot
{
@@ -101,6 +132,16 @@ protected:
}
};
+static QString cleanPath(const QString &_path)
+{
+ QString path = QDir::cleanPath(_path);
+ // QDir::cleanPath does not remove two trailing slashes under _Windows_
+ // due to support for UNC paths. Remove those manually.
+ if (path.startsWith(QLatin1String("//")))
+ path.remove(0, 1);
+ return path;
+}
+
Q_DECLARE_TYPEINFO(QResourceRoot, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, resourceMutex, (QMutex::Recursive))
@@ -216,9 +257,10 @@ QResourcePrivate::load(const QString &file)
related.clear();
QMutexLocker lock(resourceMutex());
const ResourceList *list = resourceList();
+ QString cleaned = cleanPath(file);
for(int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
- const int node = res->findNode(file);
+ const int node = res->findNode(cleaned);
if(node != -1) {
if(related.isEmpty()) {
container = res->isContainer(node);
@@ -292,6 +334,7 @@ QResourcePrivate::ensureChildren() const
if(path.startsWith(QLatin1Char(':')))
path = path.mid(1);
QSet<QString> kids;
+ QString cleaned = cleanPath(path);
for(int i = 0; i < related.size(); ++i) {
QResourceRoot *res = related.at(i);
if(res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
@@ -300,7 +343,7 @@ QResourcePrivate::ensureChildren() const
kids.insert(k);
}
} else {
- const int node = res->findNode(path);
+ const int node = res->findNode(cleaned);
if(node != -1) {
QStringList related_children = res->children(node);
for(int kid = 0; kid < related_children.size(); ++kid) {
@@ -406,7 +449,7 @@ QString QResource::absoluteFilePath() const
}
/*!
- Returns true if the resource really exists in the resource heirarchy,
+ Returns true if the resource really exists in the resource hierarchy,
false otherwise.
*/
@@ -562,18 +605,20 @@ inline QString QResourceRoot::name(int node) const
(names[name_offset+1] << 0);
name_offset += 2;
name_offset += 4; //jump past hash
- for(int i = 0; i < name_length*2; i+=2)
- ret += QChar(names[name_offset+i+1], names[name_offset+i]);
+
+ ret.resize(name_length);
+ QChar *strData = ret.data();
+ for(int i = 0; i < name_length*2; i+=2) {
+ QChar c(names[name_offset+i+1], names[name_offset+i]);
+ *strData = c;
+ ++strData;
+ }
return ret;
}
+
int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
{
- QString path = QDir::cleanPath(_path);
- // QDir::cleanPath does not remove two trailing slashes under _Windows_
- // due to support for UNC paths. Remove those manually.
- if (path.startsWith(QLatin1String("//")))
- path.remove(0, 1);
-
+ QString path = _path;
{
QString root = mappingRoot();
if(!root.isEmpty()) {
@@ -604,12 +649,11 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
//now iterate up the tree
int node = -1;
- QStringList segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
-#ifdef DEBUG_RESOURCE_MATCH
- qDebug() << "****" << segments;
-#endif
- for(int i = 0; child_count && i < segments.size(); ++i) {
- const QString &segment = segments[i];
+
+ QStringSplitter splitter(path);
+ while (child_count && splitter.hasNext()) {
+ QStringRef segment = splitter.next();
+
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " CHILDREN" << segment;
for(int j = 0; j < child_count; ++j) {
@@ -651,7 +695,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
(tree[offset+1] << 0);
offset += 2;
- if(i == segments.size()-1) {
+ if(!splitter.hasNext()) {
if(!(flags & Directory)) {
const short country = (tree[offset+0] << 8) +
(tree[offset+1] << 0);
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 484e79a..14fc2d4 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -2295,7 +2295,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
As mentioned in the \l{Fallback Mechanism} section, QSettings
stores settings for an application in up to four locations,
depending on whether the settings are user-specific or
- system-wide and whether the the settings are application-specific
+ system-wide and whether the settings are application-specific
or organization-wide. For simplicity, we're assuming the
organization is called MySoft and the application is called Star
Runner.
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index dd72fd9..93d07e0 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -146,7 +146,7 @@ inline QString QSettingsGroup::toString() const
return result;
}
-class Q_CORE_EXPORT QConfFile
+class QConfFile
{
public:
ParsedSettingsMap mergedKeyMap() const;
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 1167671..612d7f7 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -411,6 +411,7 @@ public:
QString writeBuffer;
QString readBuffer;
int readBufferOffset;
+ int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
qint64 readBufferStartDevicePos;
// streaming parameters
@@ -437,6 +438,7 @@ QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
#ifndef QT_NO_TEXTCODEC
readConverterSavedState(0),
#endif
+ readConverterSavedStateOffset(0),
locale(QLocale::C)
{
this->q_ptr = q_ptr;
@@ -559,13 +561,8 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
if (!codec || autoDetectUnicode) {
autoDetectUnicode = false;
- if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0)
- || (uchar(buf[0]) == 0 && uchar(buf[1]) == 0 && uchar(buf[2]) == 0xfe && uchar(buf[3]) == 0xff))) {
- codec = QTextCodec::codecForName("UTF-32");
- } else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe)
- || (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) {
- codec = QTextCodec::codecForName("UTF-16");
- } else if (!codec) {
+ codec = QTextCodec::codecForUtfText(QByteArray::fromRawData(buf, bytesRead), 0);
+ if (!codec) {
codec = QTextCodec::codecForLocale();
writeConverterState.flags |= QTextCodec::IgnoreHeader;
}
@@ -835,6 +832,10 @@ inline void QTextStreamPrivate::consume(int size)
readBufferOffset = 0;
readBuffer.clear();
saveConverterState(device->pos());
+ } else if (readBufferOffset > QTEXTSTREAM_BUFFERSIZE) {
+ readBuffer = readBuffer.remove(0,readBufferOffset);
+ readConverterSavedStateOffset += readBufferOffset;
+ readBufferOffset = 0;
}
}
}
@@ -856,6 +857,7 @@ inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
#endif
readBufferStartDevicePos = newPos;
+ readConverterSavedStateOffset = 0;
}
/*! \internal
@@ -1220,7 +1222,7 @@ qint64 QTextStream::pos() const
// Rewind the device to get to the current position Ensure that
// readBufferOffset is unaffected by fillReadBuffer()
- int oldReadBufferOffset = d->readBufferOffset;
+ int oldReadBufferOffset = d->readBufferOffset + d->readConverterSavedStateOffset;
while (d->readBuffer.size() < oldReadBufferOffset) {
if (!thatd->fillReadBuffer(1))
return qint64(-1);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 9ce9a2e..d1a5cdd 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -4759,6 +4759,12 @@ void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &que
Inserts the pair \a key = \a value into the query string of the
URL.
+ The key/value pair is encoded before it is added to the query. The
+ pair is converted into separate strings internally. The \a key and
+ \a value is first encoded into UTF-8 and then delimited by the
+ character returned by valueDelimiter(). Each key/value pair is
+ delimited by the character returned by pairDelimiter().
+
\sa addEncodedQueryItem()
*/
void QUrl::addQueryItem(const QString &key, const QString &value)
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index b34e59d..ecef555 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -51,10 +51,11 @@ SOURCES += \
kernel/qtimer.cpp \
kernel/qtranslator.cpp \
kernel/qvariant.cpp \
- kernel/qcoreglobaldata.cpp \
- kernel/qsharedmemory.cpp \
- kernel/qsystemsemaphore.cpp
-
+ kernel/qcoreglobaldata.cpp \
+ kernel/qsharedmemory.cpp \
+ kernel/qsystemsemaphore.cpp \
+ kernel/qpointer.cpp
+
win32 {
SOURCES += \
kernel/qeventdispatcher_win.cpp \
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index a23b2dd..77ef096 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -377,12 +377,12 @@ QString qAppName()
QLibrary) can be retrieved with libraryPaths() and manipulated by
setLibraryPaths(), addLibraryPath(), and removeLibraryPath().
- On Unix/Linux Qt is configured to use the system local settings by
- default. This can cause a conflict when using POSIX functions, for
- instance, when converting between data types such as floats and
- strings, since the notation may differ between locales. To get
- around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
- right after initializing QApplication or QCoreApplication to reset
+ On Unix/Linux Qt is configured to use the system local settings by
+ default. This can cause a conflict when using POSIX functions, for
+ instance, when converting between data types such as floats and
+ strings, since the notation may differ between locales. To get
+ around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
+ right after initializing QApplication or QCoreApplication to reset
the locale that is used for number formatting to "C"-locale.
\sa QApplication, QAbstractEventDispatcher, QEventLoop,
@@ -556,6 +556,20 @@ void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
QCoreApplicationPrivate::attribs |= 1 << attribute;
else
QCoreApplicationPrivate::attribs &= ~(1 << attribute);
+#ifdef Q_OS_MAC
+ // Turn on the no native menubar here, since we used to
+ // do this implicitly. We DO NOT flip it off if someone sets
+ // it to false.
+ // Ideally, we'd have magic that would be something along the lines of
+ // "follow MacPluginApplication" unless explicitly set.
+ // Considering this attribute isn't only at the beginning
+ // it's unlikely it will ever be a problem, but I want
+ // to have the behavior documented here.
+ if (attribute == Qt::AA_MacPluginApplication && on
+ && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
+ setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ }
+#endif
}
/*!
@@ -1696,7 +1710,7 @@ QString QCoreApplication::applicationDirPath()
}
QCoreApplicationPrivate *d = self->d_func();
- if (d->cachedApplicationDirPath == QString())
+ if (d->cachedApplicationDirPath.isNull())
d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
return d->cachedApplicationDirPath;
}
@@ -1724,7 +1738,7 @@ QString QCoreApplication::applicationFilePath()
}
QCoreApplicationPrivate *d = self->d_func();
- if (d->cachedApplicationFilePath != QString())
+ if (!d->cachedApplicationFilePath.isNull())
return d->cachedApplicationFilePath;
#if defined( Q_WS_WIN )
@@ -1908,8 +1922,7 @@ QStringList QCoreApplication::arguments()
l1arg == "-qdebug" ||
l1arg == "-reverse" ||
l1arg == "-stylesheet" ||
- l1arg == "-widgetcount" ||
- l1arg == "-direct3d")
+ l1arg == "-widgetcount")
;
else if (l1arg.startsWith("-style="))
;
diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
index 1c929c7..e0f7687 100644
--- a/src/corelib/kernel/qfunctions_wince.cpp
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -285,11 +285,6 @@ int qt_wince_SetErrorMode(int newValue)
return result;
}
-HRESULT qt_wince_CoInitialize(void* reserved)
-{
- return CoInitializeEx(reserved, 0);
-}
-
bool qt_wince__chmod(const char *file, int mode)
{
return _wchmod( reinterpret_cast<const wchar_t *> (QString::fromLatin1(file).utf16()), mode);
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
index 123bd23..5f08bb3 100644
--- a/src/corelib/kernel/qfunctions_wince.h
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -199,7 +199,9 @@ int qt_wince__fstat( int handle, struct stat *buffer);
#define SEM_FAILCRITICALERRORS 0x0001
#define SEM_NOOPENFILEERRORBOX 0x0002
int qt_wince_SetErrorMode(int);
-HRESULT qt_wince_CoInitialize(void* reserved);
+#ifndef CoInitialize
+#define CoInitialize(x) CoInitializeEx(x, COINIT_MULTITHREADED)
+#endif
bool qt_wince__chmod(const char *file, int mode);
bool qt_wince__wchmod(const WCHAR *file, int mode);
@@ -376,7 +378,6 @@ typedef DWORD OLE_COLOR;
#define _rename(a,b) qt_wince__rename(a,b)
#define _remove(a) qt_wince__remove(a)
#define SetErrorMode(a) qt_wince_SetErrorMode(a)
-#define CoInitialize(a) qt_wince_CoInitialize(a)
#define _chmod(a,b) qt_wince__chmod(a,b)
#define _wchmod(a,b) qt_wince__wchmod(a,b)
#define CreateFileA(a,b,c,d,e,f,g) qt_wince_CreateFileA(a,b,c,d,e,f,g)
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 05015c0..cfd8493 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -58,6 +58,7 @@
#include <qsemaphore.h>
#include <private/qorderedmutexlocker_p.h>
+#include <private/qmutexpool_p.h>
#include <new>
@@ -70,7 +71,7 @@ static int DIRECT_CONNECTION_ONLY = 0;
static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
{
- int *types = static_cast<int *>(qMalloc((typeNames.count() + 1) * sizeof(int)));
+ int *types = new int [typeNames.count() + 1];
for (int i = 0; i < typeNames.count(); ++i) {
const QByteArray typeName = typeNames.at(i);
if (typeName.endsWith('*'))
@@ -82,7 +83,7 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
"(Make sure '%s' is registered using qRegisterMetaType().)",
typeName.constData(), typeName.constData());
- qFree(types);
+ delete [] types;
return 0;
}
}
@@ -91,12 +92,35 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
return types;
}
+QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
+QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+/** \internal
+ * mutex to be locked when accessing the connectionlists or the senders list
+ */
+static QMutex *signalSlotLock(const QObject *o)
+{
+ if (!signalSlotMutexes) {
+ QMutexPool *mp = new QMutexPool;
+ if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
+ delete mp;
+ }
+ }
+ return signalSlotMutexes->get(o);
+}
+
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{
+ objectCount.ref();
}
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
{
+ if(!objectCount.deref()) {
+ QMutexPool *old = signalSlotMutexes;
+ signalSlotMutexes.testAndSetAcquire(old, 0);
+ delete old;
+ }
}
QObjectPrivate::QObjectPrivate(int version)
@@ -216,19 +240,20 @@ public:
}
};
+// Used by QAccessibleWidget
bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
{
Q_Q(const QObject);
int signal_index = q->metaObject()->indexOfSignal(signal);
if (signal_index < 0)
return false;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q));
if (connectionLists) {
if (signal_index < connectionLists->count()) {
const ConnectionList &connectionList = connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (c.receiver && c.receiver == receiver)
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver == receiver)
return true;
}
}
@@ -236,6 +261,7 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
return false;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
Q_Q(const QObject);
@@ -243,26 +269,27 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const
int signal_index = q->metaObject()->indexOfSignal(signal);
if (signal_index < 0)
return returnValue;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q));
if (connectionLists) {
if (signal_index < connectionLists->count()) {
const ConnectionList &connectionList = connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (c.receiver)
- returnValue << c.receiver;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver)
+ returnValue << c->receiver;
}
}
}
return returnValue;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q_func()));
for (int i = 0; i < senders.count(); ++i)
- returnValue << senders.at(i).sender;
+ returnValue << senders.at(i)->sender;
return returnValue;
}
@@ -274,33 +301,11 @@ void QObjectPrivate::addConnection(int signal, Connection *c)
connectionLists->resize(signal + 1);
ConnectionList &connectionList = (*connectionLists)[signal];
- connectionList.append(*c);
+ connectionList.append(c);
cleanConnectionLists();
}
-void QObjectPrivate::removeReceiver(int signal, QObject *receiver)
-{
- if (!connectionLists)
- return;
-
- if (signal >= connectionLists->count())
- return;
-
- ConnectionList &connectionList = (*connectionLists)[signal];
- for (int i = 0; i < connectionList.count(); ++i) {
- Connection &c = connectionList[i];
- if (c.receiver == receiver) {
- c.receiver = 0;
- if (c.argumentTypes && c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c.argumentTypes);
- c.argumentTypes = 0;
- }
- connectionLists->dirty = true;
- }
- }
-}
-
void QObjectPrivate::cleanConnectionLists()
{
if (connectionLists->dirty && !connectionLists->inUse) {
@@ -308,55 +313,17 @@ void QObjectPrivate::cleanConnectionLists()
for (int signal = -1; signal < connectionLists->count(); ++signal) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal];
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (!c.receiver)
+ QObjectPrivate::Connection *c = connectionList.at(i);
+ if (!c->receiver) {
+ delete c;
connectionList.removeAt(i--);
+ }
}
}
connectionLists->dirty = false;
}
}
-void QObjectPrivate::refSender(QObject *sender, int signal)
-{
- for (int i = 0; i < senders.count(); ++i) {
- Sender &s = senders[i];
- if (s.sender == sender && s.signal == signal) {
- ++s.ref;
- return;
- }
- }
-
- Sender s = { sender, signal, 1 };
- senders.append(s);
-}
-
-void QObjectPrivate::derefSender(QObject *sender, int signal)
-{
- for (int i = 0; i < senders.count(); ++i) {
- Sender &s = senders[i];
- if (s.sender == sender && s.signal == signal) {
- if (--s.ref == 0) {
- senders.removeAt(i);
- break;
- }
- }
- }
- // Q_ASSERT_X(false, "QObjectPrivate::derefSender", "sender not found");
-}
-
-void QObjectPrivate::removeSender(QObject *sender, int signal)
-{
- for (int i = 0; i < senders.count(); ++i) {
- Sender &s = senders[i];
- if (s.sender == sender && s.signal == signal) {
- senders.removeAt(i);
- return;
- }
- }
- // Q_ASSERT_X(false, "QObjectPrivate::removeSender", "sender not found");
-}
-
QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
Sender *sender)
{
@@ -769,7 +736,7 @@ QObject::~QObject()
emit destroyed(this);
{
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// set ref to zero to indicate that this object has been deleted
if (d->currentSender != 0)
@@ -782,23 +749,21 @@ QObject::~QObject()
for (int signal = -1; signal < d->connectionLists->count(); ++signal) {
QObjectPrivate::ConnectionList &connectionList = (*d->connectionLists)[signal];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
- if (!c->receiver)
+ QObjectPrivate::Connection *c = connectionList[i];
+ if (!c->receiver) {
+ delete c;
continue;
+ }
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- c = &connectionList[i];
+ c = connectionList[i];
if (c->receiver)
- c->receiver->d_func()->removeSender(this, signal);
+ c->receiver->d_func()->senders.removeOne(c);
if (needToUnlock)
m->unlock();
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
- }
- c->receiver = 0;
+ delete c;
}
}
@@ -811,18 +776,26 @@ QObject::~QObject()
}
// disconnect all senders
- for (int i = 0; i < d->senders.count(); ++i) {
- QObjectPrivate::Sender *s = &d->senders[i];
- if (!s->sender)
- continue;
+ for (int i = 0; i < d->senders.count(); ) {
+ QObjectPrivate::Connection *s = d->senders[i];
- QMutex *m = &s->sender->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(s->sender);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- s = &d->senders[i];
- if (s->sender)
- s->sender->d_func()->removeReceiver(s->signal, this);
+ if (m < locker.mutex()) {
+ if (i >= d->senders.count() || s != d->senders[i]) {
+ if (needToUnlock)
+ m->unlock();
+ continue;
+ }
+ }
+ s->receiver = 0;
+ QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists;
+ if (senderLists)
+ senderLists->dirty = true;
+
if (needToUnlock)
m->unlock();
+ ++i;
}
d->senders.clear();
@@ -866,6 +839,12 @@ QObject::~QObject()
d_ptr = 0;
}
+QObjectPrivate::Connection::~Connection()
+{
+ if (argumentTypes != &DIRECT_CONNECTION_ONLY)
+ delete [] argumentTypes;
+}
+
/*!
\fn QMetaObject *QObject::metaObject() const
@@ -2297,14 +2276,14 @@ QObject *QObject::sender() const
{
Q_D(const QObject);
- QMutexLocker(&d->threadData->mutex);
+ QMutexLocker(signalSlotLock(this));
if (!d->currentSender)
return 0;
// Return 0 if d->currentSender isn't in d->senders
bool found = false;
for (int i = 0; !found && i < d->senders.count(); ++i)
- found = (d->senders.at(i).sender == d->currentSender->sender);
+ found = (d->senders.at(i)->sender == d->currentSender->sender);
if (!found)
return 0;
return d->currentSender->sender;
@@ -2353,14 +2332,14 @@ int QObject::receivers(const char *signal) const
}
Q_D(const QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
if (d->connectionLists) {
if (signal_index < d->connectionLists->count()) {
const QObjectPrivate::ConnectionList &connectionList =
d->connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- receivers += c.receiver ? 1 : 0;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ receivers += c->receiver ? 1 : 0;
}
}
}
@@ -2793,20 +2772,18 @@ bool QMetaObject::connect(const QObject *sender, int signal_index,
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
- QOrderedMutexLocker locker(&s->d_func()->threadData->mutex,
- &r->d_func()->threadData->mutex);
+ QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ c->sender = s;
+ c->receiver = r;
+ c->method = method_index;
+ c->connectionType = type;
+ c->argumentTypes = types;
-#if defined(Q_CC_HPACC) && defined(QT_ARCH_PARISC)
- QObjectPrivate::Connection c;
- c.receiver = r;
- c.method = method_index;
- c.connectionType = type;
- c.argumentTypes = types;
-#else
- QObjectPrivate::Connection c = { r, method_index, type, Q_BASIC_ATOMIC_INITIALIZER(types) };
-#endif
- s->d_func()->addConnection(signal_index, &c);
- r->d_func()->refSender(s, signal_index);
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
+
+ s->d_func()->addConnection(signal_index, c);
+ r->d_func()->senders.append(c);
if (signal_index < 0)
sender->d_func()->connectedSignals = ~0u;
@@ -2828,8 +2805,8 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
- QMutex *senderMutex = &s->d_func()->threadData->mutex;
- QMutex *receiverMutex = r ? &r->d_func()->threadData->mutex : 0;
+ QMutex *senderMutex = signalSlotLock(sender);
+ QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
QOrderedMutexLocker locker(senderMutex, receiverMutex);
QObjectConnectionListVector *connectionLists = s->d_func()->connectionLists;
@@ -2845,27 +2822,23 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
+ QObjectPrivate::Connection *c = connectionList[i];
if (c->receiver
&& (r == 0 || (c->receiver == r
&& (method_index < 0 || c->method == method_index)))) {
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
if (!receiverMutex && senderMutex != m) {
// need to relock this receiver and sender in the correct order
- bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
- c = &connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->derefSender(s, signal_index);
- if (needToUnlock)
- m->unlock();
- } else {
- // no need to unlock
- c->receiver->d_func()->derefSender(s, signal_index);
- }
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
+ if (c->receiver)
+ c->receiver->d_func()->senders.removeOne(c);
+
+ if (needToUnlock)
+ m->unlock();
+
c->receiver = 0;
success = true;
@@ -2876,27 +2849,22 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
} else if (signal_index < connectionLists->count()) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
+ QObjectPrivate::Connection *c = connectionList[i];
if (c->receiver
&& (r == 0 || (c->receiver == r
&& (method_index < 0 || c->method == method_index)))) {
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
if (!receiverMutex && senderMutex != m) {
// need to relock this receiver and sender in the correct order
- bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
- c = &connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->derefSender(s, signal_index);
- if (needToUnlock)
- m->unlock();
- } else {
- // no need to unlock
- c->receiver->d_func()->derefSender(s, signal_index);
- }
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
+ if (c->receiver)
+ c->receiver->d_func()->senders.removeOne(c);
+
+ if (needToUnlock)
+ m->unlock();
c->receiver = 0;
success = true;
@@ -2979,32 +2947,31 @@ void QMetaObject::connectSlotsByName(QObject *o)
}
}
-static void queued_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c,
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c,
void **argv, QSemaphore *semaphore = 0)
{
- if (!c.argumentTypes || c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
QMetaMethod m = sender->metaObject()->method(signal);
- QObjectPrivate::Connection &x = const_cast<QObjectPrivate::Connection &>(c);
int *tmp = queuedConnectionTypes(m.parameterTypes());
if (!tmp) // cannot queue arguments
tmp = &DIRECT_CONNECTION_ONLY;
- if (!x.argumentTypes.testAndSetOrdered(0, tmp)) {
+ if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
if (tmp != &DIRECT_CONNECTION_ONLY)
- qFree(tmp);
+ delete [] tmp;
}
}
- if (c.argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
+ if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
return;
int nargs = 1; // include return type
- while (c.argumentTypes[nargs-1])
+ while (c->argumentTypes[nargs-1])
++nargs;
int *types = (int *) qMalloc(nargs*sizeof(int));
void **args = (void **) qMalloc(nargs*sizeof(void *));
types[0] = 0; // return type
args[0] = 0; // return value
for (int n = 1; n < nargs; ++n)
- args[n] = QMetaType::construct((types[n] = c.argumentTypes[n-1]), argv[n]);
- QCoreApplication::postEvent(c.receiver, new QMetaCallEvent(c.method,
+ args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method,
sender,
signal,
nargs,
@@ -3013,13 +2980,13 @@ static void queued_activate(QObject *sender, int signal, const QObjectPrivate::C
semaphore));
}
-static void blocking_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c, void **argv)
+static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
- if (QThread::currentThread() == c.receiver->thread()) {
+ if (QThread::currentThread() == c->receiver->thread()) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
"Sender is %s(%p), receiver is %s(%p)",
sender->metaObject()->className(), sender,
- c.receiver->metaObject()->className(), c.receiver);
+ c->receiver->metaObject()->className(), c->receiver);
}
#ifdef QT_NO_THREAD
@@ -3027,7 +2994,7 @@ static void blocking_activate(QObject *sender, int signal, const QObjectPrivate:
#else
QSemaphore semaphore;
queued_activate(sender, signal, c, argv, &semaphore);
- QMutex *mutex = &QThreadData::get2(sender->thread())->mutex;
+ QMutex *mutex = signalSlotLock(sender);
mutex->unlock();
semaphore.acquire();
mutex->lock();
@@ -3047,7 +3014,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
argv ? argv : empty_argv);
}
- QMutexLocker locker(&sender->d_func()->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(sender));
QThreadData *currentThreadData = QThreadData::current();
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
@@ -3069,7 +3036,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
}
int count = connectionLists->at(signal).count();
for (int i = 0; i < count; ++i) {
- const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
+ QObjectPrivate::Connection *c = connectionLists->at(signal)[i];
if (!c->receiver)
continue;
@@ -3081,10 +3048,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
&& (currentThreadData != sender->d_func()->threadData
|| receiver->d_func()->threadData != sender->d_func()->threadData))
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal, *c, argv);
+ queued_activate(sender, signal, c, argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
- blocking_activate(sender, signal, *c, argv);
+ blocking_activate(sender, signal, c, argv);
continue;
}
@@ -3399,7 +3366,7 @@ void QObject::dumpObjectInfo()
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
@@ -3412,16 +3379,16 @@ void QObject::dumpObjectInfo()
// receivers
const QObjectPrivate::ConnectionList &connectionList = d->connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (!c.receiver) {
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (!c->receiver) {
qDebug(" <Disconnected receiver>");
continue;
}
- const QMetaObject *receiverMetaObject = c.receiver->metaObject();
- const QMetaMethod method = receiverMetaObject->method(c.method);
+ const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaMethod method = receiverMetaObject->method(c->method);
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
- c.receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c.receiver->objectName()),
+ c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
method.signature());
}
}
@@ -3434,13 +3401,12 @@ void QObject::dumpObjectInfo()
if (!d->senders.isEmpty()) {
for (int i = 0; i < d->senders.count(); ++i) {
- const QObjectPrivate::Sender &s = d->senders.at(i);
- const QMetaObject *senderMetaObject = s.sender->metaObject();
- const QMetaMethod signal = senderMetaObject->method(s.signal);
- qDebug(" <-- %s::%s %s",
- senderMetaObject->className(),
- s.sender->objectName().isEmpty() ? "unnamed" : qPrintable(s.sender->objectName()),
- signal.signature());
+ const QObjectPrivate::Connection *s = d->senders.at(i);
+ const QMetaMethod slot = metaObject()->method(s->method);
+ qDebug(" <-- %s::%s %s",
+ s->sender->metaObject()->className(),
+ s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
+ slot.signature());
}
} else {
qDebug(" <None>");
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index b324334..96d79af 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -114,7 +114,6 @@ public:
int signal;
int ref;
};
-
// object currently activating the object
Sender *currentSender;
@@ -148,22 +147,20 @@ public:
// Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions
struct Connection
{
+ QObject *sender;
QObject *receiver;
int method;
uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
QBasicAtomicPointer<int> argumentTypes;
+ ~Connection();
};
- typedef QList<Connection> ConnectionList;
+ typedef QList<Connection *> ConnectionList;
QObjectConnectionListVector *connectionLists;
void addConnection(int signal, Connection *c);
- void removeReceiver(int signal, QObject *receiver);
void cleanConnectionLists();
- QList<Sender> senders;
- void refSender(QObject *sender, int signal);
- void derefSender(QObject *sender, int signal);
- void removeSender(QObject *sender, int signal);
+ ConnectionList senders;
static Sender *setCurrentSender(QObject *receiver,
Sender *sender);
@@ -208,7 +205,7 @@ private:
QSemaphore *semaphore_;
};
-class Q_CORE_EXPORT QBoolBlocker
+class QBoolBlocker
{
public:
inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 9853079..87e154f 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -129,6 +129,10 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
detached from the segment, and no references to the segment
remain. Do not mix using QtSharedMemory and QSharedMemory. Port
everything to QSharedMemory.
+
+ \warning QSharedMemory changes the key in a Qt-specific way.
+ It is therefore currently not possible to use the shared memory of
+ non-Qt applications with QSharedMemory.
*/
/*!
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index 487c653..cd248dc 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -47,12 +47,9 @@
#include <qdir.h>
#include <qdebug.h>
-#include <errno.h>
-
-QT_BEGIN_NAMESPACE
-
#ifndef QT_NO_SHAREDMEMORY
+#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -61,6 +58,8 @@ QT_BEGIN_NAMESPACE
#include <fcntl.h>
#include <unistd.h>
+QT_BEGIN_NAMESPACE
+
QSharedMemoryPrivate::QSharedMemoryPrivate()
: QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
#ifndef QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 01e81ab..4b3feb0 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE
In multithreaded applications, you can use QTimer in any thread
that has an event loop. To start an event loop from a non-GUI
- thread, use QThread::exec(). Qt uses the the timer's
+ thread, use QThread::exec(). Qt uses the timer's
\l{QObject::thread()}{thread affinity} to determine which thread
will emit the \l{QTimer::}{timeout()} signal. Because of this, you
must start and stop the timer in its thread; it is not possible to
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index b4427c0..2ff9818 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -71,27 +71,6 @@ QT_BEGIN_NAMESPACE
# define FLT_DIG 6
#endif
-
-static const void *constDataHelper(const QVariant::Private &d)
-{
- switch (d.type) {
- case QVariant::Int:
- return &d.data.i;
- case QVariant::UInt:
- return &d.data.u;
- case QVariant::Bool:
- return &d.data.b;
- case QVariant::LongLong:
- return &d.data.ll;
- case QVariant::ULongLong:
- return &d.data.ull;
- case QVariant::Double:
- return &d.data.d;
- default:
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
- }
-}
-
static void construct(QVariant::Private *x, const void *copy)
{
x->is_shared = false;
@@ -179,6 +158,9 @@ static void construct(QVariant::Private *x, const void *copy)
case QVariant::Double:
x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
break;
+ case QMetaType::Float:
+ x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
+ break;
case QVariant::LongLong:
x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
break;
@@ -274,6 +256,7 @@ static void clear(QVariant::Private *d)
case QVariant::LongLong:
case QVariant::ULongLong:
case QVariant::Double:
+ case QMetaType::Float:
break;
case QVariant::Invalid:
case QVariant::UserType:
@@ -342,6 +325,7 @@ static bool isNull(const QVariant::Private *d)
case QVariant::ULongLong:
case QVariant::Bool:
case QVariant::Double:
+ case QMetaType::Float:
break;
}
return d->is_null;
@@ -433,6 +417,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
return a->data.b == b->data.b;
case QVariant::Double:
return a->data.d == b->data.d;
+ case QMetaType::Float:
+ return a->data.f == b->data.f;
case QVariant::Date:
return *v_cast<QDate>(a) == *v_cast<QDate>(b);
case QVariant::Time:
@@ -491,7 +477,7 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
case QMetaType::Long:
return qlonglong(*static_cast<long *>(d->data.shared->ptr));
case QMetaType::Float:
- return qRound64(*static_cast<float *>(d->data.shared->ptr));
+ return qRound64(d->data.f);
case QVariant::Double:
return qRound64(d->data.d);
}
@@ -628,7 +614,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*str = QString::number(qMetaTypeUNumber(d));
break;
case QMetaType::Float:
- *str = QString::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG);
+ *str = QString::number(d->data.f, 'g', FLT_DIG);
break;
case QVariant::Double:
*str = QString::number(d->data.d, 'g', DBL_DIG);
@@ -799,7 +785,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*ba = QByteArray::number(d->data.d, 'g', DBL_DIG);
break;
case QMetaType::Float:
- *ba = QByteArray::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG);
+ *ba = QByteArray::number(d->data.f, 'g', FLT_DIG);
break;
case QMetaType::Char:
case QMetaType::UChar:
@@ -901,7 +887,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*f = double(d->data.b);
break;
case QMetaType::Float:
- *f = *static_cast<float *>(d->data.shared->ptr);
+ *f = double(d->data.f);
break;
case QVariant::LongLong:
case QVariant::Int:
@@ -1035,7 +1021,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
static void streamDebug(QDebug dbg, const QVariant &v)
{
- switch (v.type()) {
+ switch (v.userType()) {
case QVariant::Int:
dbg.nospace() << v.toInt();
break;
@@ -1048,6 +1034,9 @@ static void streamDebug(QDebug dbg, const QVariant &v)
case QVariant::ULongLong:
dbg.nospace() << v.toULongLong();
break;
+ case QMetaType::Float:
+ dbg.nospace() << qVariantValue<float>(v);
+ break;
case QVariant::Double:
dbg.nospace() << v.toDouble();
break;
@@ -1187,8 +1176,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
and versatile, but may prove less memory and speed efficient than
storing specific types in standard data structures.
- QVariant also supports the notion of null values, where you have
- a defined type with no value set.
+ QVariant also supports the notion of null values, where you can
+ have a defined type with no value set. However, note that QVariant
+ types can only be cast when they have had a value set.
\snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1
@@ -1355,7 +1345,7 @@ void QVariant::create(int type, const void *copy)
QVariant::~QVariant()
{
- if (d.type > Char && (!d.is_shared || !d.data.shared->ref.deref()))
+ if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref()))
handler->clear(&d);
}
@@ -1371,7 +1361,7 @@ QVariant::QVariant(const QVariant &p)
{
if (d.is_shared) {
d.data.shared->ref.ref();
- } else if (p.d.type > Char) {
+ } else if (p.d.type > Char && p.d.type != QMetaType::Float) {
handler->construct(&d, p.constData());
d.is_null = p.d.is_null;
}
@@ -1565,6 +1555,12 @@ QVariant::QVariant(const char *val)
*/
/*!
+ \fn QVariant::QVariant(float val)
+
+ Constructs a new variant with a floating point value, \a val.
+*/
+
+/*!
\fn QVariant::QVariant(const QList<QVariant> &val)
Constructs a new variant with a list value, \a val.
@@ -1619,44 +1615,44 @@ QVariant::QVariant(double val)
{ d.is_null = false; d.type = Double; d.data.d = val; }
QVariant::QVariant(const QByteArray &val)
-{ create(ByteArray, &val); }
+{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); }
QVariant::QVariant(const QBitArray &val)
-{ create(BitArray, &val); }
+{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); }
QVariant::QVariant(const QString &val)
-{ create(String, &val); }
+{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); }
QVariant::QVariant(const QChar &val)
-{ create (Char, &val); }
+{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); }
QVariant::QVariant(const QLatin1String &val)
-{ QString str(val); create(String, &str); }
+{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
QVariant::QVariant(const QStringList &val)
-{ create(StringList, &val); }
+{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); }
QVariant::QVariant(const QDate &val)
-{ create(Date, &val); }
+{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); }
QVariant::QVariant(const QTime &val)
-{ create(Time, &val); }
+{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); }
QVariant::QVariant(const QDateTime &val)
-{ create(DateTime, &val); }
+{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); }
QVariant::QVariant(const QList<QVariant> &list)
-{ create(List, &list); }
+{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); }
QVariant::QVariant(const QMap<QString, QVariant> &map)
-{ create(Map, &map); }
+{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); }
QVariant::QVariant(const QHash<QString, QVariant> &hash)
-{ create(Hash, &hash); }
+{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, hash); }
#ifndef QT_NO_GEOM_VARIANT
-QVariant::QVariant(const QPoint &pt) { create(Point, &pt); }
-QVariant::QVariant(const QPointF &pt) { create (PointF, &pt); }
-QVariant::QVariant(const QRectF &r) { create (RectF, &r); }
-QVariant::QVariant(const QLineF &l) { create (LineF, &l); }
-QVariant::QVariant(const QLine &l) { create (Line, &l); }
-QVariant::QVariant(const QRect &r) { create(Rect, &r); }
-QVariant::QVariant(const QSize &s) { create(Size, &s); }
-QVariant::QVariant(const QSizeF &s) { create(SizeF, &s); }
+QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); }
+QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); }
+QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); }
+QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); }
+QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); }
+QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); }
+QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); }
+QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); }
#endif
-QVariant::QVariant(const QUrl &u) { create(Url, &u); }
-QVariant::QVariant(const QLocale &l) { create(Locale, &l); }
+QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
#ifndef QT_NO_REGEXP
-QVariant::QVariant(const QRegExp &regExp) { create(RegExp, &regExp); }
+QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
#endif
QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
@@ -1721,7 +1717,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
if (variant.d.is_shared) {
variant.d.data.shared->ref.ref();
d = variant.d;
- } else if (variant.d.type > Char) {
+ } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) {
d.type = variant.d.type;
handler->construct(&d, variant.constData());
d.is_null = variant.d.is_null;
@@ -1907,7 +1903,7 @@ void QVariant::load(QDataStream &s)
}
// const cast is safe since we operate on a newly constructed variant
- if (!QMetaType::load(s, d.type, const_cast<void *>(constDataHelper(d)))) {
+ if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unable to load type %d.", d.type);
}
@@ -1947,7 +1943,7 @@ void QVariant::save(QDataStream &s) const
return;
}
- if (!QMetaType::save(s, d.type, constDataHelper(d))) {
+ if (!QMetaType::save(s, d.type, constData())) {
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
qWarning("QVariant::save: unable to save type %d.", d.type);
}
@@ -2565,57 +2561,63 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
*/
bool QVariant::canConvert(Type t) const
{
- if (d.type == uint(t))
+ //we can treat floats as double
+ //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
+ //which can't be handled by qCanConvertMatrix
+ //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
+ if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+
+ if (currentType == uint(t))
return true;
- if (d.type > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
switch (uint(t)) {
case QVariant::Int:
- return d.type == QVariant::KeySequence
- || d.type == QMetaType::ULong
- || d.type == QMetaType::Long
- || d.type == QMetaType::UShort
- || d.type == QMetaType::UChar
- || d.type == QMetaType::Char
- || d.type == QMetaType::Short;
+ return currentType == QVariant::KeySequence
+ || currentType == QMetaType::ULong
+ || currentType == QMetaType::Long
+ || currentType == QMetaType::UShort
+ || currentType == QMetaType::UChar
+ || currentType == QMetaType::Char
+ || currentType == QMetaType::Short;
case QVariant::Image:
- return d.type == QVariant::Pixmap || d.type == QVariant::Bitmap;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
case QVariant::Pixmap:
- return d.type == QVariant::Image || d.type == QVariant::Bitmap
- || d.type == QVariant::Brush;
+ return currentType == QVariant::Image || currentType == QVariant::Bitmap
+ || currentType == QVariant::Brush;
case QVariant::Bitmap:
- return d.type == QVariant::Pixmap || d.type == QVariant::Image;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Image;
case QVariant::ByteArray:
- return d.type == QVariant::Color;
+ return currentType == QVariant::Color;
case QVariant::String:
- return d.type == QVariant::KeySequence || d.type == QVariant::Font
- || d.type == QVariant::Color;
+ return currentType == QVariant::KeySequence || currentType == QVariant::Font
+ || currentType == QVariant::Color;
case QVariant::KeySequence:
- return d.type == QVariant::String || d.type == QVariant::Int;
+ return currentType == QVariant::String || currentType == QVariant::Int;
case QVariant::Font:
- return d.type == QVariant::String;
+ return currentType == QVariant::String;
case QVariant::Color:
- return d.type == QVariant::String || d.type == QVariant::ByteArray
- || d.type == QVariant::Brush;
+ return currentType == QVariant::String || currentType == QVariant::ByteArray
+ || currentType == QVariant::Brush;
case QVariant::Brush:
- return d.type == QVariant::Color || d.type == QVariant::Pixmap;
+ return currentType == QVariant::Color || currentType == QVariant::Pixmap;
case QMetaType::Long:
case QMetaType::Char:
case QMetaType::UChar:
case QMetaType::ULong:
case QMetaType::Short:
case QMetaType::UShort:
- case QMetaType::Float:
- return qCanConvertMatrix[QVariant::Int] & (1 << d.type) || d.type == QVariant::Int;
+ return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
default:
return false;
}
}
- if(t == String && d.type == StringList)
+ if(t == String && currentType == StringList)
return v_cast<QStringList>(&d)->count() == 1;
else
- return qCanConvertMatrix[t] & (1 << d.type);
+ return qCanConvertMatrix[t] & (1 << currentType);
}
/*!
@@ -2726,7 +2728,7 @@ bool QVariant::cmp(const QVariant &v) const
const void *QVariant::constData() const
{
- return constDataHelper(d);
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
}
/*!
@@ -2739,7 +2741,7 @@ const void *QVariant::constData() const
void* QVariant::data()
{
detach();
- return const_cast<void *>(constDataHelper(d));
+ return const_cast<void *>(constData());
}
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index d7b7e3c..d73fcbc 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -181,6 +181,7 @@ class Q_CORE_EXPORT QVariant
QVariant(qulonglong ull);
QVariant(bool b);
QVariant(double d);
+ QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
#endif
@@ -349,6 +350,7 @@ class Q_CORE_EXPORT QVariant
uint u;
bool b;
double d;
+ float f;
qlonglong ll;
qulonglong ull;
void *ptr;
@@ -443,7 +445,18 @@ inline QVariant qVariantFromValue(const QVariant &t) { return t; }
template <typename T>
inline void qVariantSetValue(QVariant &v, const T &t)
{
- v = QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t);
+ //if possible we reuse the current QVariant private
+ const int type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
+ QVariant::Private &d = v.data_ptr();
+ if (type <= int(QVariant::Char) || (type == d.type && v.isDetached())) {
+ d.type = type;
+ T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
+ if (QTypeInfo<T>::isComplex)
+ old->~T();
+ new (old) T(t); //call the copy constructor
+ } else {
+ v = QVariant(type, &t);
+ }
}
inline QVariant::QVariant() {}
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 0764fe3..033b760 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -60,8 +60,6 @@
QT_BEGIN_NAMESPACE
-extern Q_CORE_EXPORT const QVariant::Handler *qExtendedVariantHandler;
-
#ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack
template <typename T>
@@ -70,7 +68,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0)
QVariant::Private *d = const_cast<QVariant::Private *>(nd);
return ((sizeof(T) > sizeof(QVariant::Private::Data))
? static_cast<T *>(d->data.shared->ptr)
- : reinterpret_cast<T*>(&d->data.c));
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
}
#else // every other compiler in this world
@@ -80,7 +78,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0)
{
return ((sizeof(T) > sizeof(QVariant::Private::Data))
? static_cast<const T *>(d->data.shared->ptr)
- : reinterpret_cast<const T *>(&d->data.c));
+ : static_cast<const T *>(static_cast<const void *>(&d->data.c)));
}
template <typename T>
@@ -88,15 +86,17 @@ inline T *v_cast(QVariant::Private *d, T * = 0)
{
return ((sizeof(T) > sizeof(QVariant::Private::Data))
? static_cast<T *>(d->data.shared->ptr)
- : reinterpret_cast<T *>(&d->data.c));
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
}
#endif
-//a simple template that avoids to allocate 2 buffers when creating a QVariant
+
+//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
{
public:
+ QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t) { }
QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
private:
@@ -105,14 +105,12 @@ private:
// constructs a new variant if copy is 0, otherwise copy-constructs
template <class T>
-inline void v_construct(QVariant::Private *x, const T& t)
+inline void v_construct(QVariant::Private *x, const T &t)
{
- x->type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
x->data.shared = new QVariantPrivateSharedEx<T>(t);
x->is_shared = true;
} else {
- x->is_shared = false;
new (&x->data.ptr) T(t);
}
}
@@ -120,24 +118,31 @@ inline void v_construct(QVariant::Private *x, const T& t)
template <class T>
inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
{
- if (copy) {
- v_construct<T>(x, *reinterpret_cast<const T*>(copy));
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
+ : new QVariantPrivateSharedEx<T>;
+ x->is_shared = true;
} else {
- T t;
- v_construct<T>(x, t);
+ if (copy)
+ new (&x->data.ptr) T(*static_cast<const T *>(copy));
+ else
+ new (&x->data.ptr) T;
}
}
-
// deletes the internal structures
template <class T>
inline void v_clear(QVariant::Private *d, T* = 0)
{
- //now we need to call the destructor in any case
- //because QVariant::PrivateShared doesn't have a virtual destructor
- v_cast<T>(d)->~T();
- if (sizeof(T) > sizeof(QVariant::Private::Data))
- delete d->data.shared;
+
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ //now we need to cast
+ //because QVariant::PrivateShared doesn't have a virtual destructor
+ delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
+ } else {
+ v_cast<T>(d)->~T();
+ }
+
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index 4d0e53c..121a875 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -63,6 +63,21 @@ typedef QObject *(*QtPluginInstanceFunction)();
void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function);
+struct qt_plugin_instance_deleter
+{
+ qt_plugin_instance_deleter(QPointer<QObject> &instance)
+ : instance_(instance)
+ {
+ }
+
+ ~qt_plugin_instance_deleter()
+ {
+ delete instance_;
+ }
+
+ QPointer<QObject> &instance_;
+};
+
#define Q_IMPORT_PLUGIN(PLUGIN) \
extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \
class Static##PLUGIN##PluginInstance{ \
@@ -76,8 +91,10 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
{ \
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
- if (!_instance) \
+ if (!_instance) { \
+ static QT_PREPEND_NAMESPACE(qt_plugin_instance_deleter) deleter(_instance); \
_instance = new IMPLEMENTATION; \
+ } \
return _instance; \
}
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 65f49ae..744515b 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1306,7 +1306,7 @@ static int senderSignalIndex(const QObject *sender)
// Return -1 if d->currentSender isn't in d->senders
bool found = false;
for (int i = 0; !found && i < d->senders.count(); ++i)
- found = (d->senders.at(i).sender == d->currentSender->sender);
+ found = (d->senders.at(i)->sender == d->currentSender->sender);
if (!found)
return -1;
return d->currentSender->signal;
diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h
index 633e92c..970cbcc 100644
--- a/src/corelib/tools/qbytearraymatcher.h
+++ b/src/corelib/tools/qbytearraymatcher.h
@@ -70,7 +70,7 @@ public:
inline QByteArray pattern() const
{
if (q_pattern.isNull())
- return QByteArray((const char*)p.p, p.l);
+ return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
return q_pattern;
}
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
new file mode 100644
index 0000000..7db3a5a
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -0,0 +1,435 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontiguouscache.h"
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+void QContiguousCacheData::dump() const
+{
+ qDebug() << "capacity:" << alloc;
+ qDebug() << "count:" << count;
+ qDebug() << "start:" << start;
+ qDebug() << "offset:" << offset;
+}
+
+/*! \class QContiguousCache
+ \brief The QContiguousCache class is a template class that provides a contiguous cache.
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+ The QContiguousCache class provides an efficient way of caching items for
+ display in a user interface view. Unlike QCache, it adds a restriction
+ that elements within the cache are contiguous. This has the advantage
+ of matching how user interface views most commonly request data, as
+ a set of rows localized around the current scrolled position. This
+ restriction allows the cache to consume less memory and processor
+ cycles than QCache. The QContiguousCache class also can provide
+ an upper bound on memory usage via setCapacity().
+
+ The simplest way of using a contiguous cache is to use the append()
+ and prepend().
+
+\code
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while(row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while(row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+\endcode
+
+ If the cache is full then the item at the opposite end of the cache from
+ where the new item is appended or prepended will be removed.
+
+ This usage can be further optimized by using the insert() function
+ in the case where the requested row is a long way from the currently cached
+ items. If there is a gap between where the new item is inserted and the currently
+ cached items then the existing cached items are first removed to retain
+ the contiguous nature of the cache. Hence it is important to take some care then
+ when using insert() in order to avoid unwanted clearing of the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Calling prepend() such that the first index would become less
+ than 0 or append() such that the last index would become greater
+ than INT_MAX can result in the indexes of the cache being invalid.
+ When the cache indexes are invalid it is important to call
+ normalizeIndexes() before calling any of containsIndex(), firstIndex(),
+ lastIndex(), at() or the [] operator. Calling these
+ functions when the cache has invalid indexes will result in undefined
+ behavior. The indexes can be checked by using areIndexesValid()
+
+ In most cases the indexes will not exceed 0 to INT_MAX, and
+ normalizeIndexes() will not need to be used.
+
+ See the \l{Contiguous Cache Example}{Contiguous Cache} example.
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(int capacity)
+
+ Constructs a cache with the given \a capacity.
+
+ \sa setCapacity()
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QContiguousCache is
+ \l{implicitly shared}. This makes returning a QContiguousCache from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QContiguousCache::~QContiguousCache()
+
+ Destroys the cache.
+*/
+
+/*! \fn void QContiguousCache::detach()
+
+ \internal
+*/
+
+/*! \fn bool QContiguousCache::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QContiguousCache::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
+
+ Assigns \a other to this cache and returns a reference to this cache.
+*/
+
+/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is equal to this cache; otherwise returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is not equal to this cache; otherwise
+ returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QContiguousCache::capacity() const
+
+ Returns the number of items the cache can store before it is full.
+ When a cache contains a number of items equal to its capacity, adding new
+ items will cause items farthest from the added item to be removed.
+
+ \sa setCapacity(), size()
+*/
+
+/*! \fn int QContiguousCache::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn int QContiguousCache::size() const
+
+ Returns the number of items contained within the cache.
+
+ \sa capacity()
+*/
+
+/*! \fn bool QContiguousCache::isEmpty() const
+
+ Returns true if no items are stored within the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn bool QContiguousCache::isFull() const
+
+ Returns true if the number of items stored within the cache is equal
+ to the capacity of the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn int QContiguousCache::available() const
+
+ Returns the number of items that can be added to the cache before it becomes full.
+
+ \sa size(), capacity(), isFull()
+*/
+
+/*! \fn void QContiguousCache::clear()
+
+ Removes all items from the cache. The capacity is unchanged.
+*/
+
+/*! \fn void QContiguousCache::setCapacity(int size)
+
+ Sets the capacity of the cache to the given \a size. A cache can hold a
+ number of items equal to its capacity. When inserting, appending or prepending
+ items to the cache, if the cache is already full then the item farthest from
+ the added item will be removed.
+
+ If the given \a size is smaller than the current count of items in the cache
+ then only the last \a size items from the cache will remain.
+
+ \sa capacity(), isFull()
+*/
+
+/*! \fn const T &QContiguousCache::at(int i) const
+
+ Returns the item at index position \a i in the cache. \a i must
+ be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
+
+ The indexes in the cache refer to the number of positions the item is from the
+ first item appended into the cache. That is to say a cache with a capacity of
+ 100, that has had 150 items appended will have a valid index range of
+ 50 to 149. This allows inserting and retrieving items into the cache based
+ on a theoretical infinite list
+
+ \sa firstIndex(), lastIndex(), insert(), operator[]()
+*/
+
+/*! \fn T &QContiguousCache::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference. If
+ the cache does not contain an item at the given index position \a i
+ then it will first insert an empty item at that position.
+
+ In most cases it is better to use either at() or insert().
+
+ Note that using non-const operators can cause QContiguousCache to do a deep
+ copy.
+
+ \sa insert(), at()
+*/
+
+/*! \fn const T &QContiguousCache::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn void QContiguousCache::append(const T &value)
+
+ Inserts \a value at the end of the cache. If the cache is already full
+ the item at the start of the cache will be removed.
+
+ \sa prepend(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::prepend(const T &value)
+
+ Inserts \a value at the start of the cache. If the cache is already full
+ the item at the end of the cache will be removed.
+
+ \sa append(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::insert(int i, const T &value)
+
+ Inserts the \a value at the index position \a i. If the cache already contains
+ an item at \a i then that value is replaced. If \a i is either one more than
+ lastIndex() or one less than firstIndex() it is the equivalent to an append()
+ or a prepend().
+
+ If the given index \a i is not within the current range of the cache nor adjacent
+ to the bounds of the cache's index range, the cache is first cleared before
+ inserting the item. At this point the cache will have a size of 1. It is
+ worthwhile taking effort to insert items in an order that starts adjacent
+ to the current index range for the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Inserting outside of this range has undefined behavior.
+
+
+ \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
+*/
+
+/*! \fn bool QContiguousCache::containsIndex(int i) const
+
+ Returns true if the cache's index range includes the given index \a i.
+
+ \sa firstIndex(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::firstIndex() const
+
+ Returns the first valid index in the cache. The index will be invalid if the
+ cache is empty.
+
+ \sa capacity(), size(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::lastIndex() const
+
+ Returns the last valid index in the cache. The index will be invalid if the cache is empty.
+
+ \sa capacity(), size(), firstIndex()
+*/
+
+
+/*! \fn T &QContiguousCache::first()
+
+ Returns a reference to the first item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn T &QContiguousCache::last()
+
+ Returns a reference to the last item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QContiguousCache::first() const
+
+ \overload
+*/
+
+/*! \fn const T& QContiguousCache::last() const
+
+ \overload
+*/
+
+/*! \fn void QContiguousCache::removeFirst()
+
+ Removes the first item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeLast()
+*/
+
+/*! \fn void QContiguousCache::removeLast()
+
+ Removes the last item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeFirst()
+
+ Removes the first item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeFirst() is more efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeLast()
+
+ Removes the last item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeLast() is more efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QContiguousCache::normalizeIndexes()
+
+ Moves the first index and last index of the cache
+ such that they point to valid indexes. The function does not modify
+ the contents of the cache or the ordering of elements within the cache.
+
+ It is provided so that index overflows can be corrected when using the
+ cache as a circular buffer.
+
+ \code
+ QContiguousCache<int> cache(10);
+ cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+ cache.append(2); // cache contains two values but does not have valid indexes.
+ cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+ \endcode
+
+ \sa areIndexesValid(), append(), prepend()
+*/
+
+/*! \fn bool QContiguousCache::areIndexesValid() const
+
+ Returns whether the indexes for items stored in the cache are valid.
+ Indexes can become invalid if items are appended after the index position
+ INT_MAX or prepended before the index position 0. This is only expected
+ to occur in very long lived circular buffer style usage of the
+ contiguous cache. Indexes can be made valid again by calling
+ normalizeIndexs().
+
+ \sa normalizeIndexes(), append(), prepend()
+*/
+
+/*! \fn void QContiguousCache::dump() const
+
+ \internal
+
+ Sends information about the cache's internal structure to qDebug()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
new file mode 100644
index 0000000..5cd1582
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTIGUOUSCACHE_H
+#define QCONTIGUOUSCACHE_H
+
+#include <QtCore/qatomic.h>
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QContiguousCacheData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+
+ void dump() const;
+};
+
+template <typename T>
+struct QContiguousCacheTypedData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+
+ T array[1];
+};
+
+template<typename T>
+class QContiguousCache {
+ typedef QContiguousCacheTypedData<T> Data;
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; };
+public:
+ explicit QContiguousCache(int capacity = 0);
+ QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+
+ inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+
+ QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
+ bool operator==(const QContiguousCache<T> &other) const;
+ inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ inline int capacity() const {return d->alloc; }
+ inline int count() const { return d->count; }
+ inline int size() const { return d->count; }
+
+ inline bool isEmpty() const { return d->count == 0; }
+ inline bool isFull() const { return d->count == d->alloc; }
+ inline int available() const { return d->alloc - d->count; }
+
+ void clear();
+ void setCapacity(int size);
+
+ const T &at(int pos) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+
+ void append(const T &value);
+ void prepend(const T &value);
+ void insert(int pos, const T &value);
+
+ inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; }
+ inline int firstIndex() const { return d->offset; }
+ inline int lastIndex() const { return d->offset + d->count - 1; }
+
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; }
+ inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; }
+ inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; }
+
+ void removeFirst();
+ T takeFirst();
+ void removeLast();
+ T takeLast();
+
+ inline bool areIndexesValid() const
+ { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; }
+
+ inline void normalizeIndexes() { d->offset = d->start; }
+ // debug
+ void dump() const { p->dump(); }
+private:
+ void detach_helper();
+
+ QContiguousCacheData *malloc(int aalloc);
+ void free(Data *x);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+};
+
+template <typename T>
+void QContiguousCache<T>::detach_helper()
+{
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->count = d->count;
+ x.d->start = d->start;
+ x.d->offset = d->offset;
+ x.d->alloc = d->alloc;
+ x.d->sharable = true;
+
+ T *dest = x.d->array + x.d->start;
+ T *src = d->array + d->start;
+ int count = x.d->count;
+ while (count--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ dest++;
+ if (dest == x.d->array + x.d->alloc)
+ dest = x.d->array;
+ src++;
+ if (src == d->array + d->alloc)
+ src = d->array;
+ }
+
+ if (!d->ref.deref())
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::setCapacity(int asize)
+{
+ if (asize == d->alloc)
+ return;
+ detach();
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(asize);
+ x.d->alloc = asize;
+ x.d->count = qMin(d->count, asize);
+ x.d->offset = d->offset + d->count - x.d->count;
+ x.d->start = x.d->offset % x.d->alloc;
+ T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc;
+ T *src = d->array + (d->start + d->count-1) % d->alloc;
+ int count = x.d->count;
+ while (count--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ if (dest == x.d->array)
+ dest = x.d->array + x.d->alloc;
+ dest--;
+ if (src == d->array)
+ src = d->array + d->alloc;
+ src--;
+ }
+ /* free old */
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::clear()
+{
+ if (d->ref == 1) {
+ if (QTypeInfo<T>::isComplex) {
+ int count = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (count--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ d->count = d->start = d->offset = 0;
+ } else {
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->alloc = d->alloc;
+ x.d->count = x.d->start = x.d->offset = 0;
+ x.d->sharable = true;
+ if (!d->ref.deref()) free(d);
+ d = x.d;
+ }
+}
+
+template <typename T>
+inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
+{
+ return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+}
+
+template <typename T>
+QContiguousCache<T>::QContiguousCache(int capacity)
+{
+ p = malloc(capacity);
+ d->ref = 1;
+ d->alloc = capacity;
+ d->count = d->start = d->offset = 0;
+ d->sharable = true;
+}
+
+template <typename T>
+QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = other.d;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+template <typename T>
+bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
+{
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (int i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+}
+
+template <typename T>
+void QContiguousCache<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ int count = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (count--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ qFree(x);
+}
+template <typename T>
+void QContiguousCache<T>::append(const T &value)
+{
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ if (d->count == d->alloc)
+ (d->array + (d->start+d->count) % d->alloc)->~T();
+ new (d->array + (d->start+d->count) % d->alloc) T(value);
+ } else {
+ d->array[(d->start+d->count) % d->alloc] = value;
+ }
+
+ if (d->count == d->alloc) {
+ d->start++;
+ d->start %= d->alloc;
+ d->offset++;
+ } else {
+ d->count++;
+ }
+}
+
+template<typename T>
+void QContiguousCache<T>::prepend(const T &value)
+{
+ detach();
+ if (d->start)
+ d->start--;
+ else
+ d->start = d->alloc-1;
+ d->offset--;
+
+ if (d->count != d->alloc)
+ d->count++;
+ else
+ if (d->count == d->alloc)
+ (d->array + d->start)->~T();
+
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+}
+
+template<typename T>
+void QContiguousCache<T>::insert(int pos, const T &value)
+{
+ Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+ detach();
+ if (containsIndex(pos)) {
+ if(QTypeInfo<T>::isComplex)
+ new (d->array + pos % d->alloc) T(value);
+ else
+ d->array[pos % d->alloc] = value;
+ } else if (pos == d->offset-1)
+ prepend(value);
+ else if (pos == d->offset+d->count)
+ append(value);
+ else {
+ // we don't leave gaps.
+ clear();
+ d->offset = pos;
+ d->start = pos % d->alloc;
+ d->count = 1;
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+ }
+}
+
+template <typename T>
+inline const T &QContiguousCache<T>::at(int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+template <typename T>
+inline const T &QContiguousCache<T>::operator[](int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+
+template <typename T>
+inline T &QContiguousCache<T>::operator[](int pos)
+{
+ detach();
+ if (!containsIndex(pos))
+ insert(pos, T());
+ return d->array[pos % d->alloc];
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeFirst()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + d->start)->~T();
+ d->start = (d->start + 1) % d->alloc;
+ d->offset++;
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeLast()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + (d->start + d->count) % d->alloc)->~T();
+}
+
+template <typename T>
+inline T QContiguousCache<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+
+template <typename T>
+inline T QContiguousCache<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qdumper.cpp b/src/corelib/tools/qdumper.cpp
deleted file mode 100644
index c3b8524..0000000
--- a/src/corelib/tools/qdumper.cpp
+++ /dev/null
@@ -1,1157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, 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.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdatetime.h>
-#include <qdebug.h>
-#include <qdir.h>
-#include <qfileinfo.h>
-#include <qhash.h>
-#include <qmap.h>
-#include <qmetaobject.h>
-#include <qobject.h>
-#include <qstring.h>
-#include <qvariant.h>
-#include <qvector.h>
-
-#if !defined(Q_OS_WINCE) && !defined(QT_NO_DUMPER)
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef Q_OS_WIN
-# include <windows.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
-// This is used to abort evaluation of custom data dumpers in a "coordinated"
-// way. Abortion will happen anyway when we try to access a non-initialized
-// non-trivial object, so there is no way to prevent this from occuring at all
-// conceptionally. Gdb will catch SIGSEGV and return to the calling frame.
-// This is just fine provided we only _read_ memory in the custom handlers
-// below.
-
-volatile int qProvokeSegFaultHelper;
-
-static void qCheckAccess(const void *d)
-{
- // provoke segfault when address is not readable
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qCheckPointer(const void *d)
-{
- if (!d)
- return;
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qProvokeSegFault()
-{
- // provoke segfault unconditionally
- qCheckAccess(0);
-}
-
-static char qDumpInBuffer[100];
-static char qDumpBuffer[1000];
-#ifdef Q_OS_WIN
-static char qDumpBuffer2[sizeof(qDumpBuffer) + 100];
-#endif
-
-static char toHex(int n)
-{
- return n < 10 ? '0' + n : 'a' - 10 + n;
-}
-
-
-struct QDumper
-{
- explicit QDumper();
- ~QDumper();
- void flush();
- QDumper &operator<<(long c);
- QDumper &operator<<(int i);
- QDumper &operator<<(unsigned long c);
- QDumper &operator<<(unsigned int i);
- QDumper &operator<<(const void *p);
- void put(char c);
- void addCommaIfNeeded();
- void putEncoded(unsigned c);
- QDumper &operator<<(const char *str);
- QDumper &operator<<(const QString &str);
- void disarm();
-
- void beginHash(); // start of data hash output
- void endHash(); // start of data hash output
-
- // the dumper arguments
- int protocolVersion; // dumper protocol version
- int token; // some token to show on success
- const char *outertype; // object type
- const char *iname; // object name used for display
- const char *exp; // object expression
- const char *innertype; // 'inner type' for class templates
- const void *data; // pointer to raw data
- bool dumpChildren; // do we want to see children?
-
- // handling of nested templates
- void setupTemplateParameters();
- enum { maxTemplateParameters = 10 };
- const char *templateParameters[maxTemplateParameters + 1];
- int templateParametersCount;
-
- // internal state
- bool success; // are we finished?
- size_t pos;
-};
-
-
-QDumper::QDumper()
-{
- success = false;
- pos = 0;
-}
-
-QDumper::~QDumper()
-{
- flush();
- put(0); // our end marker
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD/%d/done\n", token);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d/done\n", token);
-#endif
- qDumpInBuffer[0] = 0;
-}
-
-void QDumper::flush()
-{
- qDumpBuffer[pos++] = 0;
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD#%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
-#endif
- pos = 0;
-}
-
-void QDumper::setupTemplateParameters()
-{
- char *s = const_cast<char *>(innertype);
-
- templateParametersCount = 1;
- templateParameters[0] = s;
- for (int i = 1; i != maxTemplateParameters + 1; ++i)
- templateParameters[i] = 0;
-
- while (*s) {
- while (*s && *s != '@')
- ++s;
- if (*s) {
- *s = '\0';
- ++s;
- templateParameters[templateParametersCount++] = s;
- }
- }
-}
-
-QDumper &QDumper::operator<<(unsigned long c)
-{
- static char buf[100];
- sprintf(buf, "%lu", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(unsigned int i)
-{
- static char buf[100];
- sprintf(buf, "%u", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(long c)
-{
- static char buf[100];
- sprintf(buf, "%ld", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(int i)
-{
- static char buf[100];
- sprintf(buf, "%d", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(const void *p)
-{
- static char buf[100];
- sprintf(buf, "%p", p);
- // we get a '0x' prefix only on some implementations.
- // if it isn't there, write it out manually.
- if (buf[1] != 'x') {
- put('0');
- put('x');
- }
- return (*this) << buf;
-}
-
-void QDumper::put(char c)
-{
- if (pos >= sizeof(qDumpBuffer) - 100)
- flush();
- qDumpBuffer[pos++] = c;
-}
-
-void QDumper::addCommaIfNeeded()
-{
- if (pos == 0)
- return;
- if (qDumpBuffer[pos - 1] == '}' || qDumpBuffer[pos - 1] == '"')
- put(',');
-}
-
-void QDumper::putEncoded(unsigned c)
-{
- if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
- put(c);
- } else {
- put('\\');
- put('u');
- put(toHex((c >> 12) & 0xf));
- put(toHex((c >> 8) & 0xf));
- put(toHex((c >> 4) & 0xf));
- put(toHex( c & 0xf));
- }
-}
-
-QDumper &QDumper::operator<<(const char *str)
-{
- while (*str)
- put(*(str++));
- return *this;
-}
-
-QDumper &QDumper::operator<<(const QString &str)
-{
- int n = str.size();
- if (n < 0) {
- qProvokeSegFault();
- } else {
- //(*this) << "[" << n << "]";
- if (n > 1000000)
- n = 1000000;
- //put(' ');
- put('\\');
- put('"');
- for (int i = 0; i != n; ++i)
- putEncoded(str[i].unicode());
- put('\\');
- put('"');
- if (n < str.size())
- (*this) << "<incomplete string>";
- }
- return *this;
-}
-
-void QDumper::disarm()
-{
- flush();
- success = true;
-}
-
-void QDumper::beginHash()
-{
- addCommaIfNeeded();
- put('{');
-}
-
-void QDumper::endHash()
-{
- put('}');
-}
-
-
-//
-// Some helpers to keep the dumper code short
-//
-
-// dump property=value pair
-#undef P
-#define P(dumper,name,value) \
- do { \
- dumper.addCommaIfNeeded(); \
- dumper << (name) << "=\"" << value << "\""; \
- } while (0)
-
-// simple string property
-#undef S
-#define S(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "QString"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple integer property
-#undef I
-#define I(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "int"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple boolean property
-#undef BL
-#define BL(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", (value ? "true" : "false")); \
- P(dumper, "type", "bool"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-#undef TT
-#define TT(type, value) \
- "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
-
-static void qDumpUnknown(QDumper &d)
-{
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<internal error>");
- P(d, "type", d.outertype);
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQPropertyList(QDumper &d)
-{
- const QObject *ob = (const QObject *)d.data;
- const QMetaObject *mo = ob->metaObject();
- P(d, "iname", d.iname);
- P(d, "addr", "<synthetic>");
- P(d, "type", "QObject");
- P(d, "numchild", mo->propertyCount());
- if (d.dumpChildren) {
- d << ",children=[";
- for (int i = mo->propertyCount(); --i >= 0; ) {
- const QMetaProperty & prop = mo->property(i);
- d.beginHash();
- P(d, "name", prop.name());
- if (QLatin1String(prop.typeName()) == QLatin1String("QString")) {
- P(d, "value", prop.read(ob).toString());
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("bool")) {
- P(d, "value", (prop.read(ob).toBool() ? "true" : "false"));
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("int")) {
- P(d, "value", prop.read(ob).toInt());
- P(d, "numchild", "0");
- } else {
- P(d, "exp", "((" << mo->className() << "*)" << ob
- << ")->" << prop.name() << "()");
- }
- P(d, "type", prop.typeName());
- P(d, "numchild", "1");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQObject(QDumper &d)
-{
- const QObject *ob = reinterpret_cast<const QObject *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", (void*)d.data);
- P(d, "type", "QObject");
- P(d, "numchild", 4);
- if (d.dumpChildren) {
- const QMetaObject *mo = ob->metaObject();
- const QObjectList &children = ob->children();
- d << ",children=[";
- S(d, "objectName", ob->objectName());
- d.beginHash();
- P(d, "name", "properties");
- // FIXME: Note that when simply using '(QObject*)'
- // in the cast below, Gdb/MI _sometimes misparses
- // expressions further down in the tree.
- P(d, "exp", "*(class QObject*)" << d.data);
- P(d, "type", "QPropertyList");
- P(d, "value", "<" << mo->propertyCount() << " items>");
- P(d, "numchild", mo->propertyCount());
- d.endHash();
- d.beginHash();
- P(d, "name", "children");
- P(d, "exp", "((class QObject*)" << d.data << ")->children()");
- P(d, "type", "QList<QObject *>");
- P(d, "value", "<" << children.size() << " items>");
- P(d, "numchild", children.size());
- d.endHash();
- d.beginHash();
- P(d, "name", "parent");
- P(d, "exp", "((class QObject*)" << d.data << ")->parent()");
- P(d, "type", "QObject *");
- P(d, "numchild", (ob->parent() ? "1" : "0"));
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDir(QDumper &d)
-{
- const QDir &dir = *reinterpret_cast<const QDir *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", dir.path());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", dir.absolutePath());
- S(d, "canonicalPath", dir.canonicalPath());
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQFileInfo(QDumper &d)
-{
- const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", info.filePath());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", info.absolutePath());
- S(d, "absoluteFilePath", info.absoluteFilePath());
- S(d, "canonicalPath", info.canonicalPath());
- S(d, "canonicalFilePath", info.canonicalFilePath());
- S(d, "completeBaseName", info.completeBaseName());
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "baseName", info.baseName());
-#ifdef Q_OS_MACX
- BL(d, "isBundle", info.isBundle());
- S(d, "bundleName", info.bundleName());
-#endif
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "fileName", info.fileName());
- S(d, "filePath", info.filePath());
- S(d, "group", info.group());
- S(d, "owner", info.owner());
- S(d, "path", info.path());
-
- I(d, "groupid", (long)info.groupId());
- I(d, "ownerid", (long)info.ownerId());
- //QFile::Permissions permissions () const
- I(d, "permissions", info.permissions());
-
- //QDir absoluteDir () const
- //QDir dir () const
-
- BL(d, "caching", info.caching());
- BL(d, "exists", info.exists());
- BL(d, "isAbsolute", info.isAbsolute());
- BL(d, "isDir", info.isDir());
- BL(d, "isExecutable", info.isExecutable());
- BL(d, "isFile", info.isFile());
- BL(d, "isHidden", info.isHidden());
- BL(d, "isReadable", info.isReadable());
- BL(d, "isRelative", info.isRelative());
- BL(d, "isRoot", info.isRoot());
- BL(d, "isSymLink", info.isSymLink());
- BL(d, "isWritable", info.isWritable());
-
-#ifndef QT_NO_DATESTRING
- d.beginHash();
- P(d, "name", "created");
- P(d, "value", info.created().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->created()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastModified");
- P(d, "value", info.lastModified().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastModified()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastRead");
- P(d, "value", info.lastRead().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastRead()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-#endif
-
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDateTime(QDumper &d)
-{
-#ifdef QT_NO_DATESTRING
- qDumpUnknown(d);
-#else
- const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", date.toString());
- P(d, "type", "QDateTime");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- BL(d, "isNull", date.isNull());
- I(d, "toTime_t", (long)date.toTime_t());
- S(d, "toString", date.toString());
- S(d, "toString_(ISO)", date.toString(Qt::ISODate));
- S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate));
- S(d, "toString_(Locale)", date.toString(Qt::LocaleDate));
- S(d, "toString", date.toString());
-
- d.beginHash();
- P(d, "name", "toUTC");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::UTC)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "toLocalTime");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::LocalTime)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d << "]";
- }
- d.disarm();
-#endif // ifdef QT_NO_DATESTRING
-}
-
-static void qDumpQString(QDumper &d)
-{
- const QString &str = *reinterpret_cast<const QString *>(d.data);
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (!str.isEmpty()) {
- volatile ushort dummy = 0;
- dummy += str.at(0).unicode();
- dummy += str.at(str.size() - 1).unicode();
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", str);
- P(d, "type", "QString");
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQStringList(QDumper &d)
-{
- const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
- int n = list.size();
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(&list.front());
- qCheckAccess(&list.back());
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- S(d, "[" << i << "]", list[i]);
- }
- if (n < list.size()) {
- d.beginHash();
- P(d, "value", "<incomplete>");
- P(d, "type", " ");
- P(d, "numchild", "0");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVariantHelper(const void *data, QString *value,
- QString *exp, int *numchild)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(data);
- switch (v.type()) {
- case QVariant::Invalid:
- *value = QLatin1String("<invalid>");
- *numchild = 0;
- break;
- case QVariant::String:
- *value = QLatin1Char('"') + v.toString() + QLatin1Char('"');
- *numchild = 0;
- break;
- case QVariant::StringList:
- *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c"))
- .arg((qulonglong)data);
- *numchild = v.toStringList().size();
- break;
- case QVariant::Int:
- *value = QString::number(v.toInt());
- *numchild= 0;
- break;
- case QVariant::Double:
- *value = QString::number(v.toDouble());
- *numchild = 0;
- break;
- default:
- // FIXME
- //*exp = QString("qVariantValue<" << v.typeName() << ">"
- // << "(*(QVariant*)" << data << ")");
- break;
- }
-}
-
-static void qDumpQVariant(QDumper &d)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(d.data);
- QString value;
- QString exp;
- int numchild = 0;
- qDumpQVariantHelper(d.data, &value, &exp, &numchild);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "(" << v.typeName() << ") " << qPrintable(value));
- P(d, "type", "QVariant");
- P(d, "numchild", 1);
- if (d.dumpChildren) {
- d << ",children=[";
- d.beginHash();
- P(d, "name", "value");
- if (!exp.isEmpty())
- P(d, "exp", qPrintable(exp));
- if (!value.isEmpty())
- P(d, "value", qPrintable(value));
- P(d, "type", v.typeName());
- P(d, "numchild", numchild);
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQList(QDumper &d)
-{
- // This uses the knowledge that QList<T> has only a single member
- // of type union { QListData p; QListData::Data *d; };
- const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
- const QListData::Data *pdata = *reinterpret_cast<const QListData::Data* const*>(d.data);
- int nn = ldata.size();
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(ldata.d->array);
- //qCheckAccess(ldata.d->array[0]);
- //qCheckAccess(ldata.d->array[nn - 1]);
- }
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- // The exact condition here is:
- // QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
- // but this data is not available in the compiled binary.
- // So as first approximation only do the 'isLarge' check:
- void *p = &(ldata.d->array[i + pdata->begin]);
- unsigned long voidpsize = sizeof(void*);
- P(d, "exp", "(sizeof(" << d.innertype << ")>" << voidpsize <<
- "?(**(" << d.innertype << "**)(" << p << "))"
- ":(*(" << d.innertype << "*)(" << p << ")))");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVector(QDumper &d)
-{
- // Use 'int' as representative value. No way (and no need)
- // to deduce proper type here.
- const QVector<int> &vec = *reinterpret_cast<const QVector<int> *>(d.data);
- const int nn = vec.size();
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(&vec.front());
- qCheckAccess(&vec.back());
- }
-
- //int innersize = 0;
- //scanf(qDumpInBuffer, "%d", &innersize);
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- if (i)
- d << ",";
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "exp", "(" << d.exp << ".d->array[" << i << "])");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHashNode(QDumper &d)
-{
- struct NodeOS { void *next; uint k; uint v; } nodeOS; // int-key optimization, small value
- struct NodeOL { void *next; uint k; void *v; } nodeOL; // int-key optimiatzion, large value
- struct NodeNS { void *next; uint h; uint k; uint v; } nodeNS; // no optimization, small value
- struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL; // no optimization, large value
- struct NodeL { void *next; uint h; void *k; void *v; } nodeL; // complex key
-
- // offsetof(...,...) not yet in Standard C++
- const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS );
- const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS );
- const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL );
- const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL );
- const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS );
- const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS );
- const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL );
- const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL );
- const ulong nodeLk ( (char *)&nodeL.k - (char *)&nodeL );
- const ulong nodeLv ( (char *)&nodeL.v - (char *)&nodeL );
-
- const QHashData *h = reinterpret_cast<const QHashData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- // there is a hash specialization in cast the key are integers or shorts
- bool isOptimizedIntKey = qstrcmp(keyType, "int") == 0
-#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- || qstrcmp(keyType, "short") == 0
- || qstrcmp(keyType, "ushort") == 0
-#endif
- || qstrcmp(keyType, "uint") == 0;
-
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- unsigned long intsize = sizeof(int);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLk << ":" << nodeOSk <<
- ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?"
- << nodeLk << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLk << ":" << nodeNSk << "))+(char*)" << h << ")");
- }
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLv << ":" << nodeOSv << ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?" << nodeLv << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLv << ":" << nodeNSv << "))+(char*)" << h << ")");
- }
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHash(QDumper &d)
-{
- QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckPointer(h->fakeNext);
- qCheckPointer(h->buckets);
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckPointer(h->fakeNext);
- qCheckPointer(*h->buckets);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QHashData::Node *node = h->firstNode();
- QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QHashNode<" << keyType << "," << valueType << " >");
- P(d, "exp", "*(QHashNode<" << keyType << "," << valueType << " >*)" << node);
- d.endHash();
-
- ++i;
- node = QHashData::nextNode(node);
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQMapNode(QDumper &d)
-{
- const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- unsigned long voidpsize = sizeof(void*);
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- P(d, "exp", "*(" << keyType << "*)"
- << "("
- << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- P(d, "exp", "*(" << valueType << "*)"
- << "("
- << "(size_t)&(('QMap<" << keyType << "," << valueType << ">::Node'*)0)->value"
- << "+" << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQMap(QDumper &d)
-{
- QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
- qCheckPointer(h->backward->backward);
- qCheckPointer(h->forward[0]->backward);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]);
- QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QMap<" << keyType << "," << valueType << ">::Node");
- P(d, "exp", "*('QMap<" << keyType << "," << valueType << ">::Node'*)" << node);
- d.endHash();
-
- ++i;
- node = node->forward[0];
- }
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQSet(QDumper &d)
-{
- // This uses the knowledge that QHash<T> has only a single member
- // of union { QHashData *d; QHashNode<Key, T> *e; };
- QHashData *hd = *(QHashData**)d.data;
- QHashData::Node *node = hd->firstNode();
-
- int n = hd->size;
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(node);
- qCheckPointer(node->next);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", 2 * n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- int i = 0;
- for (int bucket = 0; bucket != hd->numBuckets; ++bucket) {
- for (node = hd->buckets[bucket]; node->next; node = node->next) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", d.innertype);
- P(d, "exp", "(('QHashNode<" << d.innertype
- << ",QHashDummyValue>'*)"
- << static_cast<const void*>(node) << ")->key"
- );
- d.endHash();
- ++i;
- }
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void handleProtocolVersion2(QDumper & d)
-{
- if (!d.outertype[0]) {
- qDumpUnknown(d);
- return;
- }
-
- d.setupTemplateParameters();
- // d.outertype[0] is usally 'Q', so don't use it
- switch (d.outertype[1]) {
- case 'D':
- if (qstrcmp(d.outertype, "QDateTime") == 0)
- qDumpQDateTime(d);
- else if (qstrcmp(d.outertype, "QDir") == 0)
- qDumpQDir(d);
- break;
- case 'F':
- if (qstrcmp(d.outertype, "QFileInfo") == 0)
- qDumpQFileInfo(d);
- break;
- case 'H':
- if (qstrcmp(d.outertype, "QHash") == 0)
- qDumpQHash(d);
- else if (qstrcmp(d.outertype, "QHashNode") == 0)
- qDumpQHashNode(d);
- break;
- case 'L':
- if (qstrcmp(d.outertype, "QList") == 0)
- qDumpQList(d);
- break;
- case 'M':
- if (qstrcmp(d.outertype, "QMap") == 0)
- qDumpQMap(d);
- else if (qstrcmp(d.outertype, "QMap::Node") == 0)
- qDumpQMapNode(d);
- break;
- case 'O':
- if (qstrcmp(d.outertype, "QObject") == 0)
- qDumpQObject(d);
- break;
- case 'P':
- if (qstrcmp(d.outertype, "QPropertyList") == 0)
- qDumpQPropertyList(d);
- break;
- case 'S':
- if (qstrcmp(d.outertype, "QSet") == 0)
- qDumpQSet(d);
- else if (qstrcmp(d.outertype, "QString") == 0)
- qDumpQString(d);
- else if (qstrcmp(d.outertype, "QStringList") == 0)
- qDumpQStringList(d);
- break;
- case 'V':
- if (qstrcmp(d.outertype, "QVariant") == 0)
- qDumpQVariant(d);
- else if (qstrcmp(d.outertype, "QVector") == 0)
- qDumpQVector(d);
- break;
- }
-
- if (!d.success)
- qDumpUnknown(d);
-}
-
-} // anonymous namespace
-
-
-extern "C" Q_CORE_EXPORT void qDumpObjectData(
- int protocolVersion,
- int token,
- const char *outertype,
- const char *iname,
- const char *exp,
- const char *innertype,
- const void *data,
- bool dumpChildren)
-{
- if (protocolVersion == 1) {
- // used to test whether error output gets through
- //fprintf(stderr, "using stderr, qDebug follows: %d\n", token);
- //qDebug() << "using qDebug, stderr already used: " << token;
- }
-
- else if (protocolVersion == 2) {
- QDumper d;
- d.protocolVersion = protocolVersion;
- d.token = token;
- d.outertype = outertype ? outertype : "";
- d.iname = iname ? iname : "";
- d.exp = exp ? exp : "";
- d.innertype = innertype ? innertype : "";
- d.data = data ? data : "";
- d.dumpChildren = dumpChildren;
- handleProtocolVersion2(d);
- }
-
- else {
- qDebug() << "Unsupported protocol version" << protocolVersion;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // !Q_OS_WINCE && !QT_NO_QDUMPER
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index 8c37137..2b027fc 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -347,7 +347,7 @@ bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other)
}
QT_BEGIN_INCLUDE_NAMESPACE
-#include "../3rdparty/easing/easing.cpp"
+#include "../../3rdparty/easing/easing.cpp"
QT_END_INCLUDE_NAMESPACE
class QEasingCurvePrivate
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index b2512e1..2313e0e 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -380,9 +380,9 @@ void QHashData::checkSanity()
/*!
\fn uint qHash(const QPair<T1, T2> &key)
- \relates QHash
\since 4.3
-
+ \relates QHash
+
Returns the hash value for the \a key.
Types \c T1 and \c T2 must be supported by qHash().
@@ -502,7 +502,8 @@ void QHashData::checkSanity()
key. With QHash, the items are arbitrarily ordered.
\i The key type of a QMap must provide operator<(). The key
type of a QHash must provide operator==() and a global
- \l{qHash()} {hash} function.
+ hash function called qHash() (see the related non-member
+ functions).
\endlist
Here's an example QHash with QString keys and \c int values:
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index a18b531..632c422 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -97,10 +97,7 @@ Q_CORE_EXPORT uint qHash(const QBitArray &key);
#endif
template <class T> inline uint qHash(const T *key)
{
- if (sizeof(const T *) > sizeof(uint))
- return qHash(reinterpret_cast<quint64>(key));
- else
- return uint(reinterpret_cast<ulong>(key));
+ return qHash(reinterpret_cast<quintptr>(key));
}
#if defined(Q_CC_MSVC)
#pragma warning( pop )
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 559ba81..66e3921 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -1589,7 +1589,7 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
defaults to the default locale (see setDefault()).
\endlist
- The "C" locale is identical to \l{English}/\l{UnitedStates}.
+ The "C" locale is identical in behavior to \l{English}/\l{UnitedStates}.
Use language() and country() to determine the actual language and
country values used.
@@ -1632,7 +1632,7 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
This enumerated type is used to specify a language.
- \value C The "C" locale is English/UnitedStates.
+ \value C The "C" locale is identical in behavior to English/UnitedStates.
\value Abkhazian
\value Afan
\value Afar
@@ -5367,6 +5367,14 @@ static Bigint *mult(Bigint *a, Bigint *b)
static Bigint *p5s;
+struct p5s_deleter
+{
+ ~p5s_deleter()
+ {
+ Bfree(p5s);
+ }
+};
+
static Bigint *pow5mult(Bigint *b, int k)
{
Bigint *b1, *p5, *p51;
@@ -5388,6 +5396,7 @@ static Bigint *pow5mult(Bigint *b, int k)
return b;
if (!(p5 = p5s)) {
/* first time */
+ static p5s_deleter deleter;
p5 = p5s = i2b(625);
p5->next = 0;
}
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 5f13e5a..32c8d17 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -990,7 +990,7 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
{
int n = 0;
typename QMap<Key, T>::iterator i(find(key));
- typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
+ typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
if (i.value() == value) {
i = erase(i);
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index feea473..5cc71d6 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -442,6 +442,19 @@ QDebug operator<<(QDebug d, const QPointF &p)
otherwise returns false.
*/
+
+/*!
+ Returns the sum of the absolute values of x() and y(),
+ traditionally known as the "Manhattan length" of the vector from
+ the origin to the point.
+
+ \sa QPoint::manhattanLength()
+*/
+qreal QPointF::manhattanLength() const
+{
+ return qAbs(x())+qAbs(y());
+}
+
/*!
\fn qreal QPointF::x() const
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index 1dab7e2..e716bf7 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -192,6 +192,8 @@ public:
QPointF(const QPoint &p);
QPointF(qreal xpos, qreal ypos);
+ qreal manhattanLength() const;
+
bool isNull() const;
qreal x() const;
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 3930a0d..5602170 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -901,7 +901,7 @@ void QRect::moveCenter(const QPoint &p)
/*!
\fn bool QRect::contains(const QPoint &point, bool proper) const
- Returns true if the the given \a point is inside or on the edge of
+ Returns true if the given \a point is inside or on the edge of
the rectangle, otherwise returns false. If \a proper is true, this
function only returns true if the given \a point is \e inside the
rectangle (i.e., not on the edge).
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 3a0901d..02cc497 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class Q_CORE_EXPORT QRingBuffer
+class QRingBuffer
{
public:
inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
@@ -74,6 +74,52 @@ public:
return buffers.isEmpty() ? 0 : (buffers.first().constData() + head);
}
+ // access the bytes at a specified position
+ // the out-variable length will contain the amount of bytes readable
+ // from there, e.g. the amount still the same QByteArray
+ inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
+ if (buffers.isEmpty()) {
+ length = 0;
+ return 0;
+ }
+
+ if (pos >= bufferSize) {
+ length = 0;
+ return 0;
+ }
+
+ // special case: it is in the first buffer
+ int nextDataBlockSizeValue = nextDataBlockSize();
+ if (pos - head < nextDataBlockSizeValue) {
+ length = nextDataBlockSizeValue - pos;
+ return buffers.at(0).constData() + head + pos;
+ }
+
+ // special case: we only had one buffer and tried to read over it
+ if (buffers.length() == 1) {
+ length = 0;
+ return 0;
+ }
+
+ // skip the first
+ pos -= nextDataBlockSizeValue;
+
+ // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
+ for (int i = 1; i < tailBuffer; i++) {
+ if (pos >= buffers[i].size()) {
+ pos -= buffers[i].size();
+ continue;
+ }
+
+ length = buffers[i].length() - pos;
+ return buffers[i].constData() + pos;
+ }
+
+ // it is in the tail buffer
+ length = tail - pos;
+ return buffers[tailBuffer].constData() + pos;
+ }
+
inline void free(int bytes) {
bufferSize -= bytes;
if (bufferSize < 0)
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 4b19adc..993ce48 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -85,6 +85,8 @@ public:
inline bool contains(const T &value) const { return q_hash.contains(value); }
+ bool contains(const QSet<T> &set) const;
+
class const_iterator;
class iterator
@@ -274,6 +276,18 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other)
return *this;
}
+template <class T>
+Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const
+{
+ typename QSet<T>::const_iterator i = other.constBegin();
+ while (i != other.constEnd()) {
+ if (!contains(*i))
+ return false;
+ ++i;
+ }
+ return true;
+}
+
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
{
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index f1b35ee..ad2d9f2 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -238,6 +238,7 @@ namespace QtSharedPointer {
template <class X> friend class ExternalRefCount;
template <class X> friend class QWeakPointer;
template <class X, class Y> friend QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<Y> &src, X *);
+ template <class X, class Y> friend QSharedPointer<X> qSharedPointerDynamicCastHelper(const QSharedPointer<Y> &src, X *);
template <class X, class Y> friend QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<Y> &src, X *);
template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer<Y> &src, X *);
#endif
@@ -509,6 +510,14 @@ namespace QtSharedPointer {
return result;
}
template <class X, class T>
+ Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCastHelper(const QSharedPointer<T> &src, X *)
+ {
+ QSharedPointer<X> result;
+ register T *ptr = src.data();
+ result.internalSet(src.d, dynamic_cast<X *>(ptr));
+ return result;
+ }
+ template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<T> &src, X *)
{
QSharedPointer<X> result;
@@ -544,9 +553,7 @@ template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
{
X *x = 0;
- if (QtSharedPointer::qVerifyDynamicCast(src.data(), x))
- return QtSharedPointer::qSharedPointerCastHelper(src, x);
- return QSharedPointer<X>();
+ return QtSharedPointer::qSharedPointerDynamicCastHelper(src, x);
}
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
@@ -558,17 +565,13 @@ template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
{
X *x = 0;
- if (QtSharedPointer::qVerifyConstCast(src.data(), x))
- return QtSharedPointer::qSharedPointerConstCastHelper(src, x);
- return QSharedPointer<X>();
+ return QtSharedPointer::qSharedPointerConstCastHelper(src, x);
}
template <class X, class T>
Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
{
X *x = 0;
- if (QtSharedPointer::qVerifyConstCast(src.data(), x))
- return QtSharedPointer::qSharedPointerCastHelper(src, x);
- return QSharedPointer<X>();
+ return QtSharedPointer::qSharedPointerConstCastHelper(src, x);
}
template <class X, class T>
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index 76a5484..bbf6c2a 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -781,7 +781,7 @@ void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode)
\fn QDataStream &operator<<(QDataStream &stream, const QSizeF &size)
\relates QSizeF
- Writes the the given \a size to the given \a stream and returns a
+ Writes the given \a size to the given \a stream and returns a
reference to the stream.
\sa {Format of the QDataStream Operators}
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index 57c55ca..34a6c99 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -171,14 +171,14 @@ inline const QSize operator*(qreal c, const QSize &s)
inline QSize &QSize::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = qRound(wd/c); ht = qRound(ht/c);
return *this;
}
inline const QSize operator/(const QSize &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSize(qRound(s.wd/c), qRound(s.ht/c));
}
@@ -327,14 +327,14 @@ inline const QSizeF operator*(qreal c, const QSizeF &s)
inline QSizeF &QSizeF::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = wd/c; ht = ht/c;
return *this;
}
inline const QSizeF operator/(const QSizeF &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSizeF(s.wd/c, s.ht/c);
}
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 386321f1..e22f122 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -397,7 +397,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &r
\fn QString QStringList::join(const QString &separator) const
Joins all the string list's strings into a single string with each
- element separated by the the given \a separator (which can be an
+ element separated by the given \a separator (which can be an
empty string).
\sa QString::split()
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 78ce7bd..ee4f73c 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -211,7 +211,9 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
valueForTime() and emitting valueChanged(). By default, valueForTime()
applies an interpolation algorithm to generate these value. You can choose
from a set of predefined timeline algorithms by calling
- setCurveShape(). By default, QTimeLine uses the EaseInOut curve shape,
+ setCurveShape().
+
+ Note that by default, QTimeLine uses the EaseInOut curve shape,
which provides a value that grows slowly, then grows steadily, and
finally grows slowly. For a custom timeline, you can reimplement
valueForTime(), in which case QTimeLine's curveShape property is ignored.
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 1f047b8..7bdcba0 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -82,19 +82,9 @@ struct Q_CORE_EXPORT QVectorData
};
template <typename T>
-struct QVectorTypedData
-{
- QBasicAtomicInt ref;
- int alloc;
- int size;
-#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
- // workaround for bug in gcc 3.4.2
- uint sharable;
- uint capacity;
-#else
- uint sharable : 1;
- uint capacity : 1;
-#endif
+struct QVectorTypedData : private QVectorData
+{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
+ // as this would break strict aliasing rules. (in the case of shared_null)
T array[1];
};
@@ -104,14 +94,14 @@ template <typename T>
class QVector
{
typedef QVectorTypedData<T> Data;
- union { QVectorData *p; QVectorTypedData<T> *d; };
+ union { QVectorData *d; Data *p; };
public:
- inline QVector() : p(&QVectorData::shared_null) { d->ref.ref(); }
+ inline QVector() : d(&QVectorData::shared_null) { d->ref.ref(); }
explicit QVector(int size);
QVector(int size, const T &t);
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
- inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(d); }
+ inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
QVector<T> &operator=(const QVector<T> &v);
bool operator==(const QVector<T> &v) const;
inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
@@ -130,9 +120,9 @@ public:
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
- inline T *data() { detach(); return d->array; }
- inline const T *data() const { return d->array; }
- inline const T *constData() const { return d->array; }
+ inline T *data() { detach(); return p->array; }
+ inline const T *data() const { return p->array; }
+ inline const T *constData() const { return p->array; }
void clear();
const T &at(int i) const;
@@ -225,12 +215,12 @@ public:
typedef T* iterator;
typedef const T* const_iterator;
#endif
- inline iterator begin() { detach(); return d->array; }
- inline const_iterator begin() const { return d->array; }
- inline const_iterator constBegin() const { return d->array; }
- inline iterator end() { detach(); return d->array + d->size; }
- inline const_iterator end() const { return d->array + d->size; }
- inline const_iterator constEnd() const { return d->array + d->size; }
+ inline iterator begin() { detach(); return p->array; }
+ inline const_iterator begin() const { return p->array; }
+ inline const_iterator constBegin() const { return p->array; }
+ inline iterator end() { detach(); return p->array + d->size; }
+ inline const_iterator end() const { return p->array + d->size; }
+ inline const_iterator constEnd() const { return p->array + d->size; }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
@@ -327,11 +317,11 @@ inline void QVector<T>::clear()
template <typename T>
inline const T &QVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline const T &QVector<T>::operator[](int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline T &QVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
@@ -369,7 +359,7 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
v.d->ref.ref();
if (!d->ref.deref())
- free(d);
+ free(p);
d = v.d;
if (!d->sharable)
detach_helper();
@@ -385,31 +375,31 @@ inline QVectorData *QVector<T>::malloc(int aalloc)
template <typename T>
QVector<T>::QVector(int asize)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
if (QTypeInfo<T>::isComplex) {
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
new (--i) T;
} else {
- qMemSet(d->array, 0, asize * sizeof(T));
+ qMemSet(p->array, 0, asize * sizeof(T));
}
}
template <typename T>
QVector<T>::QVector(int asize, const T &t)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
- T* i = d->array + d->size;
- while (i != d->array)
+ T* i = p->array + d->size;
+ while (i != p->array)
new (--i) T(t);
}
@@ -418,7 +408,7 @@ void QVector<T>::free(Data *x)
{
if (QTypeInfo<T>::isComplex) {
T* b = x->array;
- T* i = b + x->size;
+ T* i = b + reinterpret_cast<QVectorData *>(x)->size;
while (i-- != b)
i->~T();
}
@@ -429,13 +419,13 @@ template <typename T>
void QVector<T>::realloc(int asize, int aalloc)
{
T *j, *i, *b;
- union { QVectorData *p; Data *d; } x;
+ union { QVectorData *d; Data *p; } x;
x.d = d;
if (QTypeInfo<T>::isComplex && aalloc == d->alloc && d->ref == 1) {
// pure resize
- i = d->array + d->size;
- j = d->array + asize;
+ i = p->array + d->size;
+ j = p->array + asize;
if (i > j) {
while (i-- != j)
i->~T();
@@ -450,22 +440,22 @@ void QVector<T>::realloc(int asize, int aalloc)
if (aalloc != d->alloc || d->ref != 1) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
- x.p = malloc(aalloc);
+ x.d = malloc(aalloc);
} else if (d->ref != 1) {
- x.p = QVectorData::malloc(sizeOfTypedData(), aalloc, sizeof(T), p);
+ x.d = QVectorData::malloc(sizeOfTypedData(), aalloc, sizeof(T), d);
} else {
if (QTypeInfo<T>::isComplex) {
// call the destructor on all objects that need to be
// destroyed when shrinking
if (asize < d->size) {
- j = d->array + asize;
- i = d->array + d->size;
+ j = p->array + asize;
+ i = p->array + d->size;
while (i-- != j)
i->~T();
- i = d->array + asize;
+ i = p->array + asize;
}
}
- x.p = p = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+ x.d = d = static_cast<QVectorData *>(qRealloc(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
}
x.d->ref = 1;
x.d->sharable = true;
@@ -474,31 +464,31 @@ void QVector<T>::realloc(int asize, int aalloc)
}
if (QTypeInfo<T>::isComplex) {
if (asize < d->size) {
- j = d->array + asize;
- i = x.d->array + asize;
+ j = p->array + asize;
+ i = x.p->array + asize;
} else {
// construct all new objects when growing
- i = x.d->array + asize;
- j = x.d->array + d->size;
+ i = x.p->array + asize;
+ j = x.p->array + d->size;
while (i != j)
new (--i) T;
- j = d->array + d->size;
+ j = p->array + d->size;
}
if (i != j) {
// copy objects from the old array into the new array
- b = x.d->array;
+ b = x.p->array;
while (i != b)
new (--i) T(*--j);
}
} else if (asize > d->size) {
// initialize newly allocated memory to 0
- qMemSet(x.d->array + d->size, 0, (asize - d->size) * sizeof(T));
+ qMemSet(x.p->array + d->size, 0, (asize - d->size) * sizeof(T));
}
x.d->size = asize;
x.d->alloc = aalloc;
if (d != x.d) {
if (!d->ref.deref())
- free(d);
+ free(p);
d = x.d;
}
}
@@ -506,15 +496,15 @@ void QVector<T>::realloc(int asize, int aalloc)
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
{
- if (i < 0 || i >= p->size) {
+ if (i < 0 || i >= d->size) {
return T();
}
- return d->array[i];
+ return p->array[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
{
- return ((i < 0 || i >= p->size) ? defaultValue : d->array[i]);
+ return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
}
template <typename T>
@@ -525,14 +515,14 @@ void QVector<T>::append(const T &t)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(copy);
+ new (p->array + d->size) T(copy);
else
- d->array[d->size] = copy;
+ p->array[d->size] = copy;
} else {
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(t);
+ new (p->array + d->size) T(t);
else
- d->array[d->size] = t;
+ p->array[d->size] = t;
}
++d->size;
}
@@ -540,27 +530,27 @@ void QVector<T>::append(const T &t)
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
{
- int offset = before - d->array;
+ int offset = before - p->array;
if (n != 0) {
const T copy(t);
if (d->ref != 1 || d->size + n > d->alloc)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isStatic) {
- T *b = d->array + d->size;
- T *i = d->array + d->size + n;
+ T *b = p->array + d->size;
+ T *i = p->array + d->size + n;
while (i != b)
new (--i) T;
- i = d->array + d->size;
+ i = p->array + d->size;
T *j = i + n;
- b = d->array + offset;
+ b = p->array + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
- T *b = d->array + offset;
+ T *b = p->array + offset;
T *i = b + n;
memmove(i, b, (d->size - offset) * sizeof(T));
while (i != b)
@@ -568,29 +558,29 @@ Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n,
}
d->size += n;
}
- return d->array + offset;
+ return p->array + offset;
}
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- int f = abegin - d->array;
- int l = aend - d->array;
+ int f = abegin - p->array;
+ int l = aend - p->array;
int n = l - f;
detach();
if (QTypeInfo<T>::isComplex) {
- qCopy(d->array+l, d->array+d->size, d->array+f);
- T *i = d->array+d->size;
- T* b = d->array+d->size-n;
+ qCopy(p->array+l, p->array+d->size, p->array+f);
+ T *i = p->array+d->size;
+ T* b = p->array+d->size-n;
while (i != b) {
--i;
i->~T();
}
} else {
- memmove(d->array + f, d->array + l, (d->size-l)*sizeof(T));
+ memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
}
d->size -= n;
- return d->array + f;
+ return p->array + f;
}
template <typename T>
@@ -600,9 +590,9 @@ bool QVector<T>::operator==(const QVector<T> &v) const
return false;
if (d == v.d)
return true;
- T* b = d->array;
+ T* b = p->array;
T* i = b + d->size;
- T* j = v.d->array + d->size;
+ T* j = v.p->array + d->size;
while (i != b)
if (!(*--i == *--j))
return false;
@@ -615,8 +605,8 @@ QVector<T> &QVector<T>::fill(const T &from, int asize)
const T copy(from);
resize(asize < 0 ? d->size : asize);
if (d->size) {
- T *i = d->array + d->size;
- T *b = d->array;
+ T *i = p->array + d->size;
+ T *b = p->array;
while (i != b)
*--i = copy;
}
@@ -629,9 +619,9 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
- T *w = d->array + newSize;
- T *i = l.d->array + l.d->size;
- T *b = l.d->array;
+ T *w = p->array + newSize;
+ T *i = l.p->array + l.d->size;
+ T *b = l.p->array;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
@@ -648,11 +638,11 @@ int QVector<T>::indexOf(const T &t, int from) const
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
- T* n = d->array + from - 1;
- T* e = d->array + d->size;
+ T* n = p->array + from - 1;
+ T* e = p->array + d->size;
while (++n != e)
if (*n == t)
- return n - d->array;
+ return n - p->array;
}
return -1;
}
@@ -665,8 +655,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
else if (from >= d->size)
from = d->size-1;
if (from >= 0) {
- T* b = d->array;
- T* n = d->array + from + 1;
+ T* b = p->array;
+ T* n = p->array + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
@@ -678,8 +668,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
template <typename T>
bool QVector<T>::contains(const T &t) const
{
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
return true;
@@ -690,8 +680,8 @@ template <typename T>
int QVector<T>::count(const T &t) const
{
int c = 0;
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
++c;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 41557f0..90287cb 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -20,6 +20,7 @@ HEADERS += \
tools/qlocale_p.h \
tools/qlocale_data_p.h \
tools/qmap.h \
+ tools/qcontiguouscache.h \
tools/qpodlist_p.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -46,7 +47,6 @@ SOURCES += \
tools/qbytearraymatcher.cpp \
tools/qcryptographichash.cpp \
tools/qdatetime.cpp \
- tools/qdumper.cpp \
tools/qeasingcurve.cpp \
tools/qhash.cpp \
tools/qline.cpp \
@@ -55,6 +55,7 @@ SOURCES += \
tools/qlocale.cpp \
tools/qpoint.cpp \
tools/qmap.cpp \
+ tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
tools/qshareddata.cpp \
diff --git a/src/corelib/xml/make-parser.sh b/src/corelib/xml/make-parser.sh
index 0c2ba12..0e2cbe1 100755
--- a/src/corelib/xml/make-parser.sh
+++ b/src/corelib/xml/make-parser.sh
@@ -6,10 +6,8 @@ mkdir -p $me/out
for f in $me/out/*.h; do
n=$(basename $f)
- p4 open $n
cp $f $n
done
-p4 revert -a ...
-p4 diff -dub ...
+git diff .
diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g
index d5e64a6..0cc744e 100644
--- a/src/corelib/xml/qxmlstream.g
+++ b/src/corelib/xml/qxmlstream.g
@@ -1533,8 +1533,8 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
QStringRef namespacePrefix = symString(attribute.key);
QStringRef namespaceUri = symString(attribute.value);
attributeStack.pop();
- if ((namespacePrefix == QLatin1String("xml")
- ^ namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ if (((namespacePrefix == QLatin1String("xml"))
+ ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
|| namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
|| namespaceUri.isEmpty()
|| namespacePrefix == QLatin1String("xmlns"))
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h
index 201f0c1..cf1d228 100644
--- a/src/corelib/xml/qxmlstream_p.h
+++ b/src/corelib/xml/qxmlstream_p.h
@@ -1,3 +1,4 @@
+// This file was generated by qlalr - DO NOT EDIT!
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).