Warning, file /sdk/cervisia/stringmatcher.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Copyright (c) 2003-2008 André Wöbbeking <Woebbeking@kde.org>
0003  *
0004  * This program is free software; you can redistribute it and/or modify
0005  * it under the terms of the GNU General Public License as published by
0006  * the Free Software Foundation; either version 2 of the License, or
0007  * (at your option) any later version.
0008  *
0009  * This program is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  * GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License
0015  * along with this program; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0017  */
0018 
0019 #include "stringmatcher.h"
0020 
0021 // For some reason fnmatch is defined as ap_fnmatch
0022 #define ap_fnmatch fnmatch
0023 #include <fnmatch.h>
0024 
0025 #include <QByteArray>
0026 
0027 namespace Cervisia
0028 {
0029 namespace
0030 {
0031 const QChar asterix('*');
0032 const QChar question('?');
0033 
0034 inline bool isMetaCharacter(QChar c)
0035 {
0036     return c == asterix || c == question;
0037 }
0038 
0039 unsigned int countMetaCharacters(const QString &text);
0040 }
0041 
0042 bool StringMatcher::match(const QString &text) const
0043 {
0044     if (m_exactPatterns.contains(text)) {
0045         return true;
0046     }
0047 
0048     for (QStringList::const_iterator it(m_startPatterns.begin()), itEnd(m_startPatterns.end()); it != itEnd; ++it) {
0049         if (text.startsWith(*it)) {
0050             return true;
0051         }
0052     }
0053 
0054     for (QStringList::const_iterator it(m_endPatterns.begin()), itEnd(m_endPatterns.end()); it != itEnd; ++it) {
0055         if (text.endsWith(*it)) {
0056             return true;
0057         }
0058     }
0059 
0060     for (QList<QByteArray>::const_iterator it(m_generalPatterns.begin()), itEnd(m_generalPatterns.end()); it != itEnd; ++it) {
0061         if (::fnmatch(*it, text.toLocal8Bit(), FNM_PATHNAME) == 0) {
0062             return true;
0063         }
0064     }
0065 
0066     return false;
0067 }
0068 
0069 void StringMatcher::add(const QString &pattern)
0070 {
0071     if (pattern.isEmpty()) {
0072         return;
0073     }
0074 
0075     const int lengthMinusOne(pattern.length() - 1);
0076     switch (countMetaCharacters(pattern)) {
0077     case 0:
0078         m_exactPatterns.push_back(pattern);
0079         break;
0080 
0081     case 1:
0082         if (pattern.at(0) == asterix) {
0083             m_endPatterns.push_back(pattern.right(lengthMinusOne));
0084         } else if (pattern.at(lengthMinusOne) == asterix) {
0085             m_startPatterns.push_back(pattern.left(lengthMinusOne));
0086         } else {
0087             m_generalPatterns.push_back(pattern.toLocal8Bit());
0088         }
0089         break;
0090 
0091     default:
0092         m_generalPatterns.push_back(pattern.toLocal8Bit());
0093         break;
0094     }
0095 }
0096 
0097 void StringMatcher::clear()
0098 {
0099     m_exactPatterns.clear();
0100     m_startPatterns.clear();
0101     m_endPatterns.clear();
0102     m_generalPatterns.clear();
0103 }
0104 
0105 namespace
0106 {
0107 unsigned int countMetaCharacters(const QString &text)
0108 {
0109     unsigned int count(0);
0110 
0111     const QChar *pos(text.unicode());
0112     const QChar *posEnd(pos + text.length());
0113     while (pos < posEnd) {
0114         count += isMetaCharacter(*pos++);
0115     }
0116 
0117     return count;
0118 }
0119 }
0120 } // namespace Cervisia