#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <iosfwd>
#include <limits>
#include <string>
#if defined(__cpp_lib_string_view)
#include <string_view>
#endif
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace stringpiece_internal {
class PROTOBUF_EXPORT StringPiece {
public:
using traits_type = std::char_traits<char>;
using value_type = char;
using pointer = char*;
using const_pointer = const char*;
using reference = char&;
using const_reference = const char&;
using const_iterator = const char*;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
using size_type = size_t;
using difference_type = std::ptrdiff_t;
private:
const char* ptr_;
size_type length_;
static constexpr size_type kMaxSize =
(std::numeric_limits<difference_type>::max)();
static size_type CheckSize(size_type size) {
#if !defined(NDEBUG) || defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
if (PROTOBUF_PREDICT_FALSE(size > kMaxSize)) {
LogFatalSizeTooBig(size, "string length exceeds max size");
}
#endif
return size;
}
static void LogFatalSizeTooBig(size_type size, const char* details);
public:
StringPiece() : ptr_(nullptr), length_(0) {}
StringPiece(const char* str) : ptr_(str), length_(0) {
if (str != nullptr) {
length_ = CheckSize(strlen(str));
}
}
template <class Allocator>
StringPiece( const std::basic_string<char, std::char_traits<char>, Allocator>& str)
: ptr_(str.data()), length_(0) {
length_ = CheckSize(str.size());
}
#if defined(__cpp_lib_string_view)
StringPiece( std::string_view str)
: ptr_(str.data()), length_(0) {
length_ = CheckSize(str.size());
}
#endif
StringPiece(const char* offset, size_type len)
: ptr_(offset), length_(CheckSize(len)) {}
const_pointer data() const { return ptr_; }
size_type size() const { return length_; }
size_type length() const { return length_; }
bool empty() const { return length_ == 0; }
char operator[](size_type i) const {
assert(i < length_);
return ptr_[i];
}
void remove_prefix(size_type n) {
assert(length_ >= n);
ptr_ += n;
length_ -= n;
}
void remove_suffix(size_type n) {
assert(length_ >= n);
length_ -= n;
}
int compare(StringPiece x) const {
size_type min_size = length_ < x.length_ ? length_ : x.length_;
int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
if (r < 0) return -1;
if (r > 0) return 1;
if (length_ < x.length_) return -1;
if (length_ > x.length_) return 1;
return 0;
}
std::string as_string() const { return ToString(); }
std::string ToString() const {
if (ptr_ == nullptr) return "";
return std::string(data(), static_cast<size_type>(size()));
}
explicit operator std::string() const { return ToString(); }
void CopyToString(std::string* target) const;
void AppendToString(std::string* target) const;
bool starts_with(StringPiece x) const {
return (length_ >= x.length_) &&
(memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0);
}
bool ends_with(StringPiece x) const {
return ((length_ >= x.length_) &&
(memcmp(ptr_ + (length_-x.length_), x.ptr_,
static_cast<size_t>(x.length_)) == 0));
}
bool Consume(StringPiece x);
bool ConsumeFromEnd(StringPiece x);
static const size_type npos;
const_iterator begin() const { return ptr_; }
const_iterator end() const { return ptr_ + length_; }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(ptr_ + length_);
}
const_reverse_iterator rend() const {
return const_reverse_iterator(ptr_);
}
size_type max_size() const { return length_; }
size_type capacity() const { return length_; }
size_type copy(char* buf, size_type n, size_type pos = 0) const;
bool contains(StringPiece s) const;
size_type find(StringPiece s, size_type pos = 0) const;
size_type find(char c, size_type pos = 0) const;
size_type rfind(StringPiece s, size_type pos = npos) const;
size_type rfind(char c, size_type pos = npos) const;
size_type find_first_of(StringPiece s, size_type pos = 0) const;
size_type find_first_of(char c, size_type pos = 0) const {
return find(c, pos);
}
size_type find_first_not_of(StringPiece s, size_type pos = 0) const;
size_type find_first_not_of(char c, size_type pos = 0) const;
size_type find_last_of(StringPiece s, size_type pos = npos) const;
size_type find_last_of(char c, size_type pos = npos) const {
return rfind(c, pos);
}
size_type find_last_not_of(StringPiece s, size_type pos = npos) const;
size_type find_last_not_of(char c, size_type pos = npos) const;
StringPiece substr(size_type pos, size_type n = npos) const;
};
inline bool operator==(StringPiece x, StringPiece y) {
StringPiece::size_type len = x.size();
if (len != y.size()) {
return false;
}
return x.data() == y.data() || len <= 0 ||
memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0;
}
inline bool operator!=(StringPiece x, StringPiece y) {
return !(x == y);
}
inline bool operator<(StringPiece x, StringPiece y) {
const StringPiece::size_type min_size =
x.size() < y.size() ? x.size() : y.size();
const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
return (r < 0) || (r == 0 && x.size() < y.size());
}
inline bool operator>(StringPiece x, StringPiece y) {
return y < x;
}
inline bool operator<=(StringPiece x, StringPiece y) {
return !(x > y);
}
inline bool operator>=(StringPiece x, StringPiece y) {
return !(x < y);
}
extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
}
using ::google::protobuf::stringpiece_internal::StringPiece;
} }
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
template<> struct hash<StringPiece> {
size_t operator()(const StringPiece& s) const {
size_t result = 0;
for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
result = 5 * result + static_cast<size_t>(*str);
}
return result;
}
};
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
#include <google/protobuf/port_undef.inc>
#endif