aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-03-23 16:38:39 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-03-24 14:30:16 +0000
commit9bd988eb1b4327225809d4e449af7f8b3105dd87 (patch)
tree4ce28e2882830176c8aef722548f213ce7beb72f
parent8d99ee1f6af693ad45dcd03fcae6a86f8f86302a (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.cpp9
-rw-r--r--ApiExtractor/apiextractor.h3
-rw-r--r--ApiExtractor/tests/testutil.h4
-rw-r--r--ApiExtractor/typedatabase.cpp80
-rw-r--r--ApiExtractor/typedatabase.h4
-rw-r--r--ApiExtractor/typesystem.cpp2
-rw-r--r--generator/main.cpp11
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;
+ }
}
}