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 #include <utils/String16.h>
18
19 #include <log/log.h>
20
21 #include <ctype.h>
22
23 #include "SharedBuffer.h"
24
25 #define LIBUTILS_PRAGMA(arg) _Pragma(#arg)
26 #if defined(__clang__)
27 #define LIBUTILS_PRAGMA_FOR_COMPILER(arg) LIBUTILS_PRAGMA(clang arg)
28 #elif defined(__GNUC__)
29 #define LIBUTILS_PRAGMA_FOR_COMPILER(arg) LIBUTILS_PRAGMA(GCC arg)
30 #else
31 #define LIBUTILS_PRAGMA_FOR_COMPILER(arg)
32 #endif
33 #define LIBUTILS_IGNORE(warning_flag) \
34 LIBUTILS_PRAGMA_FOR_COMPILER(diagnostic push) \
35 LIBUTILS_PRAGMA_FOR_COMPILER(diagnostic ignored warning_flag)
36 #define LIBUTILS_IGNORE_END() LIBUTILS_PRAGMA_FOR_COMPILER(diagnostic pop)
37
38 namespace android {
39
40 static const StaticString16 emptyString(u"");
getEmptyString()41 static inline char16_t* getEmptyString() {
42 return const_cast<char16_t*>(emptyString.c_str());
43 }
44
45 // ---------------------------------------------------------------------------
46
alloc(size_t size)47 void* String16::alloc(size_t size)
48 {
49 SharedBuffer* buf = SharedBuffer::alloc(size);
50 buf->mClientMetadata = kIsSharedBufferAllocated;
51 return buf;
52 }
53
allocFromUTF8(const char * u8str,size_t u8len)54 char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
55 {
56 if (u8len == 0) return getEmptyString();
57
58 const uint8_t* u8cur = (const uint8_t*) u8str;
59
60 const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
61 if (u16len < 0) {
62 return getEmptyString();
63 }
64
65 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
66 if (buf) {
67 u8cur = (const uint8_t*) u8str;
68 char16_t* u16str = (char16_t*)buf->data();
69
70 utf8_to_utf16(u8cur, u8len, u16str, ((size_t) u16len) + 1);
71
72 //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
73 //printHexData(1, str, buf->size(), 16, 1);
74 //printf("\n");
75
76 return u16str;
77 }
78
79 return getEmptyString();
80 }
81
allocFromUTF16(const char16_t * u16str,size_t u16len)82 char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
83 if (u16len >= SIZE_MAX / sizeof(char16_t)) {
84 android_errorWriteLog(0x534e4554, "73826242");
85 abort();
86 }
87
88 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
89 ALOG_ASSERT(buf, "Unable to allocate shared buffer");
90 if (buf) {
91 char16_t* str = (char16_t*)buf->data();
92 memcpy(str, u16str, u16len * sizeof(char16_t));
93 str[u16len] = 0;
94 return str;
95 }
96 return getEmptyString();
97 }
98
99 // ---------------------------------------------------------------------------
100
String16()101 String16::String16()
102 : mString(getEmptyString())
103 {
104 }
105
String16(const String16 & o)106 String16::String16(const String16& o)
107 : mString(o.mString)
108 {
109 acquire();
110 }
111
String16(String16 && o)112 String16::String16(String16&& o) noexcept
113 : mString(o.mString)
114 {
115 o.mString = getEmptyString();
116 }
117
String16(const String16 & o,size_t len,size_t begin)118 String16::String16(const String16& o, size_t len, size_t begin)
119 : mString(getEmptyString())
120 {
121 setTo(o, len, begin);
122 }
123
String16(const char16_t * o)124 String16::String16(const char16_t* o) : mString(allocFromUTF16(o, strlen16(o))) {}
125
String16(const char16_t * o,size_t len)126 String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
127
String16(const String8 & o)128 String16::String16(const String8& o) : mString(allocFromUTF8(o.c_str(), o.size())) {}
129
String16(const char * o)130 String16::String16(const char* o)
131 : mString(allocFromUTF8(o, strlen(o)))
132 {
133 }
134
String16(const char * o,size_t len)135 String16::String16(const char* o, size_t len)
136 : mString(allocFromUTF8(o, len))
137 {
138 }
139
~String16()140 String16::~String16()
141 {
142 release();
143 }
144
operator =(String16 && other)145 String16& String16::operator=(String16&& other) noexcept {
146 release();
147 mString = other.mString;
148 other.mString = getEmptyString();
149 return *this;
150 }
151
size() const152 size_t String16::size() const
153 {
154 if (isStaticString()) {
155 return staticStringSize();
156 } else {
157 return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
158 }
159 }
160
setTo(const String16 & other)161 void String16::setTo(const String16& other)
162 {
163 release();
164 mString = other.mString;
165 acquire();
166 }
167
setTo(const String16 & other,size_t len,size_t begin)168 status_t String16::setTo(const String16& other, size_t len, size_t begin)
169 {
170 const size_t N = other.size();
171 if (begin >= N) {
172 release();
173 mString = getEmptyString();
174 return OK;
175 }
176 if ((begin+len) > N) len = N-begin;
177 if (begin == 0 && len == N) {
178 setTo(other);
179 return OK;
180 }
181
182 if (&other == this) {
183 LOG_ALWAYS_FATAL("Not implemented");
184 }
185
186 return setTo(other.c_str() + begin, len);
187 }
188
setTo(const char16_t * other)189 status_t String16::setTo(const char16_t* other)
190 {
191 return setTo(other, strlen16(other));
192 }
193
setTo(const char16_t * other,size_t len)194 status_t String16::setTo(const char16_t* other, size_t len)
195 {
196 if (len >= SIZE_MAX / sizeof(char16_t)) {
197 android_errorWriteLog(0x534e4554, "73826242");
198 abort();
199 }
200
201 SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
202 if (buf) {
203 char16_t* str = (char16_t*)buf->data();
204 memmove(str, other, len*sizeof(char16_t));
205 str[len] = 0;
206 mString = str;
207 return OK;
208 }
209 return NO_MEMORY;
210 }
211
append(const String16 & other)212 status_t String16::append(const String16& other) {
213 return append(other.c_str(), other.size());
214 }
215
append(const char16_t * chrs,size_t otherLen)216 status_t String16::append(const char16_t* chrs, size_t otherLen) {
217 const size_t myLen = size();
218
219 if (myLen == 0) return setTo(chrs, otherLen);
220
221 if (otherLen == 0) return OK;
222
223 size_t size = myLen;
224 if (__builtin_add_overflow(size, otherLen, &size) ||
225 __builtin_add_overflow(size, 1, &size) ||
226 __builtin_mul_overflow(size, sizeof(char16_t), &size)) return NO_MEMORY;
227
228 SharedBuffer* buf = static_cast<SharedBuffer*>(editResize(size));
229 if (!buf) return NO_MEMORY;
230
231 char16_t* str = static_cast<char16_t*>(buf->data());
232 memcpy(str + myLen, chrs, otherLen * sizeof(char16_t));
233 str[myLen + otherLen] = 0;
234 mString = str;
235 return OK;
236 }
237
insert(size_t pos,const char16_t * chrs)238 status_t String16::insert(size_t pos, const char16_t* chrs) {
239 return insert(pos, chrs, strlen16(chrs));
240 }
241
insert(size_t pos,const char16_t * chrs,size_t otherLen)242 status_t String16::insert(size_t pos, const char16_t* chrs, size_t otherLen) {
243 const size_t myLen = size();
244
245 if (myLen == 0) return setTo(chrs, otherLen);
246
247 if (otherLen == 0) return OK;
248
249 if (pos > myLen) pos = myLen;
250
251 size_t size = myLen;
252 if (__builtin_add_overflow(size, otherLen, &size) ||
253 __builtin_add_overflow(size, 1, &size) ||
254 __builtin_mul_overflow(size, sizeof(char16_t), &size)) return NO_MEMORY;
255
256 SharedBuffer* buf = static_cast<SharedBuffer*>(editResize(size));
257 if (!buf) return NO_MEMORY;
258
259 char16_t* str = static_cast<char16_t*>(buf->data());
260 if (pos < myLen) memmove(str + pos + otherLen, str + pos, (myLen - pos) * sizeof(char16_t));
261 memcpy(str + pos, chrs, otherLen * sizeof(char16_t));
262 str[myLen + otherLen] = 0;
263 mString = str;
264 return OK;
265 }
266
findFirst(char16_t c) const267 ssize_t String16::findFirst(char16_t c) const
268 {
269 const char16_t* str = string();
270 const char16_t* p = str;
271 const char16_t* e = p + size();
272 while (p < e) {
273 if (*p == c) {
274 return p-str;
275 }
276 p++;
277 }
278 return -1;
279 }
280
findLast(char16_t c) const281 ssize_t String16::findLast(char16_t c) const
282 {
283 const char16_t* str = string();
284 const char16_t* p = str;
285 const char16_t* e = p + size();
286 while (p < e) {
287 e--;
288 if (*e == c) {
289 return e-str;
290 }
291 }
292 return -1;
293 }
294
startsWith(const String16 & prefix) const295 bool String16::startsWith(const String16& prefix) const
296 {
297 const size_t ps = prefix.size();
298 if (ps > size()) return false;
299 return strzcmp16(mString, ps, prefix.c_str(), ps) == 0;
300 }
301
startsWith(const char16_t * prefix) const302 bool String16::startsWith(const char16_t* prefix) const
303 {
304 const size_t ps = strlen16(prefix);
305 if (ps > size()) return false;
306 return strncmp16(mString, prefix, ps) == 0;
307 }
308
contains(const char16_t * chrs) const309 bool String16::contains(const char16_t* chrs) const
310 {
311 return strstr16(mString, chrs) != nullptr;
312 }
313
edit()314 void* String16::edit() {
315 SharedBuffer* buf;
316 if (isStaticString()) {
317 buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
318 if (buf) {
319 memcpy(buf->data(), mString, (size() + 1) * sizeof(char16_t));
320 }
321 } else {
322 buf = SharedBuffer::bufferFromData(mString)->edit();
323 buf->mClientMetadata = kIsSharedBufferAllocated;
324 }
325 return buf;
326 }
327
editResize(size_t newSize)328 void* String16::editResize(size_t newSize) {
329 SharedBuffer* buf;
330 if (isStaticString()) {
331 size_t copySize = (size() + 1) * sizeof(char16_t);
332 if (newSize < copySize) {
333 copySize = newSize;
334 }
335 buf = static_cast<SharedBuffer*>(alloc(newSize));
336 if (buf) {
337 memcpy(buf->data(), mString, copySize);
338 }
339 } else {
340 buf = SharedBuffer::bufferFromData(mString)->editResize(newSize);
341 buf->mClientMetadata = kIsSharedBufferAllocated;
342 }
343 return buf;
344 }
345
acquire()346 void String16::acquire()
347 {
348 if (!isStaticString()) {
349 SharedBuffer::bufferFromData(mString)->acquire();
350 }
351 }
352
release()353 void String16::release()
354 {
355 if (!isStaticString()) {
356 SharedBuffer::bufferFromData(mString)->release();
357 }
358 }
359
isStaticString() const360 bool String16::isStaticString() const {
361 // See String16.h for notes on the memory layout of String16::StaticData and
362 // SharedBuffer.
363 LIBUTILS_IGNORE("-Winvalid-offsetof")
364 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
365 LIBUTILS_IGNORE_END()
366 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
367 return (*(p - 1) & kIsSharedBufferAllocated) == 0;
368 }
369
staticStringSize() const370 size_t String16::staticStringSize() const {
371 // See String16.h for notes on the memory layout of String16::StaticData and
372 // SharedBuffer.
373 LIBUTILS_IGNORE("-Winvalid-offsetof")
374 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
375 LIBUTILS_IGNORE_END()
376 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
377 return static_cast<size_t>(*(p - 1));
378 }
379
replaceAll(char16_t replaceThis,char16_t withThis)380 status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
381 {
382 const size_t N = size();
383 const char16_t* str = string();
384 char16_t* edited = nullptr;
385 for (size_t i=0; i<N; i++) {
386 if (str[i] == replaceThis) {
387 if (!edited) {
388 SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
389 if (!buf) {
390 return NO_MEMORY;
391 }
392 edited = (char16_t*)buf->data();
393 mString = str = edited;
394 }
395 edited[i] = withThis;
396 }
397 }
398 return OK;
399 }
400
401 }; // namespace android
402