blob: 96e1477215339a68eec3342f819b7321577fa9ad [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
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
Steven Moreland066e6252023-10-07 00:29:44 +000019#include <log/log.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080020
Steven Morelandd21cfab2017-03-10 08:58:36 -080021#include <ctype.h>
22
Sergio Girod2529f22015-09-23 16:22:59 +010023#include "SharedBuffer.h"
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080024
Tomasz Wasilczyk0a2a0152024-04-30 10:47:35 -070025#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
Kenny Root9a2d83e2009-12-04 09:38:48 -080038namespace android {
39
Vic Yang9fb93ed2019-09-05 13:18:27 -070040static const StaticString16 emptyString(u"");
Steven Moreland241b93c2018-03-06 09:11:29 -080041static inline char16_t* getEmptyString() {
Tomasz Wasilczyk90af4152023-08-11 02:12:16 +000042 return const_cast<char16_t*>(emptyString.c_str());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080043}
44
45// ---------------------------------------------------------------------------
46
Vic Yang9fb93ed2019-09-05 13:18:27 -070047void* String16::alloc(size_t size)
48{
49 SharedBuffer* buf = SharedBuffer::alloc(size);
50 buf->mClientMetadata = kIsSharedBufferAllocated;
51 return buf;
52}
53
54char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080055{
Kenny Rootba0165b2010-11-09 14:37:23 -080056 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();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080063 }
Kenny Rootba0165b2010-11-09 14:37:23 -080064
Vic Yang9fb93ed2019-09-05 13:18:27 -070065 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080066 if (buf) {
Kenny Rootba0165b2010-11-09 14:37:23 -080067 u8cur = (const uint8_t*) u8str;
68 char16_t* u16str = (char16_t*)buf->data();
69
Sergio Giro1dcc0c82016-07-20 20:01:33 +010070 utf8_to_utf16(u8cur, u8len, u16str, ((size_t) u16len) + 1);
Kenny Root9a2d83e2009-12-04 09:38:48 -080071
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080072 //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
73 //printHexData(1, str, buf->size(), 16, 1);
74 //printf("\n");
Samuel Tanf9d16ef2016-02-16 15:17:10 -080075
Kenny Rootba0165b2010-11-09 14:37:23 -080076 return u16str;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080077 }
Kenny Rootba0165b2010-11-09 14:37:23 -080078
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080079 return getEmptyString();
80}
81
Vic Yang9fb93ed2019-09-05 13:18:27 -070082char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
Steven Moreland977f72f2018-03-01 11:03:04 -080083 if (u16len >= SIZE_MAX / sizeof(char16_t)) {
84 android_errorWriteLog(0x534e4554, "73826242");
85 abort();
86 }
87
Vic Yang9fb93ed2019-09-05 13:18:27 -070088 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
Steven Moreland977f72f2018-03-01 11:03:04 -080089 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
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080099// ---------------------------------------------------------------------------
100
101String16::String16()
102 : mString(getEmptyString())
103{
104}
105
106String16::String16(const String16& o)
107 : mString(o.mString)
108{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700109 acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800110}
111
Jooyung Han98b396e2021-06-27 03:30:42 +0900112String16::String16(String16&& o) noexcept
113 : mString(o.mString)
114{
115 o.mString = getEmptyString();
116}
117
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800118String16::String16(const String16& o, size_t len, size_t begin)
119 : mString(getEmptyString())
120{
121 setTo(o, len, begin);
122}
123
Steven Moreland977f72f2018-03-01 11:03:04 -0800124String16::String16(const char16_t* o) : mString(allocFromUTF16(o, strlen16(o))) {}
Samuel Tanf9d16ef2016-02-16 15:17:10 -0800125
Steven Moreland977f72f2018-03-01 11:03:04 -0800126String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800127
Tomasz Wasilczyk90af4152023-08-11 02:12:16 +0000128String16::String16(const String8& o) : mString(allocFromUTF8(o.c_str(), o.size())) {}
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800129
130String16::String16(const char* o)
131 : mString(allocFromUTF8(o, strlen(o)))
132{
133}
134
135String16::String16(const char* o, size_t len)
136 : mString(allocFromUTF8(o, len))
137{
138}
139
140String16::~String16()
141{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700142 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800143}
144
Jooyung Han98b396e2021-06-27 03:30:42 +0900145String16& String16::operator=(String16&& other) noexcept {
146 release();
147 mString = other.mString;
148 other.mString = getEmptyString();
149 return *this;
150}
151
Sergio Girod2529f22015-09-23 16:22:59 +0100152size_t String16::size() const
153{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700154 if (isStaticString()) {
155 return staticStringSize();
156 } else {
157 return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
158 }
Sergio Girod2529f22015-09-23 16:22:59 +0100159}
160
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800161void String16::setTo(const String16& other)
162{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700163 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800164 mString = other.mString;
Vic Yang9fb93ed2019-09-05 13:18:27 -0700165 acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800166}
167
168status_t String16::setTo(const String16& other, size_t len, size_t begin)
169{
170 const size_t N = other.size();
171 if (begin >= N) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700172 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800173 mString = getEmptyString();
Elliott Hughes643268f2018-10-08 11:10:11 -0700174 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800175 }
176 if ((begin+len) > N) len = N-begin;
177 if (begin == 0 && len == N) {
178 setTo(other);
Elliott Hughes643268f2018-10-08 11:10:11 -0700179 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800180 }
181
182 if (&other == this) {
183 LOG_ALWAYS_FATAL("Not implemented");
184 }
185
Tomasz Wasilczyk90af4152023-08-11 02:12:16 +0000186 return setTo(other.c_str() + begin, len);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800187}
188
189status_t String16::setTo(const char16_t* other)
190{
191 return setTo(other, strlen16(other));
192}
193
194status_t String16::setTo(const char16_t* other, size_t len)
195{
Steven Moreland977f72f2018-03-01 11:03:04 -0800196 if (len >= SIZE_MAX / sizeof(char16_t)) {
197 android_errorWriteLog(0x534e4554, "73826242");
198 abort();
199 }
200
Vic Yang9fb93ed2019-09-05 13:18:27 -0700201 SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800202 if (buf) {
203 char16_t* str = (char16_t*)buf->data();
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800204 memmove(str, other, len*sizeof(char16_t));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800205 str[len] = 0;
206 mString = str;
Elliott Hughes643268f2018-10-08 11:10:11 -0700207 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800208 }
209 return NO_MEMORY;
210}
211
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700212status_t String16::append(const String16& other) {
Tomasz Wasilczyk90af4152023-08-11 02:12:16 +0000213 return append(other.c_str(), other.size());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800214}
215
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700216status_t String16::append(const char16_t* chrs, size_t otherLen) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800217 const size_t myLen = size();
Samuel Tanf9d16ef2016-02-16 15:17:10 -0800218
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700219 if (myLen == 0) return setTo(chrs, otherLen);
Steven Moreland977f72f2018-03-01 11:03:04 -0800220
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700221 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;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800236}
237
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700238status_t String16::insert(size_t pos, const char16_t* chrs) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800239 return insert(pos, chrs, strlen16(chrs));
240}
241
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700242status_t String16::insert(size_t pos, const char16_t* chrs, size_t otherLen) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800243 const size_t myLen = size();
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700244
245 if (myLen == 0) return setTo(chrs, otherLen);
246
247 if (otherLen == 0) return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800248
249 if (pos > myLen) pos = myLen;
250
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700251 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;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800255
Elliott Hughesa6be6f02021-06-10 17:06:26 -0700256 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;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800265}
266
267ssize_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
281ssize_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
295bool String16::startsWith(const String16& prefix) const
296{
297 const size_t ps = prefix.size();
298 if (ps > size()) return false;
Tomasz Wasilczyk90af4152023-08-11 02:12:16 +0000299 return strzcmp16(mString, ps, prefix.c_str(), ps) == 0;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800300}
301
302bool 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
Michael Wright5bacef32016-05-09 14:43:31 +0100309bool String16::contains(const char16_t* chrs) const
310{
311 return strstr16(mString, chrs) != nullptr;
312}
313
Vic Yang9fb93ed2019-09-05 13:18:27 -0700314void* String16::edit() {
315 SharedBuffer* buf;
316 if (isStaticString()) {
317 buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
318 if (buf) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700319 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
328void* 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) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700337 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
346void String16::acquire()
347{
348 if (!isStaticString()) {
349 SharedBuffer::bufferFromData(mString)->acquire();
350 }
351}
352
353void String16::release()
354{
355 if (!isStaticString()) {
356 SharedBuffer::bufferFromData(mString)->release();
357 }
358}
359
360bool String16::isStaticString() const {
361 // See String16.h for notes on the memory layout of String16::StaticData and
362 // SharedBuffer.
Tomasz Wasilczyk0a2a0152024-04-30 10:47:35 -0700363 LIBUTILS_IGNORE("-Winvalid-offsetof")
Vic Yang9fb93ed2019-09-05 13:18:27 -0700364 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
Tomasz Wasilczyk0a2a0152024-04-30 10:47:35 -0700365 LIBUTILS_IGNORE_END()
Vic Yang9fb93ed2019-09-05 13:18:27 -0700366 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
367 return (*(p - 1) & kIsSharedBufferAllocated) == 0;
368}
369
370size_t String16::staticStringSize() const {
371 // See String16.h for notes on the memory layout of String16::StaticData and
372 // SharedBuffer.
Tomasz Wasilczyk0a2a0152024-04-30 10:47:35 -0700373 LIBUTILS_IGNORE("-Winvalid-offsetof")
Vic Yang9fb93ed2019-09-05 13:18:27 -0700374 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
Tomasz Wasilczyk0a2a0152024-04-30 10:47:35 -0700375 LIBUTILS_IGNORE_END()
Vic Yang9fb93ed2019-09-05 13:18:27 -0700376 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
377 return static_cast<size_t>(*(p - 1));
378}
379
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800380status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
381{
382 const size_t N = size();
383 const char16_t* str = string();
Vic Yang9fb93ed2019-09-05 13:18:27 -0700384 char16_t* edited = nullptr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800385 for (size_t i=0; i<N; i++) {
386 if (str[i] == replaceThis) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700387 if (!edited) {
388 SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800389 if (!buf) {
390 return NO_MEMORY;
391 }
Vic Yang9fb93ed2019-09-05 13:18:27 -0700392 edited = (char16_t*)buf->data();
393 mString = str = edited;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800394 }
Vic Yang9fb93ed2019-09-05 13:18:27 -0700395 edited[i] = withThis;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800396 }
397 }
Elliott Hughes643268f2018-10-08 11:10:11 -0700398 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800399}
400
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800401}; // namespace android