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