summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-05-15 04:09:06 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2009-05-15 04:09:06 (GMT)
commit49d1dd6083074a6225e6784fd185c34b76ed5648 (patch)
treefd3029d7fc0e18888c52e9303313fd9be169c667 /src/corelib
parentf9fa633257f856f03b6f8323506d1695e1705e5f (diff)
parente3fcf351dee44b4f9457a6abbed76d37fc0fbe67 (diff)
downloadQt-49d1dd6083074a6225e6784fd185c34b76ed5648.zip
Qt-49d1dd6083074a6225e6784fd185c34b76ed5648.tar.gz
Qt-49d1dd6083074a6225e6784fd185c34b76ed5648.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into kinetic-declarativeui
Conflicts: configure.exe src/gui/graphicsview/qgraphicsscene.cpp
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/arch/qatomic_mips.h106
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp2
-rw-r--r--src/corelib/io/io.pri3
-rw-r--r--src/corelib/io/qdebug.h19
-rw-r--r--src/corelib/io/qfileinfo_p.h145
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp2
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp542
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h189
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp4
-rw-r--r--src/corelib/kernel/qvariant.cpp5
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp435
-rw-r--r--src/corelib/tools/qcontiguouscache.h424
-rw-r--r--src/corelib/tools/qhash.cpp220
-rw-r--r--src/corelib/tools/qringbuffer_p.h46
-rw-r--r--src/corelib/tools/qstring.cpp4
-rw-r--r--src/corelib/tools/qtimeline.cpp4
-rw-r--r--src/corelib/tools/tools.pri2
17 files changed, 1861 insertions, 291 deletions
diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h
index b263aab..ea9954b 100644
--- a/src/corelib/arch/qatomic_mips.h
+++ b/src/corelib/arch/qatomic_mips.h
@@ -103,16 +103,25 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
#if defined(Q_CC_GNU) && !defined(Q_OS_IRIX)
+#if _MIPS_SIM == _ABIO32
+#define SET_MIPS2 ".set mips2\n\t"
+#else
+#define SET_MIPS2
+#endif
+
inline bool QBasicAtomicInt::ref()
{
register int originalValue;
register int newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"addiu %[newValue], %[originalValue], %[one]\n"
"sc %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -125,12 +134,15 @@ inline bool QBasicAtomicInt::deref()
{
register int originalValue;
register int newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"addiu %[newValue], %[originalValue], %[minusOne]\n"
"sc %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -143,7 +155,9 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
{
register int result;
register int tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
"bnez %[result], 0f\n"
@@ -153,6 +167,7 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
"beqz %[tempValue], 0b\n"
"nop\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -166,7 +181,9 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
{
register int result;
register int tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
"bnez %[result], 0f\n"
@@ -177,6 +194,7 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
"nop\n"
"sync\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -190,7 +208,9 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
{
register int result;
register int tempValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
"ll %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
@@ -201,6 +221,7 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
"beqz %[tempValue], 0b\n"
"nop\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -219,12 +240,15 @@ inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
{
register int originalValue;
register int tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
"sc %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -237,13 +261,16 @@ inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
{
register int originalValue;
register int tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
"sc %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
"sync\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -256,13 +283,16 @@ inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
{
register int originalValue;
register int tempValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
"ll %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
"sc %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -280,12 +310,15 @@ inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
{
register int originalValue;
register int newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
"sc %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -298,13 +331,16 @@ inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
{
register int originalValue;
register int newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
"ll %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
"sc %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
"sync\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -317,13 +353,16 @@ inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
{
register int originalValue;
register int newValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
"ll %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
"sc %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -350,7 +389,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu
{
register T *result;
register T *tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
"bnez %[result], 0f\n"
@@ -360,6 +401,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu
"beqz %[tempValue], 0b\n"
"nop\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -374,7 +416,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu
{
register T *result;
register T *tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
"bnez %[result], 0f\n"
@@ -385,6 +429,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu
"nop\n"
"sync\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -399,7 +444,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu
{
register T *result;
register T *tempValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
LLP" %[result], %[_q_value]\n"
"xor %[result], %[result], %[expectedValue]\n"
@@ -410,6 +457,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu
"beqz %[tempValue], 0b\n"
"nop\n"
"0:\n"
+ ".set pop\n"
: [result] "=&r" (result),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -430,12 +478,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
{
register T *originalValue;
register T *tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
SCP" %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -449,13 +500,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
{
register T *originalValue;
register T *tempValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
SCP" %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
"sync\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -469,13 +523,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
{
register T *originalValue;
register T *tempValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
LLP" %[originalValue], %[_q_value]\n"
"move %[tempValue], %[newValue]\n"
SCP" %[tempValue], %[_q_value]\n"
"beqz %[tempValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[tempValue] "=&r" (tempValue),
[_q_value] "+m" (_q_value)
@@ -495,12 +552,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueTo
{
register T *originalValue;
register T *newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
SCP" %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -514,13 +574,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueTo
{
register T *originalValue;
register T *newValue;
- asm volatile("0:\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "0:\n"
LLP" %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
SCP" %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
"sync\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
@@ -534,13 +597,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueTo
{
register T *originalValue;
register T *newValue;
- asm volatile("sync\n"
+ asm volatile(".set push\n"
+ SET_MIPS2
+ "sync\n"
"0:\n"
LLP" %[originalValue], %[_q_value]\n"
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
SCP" %[newValue], %[_q_value]\n"
"beqz %[newValue], 0b\n"
"nop\n"
+ ".set pop\n"
: [originalValue] "=&r" (originalValue),
[_q_value] "+m" (_q_value),
[newValue] "=&r" (newValue)
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/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/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/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 8a0a3f5..7a6a85b 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -780,7 +780,7 @@ QString QFSFileEngine::fileName(FileName file) const
#endif
if (len > 0) {
QString ret;
- if (S_ISDIR(d->st.st_mode) && s[0] != '/') {
+ if (d->doStat() && S_ISDIR(d->st.st_mode) && s[0] != '/') {
QDir parent(d->filePath);
parent.cdUp();
ret = parent.path();
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/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index c21cf87..77ef096 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -1710,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;
}
@@ -1738,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 )
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index b53e91f..b504604 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1173,8 +1173,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
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/qhash.cpp b/src/corelib/tools/qhash.cpp
index 21d98b5..2313e0e 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -379,6 +379,107 @@ void QHashData::checkSanity()
#endif
/*!
+ \fn uint qHash(const QPair<T1, T2> &key)
+ \since 4.3
+ \relates QHash
+
+ Returns the hash value for the \a key.
+
+ Types \c T1 and \c T2 must be supported by qHash().
+*/
+
+/*! \fn uint qHash(char key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(uchar key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(signed char key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(ushort key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(short key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(uint key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(int key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(ulong key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(long key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(quint64 key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(qint64 key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(QChar key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const QByteArray &key)
+ \fn uint qHash(const QBitArray &key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const QString &key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*! \fn uint qHash(const T *key)
+ \relates QHash
+
+ Returns the hash value for the \a key.
+*/
+
+/*!
\class QHash
\brief The QHash class is a template class that provides a hash-table-based dictionary.
@@ -401,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()}{qHash}(Key) function.
+ hash function called qHash() (see the related non-member
+ functions).
\endlist
Here's an example QHash with QString keys and \c int values:
@@ -732,7 +834,6 @@ void QHashData::checkSanity()
*/
/*! \fn const T QHash::value(const Key &key, const T &defaultValue) const
-
\overload
If the hash contains no item with the given \a key, the function returns
@@ -1490,121 +1591,6 @@ void QHashData::checkSanity()
\sa operator+=(), operator-()
*/
-/*! \fn uint qHash(char key)
- \relates QHash
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(uchar key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(signed char key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(ushort key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(short key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(uint key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(int key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(ulong key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(long key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(quint64 key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(qint64 key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(QChar key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(const QByteArray &key)
- \fn uint qHash(const QBitArray &key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(const QString &key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*! \fn uint qHash(const T *key)
- \relates QHash
- \overload
-
- Returns the hash value for the \a key.
-*/
-
-/*!
- \fn uint qHash(const QPair<T1, T2> &key)
- \relates QHash
- \since 4.3
-
- Returns the hash value for the \a key.
-
- Types \c T1 and \c T2 must be supported by qHash().
-*/
-
/*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
\relates QHash
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index eed4ba9..02cc497 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -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/qstring.cpp b/src/corelib/tools/qstring.cpp
index 375d672..c3649e3 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -743,7 +743,9 @@ int QString::grow(int size)
/*!
\since 4.2
- Returns a copy of the \a string string encoded in ucs4.
+ Returns a copy of the \a string, where the encoding of \a string depends on
+ the size of wchar. If wchar is 4 bytes, the \a string is interpreted as ucs-4,
+ if wchar is 2 bytes it is interpreted as ucs-2.
If \a size is -1 (default), the \a string has to be 0 terminated.
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/tools.pri b/src/corelib/tools/tools.pri
index 41557f0..2a1c1fc 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 \
@@ -55,6 +56,7 @@ SOURCES += \
tools/qlocale.cpp \
tools/qpoint.cpp \
tools/qmap.cpp \
+ tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
tools/qshareddata.cpp \