1 /* Copyright 2016-2021 Dimitrij Mijoski
2 *
3 * This file is part of Nuspell.
4 *
5 * Nuspell is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Nuspell is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with Nuspell. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "dictionary.hxx"
20 #include "utils.hxx"
21
22 #include <fstream>
23 #include <iostream>
24 #include <stdexcept>
25
26 using namespace std;
27
28 namespace nuspell {
29 inline namespace v5 {
30
Dictionary(std::istream & aff,std::istream & dic)31 Dictionary::Dictionary(std::istream& aff, std::istream& dic)
32 {
33 if (!parse_aff_dic(aff, dic))
34 throw Dictionary_Loading_Error("error parsing");
35 }
36
37 Dictionary::Dictionary() = default;
38
39 /**
40 * @brief Create a dictionary from opened files as iostreams
41 *
42 * Prefer using load_from_path(). Use this if you have a specific use case,
43 * like when .aff and .dic are in-memory buffers istringstream.
44 *
45 * @param aff The iostream of the .aff file
46 * @param dic The iostream of the .dic file
47 * @return Dictionary object
48 * @throws Dictionary_Loading_Error on error
49 */
load_from_aff_dic(std::istream & aff,std::istream & dic)50 auto Dictionary::load_from_aff_dic(std::istream& aff, std::istream& dic)
51 -> Dictionary
52 {
53 return Dictionary(aff, dic);
54 }
55
56 /**
57 * @brief Create a dictionary from files
58 * @param file_path_without_extension path *without* extensions (without .dic or
59 * .aff)
60 * @return Dictionary object
61 * @throws Dictionary_Loading_Error on error
62 */
load_from_path(const std::string & file_path_without_extension)63 auto Dictionary::load_from_path(const std::string& file_path_without_extension)
64 -> Dictionary
65 {
66 auto path = file_path_without_extension;
67 path += ".aff";
68 std::ifstream aff_file(path);
69 if (aff_file.fail()) {
70 auto err = "Aff file " + path + " not found";
71 throw Dictionary_Loading_Error(err);
72 }
73 path.replace(path.size() - 3, 3, "dic");
74 std::ifstream dic_file(path);
75 if (dic_file.fail()) {
76 auto err = "Dic file " + path + " not found";
77 throw Dictionary_Loading_Error(err);
78 }
79 return load_from_aff_dic(aff_file, dic_file);
80 }
81
82 /**
83 * @brief Checks if a given word is correct
84 * @param word any word
85 * @return true if correct, false otherwise
86 */
spell(std::string_view word) const87 auto Dictionary::spell(std::string_view word) const -> bool
88 {
89 auto ok_enc = validate_utf8(word);
90 if (unlikely(word.size() > 360))
91 return false;
92 if (unlikely(!ok_enc))
93 return false;
94 auto word_buf = string(word);
95 return spell_priv(word_buf);
96 }
97
98 /**
99 * @brief Suggests correct words for a given incorrect word
100 * @param[in] word incorrect word
101 * @param[out] out this object will be populated with the suggestions
102 */
suggest(std::string_view word,std::vector<std::string> & out) const103 auto Dictionary::suggest(std::string_view word,
104 std::vector<std::string>& out) const -> void
105 {
106 out.clear();
107 auto ok_enc = validate_utf8(word);
108 if (unlikely(word.size() > 360))
109 return;
110 if (unlikely(!ok_enc))
111 return;
112 suggest_priv(word, out);
113 }
114 } // namespace v5
115 } // namespace nuspell
116