1// Copyright 2001-2010 The RE2 Authors. All Rights Reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#ifndef RE2_STRINGPIECE_H_
6#define RE2_STRINGPIECE_H_
7
8// A string-like object that points to a sized piece of memory.
9//
10// Functions or methods may use const StringPiece& parameters to accept either
11// a "const char*" or a "string" value that will be implicitly converted to
12// a StringPiece. The implicit conversion means that it is often appropriate
13// to include this .h file in other files rather than forward-declaring
14// StringPiece as would be appropriate for most other Google classes.
15//
16// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
17// conversions from "const char*" to "string" and back again.
18//
19//
20// Arghh! I wish C++ literals were "string".
21
22// Doing this simplifies the logic below.
23#ifndef __has_include
24#define __has_include(x) 0
25#endif
26
27#include <stddef.h>
28#include <string.h>
29#include <algorithm>
30#include <iosfwd>
31#include <iterator>
32#include <string>
33#if __has_include(<string_view>) && __cplusplus >= 201703L
34#include <string_view>
35#endif
36
37namespace re2 {
38
39class StringPiece {
40 public:
41 typedef std::char_traits<char> traits_type;
42 typedef char value_type;
43 typedef char* pointer;
44 typedef const char* const_pointer;
45 typedef char& reference;
46 typedef const char& const_reference;
47 typedef const char* const_iterator;
48 typedef const_iterator iterator;
49 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
50 typedef const_reverse_iterator reverse_iterator;
51 typedef size_t size_type;
52 typedef ptrdiff_t difference_type;
53 static const size_type npos = static_cast<size_type>(-1);
54
55 // We provide non-explicit singleton constructors so users can pass
56 // in a "const char*" or a "string" wherever a "StringPiece" is
57 // expected.
58 StringPiece()
59 : data_(NULL), size_(0) {}
60#if __has_include(<string_view>) && __cplusplus >= 201703L
61 StringPiece(const std::string_view& str)
62 : data_(str.data()), size_(str.size()) {}
63#endif
64 StringPiece(const std::string& str)
65 : data_(str.data()), size_(str.size()) {}
66 StringPiece(const char* str)
67 : data_(str), size_(str == NULL ? 0 : strlen(str)) {}
68 StringPiece(const char* str, size_type len)
69 : data_(str), size_(len) {}
70
71 const_iterator begin() const { return data_; }
72 const_iterator end() const { return data_ + size_; }
73 const_reverse_iterator rbegin() const {
74 return const_reverse_iterator(data_ + size_);
75 }
76 const_reverse_iterator rend() const {
77 return const_reverse_iterator(data_);
78 }
79
80 size_type size() const { return size_; }
81 size_type length() const { return size_; }
82 bool empty() const { return size_ == 0; }
83
84 const_reference operator[](size_type i) const { return data_[i]; }
85 const_pointer data() const { return data_; }
86
87 void remove_prefix(size_type n) {
88 data_ += n;
89 size_ -= n;
90 }
91
92 void remove_suffix(size_type n) {
93 size_ -= n;
94 }
95
96 void set(const char* str) {
97 data_ = str;
98 size_ = str == NULL ? 0 : strlen(str);
99 }
100
101 void set(const char* str, size_type len) {
102 data_ = str;
103 size_ = len;
104 }
105
106 // Converts to `std::basic_string`.
107 template <typename A>
108 explicit operator std::basic_string<char, traits_type, A>() const {
109 if (!data_) return {};
110 return std::basic_string<char, traits_type, A>(data_, size_);
111 }
112
113 std::string as_string() const {
114 return std::string(data_, size_);
115 }
116
117 // We also define ToString() here, since many other string-like
118 // interfaces name the routine that converts to a C++ string
119 // "ToString", and it's confusing to have the method that does that
120 // for a StringPiece be called "as_string()". We also leave the
121 // "as_string()" method defined here for existing code.
122 std::string ToString() const {
123 return std::string(data_, size_);
124 }
125
126 void CopyToString(std::string* target) const {
127 target->assign(data_, size_);
128 }
129
130 void AppendToString(std::string* target) const {
131 target->append(data_, size_);
132 }
133
134 size_type copy(char* buf, size_type n, size_type pos = 0) const;
135 StringPiece substr(size_type pos = 0, size_type n = npos) const;
136
137 int compare(const StringPiece& x) const {
138 size_type min_size = std::min(size(), x.size());
139 if (min_size > 0) {
140 int r = memcmp(data(), x.data(), min_size);
141 if (r < 0) return -1;
142 if (r > 0) return 1;
143 }
144 if (size() < x.size()) return -1;
145 if (size() > x.size()) return 1;
146 return 0;
147 }
148
149 // Does "this" start with "x"?
150 bool starts_with(const StringPiece& x) const {
151 return x.empty() ||
152 (size() >= x.size() && memcmp(data(), x.data(), x.size()) == 0);
153 }
154
155 // Does "this" end with "x"?
156 bool ends_with(const StringPiece& x) const {
157 return x.empty() ||
158 (size() >= x.size() &&
159 memcmp(data() + (size() - x.size()), x.data(), x.size()) == 0);
160 }
161
162 bool contains(const StringPiece& s) const {
163 return find(s) != npos;
164 }
165
166 size_type find(const StringPiece& s, size_type pos = 0) const;
167 size_type find(char c, size_type pos = 0) const;
168 size_type rfind(const StringPiece& s, size_type pos = npos) const;
169 size_type rfind(char c, size_type pos = npos) const;
170
171 private:
172 const_pointer data_;
173 size_type size_;
174};
175
176inline bool operator==(const StringPiece& x, const StringPiece& y) {
177 StringPiece::size_type len = x.size();
178 if (len != y.size()) return false;
179 return x.data() == y.data() || len == 0 ||
180 memcmp(x.data(), y.data(), len) == 0;
181}
182
183inline bool operator!=(const StringPiece& x, const StringPiece& y) {
184 return !(x == y);
185}
186
187inline bool operator<(const StringPiece& x, const StringPiece& y) {
188 StringPiece::size_type min_size = std::min(x.size(), y.size());
189 int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
190 return (r < 0) || (r == 0 && x.size() < y.size());
191}
192
193inline bool operator>(const StringPiece& x, const StringPiece& y) {
194 return y < x;
195}
196
197inline bool operator<=(const StringPiece& x, const StringPiece& y) {
198 return !(x > y);
199}
200
201inline bool operator>=(const StringPiece& x, const StringPiece& y) {
202 return !(x < y);
203}
204
205// Allow StringPiece to be logged.
206std::ostream& operator<<(std::ostream& o, const StringPiece& p);
207
208} // namespace re2
209
210#endif // RE2_STRINGPIECE_H_
211