string_piece.cc (5947B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // Copied from strings/stringpiece.cc with modifications 7 8 #include <algorithm> 9 #include <ostream> 10 11 #include "base/string_piece.h" 12 13 typedef StringPiece::size_type size_type; 14 15 std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { 16 o.write(piece.data(), static_cast<std::streamsize>(piece.size())); 17 return o; 18 } 19 20 bool operator==(const StringPiece& x, const StringPiece& y) { 21 if (x.size() != y.size()) return false; 22 23 return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; 24 } 25 26 void StringPiece::CopyToString(std::string* target) const { 27 target->assign(!empty() ? data() : "", size()); 28 } 29 30 void StringPiece::AppendToString(std::string* target) const { 31 if (!empty()) target->append(data(), size()); 32 } 33 34 size_type StringPiece::copy(char* buf, size_type n, size_type pos) const { 35 size_type ret = std::min(length_ - pos, n); 36 memcpy(buf, ptr_ + pos, ret); 37 return ret; 38 } 39 40 size_type StringPiece::find(const StringPiece& s, size_type pos) const { 41 if (pos > length_) return npos; 42 43 const char* result = 44 std::search(ptr_ + pos, ptr_ + length_, s.ptr_, s.ptr_ + s.length_); 45 const size_type xpos = result - ptr_; 46 return xpos + s.length_ <= length_ ? xpos : npos; 47 } 48 49 size_type StringPiece::find(char c, size_type pos) const { 50 if (pos >= length_) return npos; 51 52 const char* result = std::find(ptr_ + pos, ptr_ + length_, c); 53 return result != ptr_ + length_ ? result - ptr_ : npos; 54 } 55 56 size_type StringPiece::rfind(const StringPiece& s, size_type pos) const { 57 if (length_ < s.length_) return npos; 58 59 if (s.empty()) return std::min(length_, pos); 60 61 const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_; 62 const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); 63 return result != last ? result - ptr_ : npos; 64 } 65 66 size_type StringPiece::rfind(char c, size_type pos) const { 67 if (length_ == 0) return npos; 68 69 for (size_type i = std::min(pos, length_ - 1);; --i) { 70 if (ptr_[i] == c) return i; 71 if (i == 0) break; 72 } 73 return npos; 74 } 75 76 // For each character in characters_wanted, sets the index corresponding 77 // to the ASCII code of that character to 1 in table. This is used by 78 // the find_.*_of methods below to tell whether or not a character is in 79 // the lookup table in constant time. 80 // The argument `table' must be an array that is large enough to hold all 81 // the possible values of an unsigned char. Thus it should be be declared 82 // as follows: 83 // bool table[UCHAR_MAX + 1] 84 static inline void BuildLookupTable(const StringPiece& characters_wanted, 85 bool* table) { 86 const size_type length = characters_wanted.length(); 87 const char* const data = characters_wanted.data(); 88 for (size_type i = 0; i < length; ++i) { 89 table[static_cast<unsigned char>(data[i])] = true; 90 } 91 } 92 93 size_type StringPiece::find_first_of(const StringPiece& s, 94 size_type pos) const { 95 if (length_ == 0 || s.length_ == 0) return npos; 96 97 // Avoid the cost of BuildLookupTable() for a single-character search. 98 if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); 99 100 bool lookup[UCHAR_MAX + 1] = {false}; 101 BuildLookupTable(s, lookup); 102 for (size_type i = pos; i < length_; ++i) { 103 if (lookup[static_cast<unsigned char>(ptr_[i])]) { 104 return i; 105 } 106 } 107 return npos; 108 } 109 110 size_type StringPiece::find_first_not_of(const StringPiece& s, 111 size_type pos) const { 112 if (length_ == 0) return npos; 113 114 if (s.length_ == 0) return 0; 115 116 // Avoid the cost of BuildLookupTable() for a single-character search. 117 if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos); 118 119 bool lookup[UCHAR_MAX + 1] = {false}; 120 BuildLookupTable(s, lookup); 121 for (size_type i = pos; i < length_; ++i) { 122 if (!lookup[static_cast<unsigned char>(ptr_[i])]) { 123 return i; 124 } 125 } 126 return npos; 127 } 128 129 size_type StringPiece::find_first_not_of(char c, size_type pos) const { 130 if (length_ == 0) return npos; 131 132 for (; pos < length_; ++pos) { 133 if (ptr_[pos] != c) { 134 return pos; 135 } 136 } 137 return npos; 138 } 139 140 size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const { 141 if (length_ == 0 || s.length_ == 0) return npos; 142 143 // Avoid the cost of BuildLookupTable() for a single-character search. 144 if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); 145 146 bool lookup[UCHAR_MAX + 1] = {false}; 147 BuildLookupTable(s, lookup); 148 for (size_type i = std::min(pos, length_ - 1);; --i) { 149 if (lookup[static_cast<unsigned char>(ptr_[i])]) return i; 150 if (i == 0) break; 151 } 152 return npos; 153 } 154 155 size_type StringPiece::find_last_not_of(const StringPiece& s, 156 size_type pos) const { 157 if (length_ == 0) return npos; 158 159 size_type i = std::min(pos, length_ - 1); 160 if (s.length_ == 0) return i; 161 162 // Avoid the cost of BuildLookupTable() for a single-character search. 163 if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); 164 165 bool lookup[UCHAR_MAX + 1] = {false}; 166 BuildLookupTable(s, lookup); 167 for (;; --i) { 168 if (!lookup[static_cast<unsigned char>(ptr_[i])]) return i; 169 if (i == 0) break; 170 } 171 return npos; 172 } 173 174 size_type StringPiece::find_last_not_of(char c, size_type pos) const { 175 if (length_ == 0) return npos; 176 177 for (size_type i = std::min(pos, length_ - 1);; --i) { 178 if (ptr_[i] != c) return i; 179 if (i == 0) break; 180 } 181 return npos; 182 } 183 184 StringPiece StringPiece::substr(size_type pos, size_type n) const { 185 if (pos > length_) pos = length_; 186 if (n > length_ - pos) n = length_ - pos; 187 return StringPiece(ptr_ + pos, n); 188 } 189 190 const StringPiece::size_type StringPiece::npos = size_type(-1);