From 92ecf2dfbc25b2027cdee1a5c6dee4bd3d90f3c6 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Fri, 7 May 2010 15:08:16 +0200
Subject: [PATCH] MimeDatabase: Split up findByFile in 2 passes.

Try to do a match by suffix first to avoid
scanning the file contents if at all possible.
Reviewed-by: con
(cherry picked from commit 4648a5b3a41ae177fbcc3c2fea2c617dd3357d80)
---
 src/plugins/coreplugin/mimedatabase.cpp | 48 ++++++++++++++-----------
 src/plugins/coreplugin/mimedatabase.h   |  3 +-
 2 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/src/plugins/coreplugin/mimedatabase.cpp b/src/plugins/coreplugin/mimedatabase.cpp
index 3d4fa4dabfb..ea92354a357 100644
--- a/src/plugins/coreplugin/mimedatabase.cpp
+++ b/src/plugins/coreplugin/mimedatabase.cpp
@@ -491,17 +491,23 @@ bool MimeType::matchesType(const QString &type) const
 unsigned MimeType::matchesFile(const QFileInfo &file) const
 {
     Internal::FileMatchContext context(file);
-    return matchesFile(context);
+    if (const unsigned suffixPriority = matchesFileBySuffix(context))
+        return suffixPriority;
+    return matchesFileByContent(context);
 }
 
-unsigned MimeType::matchesFile(Internal::FileMatchContext &c) const
+unsigned MimeType::matchesFileBySuffix(Internal::FileMatchContext &c) const
 {
     // check globs
     foreach (const QRegExp &pattern, m_d->globPatterns) {
         if (pattern.exactMatch(c.fileName()))
             return GlobMatchPriority;
     }
+    return 0;
+}
 
+unsigned MimeType::matchesFileByContent(Internal::FileMatchContext &c) const
+{
     // Nope, try magic matchers on context data
     if (m_d->magicMatchers.isEmpty())
         return 0;
@@ -1031,7 +1037,7 @@ MimeType MimeDatabasePrivate::findByFile(const QFileInfo &f) const
 {
     unsigned priority = 0;
     if (debugMimeDB)
-        qDebug() << '>' << Q_FUNC_INFO << f.fileName();
+        qDebug() << '>' << Q_FUNC_INFO << f.absoluteFilePath();
     const MimeType rc = findByFile(f, &priority);
     if (debugMimeDB) {
         if (rc) {
@@ -1046,8 +1052,6 @@ MimeType MimeDatabasePrivate::findByFile(const QFileInfo &f) const
 // Returns a mime type or Null one if none found
 MimeType MimeDatabasePrivate::findByFile(const QFileInfo &f, unsigned *priorityPtr) const
 {
-    typedef QList<MimeMapEntry> MimeMapEntryList;
-
     // Is the hierarchy set up in case we find several matches?
     if (m_maxLevel < 0) {
         MimeDatabasePrivate *db = const_cast<MimeDatabasePrivate *>(this);
@@ -1056,27 +1060,31 @@ MimeType MimeDatabasePrivate::findByFile(const QFileInfo &f, unsigned *priorityP
     // Starting from max level (most specific): Try to find a match of
     // best (max) priority. Return if a glob match triggers.
     *priorityPtr = 0;
-    unsigned maxPriority = 0;
-    MimeType rc;
     Internal::FileMatchContext context(f);
+    // Pass 1) Try to match on suffix
     const TypeMimeTypeMap::const_iterator cend = m_typeMimeTypeMap.constEnd();
+    for (int level = m_maxLevel; level >= 0; level--)
+        for (TypeMimeTypeMap::const_iterator it = m_typeMimeTypeMap.constBegin(); it != cend; ++it)
+            if (it.value().level == level)
+                if (const unsigned suffixPriority = it.value().type.matchesFileBySuffix(context)) {
+                    *priorityPtr = suffixPriority;
+                    return it.value().type;
+                }
+    // Pass 2) Match on content
+    MimeType rc;
+    if (!f.isReadable())
+        return rc;
+    unsigned maxPriority = 0;
     for (int level = m_maxLevel; level >= 0; level--)
         for (TypeMimeTypeMap::const_iterator it = m_typeMimeTypeMap.constBegin(); it != cend; ++it)
             if (it.value().level == level) {
-                const unsigned priority = it.value().type.matchesFile(context);
-                if (debugMimeDB > 1)
-                    qDebug() <<  "pass" << level << it.value().type.type() << " matches " << priority;
-                if (priority)
-                    if (priority > maxPriority) {
-                        rc = it.value().type;
-                        maxPriority = priority;
-                        // Glob (exact) match?! We are done
-                        if (maxPriority == MimeType::GlobMatchPriority) {
-                            *priorityPtr = priority;
-                            return rc;
-                        }
-                    }
+                const unsigned priority = it.value().type.matchesFileByContent(context);
+                if (priority && priority > maxPriority) {
+                    rc = it.value().type;
+                    maxPriority = priority;
+                }
             }
+    *priorityPtr = maxPriority;
     return rc;
 }
 
diff --git a/src/plugins/coreplugin/mimedatabase.h b/src/plugins/coreplugin/mimedatabase.h
index 74ab4749d68..077ad5431f2 100644
--- a/src/plugins/coreplugin/mimedatabase.h
+++ b/src/plugins/coreplugin/mimedatabase.h
@@ -177,7 +177,8 @@ public:
 
 private:
     explicit MimeType(const MimeTypeData &d);
-    unsigned matchesFile(Internal::FileMatchContext &c) const;
+    unsigned matchesFileBySuffix(Internal::FileMatchContext &c) const;
+    unsigned matchesFileByContent(Internal::FileMatchContext &c) const;
 
     friend class Internal::BaseMimeTypeParser;
     friend class MimeDatabasePrivate;
-- 
GitLab