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 | |
37 | namespace re2 { |
38 | |
39 | class 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 | |
176 | inline 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 | |
183 | inline bool operator!=(const StringPiece& x, const StringPiece& y) { |
184 | return !(x == y); |
185 | } |
186 | |
187 | inline 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 | |
193 | inline bool operator>(const StringPiece& x, const StringPiece& y) { |
194 | return y < x; |
195 | } |
196 | |
197 | inline bool operator<=(const StringPiece& x, const StringPiece& y) { |
198 | return !(x > y); |
199 | } |
200 | |
201 | inline bool operator>=(const StringPiece& x, const StringPiece& y) { |
202 | return !(x < y); |
203 | } |
204 | |
205 | // Allow StringPiece to be logged. |
206 | std::ostream& operator<<(std::ostream& o, const StringPiece& p); |
207 | |
208 | } // namespace re2 |
209 | |
210 | #endif // RE2_STRINGPIECE_H_ |
211 | |