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