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