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