Kate
prefixstore.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries and the Kate part. 00002 * 00003 * Copyright (C) 2009 by Michel Ludwig <michel.ludwig@kdemail.net> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "prefixstore.h" 00022 00023 #include <kdebug.h> 00024 00025 #include "katetextline.h" 00026 00027 KatePrefixStore::KatePrefixStore() 00028 : m_longestPrefixLength(0), 00029 m_lastAssignedState(0) 00030 { 00031 } 00032 00033 KatePrefixStore::~KatePrefixStore() 00034 { 00035 } 00036 00037 void KatePrefixStore::addPrefix(const QString& prefix) 00038 { 00039 if(prefix.isEmpty()) { 00040 return; 00041 } 00042 if(m_prefixSet.contains(prefix)) { 00043 return; 00044 } 00045 unsigned long long state = 0; 00046 for(int i = 0; i < prefix.length(); ++i) { 00047 QChar c = prefix.at(i); 00048 00049 CharToOccurrenceStateHash& hash = m_transitionFunction[state]; 00050 CharToOccurrenceStateHash::iterator it = hash.find(c.unicode()); 00051 if(it == hash.end()) { 00052 state = nextFreeState(); 00053 hash[c.unicode()] = QPair<unsigned int, unsigned long long>(1, state); 00054 continue; 00055 } 00056 00057 ++(*it).first; 00058 state = (*it).second; 00059 } 00060 // add the last state as accepting state 00061 m_acceptingStates.insert(state); 00062 00063 m_prefixSet.insert(prefix); 00064 00065 if(prefix.length() > m_longestPrefixLength) { 00066 m_longestPrefixLength = prefix.length(); 00067 } 00068 } 00069 00070 void KatePrefixStore::removePrefix(const QString& prefix) 00071 { 00072 if(prefix.isEmpty()) { 00073 return; 00074 } 00075 if(!m_prefixSet.contains(prefix)) { 00076 return; 00077 } 00078 m_prefixSet.remove(prefix); 00079 00080 unsigned long long state = 0; 00081 for(int i = 0; i < prefix.length(); ++i) { 00082 QChar c = prefix.at(i); 00083 00084 CharToOccurrenceStateHash& hash = m_transitionFunction[state]; 00085 CharToOccurrenceStateHash::iterator it = hash.find(c.unicode()); 00086 if(it == hash.end()) { 00087 continue; 00088 } 00089 00090 state = (*it).second; 00091 if(m_acceptingStates.contains(state) && i == prefix.length() - 1) { 00092 m_acceptingStates.remove(state); 00093 } 00094 00095 if((*it).first <= 1) { 00096 hash.erase(it); 00097 m_stateFreeList.push_back(state); 00098 } 00099 else { 00100 --(*it).first; 00101 } 00102 } 00103 00104 if(prefix.length() == m_longestPrefixLength) { 00105 m_longestPrefixLength = computeLongestPrefixLength(); 00106 } 00107 } 00108 00109 void KatePrefixStore::dump() 00110 { 00111 for(unsigned long long i = 0; i < m_lastAssignedState; ++i) { 00112 CharToOccurrenceStateHash& hash = m_transitionFunction[i]; 00113 for(CharToOccurrenceStateHash::iterator it = hash.begin(); it != hash.end(); ++it) { 00114 kDebug() << i << "x" << QChar(it.key()) << "->" << it.value().first << "x" << it.value().second; 00115 } 00116 } 00117 kDebug() << "Accepting states" << m_acceptingStates; 00118 } 00119 00120 QString KatePrefixStore::findPrefix(const QString& s, int start) const 00121 { 00122 unsigned long long state = 0; 00123 for(int i = start; i < s.length(); ++i) { 00124 QChar c = s.at(i); 00125 const CharToOccurrenceStateHash& hash = m_transitionFunction[state]; 00126 CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode()); 00127 if(it == hash.end()) { 00128 return QString(); 00129 } 00130 00131 state = (*it).second; 00132 if(m_acceptingStates.contains(state)) { 00133 return s.mid(start, i + 1 - start); 00134 } 00135 } 00136 return QString(); 00137 } 00138 00139 QString KatePrefixStore::findPrefix(const Kate::TextLine& line, int start) const 00140 { 00141 unsigned long long state = 0; 00142 for(int i = start; i < line->length(); ++i) { 00143 QChar c = line->at(i); 00144 const CharToOccurrenceStateHash& hash = m_transitionFunction[state]; 00145 CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode()); 00146 if(it == hash.end()) { 00147 return QString(); 00148 } 00149 00150 state = (*it).second; 00151 if(m_acceptingStates.contains(state)) { 00152 return line->string(start, i + 1 - start); 00153 } 00154 } 00155 return QString(); 00156 } 00157 00158 int KatePrefixStore::longestPrefixLength() const 00159 { 00160 return m_longestPrefixLength; 00161 } 00162 00163 void KatePrefixStore::clear() 00164 { 00165 m_longestPrefixLength = 0; 00166 m_prefixSet.clear(); 00167 m_transitionFunction.clear(); 00168 m_acceptingStates.clear(); 00169 m_stateFreeList.clear(); 00170 m_lastAssignedState = 0; 00171 } 00172 00173 int KatePrefixStore::computeLongestPrefixLength() 00174 { 00175 int toReturn = 0; 00176 for(QSet<QString>::iterator i = m_prefixSet.begin(); 00177 i != m_prefixSet.end(); ++i) { 00178 kDebug() << "length" << (*i).length(); 00179 toReturn = qMax(toReturn, (*i).length()); 00180 } 00181 return toReturn; 00182 } 00183 00184 unsigned long long KatePrefixStore::nextFreeState() 00185 { 00186 if(!m_stateFreeList.isEmpty()) { 00187 return m_stateFreeList.takeFirst(); 00188 } 00189 return ++m_lastAssignedState; 00190 }
KDE 4.6 API Reference