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 // Copied from strings/stringpiece.cc with modifications
9 #include "base/string_piece.h"
13 // MSVC doesn't like complex extern templates and DLLs.
14 #if !defined(COMPILER_MSVC)
16 template class StringPieceDetail
<std::string
>;
17 template class StringPieceDetail
<string16
>;
18 } // namespace internal
20 template class BasicStringPiece
<string16
>;
23 bool operator==(const StringPiece
& x
, const StringPiece
& y
) {
24 if (x
.size() != y
.size())
27 return StringPiece::wordmemcmp(x
.data(), y
.data(), x
.size()) == 0;
31 void CopyToString(const StringPiece
& self
, std::string
* target
) {
32 target
->assign(!self
.empty() ? self
.data() : "", self
.size());
35 void AppendToString(const StringPiece
& self
, std::string
* target
) {
37 target
->append(self
.data(), self
.size());
40 StringPiece::size_type
copy(const StringPiece
& self
,
42 StringPiece::size_type n
,
43 StringPiece::size_type pos
) {
44 StringPiece::size_type ret
= std::min(self
.size() - pos
, n
);
45 memcpy(buf
, self
.data() + pos
, ret
);
49 StringPiece::size_type
find(const StringPiece
& self
,
51 StringPiece::size_type pos
) {
52 if (pos
> self
.size())
53 return StringPiece::npos
;
55 StringPiece::const_iterator result
=
56 std::search(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
57 const StringPiece::size_type xpos
=
58 static_cast<size_t>(result
- self
.begin());
59 return xpos
+ s
.size() <= self
.size() ? xpos
: StringPiece::npos
;
62 StringPiece::size_type
find(const StringPiece
& self
,
64 StringPiece::size_type pos
) {
65 if (pos
>= self
.size())
66 return StringPiece::npos
;
68 StringPiece::const_iterator result
=
69 std::find(self
.begin() + pos
, self
.end(), c
);
70 return result
!= self
.end() ?
71 static_cast<size_t>(result
- self
.begin()) : StringPiece::npos
;
74 StringPiece::size_type
rfind(const StringPiece
& self
,
76 StringPiece::size_type pos
) {
77 if (self
.size() < s
.size())
78 return StringPiece::npos
;
81 return std::min(self
.size(), pos
);
83 StringPiece::const_iterator last
=
84 self
.begin() + std::min(self
.size() - s
.size(), pos
) + s
.size();
85 StringPiece::const_iterator result
=
86 std::find_end(self
.begin(), last
, s
.begin(), s
.end());
87 return result
!= last
?
88 static_cast<size_t>(result
- self
.begin()) : StringPiece::npos
;
91 StringPiece::size_type
rfind(const StringPiece
& self
,
93 StringPiece::size_type pos
) {
95 return StringPiece::npos
;
97 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
98 if (self
.data()[i
] == c
)
103 return StringPiece::npos
;
106 // For each character in characters_wanted, sets the index corresponding
107 // to the ASCII code of that character to 1 in table. This is used by
108 // the find_.*_of methods below to tell whether or not a character is in
109 // the lookup table in constant time.
110 // The argument `table' must be an array that is large enough to hold all
111 // the possible values of an unsigned char. Thus it should be be declared
113 // bool table[UCHAR_MAX + 1]
114 static inline void BuildLookupTable(const StringPiece
& characters_wanted
,
116 const StringPiece::size_type length
= characters_wanted
.length();
117 const char* const data
= characters_wanted
.data();
118 for (StringPiece::size_type i
= 0; i
< length
; ++i
) {
119 table
[static_cast<unsigned char>(data
[i
])] = true;
123 StringPiece::size_type
find_first_of(const StringPiece
& self
,
124 const StringPiece
& s
,
125 StringPiece::size_type pos
) {
126 if (self
.size() == 0 || s
.size() == 0)
127 return StringPiece::npos
;
129 // Avoid the cost of BuildLookupTable() for a single-character search.
131 return find(self
, s
.data()[0], pos
);
133 bool lookup
[UCHAR_MAX
+ 1] = { false };
134 BuildLookupTable(s
, lookup
);
135 for (StringPiece::size_type i
= pos
; i
< self
.size(); ++i
) {
136 if (lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
140 return StringPiece::npos
;
143 StringPiece::size_type
find_first_not_of(const StringPiece
& self
,
144 const StringPiece
& s
,
145 StringPiece::size_type pos
) {
146 if (self
.size() == 0)
147 return StringPiece::npos
;
152 // Avoid the cost of BuildLookupTable() for a single-character search.
154 return find_first_not_of(self
, s
.data()[0], pos
);
156 bool lookup
[UCHAR_MAX
+ 1] = { false };
157 BuildLookupTable(s
, lookup
);
158 for (StringPiece::size_type i
= pos
; i
< self
.size(); ++i
) {
159 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
163 return StringPiece::npos
;
166 StringPiece::size_type
find_first_not_of(const StringPiece
& self
,
168 StringPiece::size_type pos
) {
169 if (self
.size() == 0)
170 return StringPiece::npos
;
172 for (; pos
< self
.size(); ++pos
) {
173 if (self
.data()[pos
] != c
) {
177 return StringPiece::npos
;
180 StringPiece::size_type
find_last_of(const StringPiece
& self
,
181 const StringPiece
& s
,
182 StringPiece::size_type pos
) {
183 if (self
.size() == 0 || s
.size() == 0)
184 return StringPiece::npos
;
186 // Avoid the cost of BuildLookupTable() for a single-character search.
188 return rfind(self
, s
.data()[0], pos
);
190 bool lookup
[UCHAR_MAX
+ 1] = { false };
191 BuildLookupTable(s
, lookup
);
192 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
193 if (lookup
[static_cast<unsigned char>(self
.data()[i
])])
198 return StringPiece::npos
;
201 StringPiece::size_type
find_last_not_of(const StringPiece
& self
,
202 const StringPiece
& s
,
203 StringPiece::size_type pos
) {
204 if (self
.size() == 0)
205 return StringPiece::npos
;
207 StringPiece::size_type i
= std::min(pos
, self
.size() - 1);
211 // Avoid the cost of BuildLookupTable() for a single-character search.
213 return find_last_not_of(self
, s
.data()[0], pos
);
215 bool lookup
[UCHAR_MAX
+ 1] = { false };
216 BuildLookupTable(s
, lookup
);
218 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])])
223 return StringPiece::npos
;
226 StringPiece::size_type
find_last_not_of(const StringPiece
& self
,
228 StringPiece::size_type pos
) {
229 if (self
.size() == 0)
230 return StringPiece::npos
;
232 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
233 if (self
.data()[i
] != c
)
238 return StringPiece::npos
;
241 StringPiece
substr(const StringPiece
& self
,
242 StringPiece::size_type pos
,
243 StringPiece::size_type n
) {
244 if (pos
> self
.size()) pos
= self
.size();
245 if (n
> self
.size() - pos
) n
= self
.size() - pos
;
246 return StringPiece(self
.data() + pos
, n
);
249 } // namespace internal