string_search.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "unicode/usearch.h"
9
10namespace {
11
12bool CollationSensitiveStringSearch(const string16& find_this,
13                                    const string16& in_this,
14                                    UCollationStrength strength,
15                                    size_t* match_index,
16                                    size_t* match_length) {
17  UErrorCode status = U_ZERO_ERROR;
18
19  UStringSearch* search = usearch_open(find_this.data(), -1,
20                                       in_this.data(), -1,
21                                       uloc_getDefault(),
22                                       NULL,  // breakiter
23                                       &status);
24
25  // Default to basic substring search if usearch fails. According to
26  // http://icu-project.org/apiref/icu4c/usearch_8h.html, usearch_open will fail
27  // if either |find_this| or |in_this| are empty. In either case basic
28  // substring search will give the correct return value.
29  if (!U_SUCCESS(status)) {
30    size_t index = in_this.find(find_this);
31    if (index == string16::npos) {
32      return false;
33    } else {
34      if (match_index)
35        *match_index = index;
36      if (match_length)
37        *match_length = find_this.size();
38      return true;
39    }
40  }
41
42  UCollator* collator = usearch_getCollator(search);
43  ucol_setStrength(collator, strength);
44  usearch_reset(search);
45
46  int32_t index = usearch_first(search, &status);
47  if (!U_SUCCESS(status) || index == USEARCH_DONE) {
48    usearch_close(search);
49    return false;
50  }
51
52  if (match_index)
53    *match_index = static_cast<size_t>(index);
54  if (match_length)
55    *match_length = static_cast<size_t>(usearch_getMatchedLength(search));
56
57  usearch_close(search);
58  return true;
59}
60
61}  // namespace
62
63namespace base {
64namespace i18n {
65
66bool StringSearchIgnoringCaseAndAccents(const string16& find_this,
67                                        const string16& in_this,
68                                        size_t* match_index,
69                                        size_t* match_length) {
70  return CollationSensitiveStringSearch(find_this,
71                                        in_this,
72                                        UCOL_PRIMARY,
73                                        match_index,
74                                        match_length);
75}
76
77}  // namespace i18n
78}  // namespace base
79