#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
#include <stddef.h>
#include <cmath>
#include "base/i18n/string_search.h"
#include "base/strings/string_util.h"
#include "chromeos/ash/components/string_matching/prefix_matcher.h"
namespace ash::string_matching {
namespace {
const double kIsSubstringMultiplier = 0.4;
const double kNoMatchScore = 0.0;
}
TokenizedStringMatch::TokenizedStringMatch() : relevance_(kNoMatchScore) {}
TokenizedStringMatch::~TokenizedStringMatch() = default;
double TokenizedStringMatch::Calculate(const TokenizedString& query,
const TokenizedString& text) {
relevance_ = kNoMatchScore;
hits_.clear();
const auto& query_text = query.text();
const auto& text_text = text.text();
const auto query_size = query_text.size();
const auto text_size = text_text.size();
if (query_size > 0 && query_size == text_size &&
base::EqualsCaseInsensitiveASCII(query_text, text_text)) {
hits_.emplace_back(0, query_size);
relevance_ = 1.0;
return true;
}
PrefixMatcher matcher(query, text);
if (matcher.Match()) {
relevance_ = matcher.relevance();
hits_.assign(matcher.hits().begin(), matcher.hits().end());
}
if (relevance_ == kNoMatchScore) {
size_t substr_match_start = 0;
size_t substr_match_length = 0;
if (base::i18n::StringSearchIgnoringCaseAndAccents(
query.text(), text.text(), &substr_match_start,
&substr_match_length)) {
relevance_ = kIsSubstringMultiplier * substr_match_length;
hits_.emplace_back(substr_match_start,
substr_match_start + substr_match_length);
}
}
relevance_ = 1.0 - std::pow(0.5, relevance_);
return relevance_;
}
double TokenizedStringMatch::Calculate(const std::u16string& query,
const std::u16string& text) {
const TokenizedString tokenized_query(query);
const TokenizedString tokenized_text(text);
return Calculate(tokenized_query, tokenized_text);
}
}