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.h with modifications michael@0: // michael@0: // A string-like object that points to a sized piece of memory. michael@0: // michael@0: // Functions or methods may use const StringPiece& parameters to accept either michael@0: // a "const char*" or a "string" value that will be implicitly converted to michael@0: // a StringPiece. The implicit conversion means that it is often appropriate michael@0: // to include this .h file in other files rather than forward-declaring michael@0: // StringPiece as would be appropriate for most other Google classes. michael@0: // michael@0: // Systematic usage of StringPiece is encouraged as it will reduce unnecessary michael@0: // conversions from "const char*" to "string" and back again. michael@0: // michael@0: michael@0: #ifndef BASE_STRING_PIECE_H_ michael@0: #define BASE_STRING_PIECE_H_ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: michael@0: class StringPiece { michael@0: public: michael@0: typedef size_t size_type; michael@0: michael@0: private: michael@0: const char* ptr_; michael@0: size_type length_; michael@0: michael@0: public: michael@0: // We provide non-explicit singleton constructors so users can pass michael@0: // in a "const char*" or a "string" wherever a "StringPiece" is michael@0: // expected. michael@0: StringPiece() : ptr_(NULL), length_(0) { } michael@0: StringPiece(const char* str) michael@0: : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { } michael@0: StringPiece(const std::string& str) michael@0: : ptr_(str.data()), length_(str.size()) { } michael@0: StringPiece(const char* offset, size_type len) michael@0: : ptr_(offset), length_(len) { } michael@0: michael@0: // data() may return a pointer to a buffer with embedded NULs, and the michael@0: // returned buffer may or may not be null terminated. Therefore it is michael@0: // typically a mistake to pass data() to a routine that expects a NUL michael@0: // terminated string. michael@0: const char* data() const { return ptr_; } michael@0: size_type size() const { return length_; } michael@0: size_type length() const { return length_; } michael@0: bool empty() const { return length_ == 0; } michael@0: michael@0: void clear() { ptr_ = NULL; length_ = 0; } michael@0: void set(const char* data, size_type len) { ptr_ = data; length_ = len; } michael@0: void set(const char* str) { michael@0: ptr_ = str; michael@0: length_ = str ? strlen(str) : 0; michael@0: } michael@0: void set(const void* data, size_type len) { michael@0: ptr_ = reinterpret_cast(data); michael@0: length_ = len; michael@0: } michael@0: michael@0: char operator[](size_type i) const { return ptr_[i]; } michael@0: michael@0: void remove_prefix(size_type n) { michael@0: ptr_ += n; michael@0: length_ -= n; michael@0: } michael@0: michael@0: void remove_suffix(size_type n) { michael@0: length_ -= n; michael@0: } michael@0: michael@0: int compare(const StringPiece& x) const { michael@0: int r = wordmemcmp(ptr_, x.ptr_, std::min(length_, x.length_)); michael@0: if (r == 0) { michael@0: if (length_ < x.length_) r = -1; michael@0: else if (length_ > x.length_) r = +1; michael@0: } michael@0: return r; michael@0: } michael@0: michael@0: std::string as_string() const { michael@0: // std::string doesn't like to take a NULL pointer even with a 0 size. michael@0: return std::string(!empty() ? data() : "", size()); michael@0: } michael@0: michael@0: void CopyToString(std::string* target) const; michael@0: void AppendToString(std::string* target) const; michael@0: michael@0: // Does "this" start with "x" michael@0: bool starts_with(const StringPiece& x) const { michael@0: return ((length_ >= x.length_) && michael@0: (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); michael@0: } michael@0: michael@0: // Does "this" end with "x" michael@0: bool ends_with(const StringPiece& x) const { michael@0: return ((length_ >= x.length_) && michael@0: (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); michael@0: } michael@0: michael@0: // standard STL container boilerplate michael@0: typedef char value_type; michael@0: typedef const char* pointer; michael@0: typedef const char& reference; michael@0: typedef const char& const_reference; michael@0: typedef ptrdiff_t difference_type; michael@0: static const size_type npos; michael@0: typedef const char* const_iterator; michael@0: typedef const char* iterator; michael@0: typedef std::reverse_iterator const_reverse_iterator; michael@0: typedef std::reverse_iterator reverse_iterator; michael@0: iterator begin() const { return ptr_; } michael@0: iterator end() const { return ptr_ + length_; } michael@0: const_reverse_iterator rbegin() const { michael@0: return const_reverse_iterator(ptr_ + length_); michael@0: } michael@0: const_reverse_iterator rend() const { michael@0: return const_reverse_iterator(ptr_); michael@0: } michael@0: michael@0: size_type max_size() const { return length_; } michael@0: size_type capacity() const { return length_; } michael@0: michael@0: size_type copy(char* buf, size_type n, size_type pos = 0) const; michael@0: michael@0: size_type find(const StringPiece& s, size_type pos = 0) const; michael@0: size_type find(char c, size_type pos = 0) const; michael@0: size_type rfind(const StringPiece& s, size_type pos = npos) const; michael@0: size_type rfind(char c, size_type pos = npos) const; michael@0: michael@0: size_type find_first_of(const StringPiece& s, size_type pos = 0) const; michael@0: size_type find_first_of(char c, size_type pos = 0) const { michael@0: return find(c, pos); michael@0: } michael@0: size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const; michael@0: size_type find_first_not_of(char c, size_type pos = 0) const; michael@0: size_type find_last_of(const StringPiece& s, size_type pos = npos) const; michael@0: size_type find_last_of(char c, size_type pos = npos) const { michael@0: return rfind(c, pos); michael@0: } michael@0: size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const; michael@0: size_type find_last_not_of(char c, size_type pos = npos) const; michael@0: michael@0: StringPiece substr(size_type pos, size_type n = npos) const; michael@0: michael@0: static int wordmemcmp(const char* p, const char* p2, size_type N) { michael@0: return memcmp(p, p2, N); michael@0: } michael@0: }; michael@0: michael@0: bool operator==(const ::StringPiece& x, const ::StringPiece& y); michael@0: michael@0: inline bool operator!=(const ::StringPiece& x, const ::StringPiece& y) { michael@0: return !(x == y); michael@0: } michael@0: michael@0: inline bool operator<(const ::StringPiece& x, const ::StringPiece& y) { michael@0: const int r = ::StringPiece::wordmemcmp(x.data(), y.data(), michael@0: std::min(x.size(), y.size())); michael@0: return ((r < 0) || ((r == 0) && (x.size() < y.size()))); michael@0: } michael@0: michael@0: inline bool operator>(const ::StringPiece& x, const ::StringPiece& y) { michael@0: return y < x; michael@0: } michael@0: michael@0: inline bool operator<=(const ::StringPiece& x, const ::StringPiece& y) { michael@0: return !(x > y); michael@0: } michael@0: michael@0: inline bool operator>=(const ::StringPiece& x, const ::StringPiece& y) { michael@0: return !(x < y); michael@0: } michael@0: michael@0: // allow StringPiece to be logged (needed for unit testing). michael@0: extern std::ostream& operator<<(std::ostream& o, const ::StringPiece& piece); michael@0: michael@0: #endif // BASE_STRING_PIECE_H_