Home | History | Annotate | Download | only in i18n
      1 // Copyright (c) 2011 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 "base/i18n/string_search.h"
      6 #include "base/logging.h"
      7 
      8 #include "third_party/icu/source/i18n/unicode/usearch.h"
      9 
     10 namespace base {
     11 namespace i18n {
     12 
     13 FixedPatternStringSearchIgnoringCaseAndAccents::
     14 FixedPatternStringSearchIgnoringCaseAndAccents(const string16& find_this)
     15     : find_this_(find_this) {
     16   // usearch_open requires a valid string argument to be searched, even if we
     17   // want to set it by usearch_setText afterwards. So, supplying a dummy text.
     18   const string16& dummy = find_this_;
     19 
     20   UErrorCode status = U_ZERO_ERROR;
     21   search_ = usearch_open(find_this_.data(), find_this_.size(),
     22                          dummy.data(), dummy.size(),
     23                          uloc_getDefault(),
     24                          NULL,  // breakiter
     25                          &status);
     26   if (U_SUCCESS(status)) {
     27     UCollator* collator = usearch_getCollator(search_);
     28     ucol_setStrength(collator, UCOL_PRIMARY);
     29     usearch_reset(search_);
     30   }
     31 }
     32 
     33 FixedPatternStringSearchIgnoringCaseAndAccents::
     34 ~FixedPatternStringSearchIgnoringCaseAndAccents() {
     35   if (search_)
     36     usearch_close(search_);
     37 }
     38 
     39 bool FixedPatternStringSearchIgnoringCaseAndAccents::Search(
     40     const string16& in_this, size_t* match_index, size_t* match_length) {
     41   UErrorCode status = U_ZERO_ERROR;
     42   usearch_setText(search_, in_this.data(), in_this.size(), &status);
     43 
     44   // Default to basic substring search if usearch fails. According to
     45   // http://icu-project.org/apiref/icu4c/usearch_8h.html, usearch_open will fail
     46   // if either |find_this| or |in_this| are empty. In either case basic
     47   // substring search will give the correct return value.
     48   if (!U_SUCCESS(status)) {
     49     size_t index = in_this.find(find_this_);
     50     if (index == string16::npos) {
     51       return false;
     52     } else {
     53       if (match_index)
     54         *match_index = index;
     55       if (match_length)
     56         *match_length = find_this_.size();
     57       return true;
     58     }
     59   }
     60 
     61   int32_t index = usearch_first(search_, &status);
     62   if (!U_SUCCESS(status) || index == USEARCH_DONE)
     63     return false;
     64   if (match_index)
     65     *match_index = static_cast<size_t>(index);
     66   if (match_length)
     67     *match_length = static_cast<size_t>(usearch_getMatchedLength(search_));
     68   return true;
     69 }
     70 
     71 bool StringSearchIgnoringCaseAndAccents(const string16& find_this,
     72                                         const string16& in_this,
     73                                         size_t* match_index,
     74                                         size_t* match_length) {
     75   return FixedPatternStringSearchIgnoringCaseAndAccents(find_this).Search(
     76       in_this, match_index, match_length);
     77 }
     78 
     79 }  // namespace i18n
     80 }  // namespace base
     81