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