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