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