mimetypes/qmimeglobpattern.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtCore module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qmimeglobpattern_p.h" -
43 -
44#include <QRegExp> -
45#include <QStringList> -
46#include <QDebug> -
47 -
48QT_BEGIN_NAMESPACE -
49 -
50/*! -
51 \internal -
52 \class QMimeGlobMatchResult -
53 \inmodule QtCore -
54 \brief The QMimeGlobMatchResult class accumulates results from glob matching. -
55 -
56 Handles glob weights, and preferring longer matches over shorter matches. -
57*/ -
58 -
59void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern) -
60{ -
61 // Is this a lower-weight pattern than the last match? Skip this match then. -
62 if (weight < m_weight)
partially evaluated: weight < m_weight
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:76
0-76
63 return;
never executed: return;
0
64 bool replace = weight > m_weight;
executed (the execution status of this line is deduced): bool replace = weight > m_weight;
-
65 if (!replace) {
evaluated: !replace
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:73
3-73
66 // Compare the length of the match -
67 if (pattern.length() < m_matchingPatternLength)
partially evaluated: pattern.length() < m_matchingPatternLength
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:3
0-3
68 return; // too short, ignore
never executed: return;
0
69 else if (pattern.length() > m_matchingPatternLength) {
partially evaluated: pattern.length() > m_matchingPatternLength
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:3
0-3
70 // longer: clear any previous match (like *.bz2, when pattern is *.tar.bz2) -
71 replace = true;
never executed (the execution status of this line is deduced): replace = true;
-
72 }
never executed: }
0
73 } -
74 if (replace) {
evaluated: replace
TRUEFALSE
yes
Evaluation Count:73
yes
Evaluation Count:3
3-73
75 m_matchingMimeTypes.clear();
executed (the execution status of this line is deduced): m_matchingMimeTypes.clear();
-
76 // remember the new "longer" length -
77 m_matchingPatternLength = pattern.length();
executed (the execution status of this line is deduced): m_matchingPatternLength = pattern.length();
-
78 m_weight = weight;
executed (the execution status of this line is deduced): m_weight = weight;
-
79 }
executed: }
Execution Count:73
73
80 m_matchingMimeTypes.append(mimeType);
executed (the execution status of this line is deduced): m_matchingMimeTypes.append(mimeType);
-
81 if (pattern.startsWith(QLatin1String("*.")))
evaluated: pattern.startsWith(QLatin1String("*."))
TRUEFALSE
yes
Evaluation Count:60
yes
Evaluation Count:16
16-60
82 m_foundSuffix = pattern.mid(2);
executed: m_foundSuffix = pattern.mid(2);
Execution Count:60
60
83}
executed: }
Execution Count:76
76
84 -
85/*! -
86 \internal -
87 \class QMimeGlobPattern -
88 \inmodule QtCore -
89 \brief The QMimeGlobPattern class contains the glob pattern for file names for MIME type matching. -
90 -
91 \sa QMimeType, QMimeDatabase, QMimeMagicRuleMatcher, QMimeMagicRule -
92*/ -
93 -
94bool QMimeGlobPattern::matchFileName(const QString &inputFilename) const -
95{ -
96 // "Applications MUST match globs case-insensitively, except when the case-sensitive -
97 // attribute is set to true." -
98 // The constructor takes care of putting case-insensitive patterns in lowercase. -
99 const QString filename = m_caseSensitivity == Qt::CaseInsensitive ? inputFilename.toLower() : inputFilename;
evaluated: m_caseSensitivity == Qt::CaseInsensitive
TRUEFALSE
yes
Evaluation Count:1488
yes
Evaluation Count:93
93-1488
100 -
101 const int pattern_len = m_pattern.length();
executed (the execution status of this line is deduced): const int pattern_len = m_pattern.length();
-
102 if (!pattern_len)
partially evaluated: !pattern_len
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1581
0-1581
103 return false;
never executed: return false;
0
104 const int len = filename.length();
executed (the execution status of this line is deduced): const int len = filename.length();
-
105 -
106 const int starCount = m_pattern.count(QLatin1Char('*'));
executed (the execution status of this line is deduced): const int starCount = m_pattern.count(QLatin1Char('*'));
-
107 -
108 // Patterns like "*~", "*.extension" -
109 if (m_pattern[0] == QLatin1Char('*') && m_pattern.indexOf(QLatin1Char('[')) == -1 && starCount == 1)
evaluated: m_pattern[0] == QLatin1Char('*')
TRUEFALSE
yes
Evaluation Count:93
yes
Evaluation Count:1488
partially evaluated: m_pattern.indexOf(QLatin1Char('[')) == -1
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:93
never evaluated: starCount == 1
0-1488
110 { -
111 if (len + 1 < pattern_len) return false;
never executed: return false;
never evaluated: len + 1 < pattern_len
0
112 -
113 const QChar *c1 = m_pattern.unicode() + pattern_len - 1;
never executed (the execution status of this line is deduced): const QChar *c1 = m_pattern.unicode() + pattern_len - 1;
-
114 const QChar *c2 = filename.unicode() + len - 1;
never executed (the execution status of this line is deduced): const QChar *c2 = filename.unicode() + len - 1;
-
115 int cnt = 1;
never executed (the execution status of this line is deduced): int cnt = 1;
-
116 while (cnt < pattern_len && *c1-- == *c2--)
never evaluated: cnt < pattern_len
never evaluated: *c1-- == *c2--
0
117 ++cnt;
never executed: ++cnt;
0
118 return cnt == pattern_len;
never executed: return cnt == pattern_len;
0
119 } -
120 -
121 // Patterns like "README*" (well this is currently the only one like that...) -
122 if (starCount == 1 && m_pattern.at(pattern_len - 1) == QLatin1Char('*')) {
evaluated: starCount == 1
TRUEFALSE
yes
Evaluation Count:279
yes
Evaluation Count:1302
evaluated: m_pattern.at(pattern_len - 1) == QLatin1Char('*')
TRUEFALSE
yes
Evaluation Count:186
yes
Evaluation Count:93
93-1302
123 if (len + 1 < pattern_len) return false;
executed: return false;
Execution Count:47
evaluated: len + 1 < pattern_len
TRUEFALSE
yes
Evaluation Count:47
yes
Evaluation Count:139
47-139
124 if (m_pattern.at(0) == QLatin1Char('*'))
partially evaluated: m_pattern.at(0) == QLatin1Char('*')
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:139
0-139
125 return filename.indexOf(m_pattern.mid(1, pattern_len - 2)) != -1;
never executed: return filename.indexOf(m_pattern.mid(1, pattern_len - 2)) != -1;
0
126 -
127 const QChar *c1 = m_pattern.unicode();
executed (the execution status of this line is deduced): const QChar *c1 = m_pattern.unicode();
-
128 const QChar *c2 = filename.unicode();
executed (the execution status of this line is deduced): const QChar *c2 = filename.unicode();
-
129 int cnt = 1;
executed (the execution status of this line is deduced): int cnt = 1;
-
130 while (cnt < pattern_len && *c1++ == *c2++)
evaluated: cnt < pattern_len
TRUEFALSE
yes
Evaluation Count:192
yes
Evaluation Count:10
evaluated: *c1++ == *c2++
TRUEFALSE
yes
Evaluation Count:63
yes
Evaluation Count:129
10-192
131 ++cnt;
executed: ++cnt;
Execution Count:63
63
132 return cnt == pattern_len;
executed: return cnt == pattern_len;
Execution Count:139
139
133 } -
134 -
135 // Names without any wildcards like "README" -
136 if (m_pattern.indexOf(QLatin1Char('[')) == -1 && starCount == 0 && m_pattern.indexOf(QLatin1Char('?')))
evaluated: m_pattern.indexOf(QLatin1Char('[')) == -1
TRUEFALSE
yes
Evaluation Count:1209
yes
Evaluation Count:186
partially evaluated: starCount == 0
TRUEFALSE
yes
Evaluation Count:1209
no
Evaluation Count:0
partially evaluated: m_pattern.indexOf(QLatin1Char('?'))
TRUEFALSE
yes
Evaluation Count:1209
no
Evaluation Count:0
0-1209
137 return (m_pattern == filename);
executed: return (m_pattern == filename);
Execution Count:1209
1209
138 -
139 // Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method -
140 QRegExp rx(m_pattern, Qt::CaseSensitive, QRegExp::WildcardUnix);
executed (the execution status of this line is deduced): QRegExp rx(m_pattern, Qt::CaseSensitive, QRegExp::WildcardUnix);
-
141 return rx.exactMatch(filename);
executed: return rx.exactMatch(filename);
Execution Count:186
186
142} -
143 -
144static bool isFastPattern(const QString &pattern) -
145{ -
146 // starts with "*.", has no other '*' and no other '.' -
147 return pattern.lastIndexOf(QLatin1Char('*')) == 0
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
148 && pattern.lastIndexOf(QLatin1Char('.')) == 1
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
149 // and contains no other special character
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
150 && !pattern.contains(QLatin1Char('?'))
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
151 && !pattern.contains(QLatin1Char('['))
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
152 ;
never executed: return pattern.lastIndexOf(QLatin1Char('*')) == 0 && pattern.lastIndexOf(QLatin1Char('.')) == 1 && !pattern.contains(QLatin1Char('?')) && !pattern.contains(QLatin1Char('[')) ;
0
153} -
154 -
155void QMimeAllGlobPatterns::addGlob(const QMimeGlobPattern &glob) -
156{ -
157 const QString &pattern = glob.pattern();
never executed (the execution status of this line is deduced): const QString &pattern = glob.pattern();
-
158 Q_ASSERT(!pattern.isEmpty());
never executed (the execution status of this line is deduced): qt_noop();
-
159 -
160 // Store each patterns into either m_fastPatternDict (*.txt, *.html etc. with default weight 50) -
161 // or for the rest, like core.*, *.tar.bz2, *~, into highWeightPatternOffset (>50) -
162 // or lowWeightPatternOffset (<=50) -
163 -
164 if (glob.weight() == 50 && isFastPattern(pattern) && !glob.isCaseSensitive()) {
never evaluated: glob.weight() == 50
never evaluated: isFastPattern(pattern)
never evaluated: !glob.isCaseSensitive()
0
165 // The bulk of the patterns is *.foo with weight 50 --> those go into the fast patterns hash. -
166 const QString extension = pattern.mid(2).toLower();
never executed (the execution status of this line is deduced): const QString extension = pattern.mid(2).toLower();
-
167 QStringList &patterns = m_fastPatterns[extension]; // find or create
never executed (the execution status of this line is deduced): QStringList &patterns = m_fastPatterns[extension];
-
168 if (!patterns.contains(glob.mimeType()))
never evaluated: !patterns.contains(glob.mimeType())
0
169 patterns.append(glob.mimeType());
never executed: patterns.append(glob.mimeType());
0
170 } else {
never executed: }
0
171 if (glob.weight() > 50) {
never evaluated: glob.weight() > 50
0
172 if (!m_highWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
never evaluated: !m_highWeightGlobs.hasPattern(glob.mimeType(), glob.pattern())
0
173 m_highWeightGlobs.append(glob);
never executed: m_highWeightGlobs.append(glob);
0
174 } else {
never executed: }
0
175 if (!m_lowWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
never evaluated: !m_lowWeightGlobs.hasPattern(glob.mimeType(), glob.pattern())
0
176 m_lowWeightGlobs.append(glob);
never executed: m_lowWeightGlobs.append(glob);
0
177 }
never executed: }
0
178 } -
179} -
180 -
181void QMimeAllGlobPatterns::removeMimeType(const QString &mimeType) -
182{ -
183 QMutableHashIterator<QString, QStringList> it(m_fastPatterns);
never executed (the execution status of this line is deduced): QMutableHashIterator<QString, QStringList> it(m_fastPatterns);
-
184 while (it.hasNext()) {
never evaluated: it.hasNext()
0
185 it.next().value().removeAll(mimeType);
never executed (the execution status of this line is deduced): it.next().value().removeAll(mimeType);
-
186 }
never executed: }
0
187 m_highWeightGlobs.removeMimeType(mimeType);
never executed (the execution status of this line is deduced): m_highWeightGlobs.removeMimeType(mimeType);
-
188 m_lowWeightGlobs.removeMimeType(mimeType);
never executed (the execution status of this line is deduced): m_lowWeightGlobs.removeMimeType(mimeType);
-
189}
never executed: }
0
190 -
191void QMimeGlobPatternList::match(QMimeGlobMatchResult &result, -
192 const QString &fileName) const -
193{ -
194 -
195 QMimeGlobPatternList::const_iterator it = this->constBegin();
never executed (the execution status of this line is deduced): QMimeGlobPatternList::const_iterator it = this->constBegin();
-
196 const QMimeGlobPatternList::const_iterator endIt = this->constEnd();
never executed (the execution status of this line is deduced): const QMimeGlobPatternList::const_iterator endIt = this->constEnd();
-
197 for (; it != endIt; ++it) {
never evaluated: it != endIt
0
198 const QMimeGlobPattern &glob = *it;
never executed (the execution status of this line is deduced): const QMimeGlobPattern &glob = *it;
-
199 if (glob.matchFileName(fileName))
never evaluated: glob.matchFileName(fileName)
0
200 result.addMatch(glob.mimeType(), glob.weight(), glob.pattern());
never executed: result.addMatch(glob.mimeType(), glob.weight(), glob.pattern());
0
201 }
never executed: }
0
202}
never executed: }
0
203 -
204QStringList QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QString *foundSuffix) const -
205{ -
206 // First try the high weight matches (>50), if any. -
207 QMimeGlobMatchResult result;
never executed (the execution status of this line is deduced): QMimeGlobMatchResult result;
-
208 m_highWeightGlobs.match(result, fileName);
never executed (the execution status of this line is deduced): m_highWeightGlobs.match(result, fileName);
-
209 if (result.m_matchingMimeTypes.isEmpty()) {
never evaluated: result.m_matchingMimeTypes.isEmpty()
0
210 -
211 // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50 -
212 // (which is most of them, so this optimization is definitely worth it) -
213 const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
never executed (the execution status of this line is deduced): const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
-
214 if (lastDot != -1) { // if no '.', skip the extension lookup
never evaluated: lastDot != -1
0
215 const int ext_len = fileName.length() - lastDot - 1;
never executed (the execution status of this line is deduced): const int ext_len = fileName.length() - lastDot - 1;
-
216 const QString simpleExtension = fileName.right(ext_len).toLower();
never executed (the execution status of this line is deduced): const QString simpleExtension = fileName.right(ext_len).toLower();
-
217 // (toLower because fast patterns are always case-insensitive and saved as lowercase) -
218 -
219 const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
never executed (the execution status of this line is deduced): const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
-
220 foreach (const QString &mime, matchingMimeTypes) {
never executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(matchingMimeTypes)> _container_(matchingMimeTypes); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (const QString &mime = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
221 result.addMatch(mime, 50, QLatin1String("*.") + simpleExtension);
never executed (the execution status of this line is deduced): result.addMatch(mime, 50, QLatin1String("*.") + simpleExtension);
-
222 }
never executed: }
0
223 // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway, -
224 // at least those with weight 50. -
225 }
never executed: }
0
226 -
227 // Finally, try the low weight matches (<=50) -
228 m_lowWeightGlobs.match(result, fileName);
never executed (the execution status of this line is deduced): m_lowWeightGlobs.match(result, fileName);
-
229 }
never executed: }
0
230 if (foundSuffix)
never evaluated: foundSuffix
0
231 *foundSuffix = result.m_foundSuffix;
never executed: *foundSuffix = result.m_foundSuffix;
0
232 return result.m_matchingMimeTypes;
never executed: return result.m_matchingMimeTypes;
0
233} -
234 -
235void QMimeAllGlobPatterns::clear() -
236{ -
237 m_fastPatterns.clear();
never executed (the execution status of this line is deduced): m_fastPatterns.clear();
-
238 m_highWeightGlobs.clear();
never executed (the execution status of this line is deduced): m_highWeightGlobs.clear();
-
239 m_lowWeightGlobs.clear();
never executed (the execution status of this line is deduced): m_lowWeightGlobs.clear();
-
240}
never executed: }
0
241 -
242QT_END_NAMESPACE -
243 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial