OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <algorithm> | |
6 #include <deque> | |
7 #include <fstream> | |
8 #include <string> | |
9 | |
10 #include "base/base_paths.h" | |
11 #include "base/files/file_path.h" | |
12 #include "base/path_service.h" | |
13 #include "base/strings/string16.h" | |
14 #include "base/strings/utf_string_conversions.h" | |
15 #include "mojo/services/prediction/public/interfaces/prediction.mojom.h" | |
16 #include "mojo/tools/embed/data.h" | |
17 #include "services/prediction/dictionary_service.h" | |
18 #include "services/prediction/input_info.h" | |
19 #include "services/prediction/kDictFile.h" | |
20 #include "services/prediction/key_set.h" | |
21 #include "services/prediction/proximity_info_factory.h" | |
22 #include "third_party/prediction/suggest/core/dictionary/dictionary.h" | |
23 #include "third_party/prediction/suggest/core/result/suggestion_results.h" | |
24 #include "third_party/prediction/suggest/core/session/dic_traverse_session.h" | |
25 #include "third_party/prediction/suggest/core/session/prev_words_info.h" | |
26 #include "third_party/prediction/suggest/core/suggest_options.h" | |
27 #include "third_party/prediction/suggest/policyimpl/dictionary/structure/diction ary_structure_with_buffer_policy_factory.h" | |
28 | |
29 namespace prediction { | |
30 | |
31 DictionaryService::DictionaryService() { | |
32 max_suggestion_size_ = 50; | |
33 default_dictionary_ = nullptr; | |
APW
2015/07/31 21:49:16
you don't need to assign these to nullptr if they
riajiang
2015/08/01 01:23:09
Done.
| |
34 default_session_ = nullptr; | |
35 } | |
36 | |
37 DictionaryService::~DictionaryService() { | |
38 } | |
39 | |
40 void DictionaryService::CopyDictionaryFromRes(const std::string path) { | |
APW
2015/07/31 21:49:16
Still don't like the name of this function. You'r
riajiang
2015/08/01 01:23:09
CreatDictFromEmbeddedDataIfNotExist?
| |
41 if (std::ifstream(path.c_str())) | |
42 return; | |
43 std::ofstream dic_file(path.c_str(), | |
44 std::ofstream::out | std::ofstream::binary); | |
45 dic_file.write(prediction::kDictFile.data, prediction::kDictFile.size); | |
46 dic_file.close(); | |
47 } | |
48 | |
49 latinime::Dictionary* const DictionaryService::OpenDictionary( | |
50 const std::string path, | |
51 const int start_offset, | |
52 const int size, | |
53 const bool is_updatable) { | |
54 latinime::DictionaryStructureWithBufferPolicy::StructurePolicyPtr | |
55 dictionary_structure_with_buffer_policy( | |
56 latinime::DictionaryStructureWithBufferPolicyFactory:: | |
57 newPolicyForExistingDictFile(path.c_str(), start_offset, size, | |
58 is_updatable)); | |
59 if (!dictionary_structure_with_buffer_policy) { | |
60 return 0; | |
APW
2015/07/31 21:49:16
return nullptr, not 0
riajiang
2015/08/01 01:23:09
Done.
| |
61 } | |
62 | |
63 latinime::Dictionary* const dictionary = new latinime::Dictionary( | |
64 std::move(dictionary_structure_with_buffer_policy)); | |
65 return dictionary; | |
66 } | |
67 | |
68 mojo::Array<mojo::String> DictionaryService::GetDictionarySuggestion( | |
69 PredictionInfoPtr prediction_info, | |
70 latinime::ProximityInfo* proximity_info) { | |
71 mojo::Array<mojo::String> suggestion_words = | |
72 mojo::Array<mojo::String>::New(0); | |
73 | |
74 // dictionary | |
75 base::FilePath dir_temp; | |
76 PathService::Get(base::DIR_TEMP, &dir_temp); | |
77 std::string path = dir_temp.value() + "/main_en.dict"; | |
78 if (!default_dictionary_) { | |
79 CopyDictionaryFromRes(path); | |
80 default_dictionary_ = scoped_ptr<latinime::Dictionary>( | |
81 OpenDictionary(path, 0, prediction::kDictFile.size, false)); | |
82 if (!default_dictionary_) { | |
83 return suggestion_words.Clone().Pass(); | |
84 } | |
85 } | |
86 | |
87 // dic_traverse_session | |
88 if (!default_session_) { | |
89 default_session_ = scoped_ptr<latinime::DicTraverseSession>( | |
90 reinterpret_cast<latinime::DicTraverseSession*>( | |
91 latinime::DicTraverseSession::getSessionInstance( | |
92 "en", prediction::kDictFile.size))); | |
93 latinime::PrevWordsInfo empty_prev_words; | |
94 default_session_->init(default_dictionary_.get(), &empty_prev_words, 0); | |
95 } | |
96 | |
97 // current word | |
98 InputInfo input_info; | |
99 input_info.ProcessInput(prediction_info->current_word); | |
100 int input_size = input_info.GetRealSize(); | |
101 | |
102 // previous words | |
103 latinime::PrevWordsInfo prev_words_info = | |
104 ProcessPrevWord(prediction_info->previous_words); | |
105 | |
106 // suggestion options | |
107 // is_gesture, use_full_edit_distance, | |
108 // block_offensive_words, space_aware gesture_enabled | |
109 int options[] = {0, 0, 0, 0}; | |
110 latinime::SuggestOptions suggest_options(options, arraysize(options)); | |
111 | |
112 latinime::SuggestionResults suggestion_results(max_suggestion_size_); | |
113 if (input_size > 0) { | |
114 DictionaryService::default_dictionary_->getSuggestions( | |
115 proximity_info, default_session_.get(), input_info.GetXCoordinates(), | |
116 input_info.GetYCoordinates(), input_info.GetTimes(), | |
117 input_info.GetPointerIds(), input_info.GetCodepoints(), input_size, | |
118 &prev_words_info, &suggest_options, -1.0f, &suggestion_results); | |
119 } else { | |
120 DictionaryService::default_dictionary_->getPredictions(&prev_words_info, | |
APW
2015/07/31 21:49:16
don't need "DictionaryService::" part
riajiang
2015/08/01 01:23:09
Done.
| |
121 &suggestion_results); | |
122 } | |
123 | |
124 // process suggestion results | |
125 std::deque<std::string> suggestion_words_reverse; | |
126 char cur_beginning; | |
127 std::string lo_cur; | |
128 std::string up_cur; | |
129 if (input_size > 0) { | |
130 cur_beginning = prediction_info->current_word[0]; | |
131 std::string cur_rest = | |
132 std::string(prediction_info->current_word.data()) | |
133 .substr(1, prediction_info->current_word.size() - 1); | |
134 lo_cur = std::string(1, (char)tolower(cur_beginning)) + cur_rest; | |
135 up_cur = std::string(1, (char)toupper(cur_beginning)) + cur_rest; | |
136 } | |
137 while (!suggestion_results.mSuggestedWords.empty()) { | |
138 const latinime::SuggestedWord& suggested_word = | |
139 suggestion_results.mSuggestedWords.top(); | |
140 base::string16 word; | |
141 for (int i = 0; i < suggested_word.getCodePointCount(); i++) { | |
142 base::char16 code_point = suggested_word.getCodePoint()[i]; | |
143 word.push_back(code_point); | |
144 } | |
145 std::string word_string = base::UTF16ToUTF8(word); | |
146 if (word_string.compare(lo_cur) != 0 && word_string.compare(up_cur) != 0) { | |
147 if (isupper(cur_beginning)) | |
APW
2015/07/31 21:49:16
cur_beginning may have not been set.
riajiang
2015/08/01 01:23:09
This while loop will only be entered if current wo
APW
2015/08/03 17:26:21
can't assume that.
| |
148 word_string[0] = toupper(word_string[0]); | |
149 suggestion_words_reverse.push_front(word_string); | |
150 } | |
151 suggestion_results.mSuggestedWords.pop(); | |
152 } | |
153 | |
154 // remove dups within suggestion words | |
155 for (unsigned int i = 0; i < suggestion_words_reverse.size(); i++) { | |
156 for (unsigned int j = i + 1; j < suggestion_words_reverse.size(); j++) { | |
APW
2015/07/31 21:49:16
size_t
riajiang
2015/08/01 01:23:09
Done.
| |
157 if (suggestion_words_reverse[i].compare(suggestion_words_reverse[j]) == | |
158 0) { | |
159 suggestion_words_reverse.erase(suggestion_words_reverse.begin() + j); | |
160 j--; | |
161 } | |
162 } | |
163 } | |
164 | |
165 for (std::deque<std::string>::iterator it = suggestion_words_reverse.begin(); | |
166 it != suggestion_words_reverse.end(); ++it) { | |
167 suggestion_words.push_back(mojo::String(*it)); | |
168 } | |
169 | |
170 return suggestion_words.Clone().Pass(); | |
171 } | |
172 | |
173 // modified from Android JniDataUtils::constructPrevWordsInfo | |
174 latinime::PrevWordsInfo DictionaryService::ProcessPrevWord( | |
175 mojo::Array<PrevWordInfoPtr>& prev_words) { | |
176 int prev_word_codepoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH]; | |
177 int prev_word_codepoint_count[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
178 bool are_beginning_of_sentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
179 int prevwords_count = | |
180 std::min(prev_words.size(), (size_t)MAX_PREV_WORD_COUNT_FOR_N_GRAM); | |
APW
2015/07/31 21:49:16
static_cast<size_t>
riajiang
2015/08/01 01:23:09
Done.
| |
181 for (int i = 0; i < prevwords_count; ++i) { | |
182 prev_word_codepoint_count[i] = 0; | |
183 are_beginning_of_sentence[i] = false; | |
184 int prev_word_size = prev_words[i]->word.size(); | |
185 if (prev_word_size > MAX_WORD_LENGTH) { | |
186 continue; | |
187 } | |
188 for (int j = 0; j < prev_word_size; j++) { | |
189 prev_word_codepoints[i][j] = (int)((prev_words[i])->word)[j]; | |
190 } | |
191 prev_word_codepoint_count[i] = prev_word_size; | |
192 are_beginning_of_sentence[i] = prev_words[i]->is_beginning_of_sentence; | |
193 } | |
194 latinime::PrevWordsInfo prev_words_info = | |
195 latinime::PrevWordsInfo(prev_word_codepoints, prev_word_codepoint_count, | |
196 are_beginning_of_sentence, prevwords_count); | |
197 return prev_words_info; | |
198 } | |
199 | |
200 } // namespace prediction | |
OLD | NEW |