/Users/deen/code/yugabyte-db/src/yb/gutil/strings/stringpiece.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2004 and onwards Google Inc. |
2 | | // |
3 | | // The following only applies to changes made to this file as part of YugaByte development. |
4 | | // |
5 | | // Portions Copyright (c) YugaByte, Inc. |
6 | | // |
7 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
8 | | // in compliance with the License. You may obtain a copy of the License at |
9 | | // |
10 | | // http://www.apache.org/licenses/LICENSE-2.0 |
11 | | // |
12 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
13 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
14 | | // or implied. See the License for the specific language governing permissions and limitations |
15 | | // under the License. |
16 | | // |
17 | | // |
18 | | #include "yb/gutil/strings/stringpiece.h" |
19 | | |
20 | | #include <string.h> |
21 | | |
22 | | #include <algorithm> |
23 | | #include <string> |
24 | | |
25 | | #include <glog/logging.h> |
26 | | |
27 | | #include "yb/gutil/hash/hash.h" |
28 | | #include "yb/gutil/stl_util.h" |
29 | | #include "yb/gutil/strings/memutil.h" |
30 | | |
31 | | using std::copy; |
32 | | using std::max; |
33 | | using std::min; |
34 | | using std::reverse; |
35 | | using std::sort; |
36 | | using std::swap; |
37 | | using std::string; |
38 | | |
39 | | namespace std { |
40 | 124M | size_t hash<GStringPiece>::operator()(GStringPiece s) const { |
41 | 124M | return HashTo32(s.data(), s.size()); |
42 | 124M | } |
43 | | } // namespace std |
44 | | |
45 | 2 | std::ostream& operator<<(std::ostream& o, GStringPiece piece) { |
46 | 2 | o.write(piece.data(), piece.size()); |
47 | 2 | return o; |
48 | 2 | } |
49 | | |
50 | | GStringPiece::GStringPiece(GStringPiece x, size_type pos) |
51 | 0 | : ptr_(x.ptr_ + pos), length_(x.length_ - pos) { |
52 | 0 | DCHECK_LE(0, pos); |
53 | 0 | DCHECK_LE(pos, x.length_); |
54 | 0 | } |
55 | | |
56 | | GStringPiece::GStringPiece(GStringPiece x, size_type pos, size_type len) |
57 | 0 | : ptr_(x.ptr_ + pos), length_(min(len, x.length_ - pos)) { |
58 | 0 | DCHECK_LE(0, pos); |
59 | 0 | DCHECK_LE(pos, x.length_); |
60 | 0 | DCHECK_GE(len, 0); |
61 | 0 | } |
62 | | |
63 | 0 | void GStringPiece::CopyToString(string* target) const { |
64 | 0 | STLAssignToString(target, ptr_, length_); |
65 | 0 | } |
66 | | |
67 | 0 | void GStringPiece::AppendToString(string* target) const { |
68 | 0 | STLAppendToString(target, ptr_, length_); |
69 | 0 | } |
70 | | |
71 | 0 | GStringPiece::size_type GStringPiece::copy(char* buf, size_type n, size_type pos) const { |
72 | 0 | size_type ret = min(length_ - pos, n); |
73 | 0 | memcpy(buf, ptr_ + pos, ret); |
74 | 0 | return ret; |
75 | 0 | } |
76 | | |
77 | 2.30k | bool GStringPiece::contains(GStringPiece s) const { |
78 | 2.30k | return find(s, 0) != npos; |
79 | 2.30k | } |
80 | | |
81 | 1.24M | GStringPiece::size_type GStringPiece::find(GStringPiece s, size_type pos) const { |
82 | 1.24M | if (length_ <= 0 || pos > static_cast<size_type>(length_)1.23M ) { |
83 | 12.7k | if (length_ == 0 && pos == 0 && s.length_ == 0) return 00 ; |
84 | 12.7k | return npos; |
85 | 12.7k | } |
86 | 1.23M | const char *result = memmatch(ptr_ + pos, length_ - pos, |
87 | 1.23M | s.ptr_, s.length_); |
88 | 1.23M | return result ? result - ptr_679k : npos555k ; |
89 | 1.24M | } |
90 | | |
91 | 0 | GStringPiece::size_type GStringPiece::find(char c, size_type pos) const { |
92 | 0 | if (length_ <= 0 || pos >= static_cast<size_type>(length_)) { |
93 | 0 | return npos; |
94 | 0 | } |
95 | 0 | const char* result = static_cast<const char*>( |
96 | 0 | memchr(ptr_ + pos, c, length_ - pos)); |
97 | 0 | return result != nullptr ? result - ptr_ : npos; |
98 | 0 | } |
99 | | |
100 | 0 | GStringPiece::size_type GStringPiece::rfind(GStringPiece s, size_type pos) const { |
101 | 0 | if (length_ < s.length_) return npos; |
102 | 0 | const size_t ulen = length_; |
103 | 0 | if (s.length_ == 0) return min(ulen, pos); |
104 | | |
105 | 0 | const char* last = ptr_ + min(ulen - s.length_, pos) + s.length_; |
106 | 0 | const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); |
107 | 0 | return result != last ? result - ptr_ : npos; |
108 | 0 | } |
109 | | |
110 | | // Search range is [0..pos] inclusive. If pos == npos, search everything. |
111 | 0 | GStringPiece::size_type GStringPiece::rfind(char c, size_type pos) const { |
112 | | // Note: memrchr() is not available on Windows. |
113 | 0 | if (length_ <= 0) return npos; |
114 | 0 | for (size_t i = min(pos + 1, length_); i > 0;) { |
115 | 0 | --i; |
116 | 0 | if (ptr_[i] == c) { |
117 | 0 | return i; |
118 | 0 | } |
119 | 0 | } |
120 | 0 | return npos; |
121 | 0 | } |
122 | | |
123 | | // For each character in characters_wanted, sets the index corresponding |
124 | | // to the ASCII code of that character to 1 in table. This is used by |
125 | | // the find_.*_of methods below to tell whether or not a character is in |
126 | | // the lookup table in constant time. |
127 | | // The argument `table' must be an array that is large enough to hold all |
128 | | // the possible values of an unsigned char. Thus it should be be declared |
129 | | // as follows: |
130 | | // bool table[UCHAR_MAX + 1] |
131 | | static inline void BuildLookupTable(GStringPiece characters_wanted, |
132 | 0 | bool* table) { |
133 | 0 | const size_t length = characters_wanted.length(); |
134 | 0 | const char* const data = characters_wanted.data(); |
135 | 0 | for (size_t i = 0; i < length; ++i) { |
136 | 0 | table[static_cast<unsigned char>(data[i])] = true; |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | 0 | GStringPiece::size_type GStringPiece::find_first_of(GStringPiece s, size_type pos) const { |
141 | 0 | if (length_ <= 0 || s.length_ <= 0) { |
142 | 0 | return npos; |
143 | 0 | } |
144 | | // Avoid the cost of BuildLookupTable() for a single-character search. |
145 | 0 | if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); |
146 | | |
147 | 0 | bool lookup[UCHAR_MAX + 1] = { false }; |
148 | 0 | BuildLookupTable(s, lookup); |
149 | 0 | for (size_type i = pos; i < length_; ++i) { |
150 | 0 | if (lookup[static_cast<unsigned char>(ptr_[i])]) { |
151 | 0 | return i; |
152 | 0 | } |
153 | 0 | } |
154 | 0 | return npos; |
155 | 0 | } |
156 | | |
157 | 0 | GStringPiece::size_type GStringPiece::find_first_not_of(GStringPiece s, size_type pos) const { |
158 | 0 | if (length_ <= 0) return npos; |
159 | 0 | if (s.length_ <= 0) return 0; |
160 | | // Avoid the cost of BuildLookupTable() for a single-character search. |
161 | 0 | if (s.length_ == 1) return find_first_not_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 = pos; i < length_; ++i) { |
166 | 0 | if (!lookup[static_cast<unsigned char>(ptr_[i])]) { |
167 | 0 | return i; |
168 | 0 | } |
169 | 0 | } |
170 | 0 | return npos; |
171 | 0 | } |
172 | | |
173 | 0 | GStringPiece::size_type GStringPiece::find_first_not_of(char c, size_type pos) const { |
174 | 0 | if (length_ <= 0) return npos; |
175 | | |
176 | 0 | for (; pos < length_; ++pos) { |
177 | 0 | if (ptr_[pos] != c) { |
178 | 0 | return pos; |
179 | 0 | } |
180 | 0 | } |
181 | 0 | return npos; |
182 | 0 | } |
183 | | |
184 | 0 | GStringPiece::size_type GStringPiece::find_last_of(GStringPiece s, size_type pos) const { |
185 | 0 | if (length_ <= 0 || s.length_ <= 0) return npos; |
186 | | // Avoid the cost of BuildLookupTable() for a single-character search. |
187 | 0 | if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); |
188 | | |
189 | 0 | bool lookup[UCHAR_MAX + 1] = { false }; |
190 | 0 | BuildLookupTable(s, lookup); |
191 | 0 | for (size_t i = min(pos + 1, length_); i > 0;) { |
192 | 0 | --i; |
193 | 0 | if (lookup[static_cast<unsigned char>(ptr_[i])]) { |
194 | 0 | return i; |
195 | 0 | } |
196 | 0 | } |
197 | 0 | return npos; |
198 | 0 | } |
199 | | |
200 | 0 | GStringPiece::size_type GStringPiece::find_last_not_of(GStringPiece s, size_type pos) const { |
201 | 0 | if (length_ <= 0) return npos; |
202 | | |
203 | 0 | size_type i = min(pos + 1, length_); |
204 | 0 | if (s.length_ <= 0) return i - 1; |
205 | | |
206 | | // Avoid the cost of BuildLookupTable() for a single-character search. |
207 | 0 | if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); |
208 | | |
209 | 0 | bool lookup[UCHAR_MAX + 1] = { false }; |
210 | 0 | BuildLookupTable(s, lookup); |
211 | 0 | while (i > 0) { |
212 | 0 | --i; |
213 | 0 | if (!lookup[static_cast<unsigned char>(ptr_[i])]) { |
214 | 0 | return i; |
215 | 0 | } |
216 | 0 | } |
217 | 0 | return npos; |
218 | 0 | } |
219 | | |
220 | 0 | GStringPiece::size_type GStringPiece::find_last_not_of(char c, size_type pos) const { |
221 | 0 | if (length_ <= 0) return npos; |
222 | | |
223 | 0 | for (size_type i = min(pos + 1, length_); i > 0;) { |
224 | 0 | --i; |
225 | 0 | if (ptr_[i] != c) { |
226 | 0 | return i; |
227 | 0 | } |
228 | 0 | } |
229 | 0 | return npos; |
230 | 0 | } |
231 | | |
232 | 0 | GStringPiece GStringPiece::substr(size_type pos, size_type n) const { |
233 | 0 | if (pos > length_) pos = length_; |
234 | 0 | if (n > length_ - pos) n = length_ - pos; |
235 | 0 | return GStringPiece(ptr_ + pos, n); |
236 | 0 | } |
237 | | |
238 | | const GStringPiece::size_type GStringPiece::npos = size_type(-1); |
239 | | |
240 | 37.7M | size_t GStringPiece::hash() const { |
241 | 37.7M | return HashStringThoroughly(data(), size()); |
242 | 37.7M | } |