Chromium Code Reviews| 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() : max_suggestion_size_(50) { | |
| 32 } | |
| 33 | |
| 34 DictionaryService::~DictionaryService() { | |
| 35 } | |
| 36 | |
| 37 void DictionaryService::CreatDictFromEmbeddedDataIfNotExist( | |
| 38 const std::string path) { | |
| 39 if (std::ifstream(path.c_str())) | |
| 40 return; | |
| 41 std::ofstream dic_file(path.c_str(), | |
| 42 std::ofstream::out | std::ofstream::binary); | |
| 43 dic_file.write(prediction::kDictFile.data, prediction::kDictFile.size); | |
| 44 dic_file.close(); | |
| 45 } | |
| 46 | |
| 47 latinime::Dictionary* const DictionaryService::OpenDictionary( | |
| 48 const std::string path, | |
| 49 const int start_offset, | |
| 50 const int size, | |
| 51 const bool is_updatable) { | |
| 52 latinime::DictionaryStructureWithBufferPolicy::StructurePolicyPtr | |
| 53 dictionary_structure_with_buffer_policy( | |
| 54 latinime::DictionaryStructureWithBufferPolicyFactory:: | |
| 55 newPolicyForExistingDictFile(path.c_str(), start_offset, size, | |
| 56 is_updatable)); | |
| 57 if (!dictionary_structure_with_buffer_policy) { | |
| 58 return nullptr; | |
| 59 } | |
| 60 | |
| 61 latinime::Dictionary* const dictionary = new latinime::Dictionary( | |
| 62 std::move(dictionary_structure_with_buffer_policy)); | |
| 63 return dictionary; | |
| 64 } | |
| 65 | |
| 66 mojo::Array<mojo::String> DictionaryService::GetDictionarySuggestion( | |
| 67 PredictionInfoPtr prediction_info, | |
| 68 latinime::ProximityInfo* proximity_info) { | |
| 69 mojo::Array<mojo::String> suggestion_words = | |
| 70 mojo::Array<mojo::String>::New(0); | |
| 71 | |
| 72 // dictionary | |
| 73 base::FilePath dir_temp; | |
| 74 PathService::Get(base::DIR_TEMP, &dir_temp); | |
| 75 std::string path = dir_temp.value() + "/main_en.dict"; | |
| 76 if (!default_dictionary_) { | |
| 77 CreatDictFromEmbeddedDataIfNotExist(path); | |
| 78 default_dictionary_ = scoped_ptr<latinime::Dictionary>( | |
| 79 OpenDictionary(path, 0, prediction::kDictFile.size, false)); | |
| 80 if (!default_dictionary_) { | |
| 81 return suggestion_words.Clone().Pass(); | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 // dic_traverse_session | |
| 86 if (!default_session_) { | |
| 87 default_session_ = scoped_ptr<latinime::DicTraverseSession>( | |
| 88 reinterpret_cast<latinime::DicTraverseSession*>( | |
| 89 latinime::DicTraverseSession::getSessionInstance( | |
| 90 "en", prediction::kDictFile.size))); | |
| 91 latinime::PrevWordsInfo empty_prev_words; | |
| 92 default_session_->init(default_dictionary_.get(), &empty_prev_words, 0); | |
| 93 } | |
| 94 | |
| 95 // current word | |
| 96 int input_size = std::min( | |
| 97 static_cast<int>(prediction_info->current_word.size()), MAX_WORD_LENGTH); | |
| 98 InputInfo input_info(prediction_info->current_word, input_size); | |
| 99 input_info.ProcessInput(prediction_info->current_word, input_size); | |
| 100 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 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 default_dictionary_->getPredictions(&prev_words_info, &suggestion_results); | |
| 121 } | |
| 122 | |
| 123 // process suggestion results | |
| 124 std::deque<std::string> suggestion_words_reverse; | |
| 125 char cur_beginning; | |
| 126 std::string lo_cur = ""; | |
|
APW
2015/08/03 21:38:57
don't need to initialize, this is equivalent of de
riajiang
2015/08/03 22:25:05
Done.
| |
| 127 std::string up_cur = ""; | |
| 128 if (input_size > 0) { | |
| 129 cur_beginning = prediction_info->current_word[0]; | |
| 130 std::string cur_rest = | |
| 131 std::string(prediction_info->current_word.data()) | |
| 132 .substr(1, prediction_info->current_word.size() - 1); | |
| 133 lo_cur = std::string(1, (char)tolower(cur_beginning)) + cur_rest; | |
| 134 up_cur = std::string(1, (char)toupper(cur_beginning)) + cur_rest; | |
| 135 } | |
| 136 while (!suggestion_results.mSuggestedWords.empty()) { | |
| 137 const latinime::SuggestedWord& suggested_word = | |
| 138 suggestion_results.mSuggestedWords.top(); | |
| 139 base::string16 word; | |
| 140 for (int i = 0; i < suggested_word.getCodePointCount(); i++) { | |
| 141 base::char16 code_point = suggested_word.getCodePoint()[i]; | |
| 142 word.push_back(code_point); | |
| 143 } | |
| 144 std::string word_string = base::UTF16ToUTF8(word); | |
| 145 if (word_string.compare(lo_cur) != 0 && word_string.compare(up_cur) != 0) { | |
| 146 if (input_size > 0 && isupper(cur_beginning)) | |
|
APW
2015/08/03 21:38:57
curly braces
riajiang
2015/08/03 22:25:05
Done.
| |
| 147 word_string[0] = toupper(word_string[0]); | |
| 148 suggestion_words_reverse.push_front(word_string); | |
| 149 } | |
| 150 suggestion_results.mSuggestedWords.pop(); | |
| 151 } | |
| 152 | |
| 153 // remove dups within suggestion words | |
| 154 for (size_t i = 0; i < suggestion_words_reverse.size(); i++) { | |
| 155 for (size_t j = i + 1; j < suggestion_words_reverse.size(); j++) { | |
| 156 if (suggestion_words_reverse[i].compare(suggestion_words_reverse[j]) == | |
| 157 0) { | |
| 158 suggestion_words_reverse.erase(suggestion_words_reverse.begin() + j); | |
| 159 j--; | |
| 160 } | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 for (std::deque<std::string>::iterator it = suggestion_words_reverse.begin(); | |
| 165 it != suggestion_words_reverse.end(); ++it) { | |
| 166 suggestion_words.push_back(mojo::String(*it)); | |
| 167 } | |
| 168 | |
| 169 return suggestion_words.Clone().Pass(); | |
| 170 } | |
| 171 | |
| 172 // modified from Android JniDataUtils::constructPrevWordsInfo | |
| 173 latinime::PrevWordsInfo DictionaryService::ProcessPrevWord( | |
| 174 mojo::Array<PrevWordInfoPtr>& prev_words) { | |
| 175 int prev_word_codepoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH]; | |
| 176 int prev_word_codepoint_count[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
| 177 bool are_beginning_of_sentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; | |
| 178 int prevwords_count = std::min( | |
| 179 prev_words.size(), static_cast<size_t>(MAX_PREV_WORD_COUNT_FOR_N_GRAM)); | |
| 180 for (int i = 0; i < prevwords_count; ++i) { | |
| 181 prev_word_codepoint_count[i] = 0; | |
| 182 are_beginning_of_sentence[i] = false; | |
| 183 int prev_word_size = prev_words[i]->word.size(); | |
| 184 if (prev_word_size > MAX_WORD_LENGTH) { | |
| 185 continue; | |
| 186 } | |
| 187 for (int j = 0; j < prev_word_size; j++) { | |
| 188 prev_word_codepoints[i][j] = (int)((prev_words[i])->word)[j]; | |
| 189 } | |
| 190 prev_word_codepoint_count[i] = prev_word_size; | |
| 191 are_beginning_of_sentence[i] = prev_words[i]->is_beginning_of_sentence; | |
| 192 } | |
| 193 latinime::PrevWordsInfo prev_words_info = | |
| 194 latinime::PrevWordsInfo(prev_word_codepoints, prev_word_codepoint_count, | |
| 195 are_beginning_of_sentence, prevwords_count); | |
| 196 return prev_words_info; | |
| 197 } | |
| 198 | |
| 199 } // namespace prediction | |
| OLD | NEW |