Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: services/prediction/dictionary_service.cc

Issue 1247903003: Add spellcheck and word suggestion to the prediction service (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698