summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io')
-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
23 files changed, 1047 insertions, 252 deletions
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)