1 // Copyright 2015 Google Inc. All rights reserved 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 16 // Use of this source code is governed by a BSD-style license that can be 17 // found in the LICENSE file. 18 // Copied from strings/stringpiece.cc with modifications 19 20 // +build ignore 21 22 #include <ctype.h> 23 #include <limits.h> 24 #include <stdint.h> 25 26 #include <algorithm> 27 #include <ostream> 28 29 #include "string_piece.h" 30 31 typedef StringPiece::size_type size_type; 32 33 bool operator==(const StringPiece& x, const StringPiece& y) { 34 if (x.size() != y.size()) 35 return false; 36 size_t len = x.size(); 37 if (len >= sizeof(uint64_t)) { 38 len -= sizeof(uint64_t); 39 uint64_t xt = *reinterpret_cast<const uint64_t*>(x.data() + len); 40 uint64_t yt = *reinterpret_cast<const uint64_t*>(y.data() + len); 41 if (xt != yt) 42 return false; 43 } 44 return StringPiece::wordmemcmp(x.data(), y.data(), len) == 0; 45 } 46 47 void StringPiece::CopyToString(std::string* target) const { 48 target->assign(!empty() ? data() : "", size()); 49 } 50 51 void StringPiece::AppendToString(std::string* target) const { 52 if (!empty()) 53 target->append(data(), size()); 54 } 55 56 size_type StringPiece::copy(char* buf, size_type n, size_type pos) const { 57 size_type ret = std::min(length_ - pos, n); 58 memcpy(buf, ptr_ + pos, ret); 59 return ret; 60 } 61 62 size_type StringPiece::find(const StringPiece& s, size_type pos) const { 63 if (pos > length_) 64 return npos; 65 66 const char* result = std::search(ptr_ + pos, ptr_ + length_, 67 s.ptr_, s.ptr_ + s.length_); 68 const size_type xpos = result - ptr_; 69 return xpos + s.length_ <= length_ ? xpos : npos; 70 } 71 72 size_type StringPiece::find(char c, size_type pos) const { 73 if (pos >= length_) 74 return npos; 75 76 const char* result = std::find(ptr_ + pos, ptr_ + length_, c); 77 return result != ptr_ + length_ ? static_cast<size_t>(result - ptr_) : npos; 78 } 79 80 size_type StringPiece::rfind(const StringPiece& s, size_type pos) const { 81 if (length_ < s.length_) 82 return npos; 83 84 if (s.empty()) 85 return std::min(length_, pos); 86 87 const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_; 88 const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); 89 return result != last ? static_cast<size_t>(result - ptr_) : npos; 90 } 91 92 size_type StringPiece::rfind(char c, size_type pos) const { 93 if (length_ == 0) 94 return npos; 95 96 for (size_type i = std::min(pos, length_ - 1); ; --i) { 97 if (ptr_[i] == c) 98 return i; 99 if (i == 0) 100 break; 101 } 102 return npos; 103 } 104 105 // For each character in characters_wanted, sets the index corresponding 106 // to the ASCII code of that character to 1 in table. This is used by 107 // the find_.*_of methods below to tell whether or not a character is in 108 // the lookup table in constant time. 109 // The argument `table' must be an array that is large enough to hold all 110 // the possible values of an unsigned char. Thus it should be be declared 111 // as follows: 112 // bool table[UCHAR_MAX + 1] 113 static inline void BuildLookupTable(const StringPiece& characters_wanted, 114 bool* table) { 115 const size_type length = characters_wanted.length(); 116 const char* const data = characters_wanted.data(); 117 for (size_type i = 0; i < length; ++i) { 118 table[static_cast<unsigned char>(data[i])] = true; 119 } 120 } 121 122 size_type StringPiece::find_first_of(const StringPiece& s, 123 size_type pos) const { 124 if (length_ == 0 || s.length_ == 0) 125 return npos; 126 127 // Avoid the cost of BuildLookupTable() for a single-character search. 128 if (s.length_ == 1) 129 return find_first_of(s.ptr_[0], pos); 130 131 bool lookup[UCHAR_MAX + 1] = { false }; 132 BuildLookupTable(s, lookup); 133 for (size_type i = pos; i < length_; ++i) { 134 if (lookup[static_cast<unsigned char>(ptr_[i])]) { 135 return i; 136 } 137 } 138 return npos; 139 } 140 141 size_type StringPiece::find_first_not_of(const StringPiece& s, 142 size_type pos) const { 143 if (length_ == 0) 144 return npos; 145 146 if (s.length_ == 0) 147 return 0; 148 149 // Avoid the cost of BuildLookupTable() for a single-character search. 150 if (s.length_ == 1) 151 return find_first_not_of(s.ptr_[0], pos); 152 153 bool lookup[UCHAR_MAX + 1] = { false }; 154 BuildLookupTable(s, lookup); 155 for (size_type i = pos; i < length_; ++i) { 156 if (!lookup[static_cast<unsigned char>(ptr_[i])]) { 157 return i; 158 } 159 } 160 return npos; 161 } 162 163 size_type StringPiece::find_first_not_of(char c, size_type pos) const { 164 if (length_ == 0) 165 return npos; 166 167 for (; pos < length_; ++pos) { 168 if (ptr_[pos] != c) { 169 return pos; 170 } 171 } 172 return npos; 173 } 174 175 size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const { 176 if (length_ == 0 || s.length_ == 0) 177 return npos; 178 179 // Avoid the cost of BuildLookupTable() for a single-character search. 180 if (s.length_ == 1) 181 return find_last_of(s.ptr_[0], pos); 182 183 bool lookup[UCHAR_MAX + 1] = { false }; 184 BuildLookupTable(s, lookup); 185 for (size_type i = std::min(pos, length_ - 1); ; --i) { 186 if (lookup[static_cast<unsigned char>(ptr_[i])]) 187 return i; 188 if (i == 0) 189 break; 190 } 191 return npos; 192 } 193 194 size_type StringPiece::find_last_not_of(const StringPiece& s, 195 size_type pos) const { 196 if (length_ == 0) 197 return npos; 198 199 size_type i = std::min(pos, length_ - 1); 200 if (s.length_ == 0) 201 return i; 202 203 // Avoid the cost of BuildLookupTable() for a single-character search. 204 if (s.length_ == 1) 205 return find_last_not_of(s.ptr_[0], pos); 206 207 bool lookup[UCHAR_MAX + 1] = { false }; 208 BuildLookupTable(s, lookup); 209 for (; ; --i) { 210 if (!lookup[static_cast<unsigned char>(ptr_[i])]) 211 return i; 212 if (i == 0) 213 break; 214 } 215 return npos; 216 } 217 218 size_type StringPiece::find_last_not_of(char c, size_type pos) const { 219 if (length_ == 0) 220 return npos; 221 222 for (size_type i = std::min(pos, length_ - 1); ; --i) { 223 if (ptr_[i] != c) 224 return i; 225 if (i == 0) 226 break; 227 } 228 return npos; 229 } 230 231 StringPiece StringPiece::substr(size_type pos, size_type n) const { 232 if (pos > length_) pos = length_; 233 if (n > length_ - pos) n = length_ - pos; 234 return StringPiece(ptr_ + pos, n); 235 } 236 237 const StringPiece::size_type StringPiece::npos = size_type(-1); 238