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