File indexing completed on 2024-04-28 15:30:45
0001 /* 0002 SPDX-FileCopyrightText: 2009 Michel Ludwig <michel.ludwig@kdemail.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "prefixstore.h" 0008 0009 #include "katepartdebug.h" 0010 0011 void KatePrefixStore::addPrefix(const QString &prefix) 0012 { 0013 if (prefix.isEmpty()) { 0014 return; 0015 } 0016 if (m_prefixSet.contains(prefix)) { 0017 return; 0018 } 0019 unsigned long long state = 0; 0020 for (int i = 0; i < prefix.length(); ++i) { 0021 QChar c = prefix.at(i); 0022 0023 CharToOccurrenceStateHash &hash = m_transitionFunction[state]; 0024 CharToOccurrenceStateHash::iterator it = hash.find(c.unicode()); 0025 if (it == hash.end()) { 0026 state = nextFreeState(); 0027 hash[c.unicode()] = QPair<unsigned int, unsigned long long>(1, state); 0028 continue; 0029 } 0030 0031 ++(*it).first; 0032 state = (*it).second; 0033 } 0034 // add the last state as accepting state 0035 m_acceptingStates.insert(state); 0036 0037 m_prefixSet.insert(prefix); 0038 0039 if (prefix.length() > m_longestPrefixLength) { 0040 m_longestPrefixLength = prefix.length(); 0041 } 0042 } 0043 0044 void KatePrefixStore::removePrefix(const QString &prefix) 0045 { 0046 if (prefix.isEmpty()) { 0047 return; 0048 } 0049 if (!m_prefixSet.contains(prefix)) { 0050 return; 0051 } 0052 m_prefixSet.remove(prefix); 0053 0054 unsigned long long state = 0; 0055 for (int i = 0; i < prefix.length(); ++i) { 0056 QChar c = prefix.at(i); 0057 0058 CharToOccurrenceStateHash &hash = m_transitionFunction[state]; 0059 CharToOccurrenceStateHash::iterator it = hash.find(c.unicode()); 0060 if (it == hash.end()) { 0061 continue; 0062 } 0063 0064 state = (*it).second; 0065 if (m_acceptingStates.contains(state) && i == prefix.length() - 1) { 0066 m_acceptingStates.remove(state); 0067 } 0068 0069 if ((*it).first <= 1) { 0070 hash.erase(it); 0071 m_stateFreeList.push_back(state); 0072 } else { 0073 --(*it).first; 0074 } 0075 } 0076 0077 if (prefix.length() == m_longestPrefixLength) { 0078 m_longestPrefixLength = computeLongestPrefixLength(); 0079 } 0080 } 0081 0082 void KatePrefixStore::dump() 0083 { 0084 for (unsigned long long i = 0; i < m_lastAssignedState; ++i) { 0085 CharToOccurrenceStateHash &hash = m_transitionFunction[i]; 0086 for (CharToOccurrenceStateHash::iterator it = hash.begin(); it != hash.end(); ++it) { 0087 qCDebug(LOG_KTE) << i << "x" << QChar(it.key()) << "->" << it.value().first << "x" << it.value().second; 0088 } 0089 } 0090 qCDebug(LOG_KTE) << "Accepting states" << m_acceptingStates; 0091 } 0092 0093 QString KatePrefixStore::findPrefix(const QString &s, int start) const 0094 { 0095 unsigned long long state = 0; 0096 for (int i = start; i < s.length(); ++i) { 0097 QChar c = s.at(i); 0098 const CharToOccurrenceStateHash &hash = m_transitionFunction[state]; 0099 CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode()); 0100 if (it == hash.end()) { 0101 return QString(); 0102 } 0103 0104 state = (*it).second; 0105 if (m_acceptingStates.contains(state)) { 0106 return s.mid(start, i + 1 - start); 0107 } 0108 } 0109 return QString(); 0110 } 0111 0112 QString KatePrefixStore::findPrefix(const Kate::TextLine &line, int start) const 0113 { 0114 unsigned long long state = 0; 0115 for (int i = start; i < line->length(); ++i) { 0116 QChar c = line->at(i); 0117 const CharToOccurrenceStateHash &hash = m_transitionFunction[state]; 0118 CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode()); 0119 if (it == hash.end()) { 0120 return QString(); 0121 } 0122 0123 state = (*it).second; 0124 if (m_acceptingStates.contains(state)) { 0125 return line->string(start, i + 1 - start); 0126 } 0127 } 0128 return QString(); 0129 } 0130 0131 int KatePrefixStore::longestPrefixLength() const 0132 { 0133 return m_longestPrefixLength; 0134 } 0135 0136 void KatePrefixStore::clear() 0137 { 0138 m_longestPrefixLength = 0; 0139 m_prefixSet.clear(); 0140 m_transitionFunction.clear(); 0141 m_acceptingStates.clear(); 0142 m_stateFreeList.clear(); 0143 m_lastAssignedState = 0; 0144 } 0145 0146 int KatePrefixStore::computeLongestPrefixLength() 0147 { 0148 int toReturn = 0; 0149 for (QSet<QString>::const_iterator i = m_prefixSet.cbegin(); i != m_prefixSet.cend(); ++i) { 0150 qCDebug(LOG_KTE) << "length" << (*i).length(); 0151 toReturn = qMax(toReturn, (*i).length()); 0152 } 0153 return toReturn; 0154 } 0155 0156 unsigned long long KatePrefixStore::nextFreeState() 0157 { 0158 if (!m_stateFreeList.isEmpty()) { 0159 return m_stateFreeList.takeFirst(); 0160 } 0161 return ++m_lastAssignedState; 0162 }