jpayne@69: // Copyright (c) 2005, Google Inc. jpayne@69: // All rights reserved. jpayne@69: // jpayne@69: // Redistribution and use in source and binary forms, with or without jpayne@69: // modification, are permitted provided that the following conditions are jpayne@69: // met: jpayne@69: // jpayne@69: // * Redistributions of source code must retain the above copyright jpayne@69: // notice, this list of conditions and the following disclaimer. jpayne@69: // * Redistributions in binary form must reproduce the above jpayne@69: // copyright notice, this list of conditions and the following disclaimer jpayne@69: // in the documentation and/or other materials provided with the jpayne@69: // distribution. jpayne@69: // * Neither the name of Google Inc. nor the names of its jpayne@69: // contributors may be used to endorse or promote products derived from jpayne@69: // this software without specific prior written permission. jpayne@69: // jpayne@69: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS jpayne@69: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT jpayne@69: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR jpayne@69: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT jpayne@69: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, jpayne@69: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT jpayne@69: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, jpayne@69: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY jpayne@69: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT jpayne@69: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE jpayne@69: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jpayne@69: // jpayne@69: // Author: Sanjay Ghemawat jpayne@69: // jpayne@69: // A string like object that points into another piece of memory. jpayne@69: // Useful for providing an interface that allows clients to easily jpayne@69: // pass in either a "const char*" or a "string". jpayne@69: // jpayne@69: // Arghh! I wish C++ literals were automatically of type "string". jpayne@69: jpayne@69: #ifndef _PCRE_STRINGPIECE_H jpayne@69: #define _PCRE_STRINGPIECE_H jpayne@69: jpayne@69: #include jpayne@69: #include jpayne@69: #include // for ostream forward-declaration jpayne@69: jpayne@69: #if 0 jpayne@69: #define HAVE_TYPE_TRAITS jpayne@69: #include jpayne@69: #elif 0 jpayne@69: #define HAVE_TYPE_TRAITS jpayne@69: #include jpayne@69: #endif jpayne@69: jpayne@69: #include jpayne@69: jpayne@69: namespace pcrecpp { jpayne@69: jpayne@69: using std::memcmp; jpayne@69: using std::strlen; jpayne@69: using std::string; jpayne@69: jpayne@69: class PCRECPP_EXP_DEFN StringPiece { jpayne@69: private: jpayne@69: const char* ptr_; jpayne@69: int length_; jpayne@69: jpayne@69: public: jpayne@69: // We provide non-explicit singleton constructors so users can pass jpayne@69: // in a "const char*" or a "string" wherever a "StringPiece" is jpayne@69: // expected. jpayne@69: StringPiece() jpayne@69: : ptr_(NULL), length_(0) { } jpayne@69: StringPiece(const char* str) jpayne@69: : ptr_(str), length_(static_cast(strlen(ptr_))) { } jpayne@69: StringPiece(const unsigned char* str) jpayne@69: : ptr_(reinterpret_cast(str)), jpayne@69: length_(static_cast(strlen(ptr_))) { } jpayne@69: StringPiece(const string& str) jpayne@69: : ptr_(str.data()), length_(static_cast(str.size())) { } jpayne@69: StringPiece(const char* offset, int len) jpayne@69: : ptr_(offset), length_(len) { } jpayne@69: jpayne@69: // data() may return a pointer to a buffer with embedded NULs, and the jpayne@69: // returned buffer may or may not be null terminated. Therefore it is jpayne@69: // typically a mistake to pass data() to a routine that expects a NUL jpayne@69: // terminated string. Use "as_string().c_str()" if you really need to do jpayne@69: // this. Or better yet, change your routine so it does not rely on NUL jpayne@69: // termination. jpayne@69: const char* data() const { return ptr_; } jpayne@69: int size() const { return length_; } jpayne@69: bool empty() const { return length_ == 0; } jpayne@69: jpayne@69: void clear() { ptr_ = NULL; length_ = 0; } jpayne@69: void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; } jpayne@69: void set(const char* str) { jpayne@69: ptr_ = str; jpayne@69: length_ = static_cast(strlen(str)); jpayne@69: } jpayne@69: void set(const void* buffer, int len) { jpayne@69: ptr_ = reinterpret_cast(buffer); jpayne@69: length_ = len; jpayne@69: } jpayne@69: jpayne@69: char operator[](int i) const { return ptr_[i]; } jpayne@69: jpayne@69: void remove_prefix(int n) { jpayne@69: ptr_ += n; jpayne@69: length_ -= n; jpayne@69: } jpayne@69: jpayne@69: void remove_suffix(int n) { jpayne@69: length_ -= n; jpayne@69: } jpayne@69: jpayne@69: bool operator==(const StringPiece& x) const { jpayne@69: return ((length_ == x.length_) && jpayne@69: (memcmp(ptr_, x.ptr_, length_) == 0)); jpayne@69: } jpayne@69: bool operator!=(const StringPiece& x) const { jpayne@69: return !(*this == x); jpayne@69: } jpayne@69: jpayne@69: #define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp) \ jpayne@69: bool operator cmp (const StringPiece& x) const { \ jpayne@69: int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \ jpayne@69: return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_))); \ jpayne@69: } jpayne@69: STRINGPIECE_BINARY_PREDICATE(<, <); jpayne@69: STRINGPIECE_BINARY_PREDICATE(<=, <); jpayne@69: STRINGPIECE_BINARY_PREDICATE(>=, >); jpayne@69: STRINGPIECE_BINARY_PREDICATE(>, >); jpayne@69: #undef STRINGPIECE_BINARY_PREDICATE jpayne@69: jpayne@69: int compare(const StringPiece& x) const { jpayne@69: int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); jpayne@69: if (r == 0) { jpayne@69: if (length_ < x.length_) r = -1; jpayne@69: else if (length_ > x.length_) r = +1; jpayne@69: } jpayne@69: return r; jpayne@69: } jpayne@69: jpayne@69: string as_string() const { jpayne@69: return string(data(), size()); jpayne@69: } jpayne@69: jpayne@69: void CopyToString(string* target) const { jpayne@69: target->assign(ptr_, length_); jpayne@69: } jpayne@69: jpayne@69: // Does "this" start with "x" jpayne@69: bool starts_with(const StringPiece& x) const { jpayne@69: return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0)); jpayne@69: } jpayne@69: }; jpayne@69: jpayne@69: } // namespace pcrecpp jpayne@69: jpayne@69: // ------------------------------------------------------------------ jpayne@69: // Functions used to create STL containers that use StringPiece jpayne@69: // Remember that a StringPiece's lifetime had better be less than jpayne@69: // that of the underlying string or char*. If it is not, then you jpayne@69: // cannot safely store a StringPiece into an STL container jpayne@69: // ------------------------------------------------------------------ jpayne@69: jpayne@69: #ifdef HAVE_TYPE_TRAITS jpayne@69: // This makes vector really fast for some STL implementations jpayne@69: template<> struct __type_traits { jpayne@69: typedef __true_type has_trivial_default_constructor; jpayne@69: typedef __true_type has_trivial_copy_constructor; jpayne@69: typedef __true_type has_trivial_assignment_operator; jpayne@69: typedef __true_type has_trivial_destructor; jpayne@69: typedef __true_type is_POD_type; jpayne@69: }; jpayne@69: #endif jpayne@69: jpayne@69: // allow StringPiece to be logged jpayne@69: PCRECPP_EXP_DECL std::ostream& operator<<(std::ostream& o, jpayne@69: const pcrecpp::StringPiece& piece); jpayne@69: jpayne@69: #endif /* _PCRE_STRINGPIECE_H */