diff options
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qdebug.cpp | 16 | ||||
-rw-r--r-- | src/corelib/io/qdebug.h | 13 | ||||
-rw-r--r-- | src/corelib/io/qdebug_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qdir.cpp | 28 | ||||
-rw-r--r-- | src/corelib/io/qdir.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 12 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_fsevents.mm | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_win.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_unix.cpp | 38 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_win.cpp | 24 | ||||
-rw-r--r-- | src/corelib/io/qiodevice.cpp | 5 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry.cpp | 14 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 1 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 21 | ||||
-rw-r--r-- | src/corelib/io/qresource.cpp | 10 | ||||
-rw-r--r-- | src/corelib/io/qsettings.cpp | 6 | ||||
-rw-r--r-- | src/corelib/io/qsettings_mac.cpp | 18 | ||||
-rw-r--r-- | src/corelib/io/qsettings_win.cpp | 18 | ||||
-rw-r--r-- | src/corelib/io/qsettings_winrt.cpp | 18 | ||||
-rw-r--r-- | src/corelib/io/qurl.cpp | 66 | ||||
-rw-r--r-- | src/corelib/io/qurlrecode.cpp | 142 |
21 files changed, 303 insertions, 157 deletions
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 013d531581..2e825d2373 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -939,14 +939,18 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value) QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name) { QDebugStateSaver saver(dbg); + dbg.nospace(); QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name)); const char *key = me.valueToKey(value); - dbg.nospace() << meta->className() << "::" << name << '('; - if (key) + if (key) { + if (const char *scope = me.scope()) + dbg << scope << "::"; + if (me.isScoped()) + dbg << me.enumName() << "::"; dbg << key; - else - dbg << value; - dbg << ')'; + } else { + dbg << meta->className() << "::" << name << "(" << value << ")"; + } return dbg; } @@ -960,7 +964,7 @@ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaO const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name)); if (const char *scope = me.scope()) debug << scope << "::"; - debug << me.name() << ">(" << me.valueToKeys(value) << ')'; + debug << me.enumName() << ">(" << me.valueToKeys(value) << ')'; return debug; } #endif // !QT_NO_QOBJECT diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index ee8ef679a9..ae1869f89e 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -376,6 +376,19 @@ operator<<(QDebug dbg, T value) return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name); } +template<typename T, + typename A = typename std::enable_if<std::is_enum<T>::value, void>::type, + typename B = typename std::enable_if<sizeof(T) <= sizeof(int), void>::type, + typename C = typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, void>::type, + typename D = typename std::enable_if<QtPrivate::IsQEnumHelper<QFlags<T>>::Value, void>::type> +inline QDebug operator<<(QDebug dbg, T value) +{ + typedef QFlags<T> FlagsT; + const QMetaObject *obj = qt_getEnumMetaObject(FlagsT()); + const char *name = qt_getEnumName(FlagsT()); + return qt_QMetaEnum_debugOperator(dbg, typename FlagsT::Int(value), obj, name); +} + template <class T> inline typename std::enable_if< QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value, diff --git a/src/corelib/io/qdebug_p.h b/src/corelib/io/qdebug_p.h index a1887655d2..dcb906d156 100644 --- a/src/corelib/io/qdebug_p.h +++ b/src/corelib/io/qdebug_p.h @@ -93,7 +93,7 @@ static inline void formatQEnum(QDebug &debug, QEnum value) { const QMetaObject *metaObject = qt_getEnumMetaObject(value); const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(value))); - if (const char *key = me.valueToKey(value)) + if (const char *key = me.valueToKey(int(value))) debug << key; else debug << int(value); diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 10aee73a2f..39422c3401 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -48,7 +48,9 @@ #include "qdiriterator.h" #include "qdatetime.h" #include "qstring.h" -#include "qregexp.h" +#if QT_CONFIG(regularexpression) +# include <qregularexpression.h> +#endif #include "qvector.h" #include "qvarlengtharray.h" #include "qfilesystementry_p.h" @@ -1038,7 +1040,7 @@ QStringList QDir::nameFilters() const list of filters specified by \a nameFilters. Each name filter is a wildcard (globbing) filter that understands - \c{*} and \c{?} wildcards. (See \l{QRegExp wildcard matching}.) + \c{*} and \c{?} wildcards. (See \l{QRegularExpression wildcard matching}.) For example, the following code sets three name filters on a QDir to ensure that only files with extensions typically used for C++ @@ -2059,7 +2061,7 @@ QString QDir::homePath() Returns the system's temporary directory. - The directory is constructed using the absolute path of the temporary directory, + The directory is constructed using the absolute canonical path of the temporary directory, ensuring that its path() will be the same as its absolutePath(). See tempPath() for details. @@ -2068,7 +2070,7 @@ QString QDir::homePath() */ /*! - Returns the absolute path of the system's temporary directory. + Returns the absolute canonical path of the system's temporary directory. On Unix/Linux systems this is the path in the \c TMPDIR environment variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is @@ -2110,7 +2112,7 @@ QString QDir::rootPath() return QFileSystemEngine::rootPath(); } -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) /*! \overload @@ -2118,13 +2120,18 @@ QString QDir::rootPath() patterns in the list of \a filters; otherwise returns \c false. The matching is case insensitive. - \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList() + \sa {QRegularExpression Wildcard matching}, QRegularExpression::wildcardToRegularExpression(), + entryList(), entryInfoList() */ bool QDir::match(const QStringList &filters, const QString &fileName) { for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) { - QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard); - if (rx.exactMatch(fileName)) + QString wildcard = QRegularExpression::wildcardToRegularExpression(*sit); + // Insensitive exact match + // (see Notes for QRegExp Users in QRegularExpression's documentation) + QRegularExpression rx(QRegularExpression::anchoredPattern(wildcard), + QRegularExpression::CaseInsensitiveOption); + if (rx.match(fileName).hasMatch()) return true; } return false; @@ -2136,13 +2143,14 @@ bool QDir::match(const QStringList &filters, const QString &fileName) contain multiple patterns separated by spaces or semicolons. The matching is case insensitive. - \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList() + \sa {QRegularExpression wildcard matching}, QRegularExpression::wildcardToRegularExpression, + entryList(), entryInfoList() */ bool QDir::match(const QString &filter, const QString &fileName) { return match(nameFiltersFromString(filter), fileName); } -#endif // QT_NO_REGEXP +#endif // QT_CONFIG(regularexpression) /*! \internal diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 950a26f327..45c59d9e1d 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -206,7 +206,7 @@ public: static inline QDir temp() { return QDir(tempPath()); } static QString tempPath(); -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) static bool match(const QStringList &filters, const QString &fileName); static bool match(const QString &filter, const QString &fileName); #endif diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index deb4a9f220..835e6a6a44 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -774,7 +774,7 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QString canonicalPath = QDir::cleanPath(QFile::decodeName(ret)); free(ret); return QFileSystemEntry(canonicalPath); - } else if (errno == ENOENT) { // file doesn't exist + } else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute); return QFileSystemEntry(); @@ -853,7 +853,7 @@ QByteArray QFileSystemEngine::id(int id) //static QString QFileSystemEngine::resolveUserName(uint userId) { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); if (size_max == -1) size_max = 1024; @@ -862,7 +862,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) #if !defined(Q_OS_INTEGRITY) struct passwd *pw = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) struct passwd entry; getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw); #else @@ -877,7 +877,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) //static QString QFileSystemEngine::resolveGroupName(uint groupId) { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); if (size_max == -1) size_max = 1024; @@ -886,7 +886,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) #if !defined(Q_OS_INTEGRITY) struct group *gr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24)) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24)) size_max = sysconf(_SC_GETGR_R_SIZE_MAX); if (size_max == -1) size_max = 1024; @@ -1524,7 +1524,7 @@ QString QFileSystemEngine::tempPath() temp = QLatin1String(_PATH_TMP); } } - return QDir::cleanPath(temp); + return QDir(QDir::cleanPath(temp)).canonicalPath(); #endif } diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm index 0254d0f7a1..f68fb67d79 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.mm +++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm @@ -499,7 +499,7 @@ bool QFseventsFileSystemWatcherEngine::startStream() DEBUG() << "Starting stream with paths" << watchingState.watchedPaths.keys(); - NSMutableArray *pathsToWatch = [NSMutableArray arrayWithCapacity:watchingState.watchedPaths.size()]; + NSMutableArray<NSString *> *pathsToWatch = [NSMutableArray<NSString *> arrayWithCapacity:watchingState.watchedPaths.size()]; for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(), ei = watchingState.watchedPaths.end(); i != ei; ++i) [pathsToWatch addObject:i.key().toNSString()]; diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 9e43d11e71..3a49f4346b 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -57,6 +57,7 @@ # include <qcoreapplication.h> # include <qdir.h> # include <private/qeventdispatcher_win_p.h> +# include <private/qthread_p.h> # include <dbt.h> # include <algorithm> # include <vector> @@ -308,7 +309,8 @@ void QWindowsRemovableDriveListener::addPath(const QString &p) notify.dbch_size = sizeof(notify); notify.dbch_devicetype = DBT_DEVTYP_HANDLE; notify.dbch_handle = volumeHandle; - QEventDispatcherWin32 *winEventDispatcher = static_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance()); + QThreadData *currentData = QThreadData::current(); + QEventDispatcherWin32 *winEventDispatcher = static_cast<QEventDispatcherWin32 *>(currentData->ensureEventDispatcher()); re.devNotify = RegisterDeviceNotification(winEventDispatcher->internalHwnd(), ¬ify, DEVICE_NOTIFY_WINDOW_HANDLE); // Empirically found: The notifications also work when the handle is immediately diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index bbd262e2f9..90ad0126d6 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -82,12 +82,11 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode) if (QFSFileEnginePrivate::openModeCanCreate(mode)) oflags |= QT_OPEN_CREAT; - if (mode & QFile::Append) { + if (mode & QFile::Truncate) + oflags |= QT_OPEN_TRUNC; + + if (mode & QFile::Append) oflags |= QT_OPEN_APPEND; - } else if (mode & QFile::WriteOnly) { - if ((mode & QFile::Truncate) || !(mode & QFile::ReadOnly)) - oflags |= QT_OPEN_TRUNC; - } if (mode & QFile::NewOnly) oflags |= QT_OPEN_EXCL; @@ -531,29 +530,32 @@ QByteArray QFSFileEngine::id() const QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); - if (file == BundleName) { + switch (file) { + case BundleName: return QFileSystemEngine::bundleName(d->fileEntry); - } else if (file == BaseName) { + case BaseName: return d->fileEntry.fileName(); - } else if (file == PathName) { + case PathName: return d->fileEntry.path(); - } else if (file == AbsoluteName || file == AbsolutePathName) { + case AbsoluteName: + case AbsolutePathName: { QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry)); - if (file == AbsolutePathName) { - return entry.path(); - } - return entry.filePath(); - } else if (file == CanonicalName || file == CanonicalPathName) { + return file == AbsolutePathName ? entry.path() : entry.filePath(); + } + case CanonicalName: + case CanonicalPathName: { QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData)); - if (file == CanonicalPathName) - return entry.path(); - return entry.filePath(); - } else if (file == LinkName) { + return file == CanonicalPathName ? entry.path() : entry.filePath(); + } + case LinkName: if (d->isSymlink()) { QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData); return entry.filePath(); } return QString(); + case DefaultName: + case NFileNames: + break; } return d->fileEntry.filePath(); } diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 8199f6a846..9d3bfbba31 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -45,7 +45,6 @@ #include "qfile.h" #include "qdir.h" -#include "private/qmutexpool_p.h" #include "qvarlengtharray.h" #include "qdatetime.h" #include "qt_windows.h" @@ -591,7 +590,6 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons bool QFSFileEngine::link(const QString &newName) { #if !defined(Q_OS_WINRT) -# if QT_CONFIG(library) bool ret = false; QString linkName = newName; @@ -600,23 +598,27 @@ bool QFSFileEngine::link(const QString &newName) IShellLink *psl; bool neededCoInit = false; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, + reinterpret_cast<void **>(&psl)); if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + CoInitialize(nullptr); + hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, + reinterpret_cast<void **>(&psl)); } if (SUCCEEDED(hres)) { - hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); + const QString nativeAbsoluteName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')); + hres = psl->SetPath(reinterpret_cast<const wchar_t *>(nativeAbsoluteName.utf16())); if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); + const QString nativeAbsolutePathName = fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')); + hres = psl->SetWorkingDirectory(reinterpret_cast<const wchar_t *>(nativeAbsolutePathName.utf16())); if (SUCCEEDED(hres)) { IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); + hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void **>(&ppf)); if (SUCCEEDED(hres)) { - hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE); + hres = ppf->Save(reinterpret_cast<const wchar_t *>(linkName.utf16()), TRUE); if (SUCCEEDED(hres)) ret = true; ppf->Release(); @@ -632,10 +634,6 @@ bool QFSFileEngine::link(const QString &newName) CoUninitialize(); return ret; -# else // QT_CONFIG(library) - Q_UNUSED(newName); - return false; -# endif // QT_CONFIG(library) #else // !Q_OS_WINRT Q_UNUSED(newName); Q_UNIMPLEMENTED(); diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 95a5fb27cf..5dd5f8031e 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -312,8 +312,9 @@ QIODevicePrivate::~QIODevicePrivate() \value NotOpen The device is not open. \value ReadOnly The device is open for reading. - \value WriteOnly The device is open for writing. Note that this mode implies - Truncate. + \value WriteOnly The device is open for writing. Note that, for file-system + subclasses (e.g. QFile), this mode implies Truncate unless + combined with ReadOnly, Append or NewOnly. \value ReadWrite The device is open for reading and writing. \value Append The device is opened in append mode so that all data is written to the end of the file. diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index cd97268d71..9792d956cc 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -46,6 +46,11 @@ #include <QtCore/qdir.h> #include <QtCore/qcoreapplication.h> +#if QT_CONFIG(settings) +#include <QtCore/qsettings.h> +#include <QtCore/private/qsettings_p.h> +#endif + // We can't use the default macros because this would lead to recursion. // Instead let's define our own one that unconditionally logs... #define debugMsg QMessageLogger(__FILE__, __LINE__, __FUNCTION__, "qt.core.logging").debug @@ -230,7 +235,14 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line) int equalPos = line.indexOf(QLatin1Char('=')); if (equalPos != -1) { if (line.lastIndexOf(QLatin1Char('=')) == equalPos) { - const auto pattern = line.left(equalPos).trimmed(); + const auto key = line.left(equalPos).trimmed(); +#if QT_CONFIG(settings) + QString tmp; + QSettingsPrivate::iniUnescapedKey(key.toUtf8(), 0, key.length(), tmp); + QStringRef pattern = QStringRef(&tmp, 0, tmp.length()); +#else + QStringRef pattern = key; +#endif const auto valueStr = line.mid(equalPos + 1).trimmed(); int value = -1; if (valueStr == QLatin1String("true")) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 713af9bd40..7a2daa2a57 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -101,7 +101,6 @@ QT_END_NAMESPACE #include <qdir.h> #include <qlist.h> #include <qmutex.h> -#include <qsemaphore.h> #include <qsocketnotifier.h> #include <qthread.h> #include <qelapsedtimer.h> diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 8c4e5b41b4..1f7a49379d 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -149,7 +149,26 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe) } // Wait until connection is in place. - ConnectNamedPipe(hServer, NULL); + OVERLAPPED overlapped; + ZeroMemory(&overlapped, sizeof(overlapped)); + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (ConnectNamedPipe(hServer, &overlapped) == 0) { + DWORD dwError = GetLastError(); + switch (dwError) { + case ERROR_PIPE_CONNECTED: + break; + case ERROR_IO_PENDING: + WaitForSingleObject(overlapped.hEvent, INFINITE); + break; + default: + qErrnoWarning(dwError, "QProcess: ConnectNamedPipe failed."); + CloseHandle(overlapped.hEvent); + CloseHandle(hClient); + CloseHandle(hServer); + return; + } + } + CloseHandle(overlapped.hEvent); if (isInputPipe) { pipe[0] = hClient; diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 7502fb57a3..367cd78d65 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -52,7 +52,9 @@ #include "qendian.h" #include <qshareddata.h> #include <qplatformdefs.h> +#include <qendian.h> #include "private/qabstractfileengine_p.h" +#include "private/qsimd_p.h" #include "private/qsystemerror_p.h" #ifdef Q_OS_UNIX @@ -629,17 +631,13 @@ inline QString QResourceRoot::name(int node) const QString ret; qint32 name_offset = qFromBigEndian<qint32>(tree + offset); - const qint16 name_length = qFromBigEndian<qint16>(names + name_offset); + quint16 name_length = qFromBigEndian<qint16>(names + name_offset); name_offset += 2; name_offset += 4; //jump past hash 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; - } + qFromBigEndian<ushort>(names + name_offset, name_length, strData); return ret; } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 4b1b9888d8..1134c6bb85 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1694,10 +1694,10 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data, iniSection = iniSection.trimmed(); - if (qstricmp(iniSection.constData(), "general") == 0) { + if (iniSection.compare("general", Qt::CaseInsensitive) == 0) { currentSection.clear(); } else { - if (qstricmp(iniSection.constData(), "%general") == 0) { + if (iniSection.compare("%general", Qt::CaseInsensitive) == 0) { currentSection = QLatin1String(iniSection.constData() + 1); } else { currentSection.clear(); @@ -1857,7 +1857,7 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti if (realSection.isEmpty()) { realSection = "[General]"; - } else if (qstricmp(realSection.constData(), "general") == 0) { + } else if (realSection.compare("general", Qt::CaseInsensitive) == 0) { realSection = "[%General]"; } else { realSection.prepend('['); diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index aa14d8435a..28f01eae4d 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -355,15 +355,15 @@ public: const QString &application); ~QMacSettingsPrivate(); - void remove(const QString &key); - void set(const QString &key, const QVariant &value); - bool get(const QString &key, QVariant *value) const; - QStringList children(const QString &prefix, ChildSpec spec) const; - void clear(); - void sync(); - void flush(); - bool isWritable() const; - QString fileName() const; + void remove(const QString &key) override; + void set(const QString &key, const QVariant &value) override; + bool get(const QString &key, QVariant *value) const override; + QStringList children(const QString &prefix, ChildSpec spec) const override; + void clear() override; + void sync() override; + void flush() override; + bool isWritable() const override; + QString fileName() const override; private: struct SearchDomain diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index edcae16776..43e1411c76 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -383,17 +383,17 @@ public: QWinSettingsPrivate(QString rKey, REGSAM access = 0); ~QWinSettingsPrivate(); - void remove(const QString &uKey); - void set(const QString &uKey, const QVariant &value); - bool get(const QString &uKey, QVariant *value) const; - QStringList children(const QString &uKey, ChildSpec spec) const; - void clear(); - void sync(); - void flush(); - bool isWritable() const; + void remove(const QString &uKey) override; + void set(const QString &uKey, const QVariant &value) override; + bool get(const QString &uKey, QVariant *value) const override; + QStringList children(const QString &uKey, ChildSpec spec) const override; + void clear() override; + void sync() override; + void flush() override; + bool isWritable() const override; HKEY writeHandle() const; bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const; - QString fileName() const; + QString fileName() const override; private: RegistryKeyList regList; // list of registry locations to search for keys diff --git a/src/corelib/io/qsettings_winrt.cpp b/src/corelib/io/qsettings_winrt.cpp index 209b56d920..4c757f9dda 100644 --- a/src/corelib/io/qsettings_winrt.cpp +++ b/src/corelib/io/qsettings_winrt.cpp @@ -290,15 +290,15 @@ public: QWinRTSettingsPrivate(const QString &rKey); ~QWinRTSettingsPrivate(); - void remove(const QString &uKey); - void set(const QString &uKey, const QVariant &value); - bool get(const QString &uKey, QVariant *value) const; - QStringList children(const QString &uKey, ChildSpec spec) const; - void clear(); - void sync(); - void flush(); - bool isWritable() const; - QString fileName() const; + void remove(const QString &uKey) override; + void set(const QString &uKey, const QVariant &value) override; + bool get(const QString &uKey, QVariant *value) const override; + QStringList children(const QString &uKey, ChildSpec spec) const override; + void clear() override; + void sync() override; + void flush() override; + bool isWritable() const override; + QString fileName() const override; private: void init(QSettings::Scope scope); diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 438924bd80..e531505877 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -472,16 +472,10 @@ static inline QString webDavSslTag() return QStringLiteral("@SSL"); } -#ifdef Q_COMPILER_CLASS_ENUM -# define colon_uchar : uchar -#else -# define colon_uchar -#endif - class QUrlPrivate { public: - enum Section colon_uchar { + enum Section : uchar { Scheme = 0x01, UserName = 0x02, Password = 0x04, @@ -496,7 +490,7 @@ public: FullUrl = 0xff }; - enum Flags colon_uchar { + enum Flags : uchar { IsLocalFile = 0x01 }; @@ -616,7 +610,6 @@ public: // 32-bit: 2 bytes tail padding available // 64-bit: 6 bytes tail padding available }; -#undef colon_uchar inline QUrlPrivate::QUrlPrivate() : ref(1), port(-1), @@ -1203,15 +1196,13 @@ inline void QUrlPrivate::setQuery(const QString &value, int from, int iend) inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions options) const { - // EncodeUnicode is the only flag that matters - if ((options & QUrl::FullyDecoded) == QUrl::FullyDecoded) - options = 0; - else - options &= QUrl::EncodeUnicode; if (host.isEmpty()) return; if (host.at(0).unicode() == '[') { - // IPv6Address and IPvFuture address never require any transformation + // IPv6 addresses might contain a zone-id which needs to be recoded + if (options != 0) + if (qt_urlRecode(appendTo, host.constBegin(), host.constEnd(), options, 0)) + return; appendTo += host; } else { // this is either an IPv4Address or a reg-name @@ -1278,31 +1269,44 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar // ONLY the IPv6 address is parsed here, WITHOUT the brackets static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode) { - QIPAddressUtils::IPv6Address address; - const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end); - if (ret) { + // ### Update to use QStringView once QStringView::indexOf and QStringView::lastIndexOf exists + QString decoded; + if (mode == QUrl::TolerantMode) { // this struct is kept in automatic storage because it's only 4 bytes const ushort decodeColon[] = { decode(':'), 0 }; + if (qt_urlRecode(decoded, begin, end, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon) == 0) + decoded = QString(begin, end-begin); + } else { + decoded = QString(begin, end-begin); + } - // IPv6 failed parsing, check if it was a percent-encoded character in - // the middle and try again - QString decoded; - if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) { - // recurse - // if the parsing fails again, the qt_urlRecode above will return 0 - ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode); + const QLatin1String zoneIdIdentifier("%25"); + QIPAddressUtils::IPv6Address address; + QString zoneId; - // we can't return ret, otherwise it would be dangling - return ret ? end : 0; - } + const QChar *endBeforeZoneId = decoded.constEnd(); + + int zoneIdPosition = decoded.indexOf(zoneIdIdentifier); + if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) { + zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size()); + endBeforeZoneId = decoded.constBegin() + zoneIdPosition; - // no transformation, nothing to re-parse - return ret; + if (zoneId.isEmpty()) + return end; } - host.reserve(host.size() + (end - begin)); + const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId); + if (ret) + return begin + (ret - decoded.constBegin()); + + host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin())); host += QLatin1Char('['); QIPAddressUtils::toString(host, address); + + if (!zoneId.isEmpty()) { + host += zoneIdIdentifier; + host += zoneId; + } host += QLatin1Char(']'); return 0; } diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp index a9b23babc0..443ae18b21 100644 --- a/src/corelib/io/qurlrecode.cpp +++ b/src/corelib/io/qurlrecode.cpp @@ -40,6 +40,7 @@ #include "qurl.h" #include "private/qutfcodec_p.h" #include "private/qtools_p.h" +#include "private/qsimd_p.h" QT_BEGIN_NAMESPACE @@ -474,6 +475,88 @@ non_trivial: return 0; } +/* + * Returns true if the input it checked (if it checked anything) is not + * encoded. A return of false indicates there's a percent at \a input that + * needs to be decoded. + */ +#ifdef __SSE2__ +static bool simdCheckNonEncoded(ushort *&output, const ushort *&input, const ushort *end) +{ +# ifdef __AVX2__ + const __m256i percents256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128('%')); + const __m128i percents = _mm256_castsi256_si128(percents256); +# else + const __m128i percents = _mm_set1_epi16('%'); +# endif + + uint idx = 0; + quint32 mask = 0; + if (input + 16 <= end) { + qptrdiff offset = 0; + for ( ; input + offset + 16 <= end; offset += 16) { +# ifdef __AVX2__ + // do 32 bytes at a time using AVX2 + __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(input + offset)); + __m256i comparison = _mm256_cmpeq_epi16(data, percents256); + mask = _mm256_movemask_epi8(comparison); + _mm256_storeu_si256(reinterpret_cast<__m256i *>(output + offset), data); +# else + // do 32 bytes at a time using unrolled SSE2 + __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input + offset)); + __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input + offset + 8)); + __m128i comparison1 = _mm_cmpeq_epi16(data1, percents); + __m128i comparison2 = _mm_cmpeq_epi16(data2, percents); + uint mask1 = _mm_movemask_epi8(comparison1); + uint mask2 = _mm_movemask_epi8(comparison2); + + _mm_storeu_si128(reinterpret_cast<__m128i *>(output + offset), data1); + if (!mask1) + _mm_storeu_si128(reinterpret_cast<__m128i *>(output + offset + 8), data2); + mask = mask1 | (mask2 << 16); +# endif + + if (mask) { + idx = qCountTrailingZeroBits(mask) / 2; + break; + } + } + + input += offset; + if (output) + output += offset; + } else if (input + 8 <= end) { + // do 16 bytes at a time + __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input)); + __m128i comparison = _mm_cmpeq_epi16(data, percents); + mask = _mm_movemask_epi8(comparison); + _mm_storeu_si128(reinterpret_cast<__m128i *>(output), data); + idx = qCountTrailingZeroBits(quint16(mask)) / 2; + } else if (input + 4 <= end) { + // do 8 bytes only + __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(input)); + __m128i comparison = _mm_cmpeq_epi16(data, percents); + mask = _mm_movemask_epi8(comparison) & 0xffu; + _mm_storel_epi64(reinterpret_cast<__m128i *>(output), data); + idx = qCountTrailingZeroBits(quint8(mask)) / 2; + } else { + // no percents found (because we didn't check) + return true; + } + + // advance to the next non-encoded + input += idx; + output += idx; + + return !mask; +} +#else +static bool simdCheckNonEncoded(...) +{ + return true; +} +#endif + /*! \since 5.0 \internal @@ -497,16 +580,21 @@ non_trivial: */ static int decode(QString &appendTo, const ushort *begin, const ushort *end) { + // fast check whether there's anything to be decoded in the first place + const ushort *input = QtPrivate::qustrchr(QStringView(begin, end), '%'); + if (Q_LIKELY(input == end)) + return 0; // nothing to do, it was already decoded! + + // detach const int origSize = appendTo.size(); - const ushort *input = begin; - ushort *output = 0; + appendTo.resize(origSize + (end - begin)); + ushort *output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize; + memcpy(static_cast<void *>(output), static_cast<const void *>(begin), (input - begin) * sizeof(ushort)); + output += input - begin; + while (input != end) { - if (*input != '%') { - if (output) - *output++ = *input; - ++input; - continue; - } + // something was encoded + Q_ASSERT(*input == '%'); if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) { // badly-encoded data @@ -515,27 +603,27 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end) return end - begin; } - if (Q_UNLIKELY(!output)) { - // detach - appendTo.resize(origSize + (end - begin)); - output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize; - memcpy(static_cast<void *>(output), static_cast<const void *>(begin), (input - begin) * sizeof(ushort)); - output += input - begin; - } - ++input; *output++ = decodeNibble(input[0]) << 4 | decodeNibble(input[1]); if (output[-1] >= 0x80) output[-1] = QChar::ReplacementCharacter; input += 2; - } - if (output) { - int len = output - reinterpret_cast<ushort *>(appendTo.begin()); - appendTo.truncate(len); - return len - origSize; + // search for the next percent, copying from input to output + if (simdCheckNonEncoded(output, input, end)) { + while (input != end) { + ushort uc = *input; + if (uc == '%') + break; + *output++ = uc; + ++input; + } + } } - return 0; + + int len = output - reinterpret_cast<ushort *>(appendTo.begin()); + appendTo.truncate(len); + return len - origSize; } template <size_t N> @@ -603,6 +691,9 @@ qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end, encoding, actionTable, false); } +// qstring.cpp +bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW; + /*! \internal \since 5.0 @@ -623,12 +714,7 @@ QString qt_urlRecodeByteArray(const QByteArray &ba) // control points below 0x20 are fine in QString const char *in = ba.constData(); const char *const end = ba.constEnd(); - for ( ; in < end; ++in) { - if (*in & 0x80) - break; - } - - if (in == end) { + if (qt_is_ascii(in, end)) { // no non-ASCII found, we're safe to convert to QString return QString::fromLatin1(ba, ba.size()); } |