1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "dictionary/dictionary_mock.h"
31
32 #include <climits>
33 #include <map>
34 #include <memory>
35 #include <string>
36
37 #include "base/logging.h"
38 #include "base/stl_util.h"
39 #include "base/string_piece.h"
40 #include "base/util.h"
41 #include "dictionary/dictionary_token.h"
42
43 namespace mozc {
44 namespace dictionary {
45 namespace {
46
47 const int kDummyPosId = 1;
48
HasKeyInternal(const std::map<string,std::vector<Token * >> & dic,StringPiece key)49 bool HasKeyInternal(const std::map<string, std::vector<Token *>> &dic,
50 StringPiece key) {
51 typedef std::vector<Token *> TokenPtrVector;
52 for (std::map<string, std::vector<Token *>>::const_iterator map_it =
53 dic.begin();
54 map_it != dic.end(); ++map_it) {
55 const TokenPtrVector &v = map_it->second;
56 for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
57 if ((*it)->key == key) {
58 return true;
59 }
60 }
61 }
62 return false;
63 }
64
HasValueInternal(const std::map<string,std::vector<Token * >> & dic,StringPiece value)65 bool HasValueInternal(const std::map<string, std::vector<Token *>> &dic,
66 StringPiece value) {
67 typedef std::vector<Token *> TokenPtrVector;
68 for (std::map<string, std::vector<Token *>>::const_iterator map_it =
69 dic.begin();
70 map_it != dic.end(); ++map_it) {
71 const TokenPtrVector &v = map_it->second;
72 for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
73 if ((*it)->value == value) {
74 return true;
75 }
76 }
77 }
78 return false;
79 }
80
CreateToken(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)81 Token *CreateToken(const string &str, const string &key, const string &value,
82 Token::AttributesBitfield attributes) {
83 std::unique_ptr<Token> token(new Token());
84 token->key = key;
85 token->value = value;
86 // TODO(noriyukit): Currently, we cannot set cost and POS IDs.
87 token->cost = 0;
88 token->lid = token->rid = kDummyPosId;
89 token->attributes = attributes;
90 return token.release();
91 }
92
DeletePtrs(std::map<string,std::vector<Token * >> * m)93 void DeletePtrs(std::map<string, std::vector<Token *>> *m) {
94 for (std::map<string, std::vector<Token *>>::iterator iter = m->begin();
95 iter != m->end(); ++iter) {
96 STLDeleteElements(&iter->second);
97 }
98 }
99
100 } // namespace
101
DictionaryMock()102 DictionaryMock::DictionaryMock() {
103 LOG(INFO) << "DictionaryMock is created";
104 }
105
~DictionaryMock()106 DictionaryMock::~DictionaryMock() {
107 DeletePtrs(&prefix_dictionary_);
108 DeletePtrs(&exact_dictionary_);
109 DeletePtrs(&reverse_dictionary_);
110 DeletePtrs(&predictive_dictionary_);
111 }
112
HasKey(StringPiece key) const113 bool DictionaryMock::HasKey(StringPiece key) const {
114 return HasKeyInternal(predictive_dictionary_, key) ||
115 HasKeyInternal(prefix_dictionary_, key) ||
116 HasKeyInternal(reverse_dictionary_, key) ||
117 HasKeyInternal(exact_dictionary_, key);
118 }
119
HasValue(StringPiece value) const120 bool DictionaryMock::HasValue(StringPiece value) const {
121 return HasValueInternal(predictive_dictionary_, value) ||
122 HasValueInternal(prefix_dictionary_, value) ||
123 HasValueInternal(reverse_dictionary_, value) ||
124 HasValueInternal(exact_dictionary_, value);
125 }
126
LookupPredictive(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const127 void DictionaryMock::LookupPredictive(
128 StringPiece key,
129 const ConversionRequest &conversion_request,
130 Callback *callback) const {
131 std::map<string, std::vector<Token *>>::const_iterator vector_iter =
132 predictive_dictionary_.find(key.as_string());
133 if (vector_iter == predictive_dictionary_.end()) {
134 return;
135 }
136 if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE ||
137 callback->OnActualKey(key, key, false) != Callback::TRAVERSE_CONTINUE) {
138 return;
139 }
140 for (std::vector<Token *>::const_iterator iter = vector_iter->second.begin();
141 iter != vector_iter->second.end(); ++iter) {
142 if (callback->OnToken(key, key, **iter) != Callback::TRAVERSE_CONTINUE) {
143 return;
144 }
145 }
146 }
147
LookupPrefix(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const148 void DictionaryMock::LookupPrefix(
149 StringPiece key,
150 const ConversionRequest &conversion_request,
151 Callback *callback) const {
152 CHECK(!key.empty());
153
154 string prefix;
155 for (size_t len = 1; len <= key.size(); ++len) {
156 prefix.assign(key.data(), len);
157 std::map<string, std::vector<Token *>>::const_iterator iter =
158 prefix_dictionary_.find(prefix);
159 if (iter == prefix_dictionary_.end()) {
160 continue;
161 }
162 switch (callback->OnKey(prefix)) {
163 case Callback::TRAVERSE_DONE:
164 case Callback::TRAVERSE_CULL:
165 return;
166 case Callback::TRAVERSE_NEXT_KEY:
167 continue;
168 default:
169 break;
170 }
171 switch (callback->OnActualKey(prefix, prefix, false)) {
172 case Callback::TRAVERSE_DONE:
173 case Callback::TRAVERSE_CULL:
174 return;
175 case Callback::TRAVERSE_NEXT_KEY:
176 continue;
177 default:
178 break;
179 }
180 for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
181 token_iter != iter->second.end(); ++token_iter) {
182 Callback::ResultType ret =
183 callback->OnToken(prefix, prefix, **token_iter);
184 if (ret == Callback::TRAVERSE_DONE || ret == Callback::TRAVERSE_CULL) {
185 return;
186 }
187 if (ret == Callback::TRAVERSE_NEXT_KEY) {
188 break;
189 }
190 }
191 }
192 }
193
LookupExact(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const194 void DictionaryMock::LookupExact(
195 StringPiece key,
196 const ConversionRequest &conversion_request,
197 Callback *callback) const {
198 std::map<string, std::vector<Token *>>::const_iterator iter =
199 exact_dictionary_.find(key.as_string());
200 if (iter == exact_dictionary_.end()) {
201 return;
202 }
203 if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE) {
204 return;
205 }
206 for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
207 token_iter != iter->second.end(); ++token_iter) {
208 if (callback->OnToken(key, key, **token_iter) !=
209 Callback::TRAVERSE_CONTINUE) {
210 return;
211 }
212 }
213 }
214
LookupReverse(StringPiece str,const ConversionRequest & conversion_request,Callback * callback) const215 void DictionaryMock::LookupReverse(
216 StringPiece str,
217 const ConversionRequest &conversion_request,
218 Callback *callback) const {
219 CHECK(!str.empty());
220
221 for (int i = 1; i <= str.size(); ++i) {
222 StringPiece prefix = str.substr(0, i);
223
224 std::map<string, std::vector<Token *>>::const_iterator iter =
225 reverse_dictionary_.find(prefix.as_string());
226 if (iter == reverse_dictionary_.end()) {
227 continue;
228 }
229
230 if (callback->OnKey(prefix) != Callback::TRAVERSE_CONTINUE) {
231 return;
232 }
233 for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
234 token_iter != iter->second.end(); ++token_iter) {
235 if (callback->OnToken(prefix, prefix, **token_iter) !=
236 Callback::TRAVERSE_CONTINUE) {
237 return;
238 }
239 }
240 }
241 }
242
AddLookupPredictive(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)243 void DictionaryMock::AddLookupPredictive(const string &str,
244 const string &key, const string &value,
245 Token::AttributesBitfield attributes) {
246 predictive_dictionary_[str].push_back(
247 CreateToken(str, key, value, attributes));
248 }
249
AddLookupPrefix(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)250 void DictionaryMock::AddLookupPrefix(const string &str,
251 const string &key, const string &value,
252 Token::AttributesBitfield attributes) {
253 prefix_dictionary_[str].push_back(
254 CreateToken(str, key, value, attributes));
255 }
256
AddLookupReverse(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)257 void DictionaryMock::AddLookupReverse(const string &str,
258 const string &key, const string &value,
259 Token::AttributesBitfield attributes) {
260 reverse_dictionary_[str].push_back(
261 CreateToken(str, key, value, attributes));
262 }
263
AddLookupExact(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)264 void DictionaryMock::AddLookupExact(const string &str,
265 const string &key, const string &value,
266 Token::AttributesBitfield attributes) {
267 exact_dictionary_[str].push_back(
268 CreateToken(str, key, value, attributes));
269 }
270
271 } // namespace dictionary
272 } // namespace mozc
273