diff options
Diffstat (limited to 'src/corelib/io')
26 files changed, 1160 insertions, 307 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 845dc2e..edbab9c 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -13,6 +13,7 @@ HEADERS += \ 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 +39,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..077e720 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -65,9 +65,8 @@ template <typename T> class QSet; template <class Key, class T> class QHash; template <class Key, class T> class QMap; -class QDataStreamPrivate; - #ifndef QT_NO_DATASTREAM +class QDataStreamPrivate; class Q_CORE_EXPORT QDataStream { public: @@ -83,10 +82,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 60dc688..332058e 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 @@ -87,11 +88,11 @@ public: delete stream; } } - inline QDebug &space() { stream->space = true; stream->ts << " "; return *this; } + inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; } inline QDebug &nospace() { stream->space = false; return *this; } - inline QDebug &maybeSpace() { if (stream->space) stream->ts << " "; return *this; } + inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; } - inline QDebug &operator<<(QChar t) { stream->ts << "\'" << t << "\'"; return maybeSpace(); } + inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); } inline QDebug &operator<<(QBool t) { stream->ts << (bool(t) ? "true" : "false"); return maybeSpace(); } inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); } inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); } @@ -108,10 +109,10 @@ public: inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); } inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); } inline QDebug &operator<<(const char* t) { stream->ts << QString::fromAscii(t); return maybeSpace(); } - inline QDebug &operator<<(const QString & t) { stream->ts << "\"" << t << "\""; return maybeSpace(); } + inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); } inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); } - inline QDebug &operator<<(const QLatin1String &t) { stream->ts << "\"" << t.latin1() << "\""; return maybeSpace(); } - inline QDebug &operator<<(const QByteArray & t) { stream->ts << "\"" << t << "\""; return maybeSpace(); } + inline QDebug &operator<<(const QLatin1String &t) { stream->ts << '\"' << t.latin1() << '\"'; return maybeSpace(); } + inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); } inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); } inline QDebug &operator<<(QTextStreamFunction f) { stream->ts << f; @@ -161,13 +162,13 @@ template <class T> inline QDebug operator<<(QDebug debug, const QList<T> &list) #endif { - debug.nospace() << "("; + debug.nospace() << '('; for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) { if (i) debug << ", "; debug << list.at(i); } - debug << ")"; + debug << ')'; return debug.space(); } @@ -194,9 +195,9 @@ inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map) debug.nospace() << "QMap("; for (typename QMap<aKey, aT>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { - debug << "(" << it.key() << ", " << it.value() << ")"; + debug << '(' << it.key() << ", " << it.value() << ')'; } - debug << ")"; + debug << ')'; return debug.space(); } @@ -211,8 +212,8 @@ inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash) debug.nospace() << "QHash("; for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) - debug << "(" << it.key() << ", " << it.value() << ")"; - debug << ")"; + debug << '(' << it.key() << ", " << it.value() << ')'; + debug << ')'; return debug.space(); } @@ -224,7 +225,7 @@ template <class T1, class T2> inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair) #endif { - debug.nospace() << "QPair(" << pair.first << "," << pair.second << ")"; + debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')'; return debug.space(); } @@ -235,6 +236,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 e1cc7ac..46c29d4 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_DEBUG_STREAM #include "qdebug.h" #endif +#include "qdiriterator.h" #include "qfsfileengine.h" #include "qdatetime.h" #include "qstring.h" @@ -55,6 +56,8 @@ # include "qresource.h" #endif +#include "qvarlengtharray.h" + #include "../kernel/qcoreglobaldata_p.h" #include <stdlib.h> @@ -91,7 +94,7 @@ protected: QString initFileEngine(const QString &file); void updateFileLists() const; - void sortFileList(QDir::SortFlags, QStringList &, QStringList *, QFileInfoList *) const; + void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *) const; private: #ifdef QT3_SUPPORT @@ -261,45 +264,57 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt ? f1->filename_cache.localeAwareCompare(f2->filename_cache) : f1->filename_cache.compare(f2->filename_cache); } - + if (r == 0) // Enforce an order - the order the items appear in the array + r = (&n1) - (&n2); if (qt_cmp_si_sort_flags & QDir::Reversed) return r > 0; return r < 0; } -inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QStringList &l, +inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l, QStringList *names, QFileInfoList *infos) const { if(names) names->clear(); if(infos) infos->clear(); - if(!l.isEmpty()) { - QDirSortItem *si= new QDirSortItem[l.count()]; - int i; - for (i = 0; i < l.size(); ++i) { - QString path = data->path; - if (!path.isEmpty() && !path.endsWith(QLatin1Char('/'))) - path += QLatin1Char('/'); - si[i].item = QFileInfo(path + l.at(i)); - } - if ((sort & QDir::SortByMask) != QDir::Unsorted) - qStableSort(si, si+i, QDirSortItemComparator(sort)); - // put them back in the list(s) - for (int j = 0; j<i; j++) { + int n = l.size(); + if(n > 0) { + if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) { if(infos) - infos->append(si[j].item); - if(names) - names->append(si[j].item.fileName()); + *infos = l; + if(names) { + for (int i = 0; i < n; ++i) + names->append(l.at(i).fileName()); + } + } else { + QDirSortItem *si = new QDirSortItem[n]; + for (int i = 0; i < n; ++i) + si[i].item = l.at(i); + qSort(si, si+n, QDirSortItemComparator(sort)); + // put them back in the list(s) + if(infos) { + for (int i = 0; i < n; ++i) + infos->append(si[i].item); + } + if(names) { + for (int i = 0; i < n; ++i) + names->append(si[i].item.fileName()); + } + delete [] si; } - delete [] si; } } inline void QDirPrivate::updateFileLists() const { if(data->listsDirty) { - QStringList l = data->fileEngine->entryList(data->filters, data->nameFilters); + QFileInfoList l; + QDirIterator it(data->path, data->nameFilters, data->filters); + while (it.hasNext()) { + it.next(); + l.append(it.fileInfo()); + } sortFileList(data->sort, l, &data->files, &data->fileInfos); data->listsDirty = 0; } @@ -1303,7 +1318,6 @@ QStringList QDir::entryList(Filters filters, SortFlags sort) const \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists() */ - QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const { Q_D(const QDir); @@ -1345,10 +1359,12 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters, d->updateFileLists(); return d->data->files; } - QStringList l = d->data->fileEngine->entryList(filters, nameFilters); - if ((sort & QDir::SortByMask) == QDir::Unsorted) - return l; - + QFileInfoList l; + QDirIterator it(d->data->path, nameFilters, filters); + while (it.hasNext()) { + it.next(); + l.append(it.fileInfo()); + } QStringList ret; d->sortFileList(sort, l, &ret, 0); return ret; @@ -1388,8 +1404,13 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter d->updateFileLists(); return d->data->fileInfos; } + QFileInfoList l; + QDirIterator it(d->data->path, nameFilters, filters); + while (it.hasNext()) { + it.next(); + l.append(it.fileInfo()); + } QFileInfoList ret; - QStringList l = d->data->fileEngine->entryList(filters, nameFilters); d->sortFileList(sort, l, 0, &ret); return ret; } @@ -2056,11 +2077,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('/')) { @@ -2160,7 +2183,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('/')) @@ -2223,7 +2246,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 @@ -2415,7 +2438,7 @@ QDebug operator<<(QDebug debug, QDir::Filters filters) if (filters & QDir::System) flags << QLatin1String("System"); if (filters & QDir::CaseSensitive) flags << QLatin1String("CaseSensitive"); } - debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ")"; + debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ')'; return debug; } @@ -2437,8 +2460,8 @@ QDebug operator<<(QDebug debug, QDir::SortFlags sorting) if (sorting & QDir::LocaleAware) flags << QLatin1String("LocaleAware"); if (sorting & QDir::Type) flags << QLatin1String("Type"); debug << "QDir::SortFlags(" << qPrintable(type) - << "|" - << qPrintable(flags.join(QLatin1String("|"))) << ")"; + << '|' + << qPrintable(flags.join(QLatin1String("|"))) << ')'; } return debug; } @@ -2450,9 +2473,9 @@ QDebug operator<<(QDebug debug, const QDir &dir) << qPrintable(dir.nameFilters().join(QLatin1String(","))) << "}, " << dir.sorting() - << "," + << ',' << dir.filter() - << ")"; + << ')'; return debug.space(); } diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 1e3d5a3..9cbd3dc 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -156,17 +156,15 @@ QFilePrivate::setError(QFile::FileError err) void QFilePrivate::setError(QFile::FileError err, const QString &errStr) { - Q_Q(QFile); error = err; - q->setErrorString(errStr); + errorString = errStr; } void QFilePrivate::setError(QFile::FileError err, int errNum) { - Q_Q(QFile); error = err; - q->setErrorString(qt_error_string(errNum)); + errorString = qt_error_string(errNum); } //************* QFile @@ -707,6 +705,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)) { @@ -861,6 +860,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)) { diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index b36fb69..82b21e9 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -48,73 +48,10 @@ #include "qatomic.h" #include "qhash.h" #include "qdir.h" +#include "qfileinfo_p.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 ©) - : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)), - fileName(copy.fileName), cache_enabled(copy.cache_enabled) - { clear(); } - inline ~Data() { delete fileEngine; } - inline void clearFlags() { - fileFlags = 0; - cachedFlags = 0; - if (fileEngine) - (void)fileEngine->fileFlags(QFSFileEngine::Refresh); - } - inline void clear() { - fileNames.clear(); - clearFlags(); - } - 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(); -}; - QFileInfoPrivate::QFileInfoPrivate(const QFileInfo *copy) { if(copy) { @@ -535,8 +472,7 @@ QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo) void QFileInfo::setFile(const QString &file) { - Q_D(QFileInfo); - d->initFileEngine(file); + *this = QFileInfo(file); } /*! @@ -553,8 +489,7 @@ void QFileInfo::setFile(const QString &file) void QFileInfo::setFile(const QFile &file) { - Q_D(QFileInfo); - d->initFileEngine(file.fileName()); + *this = QFileInfo(file.fileName()); } /*! @@ -571,8 +506,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)); } /*! @@ -919,7 +853,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 index 7d66581..8155bcb 100644 --- a/src/corelib/io/qfileinfo_p.h +++ b/src/corelib/io/qfileinfo_p.h @@ -46,8 +46,8 @@ // 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 +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. @@ -76,70 +76,51 @@ public: 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 - { + 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(); - } - + { clear(); } inline Data(const Data ©) : 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(); + { clear(); } + inline ~Data() { delete fileEngine; } + inline void clearFlags() { fileFlags = 0; cachedFlags = 0; + if (fileEngine) + (void)fileEngine->fileFlags(QFSFileEngine::Refresh); + } + inline void clear() { + fileNames.clear(); + clearFlags(); } - 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 +#endif // QFILEINFO_P_H diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index b83ab85..c5a58e2 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -120,7 +120,7 @@ public: void stop(); -private slots: +private Q_SLOTS: void timeout(); }; diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp index e87375a..a8397f8 100644 --- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp @@ -114,7 +114,7 @@ private: bool isExecing; }; -Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal); +Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal) QDnotifySignalThread::QDnotifySignalThread() : isExecing(false) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 45e547f..c29e4ec 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -103,12 +103,12 @@ static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString & } else if (flags & QIODevice::WriteOnly) { mode = "wb"; if (flags & QIODevice::ReadOnly) - mode += "+"; + mode += '+'; } if (flags & QIODevice::Append) { mode = "ab"; if (flags & QIODevice::ReadOnly) - mode += "+"; + mode += '+'; } return mode; } @@ -986,7 +986,7 @@ QString QFSFileEngine::fileName(FileName file) const bool isDir = ret.endsWith(QLatin1Char('/')); ret = QDir::cleanPath(ret); if (isDir) - ret += QLatin1String("/"); + ret += QLatin1Char('/'); if (file == AbsolutePathName) { int slash = ret.lastIndexOf(QLatin1Char('/')); if (slash == -1) @@ -1202,6 +1202,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 6ae13e9..896bcc1 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -433,7 +433,7 @@ static QString nativeAbsoluteFilePathW(const QString &path) if (retLen != 0) ret = QString::fromUtf16((unsigned short *)buf.data(), retLen); #else - if (path.startsWith(QLatin1String("/")) || path.startsWith(QLatin1String("\\"))) + if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) ret = QDir::toNativeSeparators(path); else ret = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path)); @@ -1240,7 +1240,7 @@ QString QFSFileEngine::rootPath() QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); if(ret.isEmpty()) ret = QLatin1String("c:"); - ret += QLatin1String("/"); + ret += QLatin1Char('/'); #elif defined(Q_OS_OS2EMX) char dir[4]; _abspath(dir, QLatin1String("/"), _MAX_PATH); @@ -1288,19 +1288,17 @@ QFileInfoList QFSFileEngine::drives() exit(1); driveBits &= 0x3ffffff; #endif - char driveName[4]; - - qstrcpy(driveName, "A:/"); + char driveName[] = "A:/"; while(driveBits) { if(driveBits & 1) - ret.append(QString::fromLatin1(driveName).toUpper()); + ret.append(QString::fromLatin1(driveName)); driveName[0]++; driveBits = driveBits >> 1; } return ret; #else - ret.append(QString::fromLatin1("/").toUpper()); + ret.append(QString::fromLatin1("/")); return ret; #endif } @@ -1333,8 +1331,6 @@ bool QFSFileEnginePrivate::doStat() const if (tmpAttributes != -1) { fileAttrib = tmpAttributes; could_stat = true; - } else { - return false; } #endif } else { @@ -1774,10 +1770,10 @@ QString QFSFileEngine::fileName(FileName file) const if(slash == -1) { if(d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) return d->filePath.left(2); - return QString::fromLatin1("."); + return QString(QLatin1Char('.')); } else { if(!slash) - return QString::fromLatin1("/"); + return QString(QLatin1Char('/')); if(slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) slash++; return d->filePath.left(slash); @@ -1835,7 +1831,7 @@ QString QFSFileEngine::fileName(FileName file) const if (slash == -1) ret = QDir::currentPath(); else if (slash == 0) - ret = QLatin1String("/"); + ret = QString(QLatin1Char('/')); ret = ret.left(slash); } return ret; @@ -1897,7 +1893,7 @@ QString QFSFileEngine::owner(FileOwner own) const #else Q_UNUSED(own); #endif - return QString(QLatin1String("")); + return QString(); } bool QFSFileEngine::setPermissions(uint perms) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 765bf40..82e54fa 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 @@ -1756,7 +1760,7 @@ QDebug operator<<(QDebug debug, QIODevice::OpenMode modes) } qSort(modeList); debug << modeList.join(QLatin1String("|")); - debug << ")"; + debug << ')'; return debug; } #endif diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp new file mode 100644 index 0000000..1ff3a4c --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice.cpp @@ -0,0 +1,544 @@ +/**************************************************************************** +** +** 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) +{ + Q_UNUSED(data); + Q_UNUSED(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..562b759 --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice_p.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** 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; +Q_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 +{ +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 +{ +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 +{ +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 +{ +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 +{ +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 8183527..0becbb6 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) { @@ -421,6 +444,7 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; + environment = 0; startupSocketNotifier = 0; deathNotifier = 0; notifier = 0; @@ -451,6 +475,7 @@ QProcessPrivate::QProcessPrivate() */ QProcessPrivate::~QProcessPrivate() { + delete environment; if (stdinChannel.process) stdinChannel.process->stdoutChannel.clear(); if (stdoutChannel.process) @@ -1211,29 +1236,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 and Symbian, 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>(); } /*! @@ -1527,7 +1606,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM } #if defined QPROCESS_DEBUG - qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")"; + qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')'; #endif d->outputReadBuffer.clear(); @@ -1838,7 +1917,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() { @@ -1851,6 +1930,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 ae40de3..65b5b3e 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(Q_OS_SYMBIAN)) || defined(qdoc) typedef qint64 Q_PID; #elif defined(Q_OS_SYMBIAN) @@ -126,6 +128,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; @@ -161,6 +165,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 554c477..6a3342a 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 1fedd55..e87c314 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -385,17 +385,10 @@ static void qt_create_pipe(int *pipe) qt_native_close(pipe[0]); if (pipe[1] != -1) qt_native_close(pipe[1]); -#ifdef Q_OS_IRIX - if (::socketpair(AF_UNIX, SOCK_STREAM, 0, pipe) == -1) { - qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s", - pipe, qPrintable(qt_error_string(errno))); - } -#else if (::pipe(pipe) != 0) { qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s", pipe, qPrintable(qt_error_string(errno))); } -#endif ::fcntl(pipe[0], F_SETFD, FD_CLOEXEC); ::fcntl(pipe[1], F_SETFD, FD_CLOEXEC); } @@ -522,8 +515,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. @@ -532,27 +529,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; } @@ -581,29 +580,27 @@ void QProcessPrivate::startProcess() processManager()->start(); // Initialize pipes + if (!createChannel(stdinChannel) || + !createChannel(stdoutChannel) || + !createChannel(stderrChannel)) + return; qt_create_pipe(childStartedPipe); + qt_create_pipe(deathPipe); + ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC); + ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC); + if (threadData->eventDispatcher) { startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], QSocketNotifier::Read, q); QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), q, SLOT(_q_startupNotification())); - } - qt_create_pipe(deathPipe); - ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC); - if (threadData->eventDispatcher) { deathNotifier = new QSocketNotifier(deathPipe[0], QSocketNotifier::Read, q); QObject::connect(deathNotifier, SIGNAL(activated(int)), q, SLOT(_q_processDied())); } - if (!createChannel(stdinChannel) || - !createChannel(stdoutChannel) || - !createChannel(stderrChannel)) - return; - // Start the process (platform dependent) q->setProcessState(QProcess::Starting); @@ -791,7 +788,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..179c3d0 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -272,12 +272,12 @@ static QString qt_create_commandline(const QString &program, const QStringList & QString args; if (!program.isEmpty()) { QString programName = program; - if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1String(" "))) - programName = QLatin1String("\"") + programName + QLatin1String("\""); - programName.replace(QLatin1String("/"), QLatin1String("\\")); + if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' '))) + programName = QLatin1Char('\"') + programName + QLatin1Char('\"'); + programName.replace(QLatin1Char('/'), QLatin1Char('\\')); // add the prgram as the first arg ... it works better - args = programName + QLatin1String(" "); + args = programName + QLatin1Char(' '); } for (int i=0; i<arguments.size(); ++i) { @@ -285,16 +285,16 @@ static QString qt_create_commandline(const QString &program, const QStringList & // in the case of \" already being in the string the \ must also be escaped tmp.replace( QLatin1String("\\\""), QLatin1String("\\\\\"") ); // escape a single " because the arguments will be parsed - tmp.replace( QLatin1String("\""), QLatin1String("\\\"") ); + tmp.replace( QLatin1Char('\"'), QLatin1String("\\\"") ); if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) { // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" - QString endQuote(QLatin1String("\"")); + QString endQuote(QLatin1Char('\"')); int i = tmp.length(); while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) { --i; - endQuote += QLatin1String("\\"); + endQuote += QLatin1Char('\\'); } args += QLatin1String(" \"") + tmp.left(i) + endQuote; } else { @@ -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); @@ -402,7 +427,7 @@ void QProcessPrivate::startProcess() QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath(); - fullPathProgram.replace(QLatin1String("/"), QLatin1String("\\")); + fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), (WCHAR*)args.utf16(), 0, 0, false, 0, 0, 0, 0, pid); @@ -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); @@ -862,8 +887,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a #if defined(Q_OS_WINCE) QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) - fullPathProgram.prepend(QDir::currentPath().append(QLatin1String("/"))); - fullPathProgram.replace(QLatin1String("/"), QLatin1String("\\")); + fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/'))); + fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), (WCHAR*)args.utf16(), 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo); diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 0cbcc41..c3c7b76 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) { @@ -561,30 +604,32 @@ 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()) { if(root == path) { - path = QLatin1String("/"); + path = QLatin1Char('/'); } else { - if(!root.endsWith(QLatin1String("/"))) - root += QLatin1String("/"); + if(!root.endsWith(QLatin1Char('/'))) + root += QLatin1Char('/'); if(path.size() >= root.size() && path.startsWith(root)) path = path.mid(root.length()-1); if(path.isEmpty()) - path = QLatin1String("/"); + path = QLatin1Char('/'); } } } @@ -603,12 +648,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) { @@ -650,7 +694,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_p.h b/src/corelib/io/qsettings_p.h index 1bdbf2c..a0f19a4 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 Q_AUTOTEST_EXPORT QConfFile { public: ParsedSettingsMap mergedKeyMap() const; diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index a08c969..57f65d6 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -148,7 +148,7 @@ static QString errorCodeToString(DWORD errorCode) if (data != 0) LocalFree(data); }) - if (result.endsWith(QLatin1String("\n"))) + if (result.endsWith(QLatin1Char('\n'))) result.truncate(result.length() - 1); return result; diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 45a03e3..2d0d9b8 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -203,7 +203,7 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) if (QDir::isAbsolutePath(QString::fromLatin1(path))) targetPath = QLatin1String(path); else - targetPath = QDir::currentPath().append(QLatin1String("/")) + QLatin1String(path); + targetPath = QDir::currentPath().append(QLatin1Char('/')) + QLatin1String(path); if ((*doopen = QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 9382fae..0261c19 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -333,7 +333,7 @@ public: this->stream = stream; } -public slots: +public Q_SLOTS: inline void flushStream() { stream->flush(); } private: @@ -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), codec); + 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 @@ -1217,7 +1219,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); @@ -2287,7 +2289,7 @@ bool QTextStreamPrivate::putNumber(qulonglong number, bool negative) // ShowBase flag set zero should be written as '00' if (number == 0 && base == 8 && numberFlags & QTextStream::ShowBase && result == QLatin1String("0")) { - result.prepend(QLatin1String("0")); + result.prepend(QLatin1Char('0')); } } return putString(result, true); diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d1a5cdd..5846e23 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -5330,7 +5330,7 @@ QString QUrl::toString(FormattingOptions options) const url += QLatin1Char('/'); url += ourPath; // check if we need to remove trailing slashes - while ((options & StripTrailingSlash) && url.right(1) == QLatin1String("/")) + while ((options & StripTrailingSlash) && url.endsWith(QLatin1Char('/'))) url.chop(1); } @@ -5698,7 +5698,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile) // magic for drives on windows if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) { - url.setPath(QLatin1String("/") + deslashified); + url.setPath(QLatin1Char('/') + deslashified); // magic for shared drive on windows } else if (deslashified.startsWith(QLatin1String("//"))) { int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2); @@ -5728,7 +5728,7 @@ QString QUrl::toLocalFile() const // magic for shared drive on windows if (!d->host.isEmpty()) { tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') - ? QLatin1String("/") + ourPath : ourPath); + ? QLatin1Char('/') + ourPath : ourPath); } else { tmp = ourPath; // magic for drives on windows @@ -5976,7 +5976,7 @@ QDataStream &operator>>(QDataStream &in, QUrl &url) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QUrl &url) { - d.maybeSpace() << "QUrl(" << url.toString() << ")"; + d.maybeSpace() << "QUrl(" << url.toString() << ')'; return d.space(); } #endif diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 9242092..e9c4a8d 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -223,7 +223,7 @@ public: inline QT3_SUPPORT QString ref() const { return fragment(); } inline QT3_SUPPORT void setRef(const QString &txt) { setFragment(txt); } inline QT3_SUPPORT bool hasRef() const { return !fragment().isEmpty(); } - inline QT3_SUPPORT void addPath(const QString &p) { setPath(path() + QLatin1String("/") + p); } + inline QT3_SUPPORT void addPath(const QString &p) { setPath(path() + QLatin1Char('/') + p); } QT3_SUPPORT void setFileName(const QString &txt); QT3_SUPPORT QString fileName() const; QT3_SUPPORT QString dirPath() const; |