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 "mojo/services/prediction/public/interfaces/prediction.mojom.h" | |
14 #include "mojo/tools/embed/data.h" | |
15 #include "services/prediction/dictionary_service.h" | |
16 #include "services/prediction/input_info.h" | |
17 #include "services/prediction/kDictFile.h" | |
18 #include "services/prediction/key_set.h" | |
19 #include "third_party/prediction/suggest/core/dictionary/dictionary.h" | |
20 #include "third_party/prediction/suggest/core/result/suggestion_results.h" | |
21 #include "third_party/prediction/suggest/core/session/dic_traverse_session.h" | |
22 #include "third_party/prediction/suggest/core/session/prev_words_info.h" | |
23 #include "third_party/prediction/suggest/core/suggest_options.h" | |
24 #include "third_party/prediction/suggest/policyimpl/dictionary/structure/diction ary_structure_with_buffer_policy_factory.h" | |
25 | |
26 namespace prediction { | |
27 | |
28 DictionaryService::DictionaryService() { | |
29 max_suggestion_size = 50; | |
30 default_dictionary = NULL; | |
APW
2015/07/23 18:02:15
use nullptr everywhere instead of NULL.
riajiang
2015/07/31 02:13:05
Done.
| |
31 default_session = NULL; | |
32 } | |
33 | |
34 DictionaryService::~DictionaryService() { | |
35 delete default_dictionary; | |
qsr
2015/07/23 19:40:42
You want to use a std::unique_ptr instead of havin
riajiang
2015/07/31 02:13:04
I changed it to use base/memory/scoped_ptr, is it
| |
36 } | |
37 | |
38 void DictionaryService::LoadDictionary() { | |
APW
2015/07/23 19:51:38
This function name is misleading... I think you're
riajiang
2015/07/31 02:13:05
How's CopyDictionaryFromRes? And added checking if
| |
39 base::FilePath dir_temp; | |
APW
2015/07/23 19:51:39
Since the path for writing the dictionary and read
riajiang
2015/07/31 02:13:04
I changed to only creating the path once in GetDic
| |
40 PathService::Get(base::DIR_TEMP, &dir_temp); | |
41 std::string path = dir_temp.value() + "/main_en.dict"; | |
42 std::ofstream dic_file(path.c_str(), | |
43 std::ofstream::out | std::ofstream::binary); | |
44 dic_file.write(prediction::kDictFile.data, prediction::kDictFile.size); | |
45 dic_file.close(); | |
46 } | |
47 | |
48 latinime::Dictionary* const DictionaryService::OpenDictionary( | |
49 const std::string path, | |
50 const int start_offset, | |
51 const int size, | |
52 const bool is_updatable) { | |
53 latinime::DictionaryStructureWithBufferPolicy::StructurePolicyPtr | |
54 dictionary_structure_with_buffer_policy( | |
55 latinime::DictionaryStructureWithBufferPolicyFactory:: | |
56 newPolicyForExistingDictFile(path.c_str(), start_offset, size, | |
APW
2015/07/23 19:51:38
Function names must start upper case unless its a
riajiang
2015/07/31 02:13:05
This is a function in Android's native code. Since
| |
57 is_updatable)); | |
58 if (!dictionary_structure_with_buffer_policy) { | |
59 return 0; | |
60 } | |
61 | |
62 latinime::Dictionary* const dictionary = new latinime::Dictionary( | |
63 std::move(dictionary_structure_with_buffer_policy)); | |
64 return dictionary; | |
65 } | |
66 | |
67 mojo::Array<mojo::String> DictionaryService::GetDictionarySuggestion( | |
68 PredictionInfoPtr prediction_info, | |
69 ProximityInfoService* proximity_info) { | |
70 mojo::Array<mojo::String> suggestion_words = | |
71 mojo::Array<mojo::String>::New(0); | |
72 | |
73 // dictionary | |
74 base::FilePath dir_temp; | |
75 PathService::Get(base::DIR_TEMP, &dir_temp); | |
76 std::string path = dir_temp.value() + "/main_en.dict"; | |
77 if (!default_dictionary) { | |
78 LoadDictionary(); | |
79 default_dictionary = | |
APW
2015/07/23 19:51:39
default_dictionary should probably be a scoped_ptr
riajiang
2015/07/31 02:13:04
Done.
| |
80 this->OpenDictionary(path, 0, prediction::kDictFile.size, false); | |
81 if (!default_dictionary) { | |
82 suggestion_words.push_back(prediction_info->current_word); | |
83 return suggestion_words.Clone().Pass(); | |
84 } | |
85 } | |
86 | |
87 // dic_traverse_session | |
88 if (!default_session) { | |
89 default_session = reinterpret_cast<latinime::DicTraverseSession*>( | |
APW
2015/07/23 19:51:39
should this be scoped_ptr too?
riajiang
2015/07/31 02:13:04
Done.
| |
90 latinime::DicTraverseSession::getSessionInstance( | |
91 "en", prediction::kDictFile.size)); | |
92 latinime::PrevWordsInfo empty_prev_words; | |
93 default_session->init(default_dictionary, &empty_prev_words, 0); | |
94 } | |
95 | |
96 // current word | |
97 int input_size = prediction_info->current_word.size(); | |
98 InputInfo input_info(input_size); | |
99 input_info.ProcessInput(prediction_info->current_word); | |
100 | |
101 // previous words | |
102 latinime::PrevWordsInfo* prev_words_info = | |
APW
2015/07/23 19:51:38
since you allocate this here and delete it right a
riajiang
2015/07/31 02:13:05
Done.
| |
103 ProcessPrevWord(prediction_info->previous_words, | |
104 prediction_info->are_beginning_of_sentence); | |
105 | |
106 // suggestion options | |
107 // is_gesture, use_full_edit_distance, | |
108 // block_offensive_words, space_aware gesture_enabled | |
109 int options[4] = {0, 0, 0, 0}; | |
110 latinime::SuggestOptions suggest_options(options, 4); | |
APW
2015/07/23 19:51:38
there's a macro for determining the array size of
riajiang
2015/07/31 02:13:05
Done.
| |
111 | |
112 latinime::SuggestionResults suggestion_results(max_suggestion_size); | |
113 if (input_size > 0) { | |
114 DictionaryService::default_dictionary->getSuggestions( | |
115 proximity_info->GetNativeProximityInfoService(), | |
116 DictionaryService::default_session, input_info.GetXCoordinates(), | |
117 input_info.GetYCoordinates(), input_info.GetTimes(), | |
118 input_info.GetPointerIds(), input_info.GetCodepoints(), input_size, | |
119 prev_words_info, &suggest_options, -1.0f, &suggestion_results); | |
120 } else { | |
121 DictionaryService::default_dictionary->getPredictions(prev_words_info, | |
122 &suggestion_results); | |
123 } | |
124 delete prev_words_info; | |
125 | |
126 // process suggestion results | |
127 std::deque<std::string> suggestion_words_reverse; | |
128 char cur_beginning = prediction_info->current_word[0]; | |
APW
2015/07/23 19:51:39
this assumes current_word is size > 0. You didn't
riajiang
2015/07/31 02:13:05
Done.
| |
129 std::string cur_rest = | |
130 std::string(prediction_info->current_word.data()) | |
131 .substr(1, prediction_info->current_word.size() - 1); | |
132 std::string lo_cur = std::string(1, (char)tolower(cur_beginning)) + cur_rest; | |
133 std::string up_cur = std::string(1, (char)toupper(cur_beginning)) + cur_rest; | |
134 while (!suggestion_results.mSuggestedWords.empty()) { | |
APW
2015/07/23 19:51:38
Please use an iterator instead of popping and chec
riajiang
2015/07/31 02:13:05
But mSuggestedWords is a std::priority_queue?
APW
2015/07/31 21:49:15
shoudl still be iterable I think
| |
135 const latinime::SuggestedWord& suggested_word = | |
136 suggestion_results.mSuggestedWords.top(); | |
137 int word_count = | |
138 std::min(suggested_word.getCodePointCount(), MAX_WORD_LENGTH); | |
139 char word[word_count + 1]; | |
140 for (int i = 0; i < word_count; i++) { | |
141 word[i] = (char)suggested_word.getCodePoint()[i]; | |
APW
2015/07/23 19:51:38
While this conversion from code point (int) to cha
APW
2015/07/23 19:51:39
use static_cast<char>(var)
riajiang
2015/07/31 02:13:04
Changed to use char16 as we discussed.
riajiang
2015/07/31 02:13:04
Changed to use char16 as we discussed.
| |
142 } | |
143 word[word_count] = '\0'; | |
144 std::string word_string(word); | |
145 // remove dups | |
146 if (word_string != lo_cur && word_string != up_cur) { | |
APW
2015/07/23 19:51:39
I don't think this does what you think. You'll ne
riajiang
2015/07/31 02:13:05
Changed to use compare and added removing dups wit
| |
147 if (isupper(cur_beginning)) | |
148 word_string[0] = toupper(word_string[0]); | |
149 suggestion_words_reverse.push_front(word_string); | |
150 } | |
151 suggestion_results.mSuggestedWords.pop(); | |
152 } | |
153 for (std::deque<std::string>::iterator it = suggestion_words_reverse.begin(); | |
APW
2015/07/23 19:51:39
Why do the reverse thing?
You can push_back inste
riajiang
2015/07/31 02:13:05
mSuggestedWords is a priority queue but I don't kn
| |
154 it != suggestion_words_reverse.end(); ++it) { | |
155 suggestion_words.push_back(mojo::String(*it)); | |
156 } | |
157 | |
158 if (suggestion_words.size() == 0) | |
159 suggestion_words.push_back(prediction_info->current_word); | |
APW
2015/07/23 19:51:38
Why return current word as the suggestion if empty
riajiang
2015/07/31 02:13:04
I was thinking if there's no suggestion based on u
| |
160 | |
161 return suggestion_words.Clone().Pass(); | |
162 } | |
163 | |
164 // modified from Android JniDataUtils::constructPrevWordsInfo | |
165 latinime::PrevWordsInfo* DictionaryService::ProcessPrevWord( | |
166 mojo::Array<mojo::String>& prev_words, | |
167 mojo::Array<bool>& beginnings) { | |
168 int prev_word_codepoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH]; | |
169 int prev_word_codepoint_count[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
170 bool is_beginning_of_sentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
171 int prevwords_count = | |
172 std::min((int)prev_words.size(), MAX_PREV_WORD_COUNT_FOR_N_GRAM); | |
APW
2015/07/23 19:51:38
instead of using int here can you use size_t?
riajiang
2015/07/31 02:13:04
I used (size_t) for MAX_PREV_WORD_COUNT_FOR_N_GRAM
| |
173 for (int i = 0; i < prevwords_count; ++i) { | |
174 prev_word_codepoint_count[i] = 0; | |
175 is_beginning_of_sentence[i] = false; | |
176 int prev_word_size = prev_words[i].size(); | |
177 if (prev_word_size > MAX_WORD_LENGTH) { | |
178 continue; | |
179 } | |
180 for (int j = 0; j < prev_word_size; j++) { | |
181 prev_word_codepoints[i][j] = (int)prev_words[i][j]; | |
182 } | |
183 prev_word_codepoint_count[i] = prev_word_size; | |
184 is_beginning_of_sentence[i] = beginnings[i]; | |
185 } | |
186 latinime::PrevWordsInfo* prev_words_info = new latinime::PrevWordsInfo( | |
187 prev_word_codepoints, prev_word_codepoint_count, is_beginning_of_sentence, | |
188 prevwords_count); | |
189 return prev_words_info; | |
190 } | |
191 | |
192 } // namespace prediction | |
OLD | NEW |