1 : // Copyright (c) 2006-2008 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
5 :
6 : #include <algorithm>
7 : #include <iostream>
8 :
9 : #include "base/string_piece.h"
10 :
11 : typedef StringPiece::size_type size_type;
12 :
13 0 : std::ostream& operator<<(std::ostream& o, const StringPiece& piece) {
14 0 : o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
15 0 : return o;
16 : }
17 :
18 0 : bool operator==(const StringPiece& x, const StringPiece& y) {
19 0 : if (x.size() != y.size())
20 0 : return false;
21 :
22 0 : return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
23 : }
24 :
25 0 : void StringPiece::CopyToString(std::string* target) const {
26 0 : target->assign(!empty() ? data() : "", size());
27 0 : }
28 :
29 0 : void StringPiece::AppendToString(std::string* target) const {
30 0 : if (!empty())
31 0 : target->append(data(), size());
32 0 : }
33 :
34 0 : size_type StringPiece::copy(char* buf, size_type n, size_type pos) const {
35 0 : size_type ret = std::min(length_ - pos, n);
36 0 : memcpy(buf, ptr_ + pos, ret);
37 0 : return ret;
38 : }
39 :
40 0 : size_type StringPiece::find(const StringPiece& s, size_type pos) const {
41 0 : if (pos > length_)
42 0 : return npos;
43 :
44 : const char* result = std::search(ptr_ + pos, ptr_ + length_,
45 0 : s.ptr_, s.ptr_ + s.length_);
46 0 : const size_type xpos = result - ptr_;
47 0 : return xpos + s.length_ <= length_ ? xpos : npos;
48 : }
49 :
50 0 : size_type StringPiece::find(char c, size_type pos) const {
51 0 : if (pos >= length_)
52 0 : return npos;
53 :
54 0 : const char* result = std::find(ptr_ + pos, ptr_ + length_, c);
55 0 : return result != ptr_ + length_ ? result - ptr_ : npos;
56 : }
57 :
58 0 : size_type StringPiece::rfind(const StringPiece& s, size_type pos) const {
59 0 : if (length_ < s.length_)
60 0 : return npos;
61 :
62 0 : if (s.empty())
63 0 : return std::min(length_, pos);
64 :
65 0 : const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
66 0 : const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
67 0 : return result != last ? result - ptr_ : npos;
68 : }
69 :
70 0 : size_type StringPiece::rfind(char c, size_type pos) const {
71 0 : if (length_ == 0)
72 0 : return npos;
73 :
74 0 : for (size_type i = std::min(pos, length_ - 1); ; --i) {
75 0 : if (ptr_[i] == c)
76 0 : return i;
77 0 : if (i == 0)
78 : break;
79 : }
80 0 : return npos;
81 : }
82 :
83 : // For each character in characters_wanted, sets the index corresponding
84 : // to the ASCII code of that character to 1 in table. This is used by
85 : // the find_.*_of methods below to tell whether or not a character is in
86 : // the lookup table in constant time.
87 : // The argument `table' must be an array that is large enough to hold all
88 : // the possible values of an unsigned char. Thus it should be be declared
89 : // as follows:
90 : // bool table[UCHAR_MAX + 1]
91 0 : static inline void BuildLookupTable(const StringPiece& characters_wanted,
92 : bool* table) {
93 0 : const size_type length = characters_wanted.length();
94 0 : const char* const data = characters_wanted.data();
95 0 : for (size_type i = 0; i < length; ++i) {
96 0 : table[static_cast<unsigned char>(data[i])] = true;
97 : }
98 0 : }
99 :
100 0 : size_type StringPiece::find_first_of(const StringPiece& s,
101 : size_type pos) const {
102 0 : if (length_ == 0 || s.length_ == 0)
103 0 : return npos;
104 :
105 : // Avoid the cost of BuildLookupTable() for a single-character search.
106 0 : if (s.length_ == 1)
107 0 : return find_first_of(s.ptr_[0], pos);
108 :
109 0 : bool lookup[UCHAR_MAX + 1] = { false };
110 0 : BuildLookupTable(s, lookup);
111 0 : for (size_type i = pos; i < length_; ++i) {
112 0 : if (lookup[static_cast<unsigned char>(ptr_[i])]) {
113 0 : return i;
114 : }
115 : }
116 0 : return npos;
117 : }
118 :
119 0 : size_type StringPiece::find_first_not_of(const StringPiece& s,
120 : size_type pos) const {
121 0 : if (length_ == 0)
122 0 : return npos;
123 :
124 0 : if (s.length_ == 0)
125 0 : return 0;
126 :
127 : // Avoid the cost of BuildLookupTable() for a single-character search.
128 0 : if (s.length_ == 1)
129 0 : return find_first_not_of(s.ptr_[0], pos);
130 :
131 0 : bool lookup[UCHAR_MAX + 1] = { false };
132 0 : BuildLookupTable(s, lookup);
133 0 : for (size_type i = pos; i < length_; ++i) {
134 0 : if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
135 0 : return i;
136 : }
137 : }
138 0 : return npos;
139 : }
140 :
141 0 : size_type StringPiece::find_first_not_of(char c, size_type pos) const {
142 0 : if (length_ == 0)
143 0 : return npos;
144 :
145 0 : for (; pos < length_; ++pos) {
146 0 : if (ptr_[pos] != c) {
147 0 : return pos;
148 : }
149 : }
150 0 : return npos;
151 : }
152 :
153 0 : size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const {
154 0 : if (length_ == 0 || s.length_ == 0)
155 0 : return npos;
156 :
157 : // Avoid the cost of BuildLookupTable() for a single-character search.
158 0 : if (s.length_ == 1)
159 0 : return find_last_of(s.ptr_[0], pos);
160 :
161 0 : bool lookup[UCHAR_MAX + 1] = { false };
162 0 : BuildLookupTable(s, lookup);
163 0 : for (size_type i = std::min(pos, length_ - 1); ; --i) {
164 0 : if (lookup[static_cast<unsigned char>(ptr_[i])])
165 0 : return i;
166 0 : if (i == 0)
167 : break;
168 : }
169 0 : return npos;
170 : }
171 :
172 0 : size_type StringPiece::find_last_not_of(const StringPiece& s,
173 : size_type pos) const {
174 0 : if (length_ == 0)
175 0 : return npos;
176 :
177 0 : size_type i = std::min(pos, length_ - 1);
178 0 : if (s.length_ == 0)
179 0 : return i;
180 :
181 : // Avoid the cost of BuildLookupTable() for a single-character search.
182 0 : if (s.length_ == 1)
183 0 : return find_last_not_of(s.ptr_[0], pos);
184 :
185 0 : bool lookup[UCHAR_MAX + 1] = { false };
186 0 : BuildLookupTable(s, lookup);
187 0 : for (; ; --i) {
188 0 : if (!lookup[static_cast<unsigned char>(ptr_[i])])
189 0 : return i;
190 0 : if (i == 0)
191 : break;
192 : }
193 0 : return npos;
194 : }
195 :
196 0 : size_type StringPiece::find_last_not_of(char c, size_type pos) const {
197 0 : if (length_ == 0)
198 0 : return npos;
199 :
200 0 : for (size_type i = std::min(pos, length_ - 1); ; --i) {
201 0 : if (ptr_[i] != c)
202 0 : return i;
203 0 : if (i == 0)
204 : break;
205 : }
206 0 : return npos;
207 : }
208 :
209 0 : StringPiece StringPiece::substr(size_type pos, size_type n) const {
210 0 : if (pos > length_) pos = length_;
211 0 : if (n > length_ - pos) n = length_ - pos;
212 0 : return StringPiece(ptr_ + pos, n);
213 : }
214 :
215 4392 : const StringPiece::size_type StringPiece::npos = size_type(-1);
|