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