123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // Copyright (c) 2011 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 <stdint.h>
- #include "base/i18n/string_search.h"
- #include "base/check.h"
- #include "base/check_op.h"
- #include "third_party/icu/source/i18n/unicode/usearch.h"
- namespace base {
- namespace i18n {
- FixedPatternStringSearch::FixedPatternStringSearch(
- const std::u16string& find_this,
- bool case_sensitive)
- : find_this_(find_this) {
- // usearch_open requires a valid string argument to be searched, even if we
- // want to set it by usearch_setText afterwards. So, supplying a dummy text.
- const std::u16string& dummy = find_this_;
- UErrorCode status = U_ZERO_ERROR;
- search_ = usearch_open(find_this_.data(), find_this_.size(), dummy.data(),
- dummy.size(), uloc_getDefault(),
- nullptr, // breakiter
- &status);
- if (U_SUCCESS(status)) {
- // http://icu-project.org/apiref/icu4c40/ucol_8h.html#6a967f36248b0a1bc7654f538ee8ba96
- // Set comparison level to UCOL_PRIMARY to ignore secondary and tertiary
- // differences. Set comparison level to UCOL_TERTIARY to include all
- // comparison differences.
- // Diacritical differences on the same base letter represent a
- // secondary difference.
- // Uppercase and lowercase versions of the same character represents a
- // tertiary difference.
- UCollator* collator = usearch_getCollator(search_);
- ucol_setStrength(collator, case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY);
- usearch_reset(search_);
- }
- }
- FixedPatternStringSearch::~FixedPatternStringSearch() {
- if (search_)
- usearch_close(search_);
- }
- bool FixedPatternStringSearch::Search(const std::u16string& in_this,
- size_t* match_index,
- size_t* match_length,
- bool forward_search) {
- UErrorCode status = U_ZERO_ERROR;
- usearch_setText(search_, in_this.data(), in_this.size(), &status);
- // Default to basic substring search if usearch fails. According to
- // http://icu-project.org/apiref/icu4c/usearch_8h.html, usearch_open will fail
- // if either |find_this| or |in_this| are empty. In either case basic
- // substring search will give the correct return value.
- if (!U_SUCCESS(status)) {
- size_t index = in_this.find(find_this_);
- if (index == std::u16string::npos)
- return false;
- if (match_index)
- *match_index = index;
- if (match_length)
- *match_length = find_this_.size();
- return true;
- }
- int32_t index = forward_search ? usearch_first(search_, &status)
- : usearch_last(search_, &status);
- if (!U_SUCCESS(status) || index == USEARCH_DONE)
- return false;
- if (match_index)
- *match_index = static_cast<size_t>(index);
- if (match_length)
- *match_length = static_cast<size_t>(usearch_getMatchedLength(search_));
- return true;
- }
- FixedPatternStringSearchIgnoringCaseAndAccents::
- FixedPatternStringSearchIgnoringCaseAndAccents(
- const std::u16string& find_this)
- : base_search_(find_this, /*case_sensitive=*/false) {}
- bool FixedPatternStringSearchIgnoringCaseAndAccents::Search(
- const std::u16string& in_this,
- size_t* match_index,
- size_t* match_length) {
- return base_search_.Search(in_this, match_index, match_length,
- /*forward_search=*/true);
- }
- bool StringSearchIgnoringCaseAndAccents(const std::u16string& find_this,
- const std::u16string& in_this,
- size_t* match_index,
- size_t* match_length) {
- return FixedPatternStringSearchIgnoringCaseAndAccents(find_this).Search(
- in_this, match_index, match_length);
- }
- bool StringSearch(const std::u16string& find_this,
- const std::u16string& in_this,
- size_t* match_index,
- size_t* match_length,
- bool case_sensitive,
- bool forward_search) {
- return FixedPatternStringSearch(find_this, case_sensitive)
- .Search(in_this, match_index, match_length, forward_search);
- }
- RepeatingStringSearch::RepeatingStringSearch(const std::u16string& find_this,
- const std::u16string& in_this,
- bool case_sensitive)
- : find_this_(find_this), in_this_(in_this) {
- std::string locale = uloc_getDefault();
- UErrorCode status = U_ZERO_ERROR;
- search_ = usearch_open(find_this_.data(), find_this_.size(), in_this_.data(),
- in_this_.size(), locale.data(), /*breakiter=*/nullptr,
- &status);
- DCHECK(U_SUCCESS(status));
- if (U_SUCCESS(status)) {
- // http://icu-project.org/apiref/icu4c40/ucol_8h.html#6a967f36248b0a1bc7654f538ee8ba96
- // Set comparison level to UCOL_PRIMARY to ignore secondary and tertiary
- // differences. Set comparison level to UCOL_TERTIARY to include all
- // comparison differences.
- // Diacritical differences on the same base letter represent a
- // secondary difference.
- // Uppercase and lowercase versions of the same character represents a
- // tertiary difference.
- UCollator* collator = usearch_getCollator(search_);
- ucol_setStrength(collator, case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY);
- usearch_reset(search_);
- }
- }
- RepeatingStringSearch::~RepeatingStringSearch() {
- if (search_)
- usearch_close(search_);
- }
- bool RepeatingStringSearch::NextMatchResult(int& match_index,
- int& match_length) {
- UErrorCode status = U_ZERO_ERROR;
- const int match_start = usearch_next(search_, &status);
- if (U_FAILURE(status) || match_start == USEARCH_DONE)
- return false;
- DCHECK(U_SUCCESS(status));
- match_index = match_start;
- match_length = usearch_getMatchedLength(search_);
- return true;
- }
- } // namespace i18n
- } // namespace base
|