forked from qt-creator/qt-creator
Sync mimeglobpattern sources with Qt
The optimization for VdrPattern and AnimPattern speeds up loading of Qt6 project with further ~200 ms. Change-Id: I28451a627d6c509854907736da48efcf68a86019 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -83,6 +83,39 @@ void MimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MimeGlobPattern::PatternType MimeGlobPattern::detectPatternType(const QString &pattern) const
|
||||||
|
{
|
||||||
|
const int patternLength = pattern.length();
|
||||||
|
if (!patternLength)
|
||||||
|
return OtherPattern;
|
||||||
|
|
||||||
|
const bool starCount = pattern.count(QLatin1Char('*')) == 1;
|
||||||
|
const bool hasSquareBracket = pattern.indexOf(QLatin1Char('[')) != -1;
|
||||||
|
const bool hasQuestionMark = pattern.indexOf(QLatin1Char('?')) != -1;
|
||||||
|
|
||||||
|
if (!hasSquareBracket && !hasQuestionMark) {
|
||||||
|
if (starCount == 1) {
|
||||||
|
// Patterns like "*~", "*.extension"
|
||||||
|
if (pattern.at(0) == QLatin1Char('*'))
|
||||||
|
return SuffixPattern;
|
||||||
|
// Patterns like "README*" (well this is currently the only one like that...)
|
||||||
|
if (pattern.at(patternLength - 1) == QLatin1Char('*'))
|
||||||
|
return PrefixPattern;
|
||||||
|
}
|
||||||
|
// Names without any wildcards like "README"
|
||||||
|
if (starCount == 0)
|
||||||
|
return LiteralPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pattern == QLatin1String("[0-9][0-9][0-9].vdr"))
|
||||||
|
return VdrPattern;
|
||||||
|
|
||||||
|
if (pattern == QLatin1String("*.anim[1-9j]"))
|
||||||
|
return AnimPattern;
|
||||||
|
|
||||||
|
return OtherPattern;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
\class MimeGlobPattern
|
\class MimeGlobPattern
|
||||||
@@ -92,54 +125,63 @@ void MimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QS
|
|||||||
\sa MimeType, MimeDatabase, MimeMagicRuleMatcher, MimeMagicRule
|
\sa MimeType, MimeDatabase, MimeMagicRuleMatcher, MimeMagicRule
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool MimeGlobPattern::matchFileName(const QString &inputFilename) const
|
bool MimeGlobPattern::matchFileName(const QString &inputFileName) const
|
||||||
{
|
{
|
||||||
// "Applications MUST match globs case-insensitively, except when the case-sensitive
|
// "Applications MUST match globs case-insensitively, except when the case-sensitive
|
||||||
// attribute is set to true."
|
// attribute is set to true."
|
||||||
// The constructor takes care of putting case-insensitive patterns in lowercase.
|
// The constructor takes care of putting case-insensitive patterns in lowercase.
|
||||||
const QString filename = m_caseSensitivity == Qt::CaseInsensitive ? inputFilename.toLower() : inputFilename;
|
const QString fileName = m_caseSensitivity == Qt::CaseInsensitive
|
||||||
|
? inputFileName.toLower() : inputFileName;
|
||||||
|
|
||||||
const int pattern_len = m_pattern.length();
|
const int patternLength = m_pattern.length();
|
||||||
if (!pattern_len)
|
if (!patternLength)
|
||||||
return false;
|
return false;
|
||||||
const int len = filename.length();
|
const int fileNameLength = fileName.length();
|
||||||
|
|
||||||
// Patterns like "*~", "*.extension"
|
switch (m_patternType) {
|
||||||
if (m_pattern[0] == QLatin1Char('*') && m_openingSquareBracketPos == -1 && m_starCount == 1) {
|
case SuffixPattern: {
|
||||||
if (len + 1 < pattern_len)
|
if (fileNameLength + 1 < patternLength)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QChar *c1 = m_pattern.unicode() + pattern_len - 1;
|
const QChar *c1 = m_pattern.unicode() + patternLength - 1;
|
||||||
const QChar *c2 = filename.unicode() + len - 1;
|
const QChar *c2 = fileName.unicode() + fileNameLength - 1;
|
||||||
int cnt = 1;
|
int cnt = 1;
|
||||||
while (cnt < pattern_len && *c1-- == *c2--)
|
while (cnt < patternLength && *c1-- == *c2--)
|
||||||
++cnt;
|
++cnt;
|
||||||
return cnt == pattern_len;
|
return cnt == patternLength;
|
||||||
}
|
}
|
||||||
|
case PrefixPattern: {
|
||||||
// Patterns like "README*" (well this is currently the only one like that...)
|
if (fileNameLength + 1 < patternLength)
|
||||||
if (m_starCount == 1 && m_pattern.at(pattern_len - 1) == QLatin1Char('*')) {
|
|
||||||
if (len + 1 < pattern_len)
|
|
||||||
return false;
|
return false;
|
||||||
if (m_pattern.at(0) == QLatin1Char('*'))
|
|
||||||
return filename.indexOf(QStringView(m_pattern).mid(1, pattern_len - 2)) != -1;
|
|
||||||
|
|
||||||
const QChar *c1 = m_pattern.unicode();
|
const QChar *c1 = m_pattern.unicode();
|
||||||
const QChar *c2 = filename.unicode();
|
const QChar *c2 = fileName.unicode();
|
||||||
int cnt = 1;
|
int cnt = 1;
|
||||||
while (cnt < pattern_len && *c1++ == *c2++)
|
while (cnt < patternLength && *c1++ == *c2++)
|
||||||
++cnt;
|
++cnt;
|
||||||
return cnt == pattern_len;
|
return cnt == patternLength;
|
||||||
}
|
}
|
||||||
|
case LiteralPattern:
|
||||||
// Names without any wildcards like "README"
|
return (m_pattern == fileName);
|
||||||
if (m_openingSquareBracketPos == -1 && m_starCount == 0 && m_questionMarkPos == -1)
|
case VdrPattern: // "[0-9][0-9][0-9].vdr" case
|
||||||
return (m_pattern == filename);
|
return fileNameLength == 7
|
||||||
|
&& fileName.at(0).isDigit() && fileName.at(1).isDigit() && fileName.at(2).isDigit()
|
||||||
// Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method
|
&& QStringView{fileName}.mid(3, 4) == QLatin1String(".vdr");
|
||||||
const QRegularExpression rx(QRegularExpression::anchoredPattern(
|
case AnimPattern: { // "*.anim[1-9j]" case
|
||||||
|
if (fileNameLength < 6)
|
||||||
|
return false;
|
||||||
|
const QChar lastChar = fileName.at(fileNameLength - 1);
|
||||||
|
const bool lastCharOK = (lastChar.isDigit() && lastChar != QLatin1Char('0'))
|
||||||
|
|| lastChar == QLatin1Char('j');
|
||||||
|
return lastCharOK && QStringView{fileName}.mid(fileNameLength - 6, 5) == QLatin1String(".anim");
|
||||||
|
}
|
||||||
|
case OtherPattern:
|
||||||
|
// Other fallback patterns: slow but correct method
|
||||||
|
const QRegularExpression rx(QRegularExpression::anchoredPattern(
|
||||||
QRegularExpression::wildcardToRegularExpression(m_pattern)));
|
QRegularExpression::wildcardToRegularExpression(m_pattern)));
|
||||||
return rx.match(filename).hasMatch();
|
return rx.match(fileName).hasMatch();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isFastPattern(const QString &pattern)
|
static bool isFastPattern(const QString &pattern)
|
||||||
|
@@ -79,15 +79,21 @@ public:
|
|||||||
m_pattern(s == Qt::CaseInsensitive ? thePattern.toLower() : thePattern),
|
m_pattern(s == Qt::CaseInsensitive ? thePattern.toLower() : thePattern),
|
||||||
m_mimeType(theMimeType),
|
m_mimeType(theMimeType),
|
||||||
m_weight(theWeight),
|
m_weight(theWeight),
|
||||||
m_starCount(m_pattern.count(QLatin1Char('*'))),
|
m_caseSensitivity(s),
|
||||||
m_openingSquareBracketPos(m_pattern.indexOf(QLatin1Char('['))),
|
m_patternType(detectPatternType(m_pattern))
|
||||||
m_questionMarkPos(m_pattern.indexOf(QLatin1Char('?'))),
|
|
||||||
m_caseSensitivity(s)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~MimeGlobPattern() {}
|
|
||||||
|
|
||||||
bool matchFileName(const QString &filename) const;
|
void swap(MimeGlobPattern &other) noexcept
|
||||||
|
{
|
||||||
|
qSwap(m_pattern, other.m_pattern);
|
||||||
|
qSwap(m_mimeType, other.m_mimeType);
|
||||||
|
qSwap(m_weight, other.m_weight);
|
||||||
|
qSwap(m_caseSensitivity, other.m_caseSensitivity);
|
||||||
|
qSwap(m_patternType, other.m_patternType);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matchFileName(const QString &inputFileName) const;
|
||||||
|
|
||||||
inline const QString &pattern() const { return m_pattern; }
|
inline const QString &pattern() const { return m_pattern; }
|
||||||
inline unsigned weight() const { return m_weight; }
|
inline unsigned weight() const { return m_weight; }
|
||||||
@@ -95,13 +101,21 @@ public:
|
|||||||
inline bool isCaseSensitive() const { return m_caseSensitivity == Qt::CaseSensitive; }
|
inline bool isCaseSensitive() const { return m_caseSensitivity == Qt::CaseSensitive; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum PatternType {
|
||||||
|
SuffixPattern,
|
||||||
|
PrefixPattern,
|
||||||
|
LiteralPattern,
|
||||||
|
VdrPattern, // special handling for "[0-9][0-9][0-9].vdr" pattern
|
||||||
|
AnimPattern, // special handling for "*.anim[1-9j]" pattern
|
||||||
|
OtherPattern
|
||||||
|
};
|
||||||
|
PatternType detectPatternType(const QString &pattern) const;
|
||||||
|
|
||||||
QString m_pattern;
|
QString m_pattern;
|
||||||
QString m_mimeType;
|
QString m_mimeType;
|
||||||
int m_weight;
|
int m_weight;
|
||||||
int m_starCount;
|
|
||||||
int m_openingSquareBracketPos;
|
|
||||||
int m_questionMarkPos;
|
|
||||||
Qt::CaseSensitivity m_caseSensitivity;
|
Qt::CaseSensitivity m_caseSensitivity;
|
||||||
|
PatternType m_patternType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MimeGlobPatternList : public QList<MimeGlobPattern>
|
class MimeGlobPatternList : public QList<MimeGlobPattern>
|
||||||
|
Reference in New Issue
Block a user