blob: b19201aeac6d6b5f0e20c4d1992c73b52990b95c [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "dictionary/dictionary_mock.h"
#include <climits>
#include <map>
#include <string>
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/string_piece.h"
#include "base/util.h"
#include "dictionary/dictionary_token.h"
namespace mozc {
namespace {
const int kDummyPosId = 1;
bool HasKeyInternal(const map<string, vector<Token *>> &dic, StringPiece key) {
typedef vector<Token *> TokenPtrVector;
for (map<string, vector<Token *> >::const_iterator map_it = dic.begin();
map_it != dic.end(); ++map_it) {
const TokenPtrVector &v = map_it->second;
for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
if ((*it)->key == key) {
return true;
}
}
}
return false;
}
bool HasValueInternal(const map<string, vector<Token *>> &dic,
StringPiece value) {
typedef vector<Token *> TokenPtrVector;
for (map<string, vector<Token *> >::const_iterator map_it = dic.begin();
map_it != dic.end(); ++map_it) {
const TokenPtrVector &v = map_it->second;
for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
if ((*it)->value == value) {
return true;
}
}
}
return false;
}
Token *CreateToken(const string &str, const string &key, const string &value,
Token::AttributesBitfield attributes) {
scoped_ptr<Token> token(new Token());
token->key = key;
token->value = value;
// TODO(noriyukit): Currently, we cannot set cost and POS IDs.
token->cost = 0;
token->lid = token->rid = kDummyPosId;
token->attributes = attributes;
return token.release();
}
void DeletePtrs(map<string, vector<Token *> > *m) {
for (map<string, vector<Token *> >::iterator iter = m->begin();
iter != m->end(); ++iter) {
STLDeleteElements(&iter->second);
}
}
} // namespace
DictionaryMock::DictionaryMock() {
LOG(INFO) << "DictionaryMock is created";
}
DictionaryMock::~DictionaryMock() {
DeletePtrs(&prefix_dictionary_);
DeletePtrs(&exact_dictionary_);
DeletePtrs(&reverse_dictionary_);
DeletePtrs(&predictive_dictionary_);
}
bool DictionaryMock::HasKey(StringPiece key) const {
return HasKeyInternal(predictive_dictionary_, key) ||
HasKeyInternal(prefix_dictionary_, key) ||
HasKeyInternal(reverse_dictionary_, key) ||
HasKeyInternal(exact_dictionary_, key);
}
bool DictionaryMock::HasValue(StringPiece value) const {
return HasValueInternal(predictive_dictionary_, value) ||
HasValueInternal(prefix_dictionary_, value) ||
HasValueInternal(reverse_dictionary_, value) ||
HasValueInternal(exact_dictionary_, value);
}
void DictionaryMock::LookupPredictive(
StringPiece key,
bool, // use_kana_modifier_insensitive_lookup
Callback *callback) const {
map<string, vector<Token *> >::const_iterator vector_iter =
predictive_dictionary_.find(key.as_string());
if (vector_iter == predictive_dictionary_.end()) {
return;
}
if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE ||
callback->OnActualKey(key, key, false) != Callback::TRAVERSE_CONTINUE) {
return;
}
for (vector<Token *>::const_iterator iter = vector_iter->second.begin();
iter != vector_iter->second.end(); ++iter) {
if (callback->OnToken(key, key, **iter) != Callback::TRAVERSE_CONTINUE) {
return;
}
}
}
void DictionaryMock::LookupPrefix(
StringPiece key,
bool, // use_kana_modifier_insensitive_lookup
Callback *callback) const {
CHECK(!key.empty());
string prefix;
for (size_t len = 1; len <= key.size(); ++len) {
key.substr(0, len).CopyToString(&prefix);
map<string, vector<Token *> >::const_iterator iter =
prefix_dictionary_.find(prefix);
if (iter == prefix_dictionary_.end()) {
continue;
}
switch (callback->OnKey(prefix)) {
case Callback::TRAVERSE_DONE:
case Callback::TRAVERSE_CULL:
return;
case Callback::TRAVERSE_NEXT_KEY:
continue;
default:
break;
}
switch (callback->OnActualKey(prefix, prefix, false)) {
case Callback::TRAVERSE_DONE:
case Callback::TRAVERSE_CULL:
return;
case Callback::TRAVERSE_NEXT_KEY:
continue;
default:
break;
}
for (vector<Token *>::const_iterator token_iter = iter->second.begin();
token_iter != iter->second.end(); ++token_iter) {
Callback::ResultType ret =
callback->OnToken(prefix, prefix, **token_iter);
if (ret == Callback::TRAVERSE_DONE || ret == Callback::TRAVERSE_CULL) {
return;
}
if (ret == Callback::TRAVERSE_NEXT_KEY) {
break;
}
}
}
}
void DictionaryMock::LookupExact(StringPiece key, Callback *callback) const {
map<string, vector<Token *> >::const_iterator iter =
exact_dictionary_.find(key.as_string());
if (iter == exact_dictionary_.end()) {
return;
}
if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE) {
return;
}
for (vector<Token *>::const_iterator token_iter = iter->second.begin();
token_iter != iter->second.end(); ++token_iter) {
if (callback->OnToken(key, key, **token_iter) !=
Callback::TRAVERSE_CONTINUE) {
return;
}
}
}
void DictionaryMock::LookupReverse(StringPiece str,
NodeAllocatorInterface *allocator,
Callback *callback) const {
CHECK(!str.empty());
for (int i = 1; i <= str.size(); ++i) {
StringPiece prefix = str.substr(0, i);
map<string, vector<Token *> >::const_iterator iter =
reverse_dictionary_.find(prefix.as_string());
if (iter == reverse_dictionary_.end()) {
continue;
}
if (callback->OnKey(prefix) != Callback::TRAVERSE_CONTINUE) {
return;
}
for (vector<Token *>::const_iterator token_iter = iter->second.begin();
token_iter != iter->second.end(); ++token_iter) {
if (callback->OnToken(prefix, prefix, **token_iter) !=
Callback::TRAVERSE_CONTINUE) {
return;
}
}
}
}
void DictionaryMock::AddLookupPredictive(const string &str,
const string &key, const string &value,
Token::AttributesBitfield attributes) {
predictive_dictionary_[str].push_back(
CreateToken(str, key, value, attributes));
}
void DictionaryMock::AddLookupPrefix(const string &str,
const string &key, const string &value,
Token::AttributesBitfield attributes) {
prefix_dictionary_[str].push_back(
CreateToken(str, key, value, attributes));
}
void DictionaryMock::AddLookupReverse(const string &str,
const string &key, const string &value,
Token::AttributesBitfield attributes) {
reverse_dictionary_[str].push_back(
CreateToken(str, key, value, attributes));
}
void DictionaryMock::AddLookupExact(const string &str,
const string &key, const string &value,
Token::AttributesBitfield attributes) {
exact_dictionary_[str].push_back(
CreateToken(str, key, value, attributes));
}
} // namespace mozc