jpayne@69
|
1 // © 2016 and later: Unicode, Inc. and others.
|
jpayne@69
|
2 // License & terms of use: http://www.unicode.org/copyright.html
|
jpayne@69
|
3 // Copyright (C) 2009-2013, International Business Machines
|
jpayne@69
|
4 // Corporation and others. All Rights Reserved.
|
jpayne@69
|
5 //
|
jpayne@69
|
6 // Copyright 2001 and onwards Google Inc.
|
jpayne@69
|
7 // Author: Sanjay Ghemawat
|
jpayne@69
|
8
|
jpayne@69
|
9 // This code is a contribution of Google code, and the style used here is
|
jpayne@69
|
10 // a compromise between the original Google code and the ICU coding guidelines.
|
jpayne@69
|
11 // For example, data types are ICU-ified (size_t,int->int32_t),
|
jpayne@69
|
12 // and API comments doxygen-ified, but function names and behavior are
|
jpayne@69
|
13 // as in the original, if possible.
|
jpayne@69
|
14 // Assertion-style error handling, not available in ICU, was changed to
|
jpayne@69
|
15 // parameter "pinning" similar to UnicodeString.
|
jpayne@69
|
16 //
|
jpayne@69
|
17 // In addition, this is only a partial port of the original Google code,
|
jpayne@69
|
18 // limited to what was needed so far. The (nearly) complete original code
|
jpayne@69
|
19 // is in the ICU svn repository at icuhtml/trunk/design/strings/contrib
|
jpayne@69
|
20 // (see ICU ticket 6765, r25517).
|
jpayne@69
|
21
|
jpayne@69
|
22 #ifndef __STRINGPIECE_H__
|
jpayne@69
|
23 #define __STRINGPIECE_H__
|
jpayne@69
|
24
|
jpayne@69
|
25 /**
|
jpayne@69
|
26 * \file
|
jpayne@69
|
27 * \brief C++ API: StringPiece: Read-only byte string wrapper class.
|
jpayne@69
|
28 */
|
jpayne@69
|
29
|
jpayne@69
|
30 #include "unicode/utypes.h"
|
jpayne@69
|
31
|
jpayne@69
|
32 #if U_SHOW_CPLUSPLUS_API
|
jpayne@69
|
33
|
jpayne@69
|
34 #include <cstddef>
|
jpayne@69
|
35 #include <type_traits>
|
jpayne@69
|
36
|
jpayne@69
|
37 #include "unicode/uobject.h"
|
jpayne@69
|
38 #include "unicode/std_string.h"
|
jpayne@69
|
39
|
jpayne@69
|
40 // Arghh! I wish C++ literals were "string".
|
jpayne@69
|
41
|
jpayne@69
|
42 U_NAMESPACE_BEGIN
|
jpayne@69
|
43
|
jpayne@69
|
44 /**
|
jpayne@69
|
45 * A string-like object that points to a sized piece of memory.
|
jpayne@69
|
46 *
|
jpayne@69
|
47 * We provide non-explicit singleton constructors so users can pass
|
jpayne@69
|
48 * in a "const char*" or a "string" wherever a "StringPiece" is
|
jpayne@69
|
49 * expected.
|
jpayne@69
|
50 *
|
jpayne@69
|
51 * Functions or methods may use StringPiece parameters to accept either a
|
jpayne@69
|
52 * "const char*" or a "string" value that will be implicitly converted to a
|
jpayne@69
|
53 * StringPiece.
|
jpayne@69
|
54 *
|
jpayne@69
|
55 * Systematic usage of StringPiece is encouraged as it will reduce unnecessary
|
jpayne@69
|
56 * conversions from "const char*" to "string" and back again.
|
jpayne@69
|
57 *
|
jpayne@69
|
58 * @stable ICU 4.2
|
jpayne@69
|
59 */
|
jpayne@69
|
60 class U_COMMON_API StringPiece : public UMemory {
|
jpayne@69
|
61 private:
|
jpayne@69
|
62 const char* ptr_;
|
jpayne@69
|
63 int32_t length_;
|
jpayne@69
|
64
|
jpayne@69
|
65 public:
|
jpayne@69
|
66 /**
|
jpayne@69
|
67 * Default constructor, creates an empty StringPiece.
|
jpayne@69
|
68 * @stable ICU 4.2
|
jpayne@69
|
69 */
|
jpayne@69
|
70 StringPiece() : ptr_(nullptr), length_(0) { }
|
jpayne@69
|
71
|
jpayne@69
|
72 /**
|
jpayne@69
|
73 * Constructs from a NUL-terminated const char * pointer.
|
jpayne@69
|
74 * @param str a NUL-terminated const char * pointer
|
jpayne@69
|
75 * @stable ICU 4.2
|
jpayne@69
|
76 */
|
jpayne@69
|
77 StringPiece(const char* str);
|
jpayne@69
|
78 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
79 #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN)
|
jpayne@69
|
80 /**
|
jpayne@69
|
81 * Constructs from a NUL-terminated const char8_t * pointer.
|
jpayne@69
|
82 * @param str a NUL-terminated const char8_t * pointer
|
jpayne@69
|
83 * @draft ICU 67
|
jpayne@69
|
84 */
|
jpayne@69
|
85 StringPiece(const char8_t* str) : StringPiece(reinterpret_cast<const char*>(str)) {}
|
jpayne@69
|
86 #endif
|
jpayne@69
|
87 /**
|
jpayne@69
|
88 * Constructs an empty StringPiece.
|
jpayne@69
|
89 * Needed for type disambiguation from multiple other overloads.
|
jpayne@69
|
90 * @param p nullptr
|
jpayne@69
|
91 * @draft ICU 67
|
jpayne@69
|
92 */
|
jpayne@69
|
93 StringPiece(std::nullptr_t p) : ptr_(p), length_(0) {}
|
jpayne@69
|
94 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
95
|
jpayne@69
|
96 /**
|
jpayne@69
|
97 * Constructs from a std::string.
|
jpayne@69
|
98 * @stable ICU 4.2
|
jpayne@69
|
99 */
|
jpayne@69
|
100 StringPiece(const std::string& str)
|
jpayne@69
|
101 : ptr_(str.data()), length_(static_cast<int32_t>(str.size())) { }
|
jpayne@69
|
102 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
103 #if defined(__cpp_lib_char8_t) || defined(U_IN_DOXYGEN)
|
jpayne@69
|
104 /**
|
jpayne@69
|
105 * Constructs from a std::u8string.
|
jpayne@69
|
106 * @draft ICU 67
|
jpayne@69
|
107 */
|
jpayne@69
|
108 StringPiece(const std::u8string& str)
|
jpayne@69
|
109 : ptr_(reinterpret_cast<const char*>(str.data())),
|
jpayne@69
|
110 length_(static_cast<int32_t>(str.size())) { }
|
jpayne@69
|
111 #endif
|
jpayne@69
|
112 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
113
|
jpayne@69
|
114 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
115 /**
|
jpayne@69
|
116 * Constructs from some other implementation of a string piece class, from any
|
jpayne@69
|
117 * C++ record type that has these two methods:
|
jpayne@69
|
118 *
|
jpayne@69
|
119 * \code{.cpp}
|
jpayne@69
|
120 *
|
jpayne@69
|
121 * struct OtherStringPieceClass {
|
jpayne@69
|
122 * const char* data(); // or const char8_t*
|
jpayne@69
|
123 * size_t size();
|
jpayne@69
|
124 * };
|
jpayne@69
|
125 *
|
jpayne@69
|
126 * \endcode
|
jpayne@69
|
127 *
|
jpayne@69
|
128 * The other string piece class will typically be std::string_view from C++17
|
jpayne@69
|
129 * or absl::string_view from Abseil.
|
jpayne@69
|
130 *
|
jpayne@69
|
131 * Starting with C++20, data() may also return a const char8_t* pointer,
|
jpayne@69
|
132 * as from std::u8string_view.
|
jpayne@69
|
133 *
|
jpayne@69
|
134 * @param str the other string piece
|
jpayne@69
|
135 * @draft ICU 65
|
jpayne@69
|
136 */
|
jpayne@69
|
137 template <typename T,
|
jpayne@69
|
138 typename = typename std::enable_if<
|
jpayne@69
|
139 (std::is_same<decltype(T().data()), const char*>::value
|
jpayne@69
|
140 #if defined(__cpp_char8_t)
|
jpayne@69
|
141 || std::is_same<decltype(T().data()), const char8_t*>::value
|
jpayne@69
|
142 #endif
|
jpayne@69
|
143 ) &&
|
jpayne@69
|
144 std::is_same<decltype(T().size()), size_t>::value>::type>
|
jpayne@69
|
145 StringPiece(T str)
|
jpayne@69
|
146 : ptr_(reinterpret_cast<const char*>(str.data())),
|
jpayne@69
|
147 length_(static_cast<int32_t>(str.size())) {}
|
jpayne@69
|
148 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
149
|
jpayne@69
|
150 /**
|
jpayne@69
|
151 * Constructs from a const char * pointer and a specified length.
|
jpayne@69
|
152 * @param offset a const char * pointer (need not be terminated)
|
jpayne@69
|
153 * @param len the length of the string; must be non-negative
|
jpayne@69
|
154 * @stable ICU 4.2
|
jpayne@69
|
155 */
|
jpayne@69
|
156 StringPiece(const char* offset, int32_t len) : ptr_(offset), length_(len) { }
|
jpayne@69
|
157 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
158 #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN)
|
jpayne@69
|
159 /**
|
jpayne@69
|
160 * Constructs from a const char8_t * pointer and a specified length.
|
jpayne@69
|
161 * @param str a const char8_t * pointer (need not be terminated)
|
jpayne@69
|
162 * @param len the length of the string; must be non-negative
|
jpayne@69
|
163 * @draft ICU 67
|
jpayne@69
|
164 */
|
jpayne@69
|
165 StringPiece(const char8_t* str, int32_t len) :
|
jpayne@69
|
166 StringPiece(reinterpret_cast<const char*>(str), len) {}
|
jpayne@69
|
167 #endif
|
jpayne@69
|
168 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
169
|
jpayne@69
|
170 /**
|
jpayne@69
|
171 * Substring of another StringPiece.
|
jpayne@69
|
172 * @param x the other StringPiece
|
jpayne@69
|
173 * @param pos start position in x; must be non-negative and <= x.length().
|
jpayne@69
|
174 * @stable ICU 4.2
|
jpayne@69
|
175 */
|
jpayne@69
|
176 StringPiece(const StringPiece& x, int32_t pos);
|
jpayne@69
|
177 /**
|
jpayne@69
|
178 * Substring of another StringPiece.
|
jpayne@69
|
179 * @param x the other StringPiece
|
jpayne@69
|
180 * @param pos start position in x; must be non-negative and <= x.length().
|
jpayne@69
|
181 * @param len length of the substring;
|
jpayne@69
|
182 * must be non-negative and will be pinned to at most x.length() - pos.
|
jpayne@69
|
183 * @stable ICU 4.2
|
jpayne@69
|
184 */
|
jpayne@69
|
185 StringPiece(const StringPiece& x, int32_t pos, int32_t len);
|
jpayne@69
|
186
|
jpayne@69
|
187 /**
|
jpayne@69
|
188 * Returns the string pointer. May be nullptr if it is empty.
|
jpayne@69
|
189 *
|
jpayne@69
|
190 * data() may return a pointer to a buffer with embedded NULs, and the
|
jpayne@69
|
191 * returned buffer may or may not be null terminated. Therefore it is
|
jpayne@69
|
192 * typically a mistake to pass data() to a routine that expects a NUL
|
jpayne@69
|
193 * terminated string.
|
jpayne@69
|
194 * @return the string pointer
|
jpayne@69
|
195 * @stable ICU 4.2
|
jpayne@69
|
196 */
|
jpayne@69
|
197 const char* data() const { return ptr_; }
|
jpayne@69
|
198 /**
|
jpayne@69
|
199 * Returns the string length. Same as length().
|
jpayne@69
|
200 * @return the string length
|
jpayne@69
|
201 * @stable ICU 4.2
|
jpayne@69
|
202 */
|
jpayne@69
|
203 int32_t size() const { return length_; }
|
jpayne@69
|
204 /**
|
jpayne@69
|
205 * Returns the string length. Same as size().
|
jpayne@69
|
206 * @return the string length
|
jpayne@69
|
207 * @stable ICU 4.2
|
jpayne@69
|
208 */
|
jpayne@69
|
209 int32_t length() const { return length_; }
|
jpayne@69
|
210 /**
|
jpayne@69
|
211 * Returns whether the string is empty.
|
jpayne@69
|
212 * @return TRUE if the string is empty
|
jpayne@69
|
213 * @stable ICU 4.2
|
jpayne@69
|
214 */
|
jpayne@69
|
215 UBool empty() const { return length_ == 0; }
|
jpayne@69
|
216
|
jpayne@69
|
217 /**
|
jpayne@69
|
218 * Sets to an empty string.
|
jpayne@69
|
219 * @stable ICU 4.2
|
jpayne@69
|
220 */
|
jpayne@69
|
221 void clear() { ptr_ = nullptr; length_ = 0; }
|
jpayne@69
|
222
|
jpayne@69
|
223 /**
|
jpayne@69
|
224 * Reset the stringpiece to refer to new data.
|
jpayne@69
|
225 * @param xdata pointer the new string data. Need not be nul terminated.
|
jpayne@69
|
226 * @param len the length of the new data
|
jpayne@69
|
227 * @stable ICU 4.8
|
jpayne@69
|
228 */
|
jpayne@69
|
229 void set(const char* xdata, int32_t len) { ptr_ = xdata; length_ = len; }
|
jpayne@69
|
230
|
jpayne@69
|
231 /**
|
jpayne@69
|
232 * Reset the stringpiece to refer to new data.
|
jpayne@69
|
233 * @param str a pointer to a NUL-terminated string.
|
jpayne@69
|
234 * @stable ICU 4.8
|
jpayne@69
|
235 */
|
jpayne@69
|
236 void set(const char* str);
|
jpayne@69
|
237
|
jpayne@69
|
238 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
239 #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN)
|
jpayne@69
|
240 /**
|
jpayne@69
|
241 * Resets the stringpiece to refer to new data.
|
jpayne@69
|
242 * @param xdata pointer the new string data. Need not be NUL-terminated.
|
jpayne@69
|
243 * @param len the length of the new data
|
jpayne@69
|
244 * @draft ICU 67
|
jpayne@69
|
245 */
|
jpayne@69
|
246 inline void set(const char8_t* xdata, int32_t len) {
|
jpayne@69
|
247 set(reinterpret_cast<const char*>(xdata), len);
|
jpayne@69
|
248 }
|
jpayne@69
|
249
|
jpayne@69
|
250 /**
|
jpayne@69
|
251 * Resets the stringpiece to refer to new data.
|
jpayne@69
|
252 * @param str a pointer to a NUL-terminated string.
|
jpayne@69
|
253 * @draft ICU 67
|
jpayne@69
|
254 */
|
jpayne@69
|
255 inline void set(const char8_t* str) {
|
jpayne@69
|
256 set(reinterpret_cast<const char*>(str));
|
jpayne@69
|
257 }
|
jpayne@69
|
258 #endif
|
jpayne@69
|
259 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
260
|
jpayne@69
|
261 /**
|
jpayne@69
|
262 * Removes the first n string units.
|
jpayne@69
|
263 * @param n prefix length, must be non-negative and <=length()
|
jpayne@69
|
264 * @stable ICU 4.2
|
jpayne@69
|
265 */
|
jpayne@69
|
266 void remove_prefix(int32_t n) {
|
jpayne@69
|
267 if (n >= 0) {
|
jpayne@69
|
268 if (n > length_) {
|
jpayne@69
|
269 n = length_;
|
jpayne@69
|
270 }
|
jpayne@69
|
271 ptr_ += n;
|
jpayne@69
|
272 length_ -= n;
|
jpayne@69
|
273 }
|
jpayne@69
|
274 }
|
jpayne@69
|
275
|
jpayne@69
|
276 /**
|
jpayne@69
|
277 * Removes the last n string units.
|
jpayne@69
|
278 * @param n suffix length, must be non-negative and <=length()
|
jpayne@69
|
279 * @stable ICU 4.2
|
jpayne@69
|
280 */
|
jpayne@69
|
281 void remove_suffix(int32_t n) {
|
jpayne@69
|
282 if (n >= 0) {
|
jpayne@69
|
283 if (n <= length_) {
|
jpayne@69
|
284 length_ -= n;
|
jpayne@69
|
285 } else {
|
jpayne@69
|
286 length_ = 0;
|
jpayne@69
|
287 }
|
jpayne@69
|
288 }
|
jpayne@69
|
289 }
|
jpayne@69
|
290
|
jpayne@69
|
291 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
292 /**
|
jpayne@69
|
293 * Searches the StringPiece for the given search string (needle);
|
jpayne@69
|
294 * @param needle The string for which to search.
|
jpayne@69
|
295 * @param offset Where to start searching within this string (haystack).
|
jpayne@69
|
296 * @return The offset of needle in haystack, or -1 if not found.
|
jpayne@69
|
297 * @draft ICU 67
|
jpayne@69
|
298 */
|
jpayne@69
|
299 int32_t find(StringPiece needle, int32_t offset);
|
jpayne@69
|
300
|
jpayne@69
|
301 /**
|
jpayne@69
|
302 * Compares this StringPiece with the other StringPiece, with semantics
|
jpayne@69
|
303 * similar to std::string::compare().
|
jpayne@69
|
304 * @param other The string to compare to.
|
jpayne@69
|
305 * @return below zero if this < other; above zero if this > other; 0 if this == other.
|
jpayne@69
|
306 * @draft ICU 67
|
jpayne@69
|
307 */
|
jpayne@69
|
308 int32_t compare(StringPiece other);
|
jpayne@69
|
309 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
310
|
jpayne@69
|
311 /**
|
jpayne@69
|
312 * Maximum integer, used as a default value for substring methods.
|
jpayne@69
|
313 * @stable ICU 4.2
|
jpayne@69
|
314 */
|
jpayne@69
|
315 static const int32_t npos; // = 0x7fffffff;
|
jpayne@69
|
316
|
jpayne@69
|
317 /**
|
jpayne@69
|
318 * Returns a substring of this StringPiece.
|
jpayne@69
|
319 * @param pos start position; must be non-negative and <= length().
|
jpayne@69
|
320 * @param len length of the substring;
|
jpayne@69
|
321 * must be non-negative and will be pinned to at most length() - pos.
|
jpayne@69
|
322 * @return the substring StringPiece
|
jpayne@69
|
323 * @stable ICU 4.2
|
jpayne@69
|
324 */
|
jpayne@69
|
325 StringPiece substr(int32_t pos, int32_t len = npos) const {
|
jpayne@69
|
326 return StringPiece(*this, pos, len);
|
jpayne@69
|
327 }
|
jpayne@69
|
328 };
|
jpayne@69
|
329
|
jpayne@69
|
330 /**
|
jpayne@69
|
331 * Global operator == for StringPiece
|
jpayne@69
|
332 * @param x The first StringPiece to compare.
|
jpayne@69
|
333 * @param y The second StringPiece to compare.
|
jpayne@69
|
334 * @return TRUE if the string data is equal
|
jpayne@69
|
335 * @stable ICU 4.8
|
jpayne@69
|
336 */
|
jpayne@69
|
337 U_EXPORT UBool U_EXPORT2
|
jpayne@69
|
338 operator==(const StringPiece& x, const StringPiece& y);
|
jpayne@69
|
339
|
jpayne@69
|
340 /**
|
jpayne@69
|
341 * Global operator != for StringPiece
|
jpayne@69
|
342 * @param x The first StringPiece to compare.
|
jpayne@69
|
343 * @param y The second StringPiece to compare.
|
jpayne@69
|
344 * @return TRUE if the string data is not equal
|
jpayne@69
|
345 * @stable ICU 4.8
|
jpayne@69
|
346 */
|
jpayne@69
|
347 inline UBool operator!=(const StringPiece& x, const StringPiece& y) {
|
jpayne@69
|
348 return !(x == y);
|
jpayne@69
|
349 }
|
jpayne@69
|
350
|
jpayne@69
|
351 U_NAMESPACE_END
|
jpayne@69
|
352
|
jpayne@69
|
353 #endif /* U_SHOW_CPLUSPLUS_API */
|
jpayne@69
|
354
|
jpayne@69
|
355 #endif // __STRINGPIECE_H__
|