kde-workspace/kate/part/spellcheck/prefixstore.cpp
Ivailo Monev f68295ea28 generic: move sub-projects from kde-baseapps [ci reset]
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2022-05-14 21:56:54 +03:00

190 lines
4.9 KiB
C++

/* This file is part of the KDE libraries and the Kate part.
*
* Copyright (C) 2009 by Michel Ludwig <michel.ludwig@kdemail.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "prefixstore.h"
#include <kdebug.h>
#include "katetextline.h"
KatePrefixStore::KatePrefixStore()
: m_longestPrefixLength(0),
m_lastAssignedState(0)
{
}
KatePrefixStore::~KatePrefixStore()
{
}
void KatePrefixStore::addPrefix(const QString& prefix)
{
if(prefix.isEmpty()) {
return;
}
if(m_prefixSet.contains(prefix)) {
return;
}
unsigned long long state = 0;
for(int i = 0; i < prefix.length(); ++i) {
QChar c = prefix.at(i);
CharToOccurrenceStateHash& hash = m_transitionFunction[state];
CharToOccurrenceStateHash::iterator it = hash.find(c.unicode());
if(it == hash.end()) {
state = nextFreeState();
hash[c.unicode()] = QPair<unsigned int, unsigned long long>(1, state);
continue;
}
++(*it).first;
state = (*it).second;
}
// add the last state as accepting state
m_acceptingStates.insert(state);
m_prefixSet.insert(prefix);
if(prefix.length() > m_longestPrefixLength) {
m_longestPrefixLength = prefix.length();
}
}
void KatePrefixStore::removePrefix(const QString& prefix)
{
if(prefix.isEmpty()) {
return;
}
if(!m_prefixSet.contains(prefix)) {
return;
}
m_prefixSet.remove(prefix);
unsigned long long state = 0;
for(int i = 0; i < prefix.length(); ++i) {
QChar c = prefix.at(i);
CharToOccurrenceStateHash& hash = m_transitionFunction[state];
CharToOccurrenceStateHash::iterator it = hash.find(c.unicode());
if(it == hash.end()) {
continue;
}
state = (*it).second;
if(m_acceptingStates.contains(state) && i == prefix.length() - 1) {
m_acceptingStates.remove(state);
}
if((*it).first <= 1) {
hash.erase(it);
m_stateFreeList.push_back(state);
}
else {
--(*it).first;
}
}
if(prefix.length() == m_longestPrefixLength) {
m_longestPrefixLength = computeLongestPrefixLength();
}
}
void KatePrefixStore::dump()
{
for(unsigned long long i = 0; i < m_lastAssignedState; ++i) {
CharToOccurrenceStateHash& hash = m_transitionFunction[i];
for(CharToOccurrenceStateHash::iterator it = hash.begin(); it != hash.end(); ++it) {
kDebug() << i << "x" << QChar(it.key()) << "->" << it.value().first << "x" << it.value().second;
}
}
kDebug() << "Accepting states" << m_acceptingStates;
}
QString KatePrefixStore::findPrefix(const QString& s, int start) const
{
unsigned long long state = 0;
for(int i = start; i < s.length(); ++i) {
QChar c = s.at(i);
const CharToOccurrenceStateHash& hash = m_transitionFunction[state];
CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode());
if(it == hash.end()) {
return QString();
}
state = (*it).second;
if(m_acceptingStates.contains(state)) {
return s.mid(start, i + 1 - start);
}
}
return QString();
}
QString KatePrefixStore::findPrefix(const Kate::TextLine& line, int start) const
{
unsigned long long state = 0;
for(int i = start; i < line->length(); ++i) {
QChar c = line->at(i);
const CharToOccurrenceStateHash& hash = m_transitionFunction[state];
CharToOccurrenceStateHash::const_iterator it = hash.find(c.unicode());
if(it == hash.end()) {
return QString();
}
state = (*it).second;
if(m_acceptingStates.contains(state)) {
return line->string(start, i + 1 - start);
}
}
return QString();
}
int KatePrefixStore::longestPrefixLength() const
{
return m_longestPrefixLength;
}
void KatePrefixStore::clear()
{
m_longestPrefixLength = 0;
m_prefixSet.clear();
m_transitionFunction.clear();
m_acceptingStates.clear();
m_stateFreeList.clear();
m_lastAssignedState = 0;
}
int KatePrefixStore::computeLongestPrefixLength()
{
int toReturn = 0;
for(QSet<QString>::iterator i = m_prefixSet.begin();
i != m_prefixSet.end(); ++i) {
kDebug() << "length" << (*i).length();
toReturn = qMax(toReturn, (*i).length());
}
return toReturn;
}
unsigned long long KatePrefixStore::nextFreeState()
{
if(!m_stateFreeList.isEmpty()) {
return m_stateFreeList.takeFirst();
}
return ++m_lastAssignedState;
}