1 // Copyright (c) 2012 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;
30 std::ostream
& operator<<(std::ostream
& o
, const StringPiece
& piece
) {
31 o
.write(piece
.data(), static_cast<std::streamsize
>(piece
.size()));
36 void CopyToString(const StringPiece
& self
, std::string
* target
) {
37 target
->assign(!self
.empty() ? self
.data() : "", self
.size());
40 void AppendToString(const StringPiece
& self
, std::string
* target
) {
42 target
->append(self
.data(), self
.size());
45 StringPiece::size_type
copy(const StringPiece
& self
,
47 StringPiece::size_type n
,
48 StringPiece::size_type pos
) {
49 StringPiece::size_type ret
= std::min(self
.size() - pos
, n
);
50 memcpy(buf
, self
.data() + pos
, ret
);
54 StringPiece::size_type
find(const StringPiece
& self
,
56 StringPiece::size_type pos
) {
57 if (pos
> self
.size())
58 return StringPiece::npos
;
60 StringPiece::const_iterator result
=
61 std::search(self
.begin() + pos
, self
.end(), s
.begin(), s
.end());
62 const StringPiece::size_type xpos
=
63 static_cast<size_t>(result
- self
.begin());
64 return xpos
+ s
.size() <= self
.size() ? xpos
: StringPiece::npos
;
67 StringPiece::size_type
find(const StringPiece
& self
,
69 StringPiece::size_type pos
) {
70 if (pos
>= self
.size())
71 return StringPiece::npos
;
73 StringPiece::const_iterator result
=
74 std::find(self
.begin() + pos
, self
.end(), c
);
75 return result
!= self
.end() ?
76 static_cast<size_t>(result
- self
.begin()) : StringPiece::npos
;
79 StringPiece::size_type
rfind(const StringPiece
& self
,
81 StringPiece::size_type pos
) {
82 if (self
.size() < s
.size())
83 return StringPiece::npos
;
86 return std::min(self
.size(), pos
);
88 StringPiece::const_iterator last
=
89 self
.begin() + std::min(self
.size() - s
.size(), pos
) + s
.size();
90 StringPiece::const_iterator result
=
91 std::find_end(self
.begin(), last
, s
.begin(), s
.end());
92 return result
!= last
?
93 static_cast<size_t>(result
- self
.begin()) : StringPiece::npos
;
96 StringPiece::size_type
rfind(const StringPiece
& self
,
98 StringPiece::size_type pos
) {
100 return StringPiece::npos
;
102 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
103 if (self
.data()[i
] == c
)
108 return StringPiece::npos
;
111 // For each character in characters_wanted, sets the index corresponding
112 // to the ASCII code of that character to 1 in table. This is used by
113 // the find_.*_of methods below to tell whether or not a character is in
114 // the lookup table in constant time.
115 // The argument `table' must be an array that is large enough to hold all
116 // the possible values of an unsigned char. Thus it should be be declared
118 // bool table[UCHAR_MAX + 1]
119 static inline void BuildLookupTable(const StringPiece
& characters_wanted
,
121 const StringPiece::size_type length
= characters_wanted
.length();
122 const char* const data
= characters_wanted
.data();
123 for (StringPiece::size_type i
= 0; i
< length
; ++i
) {
124 table
[static_cast<unsigned char>(data
[i
])] = true;
128 StringPiece::size_type
find_first_of(const StringPiece
& self
,
129 const StringPiece
& s
,
130 StringPiece::size_type pos
) {
131 if (self
.size() == 0 || s
.size() == 0)
132 return StringPiece::npos
;
134 // Avoid the cost of BuildLookupTable() for a single-character search.
136 return find(self
, s
.data()[0], pos
);
138 bool lookup
[UCHAR_MAX
+ 1] = { false };
139 BuildLookupTable(s
, lookup
);
140 for (StringPiece::size_type i
= pos
; i
< self
.size(); ++i
) {
141 if (lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
145 return StringPiece::npos
;
148 StringPiece::size_type
find_first_not_of(const StringPiece
& self
,
149 const StringPiece
& s
,
150 StringPiece::size_type pos
) {
151 if (self
.size() == 0)
152 return StringPiece::npos
;
157 // Avoid the cost of BuildLookupTable() for a single-character search.
159 return find_first_not_of(self
, s
.data()[0], pos
);
161 bool lookup
[UCHAR_MAX
+ 1] = { false };
162 BuildLookupTable(s
, lookup
);
163 for (StringPiece::size_type i
= pos
; i
< self
.size(); ++i
) {
164 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])]) {
168 return StringPiece::npos
;
171 StringPiece::size_type
find_first_not_of(const StringPiece
& self
,
173 StringPiece::size_type pos
) {
174 if (self
.size() == 0)
175 return StringPiece::npos
;
177 for (; pos
< self
.size(); ++pos
) {
178 if (self
.data()[pos
] != c
) {
182 return StringPiece::npos
;
185 StringPiece::size_type
find_last_of(const StringPiece
& self
,
186 const StringPiece
& s
,
187 StringPiece::size_type pos
) {
188 if (self
.size() == 0 || s
.size() == 0)
189 return StringPiece::npos
;
191 // Avoid the cost of BuildLookupTable() for a single-character search.
193 return rfind(self
, s
.data()[0], pos
);
195 bool lookup
[UCHAR_MAX
+ 1] = { false };
196 BuildLookupTable(s
, lookup
);
197 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
198 if (lookup
[static_cast<unsigned char>(self
.data()[i
])])
203 return StringPiece::npos
;
206 StringPiece::size_type
find_last_not_of(const StringPiece
& self
,
207 const StringPiece
& s
,
208 StringPiece::size_type pos
) {
209 if (self
.size() == 0)
210 return StringPiece::npos
;
212 StringPiece::size_type i
= std::min(pos
, self
.size() - 1);
216 // Avoid the cost of BuildLookupTable() for a single-character search.
218 return find_last_not_of(self
, s
.data()[0], pos
);
220 bool lookup
[UCHAR_MAX
+ 1] = { false };
221 BuildLookupTable(s
, lookup
);
223 if (!lookup
[static_cast<unsigned char>(self
.data()[i
])])
228 return StringPiece::npos
;
231 StringPiece::size_type
find_last_not_of(const StringPiece
& self
,
233 StringPiece::size_type pos
) {
234 if (self
.size() == 0)
235 return StringPiece::npos
;
237 for (StringPiece::size_type i
= std::min(pos
, self
.size() - 1); ; --i
) {
238 if (self
.data()[i
] != c
)
243 return StringPiece::npos
;
246 StringPiece
substr(const StringPiece
& self
,
247 StringPiece::size_type pos
,
248 StringPiece::size_type n
) {
249 if (pos
> self
.size()) pos
= self
.size();
250 if (n
> self
.size() - pos
) n
= self
.size() - pos
;
251 return StringPiece(self
.data() + pos
, n
);
254 } // namespace internal