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