• 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/String8.h>
22 #include <utils/TextOutput.h>
23 #include <utils/threads.h>
24 
25 #include <private/utils/Static.h>
26 
27 #ifdef HAVE_WINSOCK
28 # undef  nhtol
29 # undef  htonl
30 # undef  nhtos
31 # undef  htons
32 
33 # ifdef HAVE_LITTLE_ENDIAN
34 #  define ntohl(x)    ( ((x) << 24) | (((x) >> 24) & 255) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) )
35 #  define htonl(x)    ntohl(x)
36 #  define ntohs(x)    ( (((x) << 8) & 0xff00) | (((x) >> 8) & 255) )
37 #  define htons(x)    ntohs(x)
38 # else
39 #  define ntohl(x)    (x)
40 #  define htonl(x)    (x)
41 #  define ntohs(x)    (x)
42 #  define htons(x)    (x)
43 # endif
44 #else
45 # include <netinet/in.h>
46 #endif
47 
48 #include <memory.h>
49 #include <stdio.h>
50 #include <ctype.h>
51 
52 // ---------------------------------------------------------------------------
53 
strcmp16(const char16_t * s1,const char16_t * s2)54 int strcmp16(const char16_t *s1, const char16_t *s2)
55 {
56   char16_t ch;
57   int d = 0;
58 
59   while ( 1 ) {
60     d = (int)(ch = *s1++) - (int)*s2++;
61     if ( d || !ch )
62       break;
63   }
64 
65   return d;
66 }
67 
strncmp16(const char16_t * s1,const char16_t * s2,size_t n)68 int strncmp16(const char16_t *s1, const char16_t *s2, size_t n)
69 {
70   char16_t ch;
71   int d = 0;
72 
73   while ( n-- ) {
74     d = (int)(ch = *s1++) - (int)*s2++;
75     if ( d || !ch )
76       break;
77   }
78 
79   return d;
80 }
81 
strcpy16(char16_t * dst,const char16_t * src)82 char16_t *strcpy16(char16_t *dst, const char16_t *src)
83 {
84   char16_t *q = dst;
85   const char16_t *p = src;
86   char16_t ch;
87 
88   do {
89     *q++ = ch = *p++;
90   } while ( ch );
91 
92   return dst;
93 }
94 
strlen16(const char16_t * s)95 size_t strlen16(const char16_t *s)
96 {
97   const char16_t *ss = s;
98   while ( *ss )
99     ss++;
100   return ss-s;
101 }
102 
103 
strncpy16(char16_t * dst,const char16_t * src,size_t n)104 char16_t *strncpy16(char16_t *dst, const char16_t *src, size_t n)
105 {
106   char16_t *q = dst;
107   const char16_t *p = src;
108   char ch;
109 
110   while (n) {
111     n--;
112     *q++ = ch = *p++;
113     if ( !ch )
114       break;
115   }
116 
117   *q = 0;
118 
119   return dst;
120 }
121 
strnlen16(const char16_t * s,size_t maxlen)122 size_t strnlen16(const char16_t *s, size_t maxlen)
123 {
124   const char16_t *ss = s;
125 
126   /* Important: the maxlen test must precede the reference through ss;
127      since the byte beyond the maximum may segfault */
128   while ((maxlen > 0) && *ss) {
129     ss++;
130     maxlen--;
131   }
132   return ss-s;
133 }
134 
strzcmp16(const char16_t * s1,size_t n1,const char16_t * s2,size_t n2)135 int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2)
136 {
137     const char16_t* e1 = s1+n1;
138     const char16_t* e2 = s2+n2;
139 
140     while (s1 < e1 && s2 < e2) {
141         const int d = (int)*s1++ - (int)*s2++;
142         if (d) {
143             return d;
144         }
145     }
146 
147     return n1 < n2
148         ? (0 - (int)*s2)
149         : (n1 > n2
150            ? ((int)*s1 - 0)
151            : 0);
152 }
153 
strzcmp16_h_n(const char16_t * s1H,size_t n1,const char16_t * s2N,size_t n2)154 int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2)
155 {
156     const char16_t* e1 = s1H+n1;
157     const char16_t* e2 = s2N+n2;
158 
159     while (s1H < e1 && s2N < e2) {
160         const char16_t c2 = ntohs(*s2N);
161         const int d = (int)*s1H++ - (int)c2;
162         s2N++;
163         if (d) {
164             return d;
165         }
166     }
167 
168     return n1 < n2
169         ? (0 - (int)ntohs(*s2N))
170         : (n1 > n2
171            ? ((int)*s1H - 0)
172            : 0);
173 }
174 
175 // ---------------------------------------------------------------------------
176 
177 namespace android {
178 
179 static inline size_t
utf8_char_len(uint8_t ch)180 utf8_char_len(uint8_t ch)
181 {
182     return ((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1;
183 }
184 
185 #define UTF8_SHIFT_AND_MASK(unicode, byte)  (unicode)<<=6; (unicode) |= (0x3f & (byte));
186 
187 static inline uint32_t
utf8_to_utf32(const uint8_t * src,size_t length)188 utf8_to_utf32(const uint8_t *src, size_t length)
189 {
190     uint32_t unicode;
191 
192     switch (length)
193     {
194         case 1:
195             return src[0];
196         case 2:
197             unicode = src[0] & 0x1f;
198             UTF8_SHIFT_AND_MASK(unicode, src[1])
199             return unicode;
200         case 3:
201             unicode = src[0] & 0x0f;
202             UTF8_SHIFT_AND_MASK(unicode, src[1])
203             UTF8_SHIFT_AND_MASK(unicode, src[2])
204             return unicode;
205         case 4:
206             unicode = src[0] & 0x07;
207             UTF8_SHIFT_AND_MASK(unicode, src[1])
208             UTF8_SHIFT_AND_MASK(unicode, src[2])
209             UTF8_SHIFT_AND_MASK(unicode, src[3])
210             return unicode;
211         default:
212             return 0xffff;
213     }
214 
215     //printf("Char at %p: len=%d, utf-16=%p\n", src, length, (void*)result);
216 }
217 
218 // ---------------------------------------------------------------------------
219 
220 static SharedBuffer* gEmptyStringBuf = NULL;
221 static char16_t* gEmptyString = NULL;
222 
getEmptyString()223 static inline char16_t* getEmptyString()
224 {
225     gEmptyStringBuf->acquire();
226    return gEmptyString;
227 }
228 
initialize_string16()229 void initialize_string16()
230 {
231     SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t));
232     char16_t* str = (char16_t*)buf->data();
233     *str = 0;
234     gEmptyStringBuf = buf;
235     gEmptyString = str;
236 }
237 
terminate_string16()238 void terminate_string16()
239 {
240     SharedBuffer::bufferFromData(gEmptyString)->release();
241     gEmptyStringBuf = NULL;
242     gEmptyString = NULL;
243 }
244 
245 // ---------------------------------------------------------------------------
246 
allocFromUTF8(const char * in,size_t len)247 static char16_t* allocFromUTF8(const char* in, size_t len)
248 {
249     if (len == 0) return getEmptyString();
250 
251     size_t chars = 0;
252     const char* end = in+len;
253     const char* p = in;
254 
255     while (p < end) {
256         chars++;
257         int utf8len = utf8_char_len(*p);
258         uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, utf8len);
259         if (codepoint > 0xFFFF) chars++; // this will be a surrogate pair in utf16
260         p += utf8len;
261     }
262 
263     SharedBuffer* buf = SharedBuffer::alloc((chars+1)*sizeof(char16_t));
264     if (buf) {
265         p = in;
266         char16_t* str = (char16_t*)buf->data();
267         char16_t* d = str;
268         while (p < end) {
269             size_t len = utf8_char_len(*p);
270             uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, len);
271 
272             // Convert the UTF32 codepoint to one or more UTF16 codepoints
273             if (codepoint <= 0xFFFF) {
274                 // Single UTF16 character
275                 *d++ = (char16_t) codepoint;
276             } else {
277                 // Multiple UTF16 characters with surrogates
278                 codepoint = codepoint - 0x10000;
279                 *d++ = (char16_t) ((codepoint >> 10) + 0xD800);
280                 *d++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00);
281             }
282 
283             p += len;
284         }
285         *d = 0;
286 
287         //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
288         //printHexData(1, str, buf->size(), 16, 1);
289         //printf("\n");
290 
291         return str;
292     }
293 
294     return getEmptyString();
295 }
296 
297 // ---------------------------------------------------------------------------
298 
String16()299 String16::String16()
300     : mString(getEmptyString())
301 {
302 }
303 
String16(const String16 & o)304 String16::String16(const String16& o)
305     : mString(o.mString)
306 {
307     SharedBuffer::bufferFromData(mString)->acquire();
308 }
309 
String16(const String16 & o,size_t len,size_t begin)310 String16::String16(const String16& o, size_t len, size_t begin)
311     : mString(getEmptyString())
312 {
313     setTo(o, len, begin);
314 }
315 
String16(const char16_t * o)316 String16::String16(const char16_t* o)
317 {
318     size_t len = strlen16(o);
319     SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t));
320     LOG_ASSERT(buf, "Unable to allocate shared buffer");
321     if (buf) {
322         char16_t* str = (char16_t*)buf->data();
323         strcpy16(str, o);
324         mString = str;
325         return;
326     }
327 
328     mString = getEmptyString();
329 }
330 
String16(const char16_t * o,size_t len)331 String16::String16(const char16_t* o, size_t len)
332 {
333     SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t));
334     LOG_ASSERT(buf, "Unable to allocate shared buffer");
335     if (buf) {
336         char16_t* str = (char16_t*)buf->data();
337         memcpy(str, o, len*sizeof(char16_t));
338         str[len] = 0;
339         mString = str;
340         return;
341     }
342 
343     mString = getEmptyString();
344 }
345 
String16(const String8 & o)346 String16::String16(const String8& o)
347     : mString(allocFromUTF8(o.string(), o.size()))
348 {
349 }
350 
String16(const char * o)351 String16::String16(const char* o)
352     : mString(allocFromUTF8(o, strlen(o)))
353 {
354 }
355 
String16(const char * o,size_t len)356 String16::String16(const char* o, size_t len)
357     : mString(allocFromUTF8(o, len))
358 {
359 }
360 
~String16()361 String16::~String16()
362 {
363     SharedBuffer::bufferFromData(mString)->release();
364 }
365 
setTo(const String16 & other)366 void String16::setTo(const String16& other)
367 {
368     SharedBuffer::bufferFromData(other.mString)->acquire();
369     SharedBuffer::bufferFromData(mString)->release();
370     mString = other.mString;
371 }
372 
setTo(const String16 & other,size_t len,size_t begin)373 status_t String16::setTo(const String16& other, size_t len, size_t begin)
374 {
375     const size_t N = other.size();
376     if (begin >= N) {
377         SharedBuffer::bufferFromData(mString)->release();
378         mString = getEmptyString();
379         return NO_ERROR;
380     }
381     if ((begin+len) > N) len = N-begin;
382     if (begin == 0 && len == N) {
383         setTo(other);
384         return NO_ERROR;
385     }
386 
387     if (&other == this) {
388         LOG_ALWAYS_FATAL("Not implemented");
389     }
390 
391     return setTo(other.string()+begin, len);
392 }
393 
setTo(const char16_t * other)394 status_t String16::setTo(const char16_t* other)
395 {
396     return setTo(other, strlen16(other));
397 }
398 
setTo(const char16_t * other,size_t len)399 status_t String16::setTo(const char16_t* other, size_t len)
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         memmove(str, other, len*sizeof(char16_t));
406         str[len] = 0;
407         mString = str;
408         return NO_ERROR;
409     }
410     return NO_MEMORY;
411 }
412 
append(const String16 & other)413 status_t String16::append(const String16& other)
414 {
415     const size_t myLen = size();
416     const size_t otherLen = other.size();
417     if (myLen == 0) {
418         setTo(other);
419         return NO_ERROR;
420     } else if (otherLen == 0) {
421         return NO_ERROR;
422     }
423 
424     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
425         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
426     if (buf) {
427         char16_t* str = (char16_t*)buf->data();
428         memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
429         mString = str;
430         return NO_ERROR;
431     }
432     return NO_MEMORY;
433 }
434 
append(const char16_t * chrs,size_t otherLen)435 status_t String16::append(const char16_t* chrs, size_t otherLen)
436 {
437     const size_t myLen = size();
438     if (myLen == 0) {
439         setTo(chrs, otherLen);
440         return NO_ERROR;
441     } else if (otherLen == 0) {
442         return NO_ERROR;
443     }
444 
445     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
446         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
447     if (buf) {
448         char16_t* str = (char16_t*)buf->data();
449         memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
450         str[myLen+otherLen] = 0;
451         mString = str;
452         return NO_ERROR;
453     }
454     return NO_MEMORY;
455 }
456 
insert(size_t pos,const char16_t * chrs)457 status_t String16::insert(size_t pos, const char16_t* chrs)
458 {
459     return insert(pos, chrs, strlen16(chrs));
460 }
461 
insert(size_t pos,const char16_t * chrs,size_t len)462 status_t String16::insert(size_t pos, const char16_t* chrs, size_t len)
463 {
464     const size_t myLen = size();
465     if (myLen == 0) {
466         return setTo(chrs, len);
467         return NO_ERROR;
468     } else if (len == 0) {
469         return NO_ERROR;
470     }
471 
472     if (pos > myLen) pos = myLen;
473 
474     #if 0
475     printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n",
476            String8(*this).string(), pos,
477            len, myLen, String8(chrs, len).string());
478     #endif
479 
480     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
481         ->editResize((myLen+len+1)*sizeof(char16_t));
482     if (buf) {
483         char16_t* str = (char16_t*)buf->data();
484         if (pos < myLen) {
485             memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t));
486         }
487         memcpy(str+pos, chrs, len*sizeof(char16_t));
488         str[myLen+len] = 0;
489         mString = str;
490         #if 0
491         printf("Result (%d chrs): %s\n", size(), String8(*this).string());
492         #endif
493         return NO_ERROR;
494     }
495     return NO_MEMORY;
496 }
497 
findFirst(char16_t c) const498 ssize_t String16::findFirst(char16_t c) const
499 {
500     const char16_t* str = string();
501     const char16_t* p = str;
502     const char16_t* e = p + size();
503     while (p < e) {
504         if (*p == c) {
505             return p-str;
506         }
507         p++;
508     }
509     return -1;
510 }
511 
findLast(char16_t c) const512 ssize_t String16::findLast(char16_t c) const
513 {
514     const char16_t* str = string();
515     const char16_t* p = str;
516     const char16_t* e = p + size();
517     while (p < e) {
518         e--;
519         if (*e == c) {
520             return e-str;
521         }
522     }
523     return -1;
524 }
525 
startsWith(const String16 & prefix) const526 bool String16::startsWith(const String16& prefix) const
527 {
528     const size_t ps = prefix.size();
529     if (ps > size()) return false;
530     return strzcmp16(mString, ps, prefix.string(), ps) == 0;
531 }
532 
startsWith(const char16_t * prefix) const533 bool String16::startsWith(const char16_t* prefix) const
534 {
535     const size_t ps = strlen16(prefix);
536     if (ps > size()) return false;
537     return strncmp16(mString, prefix, ps) == 0;
538 }
539 
makeLower()540 status_t String16::makeLower()
541 {
542     const size_t N = size();
543     const char16_t* str = string();
544     char16_t* edit = NULL;
545     for (size_t i=0; i<N; i++) {
546         const char16_t v = str[i];
547         if (v >= 'A' && v <= 'Z') {
548             if (!edit) {
549                 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
550                 if (!buf) {
551                     return NO_MEMORY;
552                 }
553                 edit = (char16_t*)buf->data();
554                 mString = str = edit;
555             }
556             edit[i] = tolower((char)v);
557         }
558     }
559     return NO_ERROR;
560 }
561 
replaceAll(char16_t replaceThis,char16_t withThis)562 status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
563 {
564     const size_t N = size();
565     const char16_t* str = string();
566     char16_t* edit = NULL;
567     for (size_t i=0; i<N; i++) {
568         if (str[i] == replaceThis) {
569             if (!edit) {
570                 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
571                 if (!buf) {
572                     return NO_MEMORY;
573                 }
574                 edit = (char16_t*)buf->data();
575                 mString = str = edit;
576             }
577             edit[i] = withThis;
578         }
579     }
580     return NO_ERROR;
581 }
582 
remove(size_t len,size_t begin)583 status_t String16::remove(size_t len, size_t begin)
584 {
585     const size_t N = size();
586     if (begin >= N) {
587         SharedBuffer::bufferFromData(mString)->release();
588         mString = getEmptyString();
589         return NO_ERROR;
590     }
591     if ((begin+len) > N) len = N-begin;
592     if (begin == 0 && len == N) {
593         return NO_ERROR;
594     }
595 
596     if (begin > 0) {
597         SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
598             ->editResize((N+1)*sizeof(char16_t));
599         if (!buf) {
600             return NO_MEMORY;
601         }
602         char16_t* str = (char16_t*)buf->data();
603         memmove(str, str+begin, (N-begin+1)*sizeof(char16_t));
604         mString = str;
605     }
606     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
607         ->editResize((len+1)*sizeof(char16_t));
608     if (buf) {
609         char16_t* str = (char16_t*)buf->data();
610         str[len] = 0;
611         mString = str;
612         return NO_ERROR;
613     }
614     return NO_MEMORY;
615 }
616 
operator <<(TextOutput & to,const String16 & val)617 TextOutput& operator<<(TextOutput& to, const String16& val)
618 {
619     to << String8(val).string();
620     return to;
621 }
622 
623 }; // namespace android
624