1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
12 #include <string_view>
14 #include <editeng/Trie.hxx>
23 static const int LATIN_ARRAY_SIZE
= 26;
25 sal_Unicode mCharacter
;
27 std::vector
<std::unique_ptr
<TrieNode
>> mChildren
;
28 std::unique_ptr
<TrieNode
> mLatinArray
[LATIN_ARRAY_SIZE
];
30 explicit TrieNode(sal_Unicode aCharacter
= '\0');
33 TrieNode
* findChild(sal_Unicode aCharacter
);
34 TrieNode
* traversePath(std::u16string_view sPath
);
35 void addNewChild(TrieNode
* pChild
);
36 void collectSuggestions(std::u16string_view sPath
, std::vector
<OUString
>& rSuggestionList
);
37 static void collectSuggestionsForCurrentNode(TrieNode
* pCurrent
, std::u16string_view sPath
, std::vector
<OUString
>& rSuggestionList
);
40 TrieNode::TrieNode(sal_Unicode aCharacter
) :
41 mCharacter(aCharacter
),
44 for (auto & i
: mLatinArray
)
50 void TrieNode::markWord()
55 void TrieNode::addNewChild(TrieNode
* pChild
)
57 if (pChild
->mCharacter
>= 'a' &&
58 pChild
->mCharacter
<= 'z')
60 mLatinArray
[pChild
->mCharacter
- u
'a'].reset(pChild
);
64 mChildren
.push_back(std::unique_ptr
<TrieNode
>(pChild
));
68 TrieNode
* TrieNode::findChild(sal_Unicode aInputCharacter
)
70 if (aInputCharacter
>= 'a' &&
71 aInputCharacter
<= 'z')
73 return mLatinArray
[aInputCharacter
- u
'a'].get();
76 for(auto const & pCurrent
: mChildren
)
78 if ( pCurrent
->mCharacter
== aInputCharacter
)
79 return pCurrent
.get();
85 void TrieNode::collectSuggestions(std::u16string_view sPath
, std::vector
<OUString
>& rSuggestionList
)
87 // first traverse nodes for alphabet characters
88 for (auto const & pCurrent
: mLatinArray
)
90 if (pCurrent
!= nullptr)
91 collectSuggestionsForCurrentNode(pCurrent
.get(), sPath
, rSuggestionList
);
94 // traverse nodes for other characters
95 for(auto const & pCurrent
: mChildren
)
97 if (pCurrent
!= nullptr)
98 collectSuggestionsForCurrentNode(pCurrent
.get(), sPath
, rSuggestionList
);
102 void TrieNode::collectSuggestionsForCurrentNode(TrieNode
* pCurrent
, std::u16string_view sPath
, std::vector
<OUString
>& rSuggestionList
)
104 OUString aStringPath
= sPath
+ OUStringChar(pCurrent
->mCharacter
);
105 if(pCurrent
->mMarker
)
107 rSuggestionList
.push_back(aStringPath
);
109 // recursively descend tree
110 pCurrent
->collectSuggestions(aStringPath
, rSuggestionList
);
113 TrieNode
* TrieNode::traversePath(std::u16string_view sPath
)
115 TrieNode
* pCurrent
= this;
117 for ( const auto aCurrentChar
: sPath
)
119 pCurrent
= pCurrent
->findChild(aCurrentChar
);
120 if ( pCurrent
== nullptr )
130 mRoot(new TrieNode())
136 void Trie::insert(std::u16string_view sInputString
) const
138 // adding an empty word is not allowed
139 if ( sInputString
.empty() )
144 // traverse the input string and modify the tree with new nodes / characters
146 TrieNode
* pCurrent
= mRoot
.get();
148 for ( const auto aCurrentChar
: sInputString
)
150 TrieNode
* pChild
= pCurrent
->findChild(aCurrentChar
);
151 if ( pChild
== nullptr )
153 TrieNode
* pNewNode
= new TrieNode(aCurrentChar
);
154 pCurrent
->addNewChild(pNewNode
);
163 pCurrent
->markWord();
166 void Trie::findSuggestions(std::u16string_view sWordPart
, std::vector
<OUString
>& rSuggestionList
) const
168 TrieNode
* pNode
= mRoot
->traversePath(sWordPart
);
170 if (pNode
!= nullptr)
172 pNode
->collectSuggestions(sWordPart
, rSuggestionList
);
176 size_t Trie::size() const
180 std::vector
<OUString
> entries
;
181 mRoot
->collectSuggestions(std::u16string_view(), entries
);
182 return entries
.size();
186 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */