1 /*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ANDROID_STRING8_H
18 #define ANDROID_STRING8_H
19
20 #include <iostream>
21
22 #include <utils/Errors.h>
23 #include <utils/Unicode.h>
24 #include <utils/TypeHelpers.h>
25
26 #include <string.h> // for strcmp
27 #include <stdarg.h>
28
29 #if __has_include(<string>)
30 #include <string>
31 #define HAS_STRING
32 #endif
33
34 #if __has_include(<string_view>)
35 #include <string_view>
36 #define HAS_STRING_VIEW
37 #endif
38
39 #if __cplusplus >= 202002L
40 #include <compare>
41 #endif
42
43 // ---------------------------------------------------------------------------
44
45 namespace android {
46
47 class String16;
48
49 // DO NOT USE: please use std::string
50
51 //! This is a string holding UTF-8 characters. Does not allow the value more
52 // than 0x10FFFF, which is not valid unicode codepoint.
53 class String8
54 {
55 public:
56 String8();
57 String8(const String8& o);
58 explicit String8(const char* o);
59 explicit String8(const char* o, size_t numChars);
60
61 explicit String8(const String16& o);
62 explicit String8(const char16_t* o);
63 explicit String8(const char16_t* o, size_t numChars);
64 explicit String8(const char32_t* o);
65 explicit String8(const char32_t* o, size_t numChars);
66 ~String8();
67
68 static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
69 static String8 formatV(const char* fmt, va_list args);
70
71 inline const char* c_str() const;
72
73 inline size_t size() const;
74 inline size_t bytes() const;
75 inline bool empty() const;
76
77 size_t length() const;
78
79 void clear();
80
81 void setTo(const String8& other);
82 status_t setTo(const char* other);
83 status_t setTo(const char* other, size_t numChars);
84 status_t setTo(const char16_t* other, size_t numChars);
85 status_t setTo(const char32_t* other,
86 size_t length);
87
88 status_t append(const String8& other);
89 status_t append(const char* other);
90 status_t append(const char* other, size_t numChars);
91
92 status_t appendFormat(const char* fmt, ...)
93 __attribute__((format (printf, 2, 3)));
94 status_t appendFormatV(const char* fmt, va_list args);
95
96 inline String8& operator=(const String8& other);
97 inline String8& operator=(const char* other);
98
99 inline String8& operator+=(const String8& other);
100 inline String8 operator+(const String8& other) const;
101
102 inline String8& operator+=(const char* other);
103 inline String8 operator+(const char* other) const;
104
105 inline int compare(const String8& other) const;
106
107 inline bool operator<(const String8& other) const;
108 inline bool operator<=(const String8& other) const;
109 inline bool operator==(const String8& other) const;
110 inline bool operator!=(const String8& other) const;
111 inline bool operator>=(const String8& other) const;
112 inline bool operator>(const String8& other) const;
113 #if __cplusplus >= 202002L
114 inline std::strong_ordering operator<=>(const String8& other) const;
115 #endif
116
117 inline bool operator<(const char* other) const;
118 inline bool operator<=(const char* other) const;
119 inline bool operator==(const char* other) const;
120 inline bool operator!=(const char* other) const;
121 inline bool operator>=(const char* other) const;
122 inline bool operator>(const char* other) const;
123 #if __cplusplus >= 202002L
124 inline std::strong_ordering operator<=>(const char* other) const;
125 #endif
126
127 inline operator const char*() const;
128
129 #ifdef HAS_STRING_VIEW
130 inline explicit operator std::string_view() const;
131 #endif
132
133 char* lockBuffer(size_t size);
134 void unlockBuffer();
135 status_t unlockBuffer(size_t size);
136
137 // return the index of the first byte of other in this at or after
138 // start, or -1 if not found
139 ssize_t find(const char* other, size_t start = 0) const;
140 inline ssize_t find(const String8& other, size_t start = 0) const;
141
142 // return true if this string contains the specified substring
143 inline bool contains(const char* other) const;
144 inline bool contains(const String8& other) const;
145
146 // removes all occurrence of the specified substring
147 // returns true if any were found and removed
148 bool removeAll(const char* other);
149 inline bool removeAll(const String8& other);
150
151 void toLower();
152
153 private:
154 String8 getPathDir(void) const;
155 String8 getPathExtension(void) const;
156
157 status_t real_append(const char* other, size_t numChars);
158
159 const char* mString;
160
161 // These symbols are for potential backward compatibility with prebuilts. To be removed.
162 #ifdef ENABLE_STRING8_OBSOLETE_METHODS
163 public:
164 #else
165 private:
166 #endif
167 inline const char* string() const;
168 inline bool isEmpty() const;
169 };
170
171 // String8 can be trivially moved using memcpy() because moving does not
172 // require any change to the underlying SharedBuffer contents or reference count.
173 ANDROID_TRIVIAL_MOVE_TRAIT(String8)
174
175 static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
176 os << str.c_str();
177 return os;
178 }
179
180 // ---------------------------------------------------------------------------
181 // No user servicable parts below.
182
compare_type(const String8 & lhs,const String8 & rhs)183 inline int compare_type(const String8& lhs, const String8& rhs)
184 {
185 return lhs.compare(rhs);
186 }
187
strictly_order_type(const String8 & lhs,const String8 & rhs)188 inline int strictly_order_type(const String8& lhs, const String8& rhs)
189 {
190 return compare_type(lhs, rhs) < 0;
191 }
192
c_str()193 inline const char* String8::c_str() const
194 {
195 return mString;
196 }
string()197 inline const char* String8::string() const
198 {
199 return mString;
200 }
201
size()202 inline size_t String8::size() const
203 {
204 return length();
205 }
206
empty()207 inline bool String8::empty() const
208 {
209 return length() == 0;
210 }
211
isEmpty()212 inline bool String8::isEmpty() const
213 {
214 return length() == 0;
215 }
216
bytes()217 inline size_t String8::bytes() const
218 {
219 return length();
220 }
221
find(const String8 & other,size_t start)222 inline ssize_t String8::find(const String8& other, size_t start) const
223 {
224 return find(other.c_str(), start);
225 }
226
contains(const char * other)227 inline bool String8::contains(const char* other) const
228 {
229 return find(other) >= 0;
230 }
231
contains(const String8 & other)232 inline bool String8::contains(const String8& other) const
233 {
234 return contains(other.c_str());
235 }
236
removeAll(const String8 & other)237 inline bool String8::removeAll(const String8& other)
238 {
239 return removeAll(other.c_str());
240 }
241
242 inline String8& String8::operator=(const String8& other)
243 {
244 setTo(other);
245 return *this;
246 }
247
248 inline String8& String8::operator=(const char* other)
249 {
250 setTo(other);
251 return *this;
252 }
253
254 inline String8& String8::operator+=(const String8& other)
255 {
256 append(other);
257 return *this;
258 }
259
260 inline String8 String8::operator+(const String8& other) const
261 {
262 String8 tmp(*this);
263 tmp += other;
264 return tmp;
265 }
266
267 inline String8& String8::operator+=(const char* other)
268 {
269 append(other);
270 return *this;
271 }
272
273 inline String8 String8::operator+(const char* other) const
274 {
275 String8 tmp(*this);
276 tmp += other;
277 return tmp;
278 }
279
compare(const String8 & other)280 inline int String8::compare(const String8& other) const
281 {
282 return strcmp(mString, other.mString);
283 }
284
285 inline bool String8::operator<(const String8& other) const
286 {
287 return strcmp(mString, other.mString) < 0;
288 }
289
290 inline bool String8::operator<=(const String8& other) const
291 {
292 return strcmp(mString, other.mString) <= 0;
293 }
294
295 inline bool String8::operator==(const String8& other) const
296 {
297 return strcmp(mString, other.mString) == 0;
298 }
299
300 inline bool String8::operator!=(const String8& other) const
301 {
302 return strcmp(mString, other.mString) != 0;
303 }
304
305 inline bool String8::operator>=(const String8& other) const
306 {
307 return strcmp(mString, other.mString) >= 0;
308 }
309
310 inline bool String8::operator>(const String8& other) const
311 {
312 return strcmp(mString, other.mString) > 0;
313 }
314
315 #if __cplusplus >= 202002L
316 inline std::strong_ordering String8::operator<=>(const String8& other) const {
317 int result = strcmp(mString, other.mString);
318 if (result == 0) {
319 return std::strong_ordering::equal;
320 } else if (result < 0) {
321 return std::strong_ordering::less;
322 } else {
323 return std::strong_ordering::greater;
324 }
325 }
326 #endif
327
328 inline bool String8::operator<(const char* other) const
329 {
330 return strcmp(mString, other) < 0;
331 }
332
333 inline bool String8::operator<=(const char* other) const
334 {
335 return strcmp(mString, other) <= 0;
336 }
337
338 inline bool String8::operator==(const char* other) const
339 {
340 return strcmp(mString, other) == 0;
341 }
342
343 inline bool String8::operator!=(const char* other) const
344 {
345 return strcmp(mString, other) != 0;
346 }
347
348 inline bool String8::operator>=(const char* other) const
349 {
350 return strcmp(mString, other) >= 0;
351 }
352
353 inline bool String8::operator>(const char* other) const
354 {
355 return strcmp(mString, other) > 0;
356 }
357
358 #if __cplusplus >= 202002L
359 inline std::strong_ordering String8::operator<=>(const char* other) const {
360 int result = strcmp(mString, other);
361 if (result == 0) {
362 return std::strong_ordering::equal;
363 } else if (result < 0) {
364 return std::strong_ordering::less;
365 } else {
366 return std::strong_ordering::greater;
367 }
368 }
369 #endif
370
371 inline String8::operator const char*() const
372 {
373 return mString;
374 }
375
376 #ifdef HAS_STRING_VIEW
string_view()377 inline String8::operator std::string_view() const
378 {
379 return {mString, length()};
380 }
381 #endif
382
383 } // namespace android
384
385 // ---------------------------------------------------------------------------
386
387 #undef HAS_STRING
388 #undef HAS_STRING_VIEW
389
390 #endif // ANDROID_STRING8_H
391