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