diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-03-23 16:38:39 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-03-24 14:30:16 +0000 |
commit | 9bd988eb1b4327225809d4e449af7f8b3105dd87 (patch) | |
tree | 4ce28e2882830176c8aef722548f213ce7beb72f | |
parent | 8d99ee1f6af693ad45dcd03fcae6a86f8f86302a (diff) |
TypeDatabase: Refactor API version checking
The repeated construction of a QRegExp in the version checking
loop shows up in the profiler.
Change the API to accept a QString, reducing conversions and
remove obsolete API.
Port the version checking code to use QRegularExpression and
QVersionNumber and store the regexps in a vector.
Change-Id: Id3e509e065d73699f49109df1f184edbefb8a09a
Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r-- | ApiExtractor/apiextractor.cpp | 9 | ||||
-rw-r--r-- | ApiExtractor/apiextractor.h | 3 | ||||
-rw-r--r-- | ApiExtractor/tests/testutil.h | 4 | ||||
-rw-r--r-- | ApiExtractor/typedatabase.cpp | 80 | ||||
-rw-r--r-- | ApiExtractor/typedatabase.h | 4 | ||||
-rw-r--r-- | ApiExtractor/typesystem.cpp | 2 | ||||
-rw-r--r-- | generator/main.cpp | 11 |
7 files changed, 61 insertions, 52 deletions
diff --git a/ApiExtractor/apiextractor.cpp b/ApiExtractor/apiextractor.cpp index 92107de35..371ccf559 100644 --- a/ApiExtractor/apiextractor.cpp +++ b/ApiExtractor/apiextractor.cpp @@ -113,14 +113,9 @@ void ApiExtractor::setSilent ( bool value ) ReportHandler::setSilent(value); } -void ApiExtractor::setApiVersion(double version) +bool ApiExtractor::setApiVersion(const QString& package, const QString &version) { - TypeDatabase::instance()->setApiVersion(QLatin1String("*"), QByteArray::number(version)); -} - -void ApiExtractor::setApiVersion(const QString& package, const QByteArray& version) -{ - TypeDatabase::instance()->setApiVersion(package, version); + return TypeDatabase::instance()->setApiVersion(package, version); } void ApiExtractor::setDropTypeEntries(QString dropEntries) diff --git a/ApiExtractor/apiextractor.h b/ApiExtractor/apiextractor.h index 85f515219..1080ff507 100644 --- a/ApiExtractor/apiextractor.h +++ b/ApiExtractor/apiextractor.h @@ -71,8 +71,7 @@ public: void addIncludePath(const QStringList& paths); QStringList includePaths() const { return m_includePaths; } void setLogDirectory(const QString& logDir); - APIEXTRACTOR_DEPRECATED(void setApiVersion(double version)); - void setApiVersion(const QString& package, const QByteArray& version); + bool setApiVersion(const QString& package, const QString& version); void setDropTypeEntries(QString dropEntries); AbstractMetaEnumList globalEnums() const; diff --git a/ApiExtractor/tests/testutil.h b/ApiExtractor/tests/testutil.h index ad2e3a7d5..d4eb2fdf6 100644 --- a/ApiExtractor/tests/testutil.h +++ b/ApiExtractor/tests/testutil.h @@ -42,8 +42,8 @@ namespace TestUtil { ReportHandler::setSilent(silent); TypeDatabase* td = TypeDatabase::instance(true); - if (apiVersion) - td->setApiVersion(QLatin1String("*"), apiVersion); + if (apiVersion && !td->setApiVersion(QLatin1String("*"), QLatin1String(apiVersion))) + return Q_NULLPTR; td->setDropTypeEntries(dropTypeEntries); QBuffer buffer; // parse typesystem diff --git a/ApiExtractor/typedatabase.cpp b/ApiExtractor/typedatabase.cpp index c80efcaba..c6f42af7a 100644 --- a/ApiExtractor/typedatabase.cpp +++ b/ApiExtractor/typedatabase.cpp @@ -32,15 +32,28 @@ #include <QtCore/QFile> #include <QtCore/QDir> +#include <QtCore/QPair> +#include <QtCore/QVector> +#include <QtCore/QRegularExpression> +#include <QtCore/QVersionNumber> #include <QtCore/QXmlStreamReader> #include "reporthandler.h" // #include <tr1/tuple> #include <algorithm> // package -> api-version -typedef QMap<QString, QByteArray> ApiVersionMap; -Q_GLOBAL_STATIC(ApiVersionMap, apiVersions) +static QString wildcardToRegExp(QString w) +{ + w.replace(QLatin1Char('?'), QLatin1Char('.')); + w.replace(QLatin1Char('*'), QStringLiteral(".*")); + return w; +} + +typedef QPair<QRegularExpression, QVersionNumber> ApiVersion; +typedef QVector<ApiVersion> ApiVersions; + +Q_GLOBAL_STATIC(ApiVersions, apiVersions) TypeDatabase::TypeDatabase() : m_suppressWarnings(true) { @@ -525,46 +538,39 @@ int getMaxTypeIndex() return maxTypeIndex; } -void TypeDatabase::setApiVersion(const QString& package, const QByteArray& version) +bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QString &version) { - (*apiVersions())[package.trimmed()] = version.trimmed(); -} - -/** - * Returns -1, 0 or 1 if v1 is less, equal or greater than v2 - */ -static int versionCheck(const QByteArray& v1, const QByteArray& v2) -{ - if (v1.isEmpty() || v2.isEmpty()) - return 0; - - QList<QByteArray> v1Components = v1.split('.'); - QList<QByteArray> v2Components = v2.split('.'); - int numComponents = qMax(v1Components.count(), v2Components.count()); - while (v1Components.count() < numComponents) - v1Components.append("0"); - while (v2Components.count() < numComponents) - v2Components.append("0"); - - for (int i = 0, max = v1Components.count(); i < max; ++i) { - int v1Comp = v1Components[i].toInt(); - int v2Comp = v2Components[i].toInt(); - if (v1Comp > v2Comp) - return 1; - else if (v1Comp < v2Comp) - return -1; + const QString packagePattern = wildcardToRegExp(packageWildcardPattern.trimmed()); + const QVersionNumber versionNumber = QVersionNumber::fromString(version); + if (versionNumber.isNull()) + return false; + ApiVersions &versions = *apiVersions(); + for (int i = 0, size = versions.size(); i < size; ++i) { + if (versions.at(i).first.pattern() == packagePattern) { + versions[i].second = versionNumber; + return true; + } } - return 0; + const QRegularExpression packageRegex(packagePattern); + if (!packageRegex.isValid()) + return false; + versions.append(qMakePair(packageRegex, versionNumber)); + return true; } -bool TypeDatabase::checkApiVersion(const QString& package, const QByteArray& version) const +bool TypeDatabase::checkApiVersion(const QString& package, const QString& version) const { - ApiVersionMap* vMap = apiVersions(); - ApiVersionMap::const_iterator it = vMap->begin(); - for (; it != vMap->end(); ++it) { - QRegExp regex(it.key(), Qt::CaseSensitive, QRegExp::Wildcard); - if (regex.exactMatch(package)) - return versionCheck(it.value(), version) >= 0; + const QVersionNumber versionNumber = QVersionNumber::fromString(version); + if (versionNumber.isNull()) { + qCWarning(lcShiboken).noquote().nospace() + << "checkApiVersion: Invalid version \"" << version << "\" specified for package " + << package << '.'; + return false; + } + const ApiVersions &versions = *apiVersions(); + for (int i = 0, size = versions.size(); i < size; ++i) { + if (versions.at(i).first.match(package).hasMatch()) + return versions.at(i).second >= versionNumber; } return false; } diff --git a/ApiExtractor/typedatabase.h b/ApiExtractor/typedatabase.h index cf5028d82..b28fc9ba4 100644 --- a/ApiExtractor/typedatabase.h +++ b/ApiExtractor/typedatabase.h @@ -136,9 +136,9 @@ public: bool parseFile(const QString &filename, bool generate = true); bool parseFile(QIODevice* device, bool generate = true); - void setApiVersion(const QString& package, const QByteArray& version); + bool setApiVersion(const QString& package, const QString& version); - bool checkApiVersion(const QString& package, const QByteArray& version) const; + bool checkApiVersion(const QString& package, const QString &version) const; bool hasDroppedTypeEntries() const { return !m_dropTypeEntries.isEmpty(); } diff --git a/ApiExtractor/typesystem.cpp b/ApiExtractor/typesystem.cpp index b93b761b7..f63f59114 100644 --- a/ApiExtractor/typesystem.cpp +++ b/ApiExtractor/typesystem.cpp @@ -594,7 +594,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts if (!m_defaultPackage.isEmpty() && atts.hasAttribute(sinceAttribute())) { TypeDatabase* td = TypeDatabase::instance(); - if (!td->checkApiVersion(m_defaultPackage, atts.value(sinceAttribute()).toUtf8())) { + if (!td->checkApiVersion(m_defaultPackage, atts.value(sinceAttribute()).toString())) { ++m_ignoreDepth; return true; } diff --git a/generator/main.cpp b/generator/main.cpp index ac8f77f47..874540e54 100644 --- a/generator/main.cpp +++ b/generator/main.cpp @@ -341,6 +341,12 @@ static inline void errorPrint(const QString& s) << "\nCommand line: " << qPrintable(arguments.join(QLatin1Char(' '))) << '\n'; } +static QString msgInvalidVersion(const QString &package, const QString &version) +{ + return QLatin1String("Invalid version \"") + version + + QLatin1String("\" specified for package ") + package + QLatin1Char('.'); +} + int main(int argc, char *argv[]) { QElapsedTimer timer; @@ -439,7 +445,10 @@ int main(int argc, char *argv[]) // avoid constFirst to stay Qt 5.5 compatible package = parts.count() == 1 ? QLatin1String("*") : parts.first(); version = parts.last(); - extractor.setApiVersion(package, version.toUtf8()); + if (!extractor.setApiVersion(package, version)) { + errorPrint(msgInvalidVersion(package, version)); + return EXIT_FAILURE; + } } } |