15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2001-2010 The RE2 Authors. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// license that can be found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A string-like object that points to a sized piece of memory. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions or methods may use const StringPiece& parameters to accept either 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a "const char*" or a "string" value that will be implicitly converted to 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a StringPiece. The implicit conversion means that it is often appropriate 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to include this .h file in other files rather than forward-declaring 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StringPiece as would be appropriate for most other Google classes. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Systematic usage of StringPiece is encouraged as it will reduce unnecessary 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// conversions from "const char*" to "string" and back again. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arghh! I wish C++ literals were "string". 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef STRINGS_STRINGPIECE_H__ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRINGS_STRINGPIECE_H__ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstddef> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iosfwd> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace re2 { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StringPiece { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* ptr_; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length_; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We provide non-explicit singleton constructors so users can pass 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a "const char*" or a "string" wherever a "StringPiece" is 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expected. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece() : ptr_(NULL), length_(0) { } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece(const char* str) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ptr_(str), length_((str == NULL) ? 0 : static_cast<int>(strlen(str))) { } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece(const std::string& str) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ptr_(str.data()), length_(static_cast<int>(str.size())) { } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data() may return a pointer to a buffer with embedded NULs, and the 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned buffer may or may not be null terminated. Therefore it is 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typically a mistake to pass data() to a routine that expects a NUL 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // terminated string. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data() const { return ptr_; } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size() const { return length_; } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length() const { return length_; } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool empty() const { return length_ == 0; } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void clear() { ptr_ = NULL; length_ = 0; } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set(const char* data, int len) { ptr_ = data; length_ = len; } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set(const char* str) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr_ = str; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (str != NULL) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_ = static_cast<int>(strlen(str)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_ = 0; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set(const void* data, int len) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr_ = reinterpret_cast<const char*>(data); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_ = len; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char operator[](int i) const { return ptr_[i]; } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void remove_prefix(int n) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr_ += n; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_ -= n; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void remove_suffix(int n) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_ -= n; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int compare(const StringPiece& x) const { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = memcmp(ptr_, x.ptr_, std::min(length_, x.length_)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r == 0) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length_ < x.length_) r = -1; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (length_ > x.length_) r = +1; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string as_string() const { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(data(), size()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also define ToString() here, since many other string-like 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interfaces name the routine that converts to a C++ string 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "ToString", and it's confusing to have the method that does that 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for a StringPiece be called "as_string()". We also leave the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "as_string()" method defined here for existing code. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string ToString() const { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(data(), size()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CopyToString(std::string* target) const; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AppendToString(std::string* target) const; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does "this" start with "x" 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool starts_with(const StringPiece& x) const { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((length_ >= x.length_) && 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (memcmp(ptr_, x.ptr_, x.length_) == 0)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does "this" end with "x" 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ends_with(const StringPiece& x) const { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((length_ >= x.length_) && 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // standard STL container boilerplate 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef char value_type; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const char* pointer; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const char& reference; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const char& const_reference; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef size_t size_type; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ptrdiff_t difference_type; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_type npos; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const char* const_iterator; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const char* iterator; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::reverse_iterator<iterator> reverse_iterator; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator begin() const { return ptr_; } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator end() const { return ptr_ + length_; } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_reverse_iterator rbegin() const { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_reverse_iterator(ptr_ + length_); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_reverse_iterator rend() const { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_reverse_iterator(ptr_); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // STLS says return size_type, but Google says return int 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_size() const { return length_; } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int capacity() const { return length_; } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int copy(char* buf, size_type n, size_type pos = 0) const; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int find(const StringPiece& s, size_type pos = 0) const; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int find(char c, size_type pos = 0) const; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rfind(const StringPiece& s, size_type pos = npos) const; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rfind(char c, size_type pos = npos) const; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece substr(size_type pos, size_type n = npos) const; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool _equal(const StringPiece&, const StringPiece&); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator==(const StringPiece& x, const StringPiece& y) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringPiece::_equal(x, y); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator!=(const StringPiece& x, const StringPiece& y) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(x == y); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator<(const StringPiece& x, const StringPiece& y) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int r = memcmp(x.data(), y.data(), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(x.size(), y.size())); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator>(const StringPiece& x, const StringPiece& y) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return y < x; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator<=(const StringPiece& x, const StringPiece& y) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(x > y); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator>=(const StringPiece& x, const StringPiece& y) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(x < y); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace re2 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allow StringPiece to be logged 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern std::ostream& operator<<(std::ostream& o, const re2::StringPiece& piece); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // STRINGS_STRINGPIECE_H__ 186