• 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 #include <utils/String16.h>
18 
19 #include <utils/Log.h>
20 
21 #include <ctype.h>
22 
23 #include "SharedBuffer.h"
24 
25 namespace android {
26 
getEmptyString()27 static inline char16_t* getEmptyString() {
28     static SharedBuffer* gEmptyStringBuf = [] {
29         SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t));
30         char16_t* str = static_cast<char16_t*>(buf->data());
31         *str = 0;
32         return buf;
33     }();
34 
35     gEmptyStringBuf->acquire();
36     return static_cast<char16_t*>(gEmptyStringBuf->data());
37 }
38 
39 // ---------------------------------------------------------------------------
40 
allocFromUTF8(const char * u8str,size_t u8len)41 static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
42 {
43     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();
50     }
51 
52     SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
53     if (buf) {
54         u8cur = (const uint8_t*) u8str;
55         char16_t* u16str = (char16_t*)buf->data();
56 
57         utf8_to_utf16(u8cur, u8len, u16str, ((size_t) u16len) + 1);
58 
59         //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
60         //printHexData(1, str, buf->size(), 16, 1);
61         //printf("\n");
62 
63         return u16str;
64     }
65 
66     return getEmptyString();
67 }
68 
allocFromUTF16(const char16_t * u16str,size_t u16len)69 static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len) {
70     if (u16len >= SIZE_MAX / sizeof(char16_t)) {
71         android_errorWriteLog(0x534e4554, "73826242");
72         abort();
73     }
74 
75     SharedBuffer* buf = SharedBuffer::alloc((u16len + 1) * sizeof(char16_t));
76     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 
86 // ---------------------------------------------------------------------------
87 
String16()88 String16::String16()
89     : mString(getEmptyString())
90 {
91 }
92 
String16(StaticLinkage)93 String16::String16(StaticLinkage)
94     : mString(nullptr)
95 {
96     // this constructor is used when we can't rely on the static-initializers
97     // having run. In this case we always allocate an empty string. It's less
98     // efficient than using getEmptyString(), but we assume it's uncommon.
99 
100     char16_t* data = static_cast<char16_t*>(
101             SharedBuffer::alloc(sizeof(char16_t))->data());
102     data[0] = 0;
103     mString = data;
104 }
105 
String16(const String16 & o)106 String16::String16(const String16& o)
107     : mString(o.mString)
108 {
109     SharedBuffer::bufferFromData(mString)->acquire();
110 }
111 
String16(const String16 & o,size_t len,size_t begin)112 String16::String16(const String16& o, size_t len, size_t begin)
113     : mString(getEmptyString())
114 {
115     setTo(o, len, begin);
116 }
117 
String16(const char16_t * o)118 String16::String16(const char16_t* o) : mString(allocFromUTF16(o, strlen16(o))) {}
119 
String16(const char16_t * o,size_t len)120 String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
121 
String16(const String8 & o)122 String16::String16(const String8& o)
123     : mString(allocFromUTF8(o.string(), o.size()))
124 {
125 }
126 
String16(const char * o)127 String16::String16(const char* o)
128     : mString(allocFromUTF8(o, strlen(o)))
129 {
130 }
131 
String16(const char * o,size_t len)132 String16::String16(const char* o, size_t len)
133     : mString(allocFromUTF8(o, len))
134 {
135 }
136 
~String16()137 String16::~String16()
138 {
139     SharedBuffer::bufferFromData(mString)->release();
140 }
141 
size() const142 size_t String16::size() const
143 {
144     return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
145 }
146 
setTo(const String16 & other)147 void String16::setTo(const String16& other)
148 {
149     SharedBuffer::bufferFromData(other.mString)->acquire();
150     SharedBuffer::bufferFromData(mString)->release();
151     mString = other.mString;
152 }
153 
setTo(const String16 & other,size_t len,size_t begin)154 status_t String16::setTo(const String16& other, size_t len, size_t begin)
155 {
156     const size_t N = other.size();
157     if (begin >= N) {
158         SharedBuffer::bufferFromData(mString)->release();
159         mString = getEmptyString();
160         return OK;
161     }
162     if ((begin+len) > N) len = N-begin;
163     if (begin == 0 && len == N) {
164         setTo(other);
165         return OK;
166     }
167 
168     if (&other == this) {
169         LOG_ALWAYS_FATAL("Not implemented");
170     }
171 
172     return setTo(other.string()+begin, len);
173 }
174 
setTo(const char16_t * other)175 status_t String16::setTo(const char16_t* other)
176 {
177     return setTo(other, strlen16(other));
178 }
179 
setTo(const char16_t * other,size_t len)180 status_t String16::setTo(const char16_t* other, size_t len)
181 {
182     if (len >= SIZE_MAX / sizeof(char16_t)) {
183         android_errorWriteLog(0x534e4554, "73826242");
184         abort();
185     }
186 
187     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
188         ->editResize((len+1)*sizeof(char16_t));
189     if (buf) {
190         char16_t* str = (char16_t*)buf->data();
191         memmove(str, other, len*sizeof(char16_t));
192         str[len] = 0;
193         mString = str;
194         return OK;
195     }
196     return NO_MEMORY;
197 }
198 
append(const String16 & other)199 status_t String16::append(const String16& other)
200 {
201     const size_t myLen = size();
202     const size_t otherLen = other.size();
203     if (myLen == 0) {
204         setTo(other);
205         return OK;
206     } else if (otherLen == 0) {
207         return OK;
208     }
209 
210     if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
211         android_errorWriteLog(0x534e4554, "73826242");
212         abort();
213     }
214 
215     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
216         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
217     if (buf) {
218         char16_t* str = (char16_t*)buf->data();
219         memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
220         mString = str;
221         return OK;
222     }
223     return NO_MEMORY;
224 }
225 
append(const char16_t * chrs,size_t otherLen)226 status_t String16::append(const char16_t* chrs, size_t otherLen)
227 {
228     const size_t myLen = size();
229     if (myLen == 0) {
230         setTo(chrs, otherLen);
231         return OK;
232     } else if (otherLen == 0) {
233         return OK;
234     }
235 
236     if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
237         android_errorWriteLog(0x534e4554, "73826242");
238         abort();
239     }
240 
241     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
242         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
243     if (buf) {
244         char16_t* str = (char16_t*)buf->data();
245         memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
246         str[myLen+otherLen] = 0;
247         mString = str;
248         return OK;
249     }
250     return NO_MEMORY;
251 }
252 
insert(size_t pos,const char16_t * chrs)253 status_t String16::insert(size_t pos, const char16_t* chrs)
254 {
255     return insert(pos, chrs, strlen16(chrs));
256 }
257 
insert(size_t pos,const char16_t * chrs,size_t len)258 status_t String16::insert(size_t pos, const char16_t* chrs, size_t len)
259 {
260     const size_t myLen = size();
261     if (myLen == 0) {
262         return setTo(chrs, len);
263         return OK;
264     } else if (len == 0) {
265         return OK;
266     }
267 
268     if (pos > myLen) pos = myLen;
269 
270     #if 0
271     printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n",
272            String8(*this).string(), pos,
273            len, myLen, String8(chrs, len).string());
274     #endif
275 
276     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
277         ->editResize((myLen+len+1)*sizeof(char16_t));
278     if (buf) {
279         char16_t* str = (char16_t*)buf->data();
280         if (pos < myLen) {
281             memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t));
282         }
283         memcpy(str+pos, chrs, len*sizeof(char16_t));
284         str[myLen+len] = 0;
285         mString = str;
286         #if 0
287         printf("Result (%d chrs): %s\n", size(), String8(*this).string());
288         #endif
289         return OK;
290     }
291     return NO_MEMORY;
292 }
293 
findFirst(char16_t c) const294 ssize_t String16::findFirst(char16_t c) const
295 {
296     const char16_t* str = string();
297     const char16_t* p = str;
298     const char16_t* e = p + size();
299     while (p < e) {
300         if (*p == c) {
301             return p-str;
302         }
303         p++;
304     }
305     return -1;
306 }
307 
findLast(char16_t c) const308 ssize_t String16::findLast(char16_t c) const
309 {
310     const char16_t* str = string();
311     const char16_t* p = str;
312     const char16_t* e = p + size();
313     while (p < e) {
314         e--;
315         if (*e == c) {
316             return e-str;
317         }
318     }
319     return -1;
320 }
321 
startsWith(const String16 & prefix) const322 bool String16::startsWith(const String16& prefix) const
323 {
324     const size_t ps = prefix.size();
325     if (ps > size()) return false;
326     return strzcmp16(mString, ps, prefix.string(), ps) == 0;
327 }
328 
startsWith(const char16_t * prefix) const329 bool String16::startsWith(const char16_t* prefix) const
330 {
331     const size_t ps = strlen16(prefix);
332     if (ps > size()) return false;
333     return strncmp16(mString, prefix, ps) == 0;
334 }
335 
contains(const char16_t * chrs) const336 bool String16::contains(const char16_t* chrs) const
337 {
338     return strstr16(mString, chrs) != nullptr;
339 }
340 
makeLower()341 status_t String16::makeLower()
342 {
343     const size_t N = size();
344     const char16_t* str = string();
345     char16_t* edit = nullptr;
346     for (size_t i=0; i<N; i++) {
347         const char16_t v = str[i];
348         if (v >= 'A' && v <= 'Z') {
349             if (!edit) {
350                 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
351                 if (!buf) {
352                     return NO_MEMORY;
353                 }
354                 edit = (char16_t*)buf->data();
355                 mString = str = edit;
356             }
357             edit[i] = tolower((char)v);
358         }
359     }
360     return OK;
361 }
362 
replaceAll(char16_t replaceThis,char16_t withThis)363 status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
364 {
365     const size_t N = size();
366     const char16_t* str = string();
367     char16_t* edit = nullptr;
368     for (size_t i=0; i<N; i++) {
369         if (str[i] == replaceThis) {
370             if (!edit) {
371                 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
372                 if (!buf) {
373                     return NO_MEMORY;
374                 }
375                 edit = (char16_t*)buf->data();
376                 mString = str = edit;
377             }
378             edit[i] = withThis;
379         }
380     }
381     return OK;
382 }
383 
remove(size_t len,size_t begin)384 status_t String16::remove(size_t len, size_t begin)
385 {
386     const size_t N = size();
387     if (begin >= N) {
388         SharedBuffer::bufferFromData(mString)->release();
389         mString = getEmptyString();
390         return OK;
391     }
392     if (len > N || len > N - begin) len = N - begin;
393     if (begin == 0 && len == N) {
394         return OK;
395     }
396 
397     if (begin > 0) {
398         SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
399             ->editResize((N+1)*sizeof(char16_t));
400         if (!buf) {
401             return NO_MEMORY;
402         }
403         char16_t* str = (char16_t*)buf->data();
404         memmove(str, str+begin, (N-begin+1)*sizeof(char16_t));
405         mString = str;
406     }
407     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
408         ->editResize((len+1)*sizeof(char16_t));
409     if (buf) {
410         char16_t* str = (char16_t*)buf->data();
411         str[len] = 0;
412         mString = str;
413         return OK;
414     }
415     return NO_MEMORY;
416 }
417 
418 }; // namespace android
419