michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // Copied from strings/stringpiece.cc with modifications michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/string_piece.h" michael@0: michael@0: typedef StringPiece::size_type size_type; michael@0: michael@0: std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { michael@0: o.write(piece.data(), static_cast(piece.size())); michael@0: return o; michael@0: } michael@0: michael@0: bool operator==(const StringPiece& x, const StringPiece& y) { michael@0: if (x.size() != y.size()) michael@0: return false; michael@0: michael@0: return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; michael@0: } michael@0: michael@0: void StringPiece::CopyToString(std::string* target) const { michael@0: target->assign(!empty() ? data() : "", size()); michael@0: } michael@0: michael@0: void StringPiece::AppendToString(std::string* target) const { michael@0: if (!empty()) michael@0: target->append(data(), size()); michael@0: } michael@0: michael@0: size_type StringPiece::copy(char* buf, size_type n, size_type pos) const { michael@0: size_type ret = std::min(length_ - pos, n); michael@0: memcpy(buf, ptr_ + pos, ret); michael@0: return ret; michael@0: } michael@0: michael@0: size_type StringPiece::find(const StringPiece& s, size_type pos) const { michael@0: if (pos > length_) michael@0: return npos; michael@0: michael@0: const char* result = std::search(ptr_ + pos, ptr_ + length_, michael@0: s.ptr_, s.ptr_ + s.length_); michael@0: const size_type xpos = result - ptr_; michael@0: return xpos + s.length_ <= length_ ? xpos : npos; michael@0: } michael@0: michael@0: size_type StringPiece::find(char c, size_type pos) const { michael@0: if (pos >= length_) michael@0: return npos; michael@0: michael@0: const char* result = std::find(ptr_ + pos, ptr_ + length_, c); michael@0: return result != ptr_ + length_ ? result - ptr_ : npos; michael@0: } michael@0: michael@0: size_type StringPiece::rfind(const StringPiece& s, size_type pos) const { michael@0: if (length_ < s.length_) michael@0: return npos; michael@0: michael@0: if (s.empty()) michael@0: return std::min(length_, pos); michael@0: michael@0: const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_; michael@0: const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); michael@0: return result != last ? result - ptr_ : npos; michael@0: } michael@0: michael@0: size_type StringPiece::rfind(char c, size_type pos) const { michael@0: if (length_ == 0) michael@0: return npos; michael@0: michael@0: for (size_type i = std::min(pos, length_ - 1); ; --i) { michael@0: if (ptr_[i] == c) michael@0: return i; michael@0: if (i == 0) michael@0: break; michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: // For each character in characters_wanted, sets the index corresponding michael@0: // to the ASCII code of that character to 1 in table. This is used by michael@0: // the find_.*_of methods below to tell whether or not a character is in michael@0: // the lookup table in constant time. michael@0: // The argument `table' must be an array that is large enough to hold all michael@0: // the possible values of an unsigned char. Thus it should be be declared michael@0: // as follows: michael@0: // bool table[UCHAR_MAX + 1] michael@0: static inline void BuildLookupTable(const StringPiece& characters_wanted, michael@0: bool* table) { michael@0: const size_type length = characters_wanted.length(); michael@0: const char* const data = characters_wanted.data(); michael@0: for (size_type i = 0; i < length; ++i) { michael@0: table[static_cast(data[i])] = true; michael@0: } michael@0: } michael@0: michael@0: size_type StringPiece::find_first_of(const StringPiece& s, michael@0: size_type pos) const { michael@0: if (length_ == 0 || s.length_ == 0) michael@0: return npos; michael@0: michael@0: // Avoid the cost of BuildLookupTable() for a single-character search. michael@0: if (s.length_ == 1) michael@0: return find_first_of(s.ptr_[0], pos); michael@0: michael@0: bool lookup[UCHAR_MAX + 1] = { false }; michael@0: BuildLookupTable(s, lookup); michael@0: for (size_type i = pos; i < length_; ++i) { michael@0: if (lookup[static_cast(ptr_[i])]) { michael@0: return i; michael@0: } michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: size_type StringPiece::find_first_not_of(const StringPiece& s, michael@0: size_type pos) const { michael@0: if (length_ == 0) michael@0: return npos; michael@0: michael@0: if (s.length_ == 0) michael@0: return 0; michael@0: michael@0: // Avoid the cost of BuildLookupTable() for a single-character search. michael@0: if (s.length_ == 1) michael@0: return find_first_not_of(s.ptr_[0], pos); michael@0: michael@0: bool lookup[UCHAR_MAX + 1] = { false }; michael@0: BuildLookupTable(s, lookup); michael@0: for (size_type i = pos; i < length_; ++i) { michael@0: if (!lookup[static_cast(ptr_[i])]) { michael@0: return i; michael@0: } michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: size_type StringPiece::find_first_not_of(char c, size_type pos) const { michael@0: if (length_ == 0) michael@0: return npos; michael@0: michael@0: for (; pos < length_; ++pos) { michael@0: if (ptr_[pos] != c) { michael@0: return pos; michael@0: } michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const { michael@0: if (length_ == 0 || s.length_ == 0) michael@0: return npos; michael@0: michael@0: // Avoid the cost of BuildLookupTable() for a single-character search. michael@0: if (s.length_ == 1) michael@0: return find_last_of(s.ptr_[0], pos); michael@0: michael@0: bool lookup[UCHAR_MAX + 1] = { false }; michael@0: BuildLookupTable(s, lookup); michael@0: for (size_type i = std::min(pos, length_ - 1); ; --i) { michael@0: if (lookup[static_cast(ptr_[i])]) michael@0: return i; michael@0: if (i == 0) michael@0: break; michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: size_type StringPiece::find_last_not_of(const StringPiece& s, michael@0: size_type pos) const { michael@0: if (length_ == 0) michael@0: return npos; michael@0: michael@0: size_type i = std::min(pos, length_ - 1); michael@0: if (s.length_ == 0) michael@0: return i; michael@0: michael@0: // Avoid the cost of BuildLookupTable() for a single-character search. michael@0: if (s.length_ == 1) michael@0: return find_last_not_of(s.ptr_[0], pos); michael@0: michael@0: bool lookup[UCHAR_MAX + 1] = { false }; michael@0: BuildLookupTable(s, lookup); michael@0: for (; ; --i) { michael@0: if (!lookup[static_cast(ptr_[i])]) michael@0: return i; michael@0: if (i == 0) michael@0: break; michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: size_type StringPiece::find_last_not_of(char c, size_type pos) const { michael@0: if (length_ == 0) michael@0: return npos; michael@0: michael@0: for (size_type i = std::min(pos, length_ - 1); ; --i) { michael@0: if (ptr_[i] != c) michael@0: return i; michael@0: if (i == 0) michael@0: break; michael@0: } michael@0: return npos; michael@0: } michael@0: michael@0: StringPiece StringPiece::substr(size_type pos, size_type n) const { michael@0: if (pos > length_) pos = length_; michael@0: if (n > length_ - pos) n = length_ - pos; michael@0: return StringPiece(ptr_ + pos, n); michael@0: } michael@0: michael@0: const StringPiece::size_type StringPiece::npos = size_type(-1);