forked from qt-creator/qt-creator
get rid of lots of qfileinfo and qfile calls
partly by removing unnecessary calls, partly by providing minimalistic reimplementations. this gives a quite incredible performance boost ...
This commit is contained in:
@@ -47,6 +47,7 @@ public:
|
||||
ProFileReader(ProFileOption *option);
|
||||
~ProFileReader();
|
||||
|
||||
// fileName is expected to be absolute and cleanPath()ed.
|
||||
bool readProFile(const QString &fileName);
|
||||
QList<ProFile*> includeFiles() const;
|
||||
|
||||
|
||||
88
src/shared/proparser/ioutils.cpp
Normal file
88
src/shared/proparser/ioutils.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "ioutils.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace ProFileEvaluatorInternal;
|
||||
|
||||
IoUtils::FileType IoUtils::fileType(const QString &fileName)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
DWORD attr = GetFileAttributesW((WCHAR*)fileName.constData());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
return FileNotFound;
|
||||
return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular;
|
||||
#else
|
||||
struct ::stat st;
|
||||
if (::stat(fileName.toLatin1().constData(), &st)) // latin1 symmetric to the file reader
|
||||
return FileNotFound;
|
||||
return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IoUtils::isRelativePath(const QString &path)
|
||||
{
|
||||
if (path.startsWith(QLatin1Char('/')))
|
||||
return false;
|
||||
#ifdef Q_OS_WIN
|
||||
if (path.startsWith(QLatin1Char('\\')))
|
||||
return false;
|
||||
// Unlike QFileInfo, this won't accept a relative path with a drive letter.
|
||||
// Such paths result in a royal mess anyway ...
|
||||
if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
|
||||
&& (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\')))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringRef IoUtils::fileName(const QString &fileName)
|
||||
{
|
||||
return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
}
|
||||
|
||||
QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
|
||||
{
|
||||
if (fileName.isEmpty())
|
||||
return QString();
|
||||
if (isAbsolutePath(fileName))
|
||||
return QDir::cleanPath(fileName);
|
||||
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
|
||||
}
|
||||
59
src/shared/proparser/ioutils.h
Normal file
59
src/shared/proparser/ioutils.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IOUTILS_H
|
||||
#define IOUTILS_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace ProFileEvaluatorInternal {
|
||||
|
||||
/*!
|
||||
This class provides replacement functionality for QFileInfo, QFile & QDir,
|
||||
as these are abysmally slow.
|
||||
*/
|
||||
class IoUtils {
|
||||
public:
|
||||
enum FileType {
|
||||
FileNotFound = 0,
|
||||
FileIsRegular = 1,
|
||||
FileIsDir = 2
|
||||
};
|
||||
|
||||
static FileType fileType(const QString &fileName);
|
||||
static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; }
|
||||
static bool isRelativePath(const QString &fileName);
|
||||
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
|
||||
static QStringRef fileName(const QString &fileName); // Requires normalized path
|
||||
static QString resolvePath(const QString &baseDir, const QString &fileName);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // IOUTILS_H
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "profileevaluator.h"
|
||||
#include "proitems.h"
|
||||
#include "ioutils.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QDateTime>
|
||||
@@ -61,6 +62,8 @@
|
||||
#define QT_PCLOSE pclose
|
||||
#endif
|
||||
|
||||
using namespace ProFileEvaluatorInternal;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static void refFunctions(QHash<QString, ProBlock *> *defs)
|
||||
@@ -240,6 +243,8 @@ public:
|
||||
QString currentFileName() const;
|
||||
QString currentDirectory() const;
|
||||
ProFile *currentProFile() const;
|
||||
QString resolvePath(const QString &fileName) const
|
||||
{ return IoUtils::resolvePath(currentDirectory(), fileName); }
|
||||
|
||||
ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
|
||||
ProFile *parsedProFile(const QString &fileName, bool cache,
|
||||
@@ -328,7 +333,8 @@ bool ProFileEvaluator::Private::read(ProFile *pro)
|
||||
{
|
||||
QFile file(pro->fileName());
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
errorMessage(format("%1 not readable.").arg(pro->fileName()));
|
||||
if (IoUtils::exists(pro->fileName()))
|
||||
errorMessage(format("%1 not readable.").arg(pro->fileName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1022,8 +1028,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
|
||||
if (qmake_cache.isEmpty() && !m_outputDir.isEmpty()) { //find it as it has not been specified
|
||||
QDir dir(m_outputDir);
|
||||
forever {
|
||||
qmake_cache = dir.filePath(QLatin1String(".qmake.cache"));
|
||||
if (QFile::exists(qmake_cache))
|
||||
qmake_cache = dir.path() + QLatin1String("/.qmake.cache");
|
||||
if (IoUtils::exists(qmake_cache))
|
||||
break;
|
||||
if (!dir.cdUp() || dir.isRoot()) {
|
||||
qmake_cache.clear();
|
||||
@@ -1050,8 +1056,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
|
||||
if (qmakespec.isEmpty()) {
|
||||
foreach (const QString &root, mkspec_roots) {
|
||||
QString mkspec = root + QLatin1String("/default");
|
||||
QFileInfo default_info(mkspec);
|
||||
if (default_info.exists() && default_info.isDir()) {
|
||||
if (IoUtils::fileType(mkspec) == IoUtils::FileIsDir) {
|
||||
qmakespec = mkspec;
|
||||
break;
|
||||
}
|
||||
@@ -1062,17 +1067,17 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
|
||||
}
|
||||
}
|
||||
|
||||
if (QDir::isRelativePath(qmakespec)) {
|
||||
if (QFile::exists(qmakespec + QLatin1String("/qmake.conf"))) {
|
||||
qmakespec = QFileInfo(qmakespec).absoluteFilePath();
|
||||
if (IoUtils::isRelativePath(qmakespec)) {
|
||||
if (IoUtils::exists(qmakespec + QLatin1String("/qmake.conf"))) {
|
||||
qmakespec = currentDirectory() + QLatin1Char('/') + qmakespec;
|
||||
} else if (!m_outputDir.isEmpty()
|
||||
&& QFile::exists(m_outputDir + QLatin1Char('/') + qmakespec
|
||||
+ QLatin1String("/qmake.conf"))) {
|
||||
&& IoUtils::exists(m_outputDir + QLatin1Char('/') + qmakespec
|
||||
+ QLatin1String("/qmake.conf"))) {
|
||||
qmakespec = m_outputDir + QLatin1Char('/') + qmakespec;
|
||||
} else {
|
||||
foreach (const QString &root, mkspec_roots) {
|
||||
QString mkspec = root + QLatin1Char('/') + qmakespec;
|
||||
if (QFile::exists(mkspec)) {
|
||||
if (IoUtils::exists(mkspec)) {
|
||||
qmakespec = mkspec;
|
||||
goto cool;
|
||||
}
|
||||
@@ -1260,7 +1265,7 @@ QStringList ProFileEvaluator::Private::qmakeFeaturePaths() const
|
||||
while (!specdir.isRoot()) {
|
||||
if (!specdir.cdUp() || specdir.isRoot())
|
||||
break;
|
||||
if (QFile::exists(specdir.path() + features_concat)) {
|
||||
if (IoUtils::exists(specdir.path() + features_concat)) {
|
||||
foreach (const QString &concat_it, concat)
|
||||
feature_roots << (specdir.path() + concat_it);
|
||||
break;
|
||||
@@ -1892,7 +1897,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
|
||||
logMessage(format("fromfile(file, variable) requires two arguments."));
|
||||
} else {
|
||||
QHash<QString, QStringList> vars;
|
||||
if (evaluateFileInto(args.at(0), &vars, 0))
|
||||
if (evaluateFileInto(resolvePath(args.at(0)), &vars, 0))
|
||||
ret = vars.value(args.at(1));
|
||||
}
|
||||
break;
|
||||
@@ -2036,7 +2041,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
|
||||
if (qdir[i] == QLatin1String(".") || qdir[i] == QLatin1String(".."))
|
||||
continue;
|
||||
QString fname = dir + qdir[i];
|
||||
if (QFileInfo(fname).isDir()) {
|
||||
if (IoUtils::fileType(fname) == IoUtils::FileIsDir) {
|
||||
if (recursive)
|
||||
dirs.append(fname);
|
||||
}
|
||||
@@ -2205,7 +2210,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
|
||||
logMessage(format("infile(file, var, [values]) requires two or three arguments."));
|
||||
} else {
|
||||
QHash<QString, QStringList> vars;
|
||||
if (!evaluateFileInto(args.at(0), &vars, 0))
|
||||
if (!evaluateFileInto(resolvePath(args.at(0)), &vars, 0))
|
||||
return ProItem::ReturnFalse;
|
||||
if (args.count() == 2)
|
||||
return returnBool(vars.contains(args.at(1)));
|
||||
@@ -2526,12 +2531,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
|
||||
logMessage(format("include(file) requires one, two or three arguments."));
|
||||
return ProItem::ReturnFalse;
|
||||
}
|
||||
QString fileName = args.first();
|
||||
// ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style.
|
||||
QDir currentProPath(currentDirectory());
|
||||
fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName));
|
||||
State sts = m_sts;
|
||||
bool ok = evaluateFile(fileName);
|
||||
bool ok = evaluateFile(resolvePath(args.first()));
|
||||
m_sts = sts;
|
||||
return returnBool(ok);
|
||||
}
|
||||
@@ -2595,7 +2596,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
|
||||
QString file = args.first();
|
||||
file = fixPathToLocalOS(file);
|
||||
|
||||
if (QFile::exists(file)) {
|
||||
if (IoUtils::exists(file)) {
|
||||
return ProItem::ReturnTrue;
|
||||
}
|
||||
//regular expression I guess
|
||||
@@ -2648,7 +2649,7 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName,
|
||||
if (variableName == QLatin1String("_PRO_FILE_"))
|
||||
return QStringList(m_profileStack.first()->fileName());
|
||||
if (variableName == QLatin1String("_PRO_FILE_PWD_"))
|
||||
return QStringList(QFileInfo(m_profileStack.first()->fileName()).absolutePath());
|
||||
return QStringList(m_profileStack.first()->directoryName());
|
||||
if (variableName == QLatin1String("_QMAKE_CACHE_"))
|
||||
return QStringList(m_option->cachefile);
|
||||
if (variableName.startsWith(QLatin1String("QMAKE_HOST."))) {
|
||||
@@ -2763,16 +2764,14 @@ ProFile *ProFileEvaluator::Private::parsedProFile(const QString &fileName, bool
|
||||
|
||||
bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
if (!fi.exists())
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
QString fn = QDir::cleanPath(fi.absoluteFilePath());
|
||||
foreach (const ProFile *pf, m_profileStack)
|
||||
if (pf->fileName() == fn) {
|
||||
errorMessage(format("circular inclusion of %1").arg(fn));
|
||||
if (pf->fileName() == fileName) {
|
||||
errorMessage(format("circular inclusion of %1").arg(fileName));
|
||||
return false;
|
||||
}
|
||||
if (ProFile *pro = parsedProFile(fn, true)) {
|
||||
if (ProFile *pro = parsedProFile(fileName, true)) {
|
||||
q->aboutToEval(pro);
|
||||
bool ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
||||
pro->deref();
|
||||
@@ -2789,12 +2788,12 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
|
||||
if (!fn.endsWith(QLatin1String(".prf")))
|
||||
fn += QLatin1String(".prf");
|
||||
|
||||
if (!fileName.contains((ushort)'/') || !QFile::exists(fn)) {
|
||||
if (!fileName.contains((ushort)'/') || !IoUtils::exists(fn)) {
|
||||
if (m_option->feature_roots.isEmpty())
|
||||
m_option->feature_roots = qmakeFeaturePaths();
|
||||
int start_root = 0;
|
||||
QString currFn = currentFileName();
|
||||
if (QFileInfo(currFn).fileName() == QFileInfo(fn).fileName()) {
|
||||
if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) {
|
||||
for (int root = 0; root < m_option->feature_roots.size(); ++root)
|
||||
if (m_option->feature_roots.at(root) + fn == currFn) {
|
||||
start_root = root + 1;
|
||||
@@ -2803,7 +2802,7 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
|
||||
}
|
||||
for (int root = start_root; root < m_option->feature_roots.size(); ++root) {
|
||||
QString fname = m_option->feature_roots.at(root) + fn;
|
||||
if (QFileInfo(fname).exists()) {
|
||||
if (IoUtils::exists(fname)) {
|
||||
fn = fname;
|
||||
goto cool;
|
||||
}
|
||||
@@ -2817,7 +2816,7 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
|
||||
return true;
|
||||
already.append(fn);
|
||||
} else {
|
||||
fn = QDir::cleanPath(fn);
|
||||
fn = resolvePath(fn);
|
||||
}
|
||||
|
||||
if (values) {
|
||||
@@ -2924,9 +2923,9 @@ QStringList ProFileEvaluator::absolutePathValues(
|
||||
{
|
||||
QStringList result;
|
||||
foreach (const QString &el, values(variable)) {
|
||||
const QFileInfo info = QFileInfo(baseDirectory, el);
|
||||
if (info.isDir())
|
||||
result << QDir::cleanPath(info.absoluteFilePath());
|
||||
QString absEl = IoUtils::resolvePath(baseDirectory, el);
|
||||
if (IoUtils::fileType(absEl) == IoUtils::FileIsDir)
|
||||
result << QDir::cleanPath(absEl);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2937,33 +2936,37 @@ QStringList ProFileEvaluator::absoluteFileValues(
|
||||
{
|
||||
QStringList result;
|
||||
foreach (const QString &el, pro ? values(variable, pro) : values(variable)) {
|
||||
QFileInfo info(el);
|
||||
if (info.isAbsolute()) {
|
||||
if (info.exists()) {
|
||||
QString absEl;
|
||||
if (IoUtils::isAbsolutePath(el)) {
|
||||
if (IoUtils::exists(el)) {
|
||||
result << QDir::cleanPath(el);
|
||||
goto next;
|
||||
}
|
||||
absEl = el;
|
||||
} else {
|
||||
foreach (const QString &dir, searchDirs) {
|
||||
QFileInfo info(dir, el);
|
||||
if (info.isFile()) {
|
||||
result << QDir::cleanPath(info.filePath());
|
||||
QString fn = dir + QLatin1Char('/') + el;
|
||||
if (IoUtils::exists(fn)) {
|
||||
result << QDir::cleanPath(fn);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
if (baseDirectory.isEmpty())
|
||||
goto next;
|
||||
info = QFileInfo(baseDirectory, el);
|
||||
absEl = baseDirectory + QLatin1Char('/') + el;
|
||||
}
|
||||
{
|
||||
QFileInfo baseInfo(info.absolutePath());
|
||||
if (baseInfo.exists()) {
|
||||
QString wildcard = info.fileName();
|
||||
absEl = QDir::cleanPath(absEl);
|
||||
int nameOff = absEl.lastIndexOf(QLatin1Char('/'));
|
||||
QString absDir = QString::fromRawData(absEl.constData(), nameOff);
|
||||
if (IoUtils::exists(absDir)) {
|
||||
QString wildcard = QString::fromRawData(absEl.constData() + nameOff + 1,
|
||||
absEl.length() - nameOff - 1);
|
||||
if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) {
|
||||
QDir theDir(QDir::cleanPath(baseInfo.filePath()));
|
||||
QDir theDir(absDir);
|
||||
foreach (const QString &fn, theDir.entryList(QStringList(wildcard)))
|
||||
if (fn != QLatin1String(".") && fn != QLatin1String(".."))
|
||||
result << theDir.absoluteFilePath(fn);
|
||||
result << absDir + QLatin1Char('/') + fn;
|
||||
} // else if (acceptMissing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
void setConfigCommandLineArguments(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
|
||||
void setParsePreAndPostFiles(bool on); // Default is true
|
||||
|
||||
// fileName is expected to be absolute and cleanPath()ed.
|
||||
// If contents is non-null, it will be used instead of the file's actual content
|
||||
ProFile *parsedProFile(const QString &fileName, const QString &contents = QString());
|
||||
bool accept(ProFile *pro);
|
||||
|
||||
@@ -260,9 +260,11 @@ ProFile::ProFile(const QString &fileName)
|
||||
setBlockKind(ProBlock::ProFileKind);
|
||||
m_fileName = fileName;
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
m_displayFileName = fi.fileName();
|
||||
m_directoryName = fi.absolutePath();
|
||||
// If the full name does not outlive the parts, things will go boom ...
|
||||
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
|
||||
m_displayFileName = QString::fromRawData(fileName.constData() + nameOff + 1,
|
||||
fileName.length() - nameOff - 1);
|
||||
m_directoryName = QString::fromRawData(fileName.constData(), nameOff);
|
||||
}
|
||||
|
||||
ProFile::~ProFile()
|
||||
|
||||
@@ -10,11 +10,13 @@ HEADERS += \
|
||||
profileevaluator.h \
|
||||
proitems.h \
|
||||
prowriter.h \
|
||||
ioutils.h \
|
||||
$$PWD/../namespace_global.h
|
||||
|
||||
SOURCES += \
|
||||
profileevaluator.cpp \
|
||||
proitems.cpp \
|
||||
prowriter.cpp
|
||||
prowriter.cpp \
|
||||
ioutils.cpp
|
||||
|
||||
RESOURCES += proparser.qrc
|
||||
|
||||
Reference in New Issue
Block a user