Index: services/prediction/dictionary_service.cc |
diff --git a/services/prediction/dictionary_service.cc b/services/prediction/dictionary_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0cf40e2cfcd81ddd597bb2e3f8b6ec56811afd86 |
--- /dev/null |
+++ b/services/prediction/dictionary_service.cc |
@@ -0,0 +1,199 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <algorithm> |
+#include <deque> |
+#include <fstream> |
+#include <string> |
+ |
+#include "base/base_paths.h" |
+#include "base/files/file_path.h" |
+#include "base/path_service.h" |
+#include "base/strings/string16.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "mojo/services/prediction/public/interfaces/prediction.mojom.h" |
+#include "mojo/tools/embed/data.h" |
+#include "services/prediction/dictionary_service.h" |
+#include "services/prediction/input_info.h" |
+#include "services/prediction/kDictFile.h" |
+#include "services/prediction/key_set.h" |
+#include "services/prediction/proximity_info_factory.h" |
+#include "third_party/prediction/suggest/core/dictionary/dictionary.h" |
+#include "third_party/prediction/suggest/core/result/suggestion_results.h" |
+#include "third_party/prediction/suggest/core/session/dic_traverse_session.h" |
+#include "third_party/prediction/suggest/core/session/prev_words_info.h" |
+#include "third_party/prediction/suggest/core/suggest_options.h" |
+#include "third_party/prediction/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h" |
+ |
+namespace prediction { |
+ |
+DictionaryService::DictionaryService() : max_suggestion_size_(50) { |
+} |
+ |
+DictionaryService::~DictionaryService() { |
+} |
+ |
+void DictionaryService::CreatDictFromEmbeddedDataIfNotExist( |
+ const std::string path) { |
+ if (std::ifstream(path.c_str())) |
+ return; |
+ std::ofstream dic_file(path.c_str(), |
+ std::ofstream::out | std::ofstream::binary); |
+ dic_file.write(prediction::kDictFile.data, prediction::kDictFile.size); |
+ dic_file.close(); |
+} |
+ |
+latinime::Dictionary* const DictionaryService::OpenDictionary( |
+ const std::string path, |
+ const int start_offset, |
+ const int size, |
+ const bool is_updatable) { |
+ latinime::DictionaryStructureWithBufferPolicy::StructurePolicyPtr |
+ dictionary_structure_with_buffer_policy( |
+ latinime::DictionaryStructureWithBufferPolicyFactory:: |
+ newPolicyForExistingDictFile(path.c_str(), start_offset, size, |
+ is_updatable)); |
+ if (!dictionary_structure_with_buffer_policy) { |
+ return nullptr; |
+ } |
+ |
+ latinime::Dictionary* const dictionary = new latinime::Dictionary( |
+ std::move(dictionary_structure_with_buffer_policy)); |
+ return dictionary; |
+} |
+ |
+mojo::Array<mojo::String> DictionaryService::GetDictionarySuggestion( |
+ PredictionInfoPtr prediction_info, |
+ latinime::ProximityInfo* proximity_info) { |
+ mojo::Array<mojo::String> suggestion_words = |
+ mojo::Array<mojo::String>::New(0); |
+ |
+ // dictionary |
+ base::FilePath dir_temp; |
+ PathService::Get(base::DIR_TEMP, &dir_temp); |
+ std::string path = dir_temp.value() + "/main_en.dict"; |
+ if (!default_dictionary_) { |
+ CreatDictFromEmbeddedDataIfNotExist(path); |
+ default_dictionary_ = scoped_ptr<latinime::Dictionary>( |
+ OpenDictionary(path, 0, prediction::kDictFile.size, false)); |
+ if (!default_dictionary_) { |
+ return suggestion_words.Clone().Pass(); |
+ } |
+ } |
+ |
+ // dic_traverse_session |
+ if (!default_session_) { |
+ default_session_ = scoped_ptr<latinime::DicTraverseSession>( |
+ reinterpret_cast<latinime::DicTraverseSession*>( |
+ latinime::DicTraverseSession::getSessionInstance( |
+ "en", prediction::kDictFile.size))); |
+ latinime::PrevWordsInfo empty_prev_words; |
+ default_session_->init(default_dictionary_.get(), &empty_prev_words, 0); |
+ } |
+ |
+ // current word |
+ int input_size = std::min( |
+ static_cast<int>(prediction_info->current_word.size()), MAX_WORD_LENGTH); |
+ InputInfo input_info(prediction_info->current_word, input_size); |
+ input_info.ProcessInput(prediction_info->current_word, input_size); |
+ input_size = input_info.GetRealSize(); |
+ |
+ // previous words |
+ latinime::PrevWordsInfo prev_words_info = |
+ ProcessPrevWord(prediction_info->previous_words); |
+ |
+ // suggestion options |
+ // is_gesture, use_full_edit_distance, |
+ // block_offensive_words, space_aware gesture_enabled |
+ int options[] = {0, 0, 0, 0}; |
+ latinime::SuggestOptions suggest_options(options, arraysize(options)); |
+ |
+ latinime::SuggestionResults suggestion_results(max_suggestion_size_); |
+ if (input_size > 0) { |
+ default_dictionary_->getSuggestions( |
+ proximity_info, default_session_.get(), input_info.GetXCoordinates(), |
+ input_info.GetYCoordinates(), input_info.GetTimes(), |
+ input_info.GetPointerIds(), input_info.GetCodepoints(), input_size, |
+ &prev_words_info, &suggest_options, -1.0f, &suggestion_results); |
+ } else { |
+ default_dictionary_->getPredictions(&prev_words_info, &suggestion_results); |
+ } |
+ |
+ // process suggestion results |
+ std::deque<std::string> suggestion_words_reverse; |
+ char cur_beginning; |
+ 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.
|
+ std::string up_cur = ""; |
+ if (input_size > 0) { |
+ cur_beginning = prediction_info->current_word[0]; |
+ std::string cur_rest = |
+ std::string(prediction_info->current_word.data()) |
+ .substr(1, prediction_info->current_word.size() - 1); |
+ lo_cur = std::string(1, (char)tolower(cur_beginning)) + cur_rest; |
+ up_cur = std::string(1, (char)toupper(cur_beginning)) + cur_rest; |
+ } |
+ while (!suggestion_results.mSuggestedWords.empty()) { |
+ const latinime::SuggestedWord& suggested_word = |
+ suggestion_results.mSuggestedWords.top(); |
+ base::string16 word; |
+ for (int i = 0; i < suggested_word.getCodePointCount(); i++) { |
+ base::char16 code_point = suggested_word.getCodePoint()[i]; |
+ word.push_back(code_point); |
+ } |
+ std::string word_string = base::UTF16ToUTF8(word); |
+ if (word_string.compare(lo_cur) != 0 && word_string.compare(up_cur) != 0) { |
+ if (input_size > 0 && isupper(cur_beginning)) |
APW
2015/08/03 21:38:57
curly braces
riajiang
2015/08/03 22:25:05
Done.
|
+ word_string[0] = toupper(word_string[0]); |
+ suggestion_words_reverse.push_front(word_string); |
+ } |
+ suggestion_results.mSuggestedWords.pop(); |
+ } |
+ |
+ // remove dups within suggestion words |
+ for (size_t i = 0; i < suggestion_words_reverse.size(); i++) { |
+ for (size_t j = i + 1; j < suggestion_words_reverse.size(); j++) { |
+ if (suggestion_words_reverse[i].compare(suggestion_words_reverse[j]) == |
+ 0) { |
+ suggestion_words_reverse.erase(suggestion_words_reverse.begin() + j); |
+ j--; |
+ } |
+ } |
+ } |
+ |
+ for (std::deque<std::string>::iterator it = suggestion_words_reverse.begin(); |
+ it != suggestion_words_reverse.end(); ++it) { |
+ suggestion_words.push_back(mojo::String(*it)); |
+ } |
+ |
+ return suggestion_words.Clone().Pass(); |
+} |
+ |
+// modified from Android JniDataUtils::constructPrevWordsInfo |
+latinime::PrevWordsInfo DictionaryService::ProcessPrevWord( |
+ mojo::Array<PrevWordInfoPtr>& prev_words) { |
+ int prev_word_codepoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH]; |
+ int prev_word_codepoint_count[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; |
+ bool are_beginning_of_sentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; |
+ int prevwords_count = std::min( |
+ prev_words.size(), static_cast<size_t>(MAX_PREV_WORD_COUNT_FOR_N_GRAM)); |
+ for (int i = 0; i < prevwords_count; ++i) { |
+ prev_word_codepoint_count[i] = 0; |
+ are_beginning_of_sentence[i] = false; |
+ int prev_word_size = prev_words[i]->word.size(); |
+ if (prev_word_size > MAX_WORD_LENGTH) { |
+ continue; |
+ } |
+ for (int j = 0; j < prev_word_size; j++) { |
+ prev_word_codepoints[i][j] = (int)((prev_words[i])->word)[j]; |
+ } |
+ prev_word_codepoint_count[i] = prev_word_size; |
+ are_beginning_of_sentence[i] = prev_words[i]->is_beginning_of_sentence; |
+ } |
+ latinime::PrevWordsInfo prev_words_info = |
+ latinime::PrevWordsInfo(prev_word_codepoints, prev_word_codepoint_count, |
+ are_beginning_of_sentence, prevwords_count); |
+ return prev_words_info; |
+} |
+ |
+} // namespace prediction |