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_STRING16_H
18 #define ANDROID_STRING16_H
19
20 #include <iostream>
21 #include <string>
22
23 #include <utils/Errors.h>
24 #include <utils/String8.h>
25 #include <utils/TypeHelpers.h>
26
27 #if __has_include(<string_view>)
28 #include <string_view>
29 #define HAS_STRING_VIEW
30 #endif
31
32 #if __cplusplus >= 202002L
33 #include <compare>
34 #endif
35
36 // ---------------------------------------------------------------------------
37
38 namespace android {
39
40 // ---------------------------------------------------------------------------
41
42 template <size_t N>
43 class StaticString16;
44
45 // DO NOT USE: please use std::u16string
46
47 //! This is a string holding UTF-16 characters.
48 class String16
49 {
50 public:
51 String16();
52 String16(const String16& o);
53 String16(String16&& o) noexcept;
54 String16(const String16& o,
55 size_t len,
56 size_t begin=0);
57 explicit String16(const char16_t* o);
58 explicit String16(const char16_t* o, size_t len);
59 explicit String16(const String8& o);
60 explicit String16(const char* o);
61 explicit String16(const char* o, size_t len);
62
63 ~String16();
64
65 inline const char16_t* c_str() const;
66
67 size_t size() const;
68 inline bool empty() const;
69
70 inline size_t length() const;
71
72 void setTo(const String16& other);
73 status_t setTo(const char16_t* other);
74 status_t setTo(const char16_t* other, size_t len);
75 status_t setTo(const String16& other,
76 size_t len,
77 size_t begin=0);
78
79 status_t append(const String16& other);
80 status_t append(const char16_t* other, size_t len);
81
82 inline String16& operator=(const String16& other);
83 String16& operator=(String16&& other) noexcept;
84
85 inline String16& operator+=(const String16& other);
86 inline String16 operator+(const String16& other) const;
87
88 status_t insert(size_t pos, const char16_t* chrs);
89 status_t insert(size_t pos,
90 const char16_t* chrs, size_t len);
91
92 ssize_t findFirst(char16_t c) const;
93 ssize_t findLast(char16_t c) const;
94
95 bool startsWith(const String16& prefix) const;
96 bool startsWith(const char16_t* prefix) const;
97
98 bool contains(const char16_t* chrs) const;
99 inline bool contains(const String16& other) const;
100
101 status_t replaceAll(char16_t replaceThis,
102 char16_t withThis);
103
104 inline int compare(const String16& other) const;
105
106 inline bool operator<(const String16& other) const;
107 inline bool operator<=(const String16& other) const;
108 inline bool operator==(const String16& other) const;
109 inline bool operator!=(const String16& other) const;
110 inline bool operator>=(const String16& other) const;
111 inline bool operator>(const String16& other) const;
112 #if __cplusplus >= 202002L
113 inline std::strong_ordering operator<=>(const String16& other) const;
114 #endif
115
116 inline bool operator<(const char16_t* other) const;
117 inline bool operator<=(const char16_t* other) const;
118 inline bool operator==(const char16_t* other) const;
119 inline bool operator!=(const char16_t* other) const;
120 inline bool operator>=(const char16_t* other) const;
121 inline bool operator>(const char16_t* other) const;
122 #if __cplusplus >= 202002L
123 inline std::strong_ordering operator<=>(const char16_t* other) const;
124 #endif
125
126 inline operator const char16_t*() const;
127
128 #ifdef HAS_STRING_VIEW
129 // Implicit cast to std::u16string is not implemented on purpose - u16string_view is much
130 // lighter and if one needs, they can still create u16string from u16string_view.
131 inline operator std::u16string_view() const;
132 #endif
133
134 // Static and non-static String16 behave the same for the users, so
135 // this method isn't of much use for the users. It is public for testing.
136 bool isStaticString() const;
137
138 private:
139 /*
140 * A flag indicating the type of underlying buffer.
141 */
142 static constexpr uint32_t kIsSharedBufferAllocated = 0x80000000;
143
144 /*
145 * alloc() returns void* so that SharedBuffer class is not exposed.
146 */
147 static void* alloc(size_t size);
148 static char16_t* allocFromUTF8(const char* u8str, size_t u8len);
149 static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len);
150
151 /*
152 * edit() and editResize() return void* so that SharedBuffer class
153 * is not exposed.
154 */
155 void* edit();
156 void* editResize(size_t new_size);
157
158 void acquire();
159 void release();
160
161 size_t staticStringSize() const;
162
163 const char16_t* mString;
164
165 protected:
166 /*
167 * Data structure used to allocate static storage for static String16.
168 *
169 * Note that this data structure and SharedBuffer are used interchangably
170 * as the underlying data structure for a String16. Therefore, the layout
171 * of this data structure must match the part in SharedBuffer that is
172 * visible to String16.
173 */
174 template <size_t N>
175 struct StaticData {
176 // The high bit of 'size' is used as a flag.
177 static_assert(N - 1 < kIsSharedBufferAllocated, "StaticString16 too long!");
StaticDataStaticData178 constexpr StaticData() : size(N - 1), data{0} {}
179 const uint32_t size;
180 char16_t data[N];
181
182 constexpr StaticData(const StaticData<N>&) = default;
183 };
184
185 /*
186 * Helper function for constructing a StaticData object.
187 */
188 template <size_t N>
makeStaticData(const char16_t (& s)[N])189 static constexpr const StaticData<N> makeStaticData(const char16_t (&s)[N]) {
190 StaticData<N> r;
191 // The 'size' field is at the same location where mClientMetadata would
192 // be for a SharedBuffer. We do NOT set kIsSharedBufferAllocated flag
193 // here.
194 for (size_t i = 0; i < N - 1; ++i) r.data[i] = s[i];
195 return r;
196 }
197
198 template <size_t N>
String16(const StaticData<N> & s)199 explicit constexpr String16(const StaticData<N>& s) : mString(s.data) {}
200
201 // These symbols are for potential backward compatibility with prebuilts. To be removed.
202 #ifdef ENABLE_STRING16_OBSOLETE_METHODS
203 public:
204 #else
205 private:
206 #endif
207 inline const char16_t* string() const;
208 };
209
210 // String16 can be trivially moved using memcpy() because moving does not
211 // require any change to the underlying SharedBuffer contents or reference count.
212 ANDROID_TRIVIAL_MOVE_TRAIT(String16)
213
214 static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
215 os << String8(str);
216 return os;
217 }
218
219 // ---------------------------------------------------------------------------
220
221 /*
222 * A StaticString16 object is a specialized String16 object. Instead of holding
223 * the string data in a ref counted SharedBuffer object, it holds data in a
224 * buffer within StaticString16 itself. Note that this buffer is NOT ref
225 * counted and is assumed to be available for as long as there is at least a
226 * String16 object using it. Therefore, one must be extra careful to NEVER
227 * assign a StaticString16 to a String16 that outlives the StaticString16
228 * object.
229 *
230 * THE SAFEST APPROACH IS TO USE StaticString16 ONLY AS GLOBAL VARIABLES.
231 *
232 * A StaticString16 SHOULD NEVER APPEAR IN APIs. USE String16 INSTEAD.
233 */
234 template <size_t N>
235 class StaticString16 : public String16 {
236 public:
StaticString16(const char16_t (& s)[N])237 constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {}
238
StaticString16(const StaticString16<N> & other)239 constexpr StaticString16(const StaticString16<N>& other)
240 : String16(mData), mData(other.mData) {}
241
242 constexpr StaticString16(const StaticString16<N>&&) = delete;
243
244 // There is no reason why one would want to 'new' a StaticString16. Delete
245 // it to discourage misuse.
246 static void* operator new(std::size_t) = delete;
247
248 private:
249 const StaticData<N> mData;
250 };
251
252 template <typename F>
253 StaticString16(const F&)->StaticString16<sizeof(F) / sizeof(char16_t)>;
254
255 // ---------------------------------------------------------------------------
256 // No user servicable parts below.
257
compare_type(const String16 & lhs,const String16 & rhs)258 inline int compare_type(const String16& lhs, const String16& rhs)
259 {
260 return lhs.compare(rhs);
261 }
262
strictly_order_type(const String16 & lhs,const String16 & rhs)263 inline int strictly_order_type(const String16& lhs, const String16& rhs)
264 {
265 return compare_type(lhs, rhs) < 0;
266 }
267
c_str()268 inline const char16_t* String16::c_str() const
269 {
270 return mString;
271 }
272
string()273 inline const char16_t* String16::string() const
274 {
275 return mString;
276 }
277
empty()278 inline bool String16::empty() const
279 {
280 return length() == 0;
281 }
282
length()283 inline size_t String16::length() const
284 {
285 return size();
286 }
287
contains(const String16 & other)288 inline bool String16::contains(const String16& other) const
289 {
290 return contains(other.c_str());
291 }
292
293 inline String16& String16::operator=(const String16& other)
294 {
295 setTo(other);
296 return *this;
297 }
298
299 inline String16& String16::operator+=(const String16& other)
300 {
301 append(other);
302 return *this;
303 }
304
305 inline String16 String16::operator+(const String16& other) const
306 {
307 String16 tmp(*this);
308 tmp += other;
309 return tmp;
310 }
311
compare(const String16 & other)312 inline int String16::compare(const String16& other) const
313 {
314 return strzcmp16(mString, size(), other.mString, other.size());
315 }
316
317 inline bool String16::operator<(const String16& other) const
318 {
319 return strzcmp16(mString, size(), other.mString, other.size()) < 0;
320 }
321
322 inline bool String16::operator<=(const String16& other) const
323 {
324 return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
325 }
326
327 inline bool String16::operator==(const String16& other) const
328 {
329 return strzcmp16(mString, size(), other.mString, other.size()) == 0;
330 }
331
332 inline bool String16::operator!=(const String16& other) const
333 {
334 return strzcmp16(mString, size(), other.mString, other.size()) != 0;
335 }
336
337 inline bool String16::operator>=(const String16& other) const
338 {
339 return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
340 }
341
342 inline bool String16::operator>(const String16& other) const
343 {
344 return strzcmp16(mString, size(), other.mString, other.size()) > 0;
345 }
346
347 #if __cplusplus >= 202002L
348 inline std::strong_ordering String16::operator<=>(const String16& other) const {
349 int result = strzcmp16(mString, size(), other.mString, other.size());
350 if (result == 0) {
351 return std::strong_ordering::equal;
352 } else if (result < 0) {
353 return std::strong_ordering::less;
354 } else {
355 return std::strong_ordering::greater;
356 }
357 }
358 #endif
359
360 inline bool String16::operator<(const char16_t* other) const
361 {
362 return strcmp16(mString, other) < 0;
363 }
364
365 inline bool String16::operator<=(const char16_t* other) const
366 {
367 return strcmp16(mString, other) <= 0;
368 }
369
370 inline bool String16::operator==(const char16_t* other) const
371 {
372 return strcmp16(mString, other) == 0;
373 }
374
375 inline bool String16::operator!=(const char16_t* other) const
376 {
377 return strcmp16(mString, other) != 0;
378 }
379
380 inline bool String16::operator>=(const char16_t* other) const
381 {
382 return strcmp16(mString, other) >= 0;
383 }
384
385 inline bool String16::operator>(const char16_t* other) const
386 {
387 return strcmp16(mString, other) > 0;
388 }
389
390 #if __cplusplus >= 202002L
391 inline std::strong_ordering String16::operator<=>(const char16_t* other) const {
392 int result = strcmp16(mString, other);
393 if (result == 0) {
394 return std::strong_ordering::equal;
395 } else if (result < 0) {
396 return std::strong_ordering::less;
397 } else {
398 return std::strong_ordering::greater;
399 }
400 }
401 #endif
402
403 inline String16::operator const char16_t*() const
404 {
405 return mString;
406 }
407
u16string_view()408 inline String16::operator std::u16string_view() const
409 {
410 return {mString, length()};
411 }
412
413 } // namespace android
414
415 // ---------------------------------------------------------------------------
416
417 #undef HAS_STRING_VIEW
418
419 #endif // ANDROID_STRING16_H
420