blob: faf90c233893a8530ab999034638f25d35c096cd [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
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080019#include <utils/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
Kenny Root9a2d83e2009-12-04 09:38:48 -080025namespace android {
26
Vic Yang9fb93ed2019-09-05 13:18:27 -070027static const StaticString16 emptyString(u"");
Steven Moreland241b93c2018-03-06 09:11:29 -080028static inline char16_t* getEmptyString() {
Vic Yang9fb93ed2019-09-05 13:18:27 -070029 return const_cast<char16_t*>(emptyString.string());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080030}
31
32// ---------------------------------------------------------------------------
33
Vic Yang9fb93ed2019-09-05 13:18:27 -070034void* String16::alloc(size_t size)
35{
36 SharedBuffer* buf = SharedBuffer::alloc(size);
37 buf->mClientMetadata = kIsSharedBufferAllocated;
38 return buf;
39}
40
41char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080042{
Kenny Rootba0165b2010-11-09 14:37:23 -080043 if (u8len == 0) return getEmptyString();
44
45 const uint8_t* u8cur = (const uint8_t*) u8str;
46
47 const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
48 if (u16len < 0) {
49 return getEmptyString();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080050 }
Kenny Rootba0165b2010-11-09 14:37:23 -080051
Vic Yang9fb93ed2019-09-05 13:18:27 -070052 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080053 if (buf) {
Kenny Rootba0165b2010-11-09 14:37:23 -080054 u8cur = (const uint8_t*) u8str;
55 char16_t* u16str = (char16_t*)buf->data();
56
Sergio Giro1dcc0c82016-07-20 20:01:33 +010057 utf8_to_utf16(u8cur, u8len, u16str, ((size_t) u16len) + 1);
Kenny Root9a2d83e2009-12-04 09:38:48 -080058
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080059 //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
60 //printHexData(1, str, buf->size(), 16, 1);
61 //printf("\n");
Samuel Tanf9d16ef2016-02-16 15:17:10 -080062
Kenny Rootba0165b2010-11-09 14:37:23 -080063 return u16str;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080064 }
Kenny Rootba0165b2010-11-09 14:37:23 -080065
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080066 return getEmptyString();
67}
68
Vic Yang9fb93ed2019-09-05 13:18:27 -070069char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
Steven Moreland977f72f2018-03-01 11:03:04 -080070 if (u16len >= SIZE_MAX / sizeof(char16_t)) {
71 android_errorWriteLog(0x534e4554, "73826242");
72 abort();
73 }
74
Vic Yang9fb93ed2019-09-05 13:18:27 -070075 SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
Steven Moreland977f72f2018-03-01 11:03:04 -080076 ALOG_ASSERT(buf, "Unable to allocate shared buffer");
77 if (buf) {
78 char16_t* str = (char16_t*)buf->data();
79 memcpy(str, u16str, u16len * sizeof(char16_t));
80 str[u16len] = 0;
81 return str;
82 }
83 return getEmptyString();
84}
85
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080086// ---------------------------------------------------------------------------
87
88String16::String16()
89 : mString(getEmptyString())
90{
91}
92
93String16::String16(const String16& o)
94 : mString(o.mString)
95{
Vic Yang9fb93ed2019-09-05 13:18:27 -070096 acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080097}
98
99String16::String16(const String16& o, size_t len, size_t begin)
100 : mString(getEmptyString())
101{
102 setTo(o, len, begin);
103}
104
Steven Moreland977f72f2018-03-01 11:03:04 -0800105String16::String16(const char16_t* o) : mString(allocFromUTF16(o, strlen16(o))) {}
Samuel Tanf9d16ef2016-02-16 15:17:10 -0800106
Steven Moreland977f72f2018-03-01 11:03:04 -0800107String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800108
109String16::String16(const String8& o)
110 : mString(allocFromUTF8(o.string(), o.size()))
111{
112}
113
114String16::String16(const char* o)
115 : mString(allocFromUTF8(o, strlen(o)))
116{
117}
118
119String16::String16(const char* o, size_t len)
120 : mString(allocFromUTF8(o, len))
121{
122}
123
124String16::~String16()
125{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700126 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800127}
128
Sergio Girod2529f22015-09-23 16:22:59 +0100129size_t String16::size() const
130{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700131 if (isStaticString()) {
132 return staticStringSize();
133 } else {
134 return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
135 }
Sergio Girod2529f22015-09-23 16:22:59 +0100136}
137
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800138void String16::setTo(const String16& other)
139{
Vic Yang9fb93ed2019-09-05 13:18:27 -0700140 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800141 mString = other.mString;
Vic Yang9fb93ed2019-09-05 13:18:27 -0700142 acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800143}
144
145status_t String16::setTo(const String16& other, size_t len, size_t begin)
146{
147 const size_t N = other.size();
148 if (begin >= N) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700149 release();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800150 mString = getEmptyString();
Elliott Hughes643268f2018-10-08 11:10:11 -0700151 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800152 }
153 if ((begin+len) > N) len = N-begin;
154 if (begin == 0 && len == N) {
155 setTo(other);
Elliott Hughes643268f2018-10-08 11:10:11 -0700156 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800157 }
158
159 if (&other == this) {
160 LOG_ALWAYS_FATAL("Not implemented");
161 }
162
163 return setTo(other.string()+begin, len);
164}
165
166status_t String16::setTo(const char16_t* other)
167{
168 return setTo(other, strlen16(other));
169}
170
171status_t String16::setTo(const char16_t* other, size_t len)
172{
Steven Moreland977f72f2018-03-01 11:03:04 -0800173 if (len >= SIZE_MAX / sizeof(char16_t)) {
174 android_errorWriteLog(0x534e4554, "73826242");
175 abort();
176 }
177
Vic Yang9fb93ed2019-09-05 13:18:27 -0700178 SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800179 if (buf) {
180 char16_t* str = (char16_t*)buf->data();
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800181 memmove(str, other, len*sizeof(char16_t));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800182 str[len] = 0;
183 mString = str;
Elliott Hughes643268f2018-10-08 11:10:11 -0700184 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800185 }
186 return NO_MEMORY;
187}
188
189status_t String16::append(const String16& other)
190{
191 const size_t myLen = size();
192 const size_t otherLen = other.size();
193 if (myLen == 0) {
194 setTo(other);
Elliott Hughes643268f2018-10-08 11:10:11 -0700195 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800196 } else if (otherLen == 0) {
Elliott Hughes643268f2018-10-08 11:10:11 -0700197 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800198 }
Samuel Tanf9d16ef2016-02-16 15:17:10 -0800199
Steven Moreland977f72f2018-03-01 11:03:04 -0800200 if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
201 android_errorWriteLog(0x534e4554, "73826242");
202 abort();
203 }
204
Vic Yang9fb93ed2019-09-05 13:18:27 -0700205 SharedBuffer* buf =
206 static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800207 if (buf) {
208 char16_t* str = (char16_t*)buf->data();
209 memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
210 mString = str;
Elliott Hughes643268f2018-10-08 11:10:11 -0700211 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800212 }
213 return NO_MEMORY;
214}
215
216status_t String16::append(const char16_t* chrs, size_t otherLen)
217{
218 const size_t myLen = size();
219 if (myLen == 0) {
220 setTo(chrs, otherLen);
Elliott Hughes643268f2018-10-08 11:10:11 -0700221 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800222 } else if (otherLen == 0) {
Elliott Hughes643268f2018-10-08 11:10:11 -0700223 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800224 }
Samuel Tanf9d16ef2016-02-16 15:17:10 -0800225
Steven Moreland977f72f2018-03-01 11:03:04 -0800226 if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
227 android_errorWriteLog(0x534e4554, "73826242");
228 abort();
229 }
230
Vic Yang9fb93ed2019-09-05 13:18:27 -0700231 SharedBuffer* buf =
232 static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800233 if (buf) {
234 char16_t* str = (char16_t*)buf->data();
235 memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
236 str[myLen+otherLen] = 0;
237 mString = str;
Elliott Hughes643268f2018-10-08 11:10:11 -0700238 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800239 }
240 return NO_MEMORY;
241}
242
243status_t String16::insert(size_t pos, const char16_t* chrs)
244{
245 return insert(pos, chrs, strlen16(chrs));
246}
247
248status_t String16::insert(size_t pos, const char16_t* chrs, size_t len)
249{
250 const size_t myLen = size();
251 if (myLen == 0) {
252 return setTo(chrs, len);
Elliott Hughes643268f2018-10-08 11:10:11 -0700253 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800254 } else if (len == 0) {
Elliott Hughes643268f2018-10-08 11:10:11 -0700255 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800256 }
257
258 if (pos > myLen) pos = myLen;
259
260 #if 0
261 printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n",
262 String8(*this).string(), pos,
263 len, myLen, String8(chrs, len).string());
264 #endif
265
Vic Yang9fb93ed2019-09-05 13:18:27 -0700266 SharedBuffer* buf =
267 static_cast<SharedBuffer*>(editResize((myLen + len + 1) * sizeof(char16_t)));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800268 if (buf) {
269 char16_t* str = (char16_t*)buf->data();
270 if (pos < myLen) {
271 memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t));
272 }
273 memcpy(str+pos, chrs, len*sizeof(char16_t));
274 str[myLen+len] = 0;
275 mString = str;
276 #if 0
277 printf("Result (%d chrs): %s\n", size(), String8(*this).string());
278 #endif
Elliott Hughes643268f2018-10-08 11:10:11 -0700279 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800280 }
281 return NO_MEMORY;
282}
283
284ssize_t String16::findFirst(char16_t c) const
285{
286 const char16_t* str = string();
287 const char16_t* p = str;
288 const char16_t* e = p + size();
289 while (p < e) {
290 if (*p == c) {
291 return p-str;
292 }
293 p++;
294 }
295 return -1;
296}
297
298ssize_t String16::findLast(char16_t c) const
299{
300 const char16_t* str = string();
301 const char16_t* p = str;
302 const char16_t* e = p + size();
303 while (p < e) {
304 e--;
305 if (*e == c) {
306 return e-str;
307 }
308 }
309 return -1;
310}
311
312bool String16::startsWith(const String16& prefix) const
313{
314 const size_t ps = prefix.size();
315 if (ps > size()) return false;
316 return strzcmp16(mString, ps, prefix.string(), ps) == 0;
317}
318
319bool String16::startsWith(const char16_t* prefix) const
320{
321 const size_t ps = strlen16(prefix);
322 if (ps > size()) return false;
323 return strncmp16(mString, prefix, ps) == 0;
324}
325
Michael Wright5bacef32016-05-09 14:43:31 +0100326bool String16::contains(const char16_t* chrs) const
327{
328 return strstr16(mString, chrs) != nullptr;
329}
330
Vic Yang9fb93ed2019-09-05 13:18:27 -0700331void* String16::edit() {
332 SharedBuffer* buf;
333 if (isStaticString()) {
334 buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
335 if (buf) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700336 memcpy(buf->data(), mString, (size() + 1) * sizeof(char16_t));
337 }
338 } else {
339 buf = SharedBuffer::bufferFromData(mString)->edit();
340 buf->mClientMetadata = kIsSharedBufferAllocated;
341 }
342 return buf;
343}
344
345void* String16::editResize(size_t newSize) {
346 SharedBuffer* buf;
347 if (isStaticString()) {
348 size_t copySize = (size() + 1) * sizeof(char16_t);
349 if (newSize < copySize) {
350 copySize = newSize;
351 }
352 buf = static_cast<SharedBuffer*>(alloc(newSize));
353 if (buf) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700354 memcpy(buf->data(), mString, copySize);
355 }
356 } else {
357 buf = SharedBuffer::bufferFromData(mString)->editResize(newSize);
358 buf->mClientMetadata = kIsSharedBufferAllocated;
359 }
360 return buf;
361}
362
363void String16::acquire()
364{
365 if (!isStaticString()) {
366 SharedBuffer::bufferFromData(mString)->acquire();
367 }
368}
369
370void String16::release()
371{
372 if (!isStaticString()) {
373 SharedBuffer::bufferFromData(mString)->release();
374 }
375}
376
377bool String16::isStaticString() const {
378 // See String16.h for notes on the memory layout of String16::StaticData and
379 // SharedBuffer.
380 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
381 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
382 return (*(p - 1) & kIsSharedBufferAllocated) == 0;
383}
384
385size_t String16::staticStringSize() const {
386 // See String16.h for notes on the memory layout of String16::StaticData and
387 // SharedBuffer.
388 static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
389 const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
390 return static_cast<size_t>(*(p - 1));
391}
392
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800393status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
394{
395 const size_t N = size();
396 const char16_t* str = string();
Vic Yang9fb93ed2019-09-05 13:18:27 -0700397 char16_t* edited = nullptr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800398 for (size_t i=0; i<N; i++) {
399 if (str[i] == replaceThis) {
Vic Yang9fb93ed2019-09-05 13:18:27 -0700400 if (!edited) {
401 SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800402 if (!buf) {
403 return NO_MEMORY;
404 }
Vic Yang9fb93ed2019-09-05 13:18:27 -0700405 edited = (char16_t*)buf->data();
406 mString = str = edited;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800407 }
Vic Yang9fb93ed2019-09-05 13:18:27 -0700408 edited[i] = withThis;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800409 }
410 }
Elliott Hughes643268f2018-10-08 11:10:11 -0700411 return OK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800412}
413
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800414}; // namespace android