QFileDialog: optimize string handling in qt_tildeExpansion
- Instead of QString::split()-ing the path, just to inspect the
first item in the list returned, simply find the location of
the first separator and work with that.
-> saves creating a QList, and its QString elements
-> saves attempted detaches of that list when calling
first()
- When extracting the user name, don't do it in a QString, do
it in a QStringRef.
- When constructing the result, don't use QString::replace(),
use QStringBuilder with a QStringRef into the original string.
- Eradicate the out parameter, it is easily calculated from the
return value.
- Don't calculate userName on VXWORKS and INTEGRITY, where it
is not used. Requires a different #ifdef sequence. Fixed
preprocessor directives' indention as a drive-by.
Costs 84b in text size on optimized GCC 4.9 Linux AMD64 builds.
Change-Id: I61f1e8d558db7fb0c5c1170bdfd6f5ac1f1a9e62
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
bb10
parent
024a52d0d1
commit
be94e009ae
|
|
@ -1091,46 +1091,43 @@ void QFileDialog::selectUrl(const QUrl &url)
|
|||
}
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0)
|
||||
Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)
|
||||
{
|
||||
if (expanded != 0)
|
||||
*expanded = false;
|
||||
if (!path.startsWith(QLatin1Char('~')))
|
||||
return path;
|
||||
QString ret = path;
|
||||
QStringList tokens = ret.split(QDir::separator());
|
||||
if (tokens.first() == QLatin1String("~")) {
|
||||
ret.replace(0, 1, QDir::homePath());
|
||||
int separatorPosition = path.indexOf(QDir::separator());
|
||||
if (separatorPosition < 0)
|
||||
separatorPosition = path.size();
|
||||
if (separatorPosition == 1) {
|
||||
return QDir::homePath() + path.midRef(1);
|
||||
} else {
|
||||
QString userName = tokens.first();
|
||||
userName.remove(0, 1);
|
||||
#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
|
||||
const QString homePath = QDir::homePath();
|
||||
#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||
#else
|
||||
const QByteArray userName = path.midRef(1, separatorPosition - 1).toLocal8Bit();
|
||||
# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||
passwd pw;
|
||||
passwd *tmpPw;
|
||||
char buf[200];
|
||||
const int bufSize = sizeof(buf);
|
||||
int err = 0;
|
||||
#if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
|
||||
tmpPw = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize);
|
||||
#else
|
||||
err = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize, &tmpPw);
|
||||
#endif
|
||||
# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
|
||||
tmpPw = getpwnam_r(userName.constData(), &pw, buf, bufSize);
|
||||
# else
|
||||
err = getpwnam_r(userName.constData(), &pw, buf, bufSize, &tmpPw);
|
||||
# endif
|
||||
if (err || !tmpPw)
|
||||
return ret;
|
||||
return path;
|
||||
const QString homePath = QString::fromLocal8Bit(pw.pw_dir);
|
||||
#else
|
||||
passwd *pw = getpwnam(userName.toLocal8Bit().constData());
|
||||
# else
|
||||
passwd *pw = getpwnam(userName.constData());
|
||||
if (!pw)
|
||||
return ret;
|
||||
return path;
|
||||
const QString homePath = QString::fromLocal8Bit(pw->pw_dir);
|
||||
# endif
|
||||
#endif
|
||||
ret.replace(0, tokens.first().length(), homePath);
|
||||
return homePath + path.midRef(separatorPosition);
|
||||
}
|
||||
if (expanded != 0)
|
||||
*expanded = true;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -4044,15 +4041,17 @@ QStringList QFSCompleter::splitPath(const QString &path) const
|
|||
else
|
||||
doubleSlash.clear();
|
||||
#elif defined(Q_OS_UNIX)
|
||||
bool expanded;
|
||||
pathCopy = qt_tildeExpansion(pathCopy, &expanded);
|
||||
if (expanded) {
|
||||
QFileSystemModel *dirModel;
|
||||
if (proxyModel)
|
||||
dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
|
||||
else
|
||||
dirModel = sourceModel;
|
||||
dirModel->fetchMore(dirModel->index(pathCopy));
|
||||
{
|
||||
QString tildeExpanded = qt_tildeExpansion(pathCopy);
|
||||
if (tildeExpanded != pathCopy) {
|
||||
QFileSystemModel *dirModel;
|
||||
if (proxyModel)
|
||||
dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
|
||||
else
|
||||
dirModel = sourceModel;
|
||||
dirModel->fetchMore(dirModel->index(tildeExpanded));
|
||||
}
|
||||
pathCopy = std::move(tildeExpanded);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
#include <unistd.h> // for pathconf() on OS X
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QT_BEGIN_NAMESPACE
|
||||
extern Q_GUI_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0);
|
||||
extern Q_GUI_EXPORT QString qt_tildeExpansion(const QString &path);
|
||||
QT_END_NAMESPACE
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -1395,15 +1395,18 @@ void tst_QFiledialog::tildeExpansion_data()
|
|||
QTest::addColumn<QString>("tildePath");
|
||||
QTest::addColumn<QString>("expandedPath");
|
||||
|
||||
const QString tilde = QStringLiteral("~");
|
||||
const QString tildeUser = tilde + QString(qgetenv("USER"));
|
||||
const QLatin1String someSubDir("/some/sub/dir");
|
||||
const QString homePath = QDir::homePath();
|
||||
const QString invalid = QStringLiteral("~thisIsNotAValidUserName");
|
||||
|
||||
QTest::newRow("empty path") << QString() << QString();
|
||||
QTest::newRow("~") << QString::fromLatin1("~") << QDir::homePath();
|
||||
QTest::newRow("~/some/sub/dir/") << QString::fromLatin1("~/some/sub/dir") << QDir::homePath()
|
||||
+ QString::fromLatin1("/some/sub/dir");
|
||||
QString userHome = QString(qgetenv("USER"));
|
||||
userHome.prepend('~');
|
||||
QTest::newRow("current user (~<user> syntax)") << userHome << QDir::homePath();
|
||||
QString invalid = QString::fromLatin1("~thisIsNotAValidUserName");
|
||||
QTest::newRow("invalid user name") << invalid << invalid;
|
||||
QTest::newRow("~") << tilde << homePath;
|
||||
QTest::newRow("~/some/sub/dir/") << tilde + someSubDir << homePath + someSubDir;
|
||||
QTest::newRow("~<user>") << tildeUser << homePath;
|
||||
QTest::newRow("~<user>/some/sub/dir") << tildeUser + someSubDir << homePath + someSubDir;
|
||||
QTest::newRow("invalid user name") << invalid << invalid;
|
||||
}
|
||||
#endif // QT_BUILD_INTERNAL
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue