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