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