Home | History | Annotate | Download | only in utils
      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 
     38 static inline char16_t* getEmptyString()
     39 {
     40     gEmptyStringBuf->acquire();
     41    return gEmptyString;
     42 }
     43 
     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 
     53 void terminate_string16()
     54 {
     55     SharedBuffer::bufferFromData(gEmptyString)->release();
     56     gEmptyStringBuf = NULL;
     57     gEmptyString = NULL;
     58 }
     59 
     60 // ---------------------------------------------------------------------------
     61 
     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 
     94 String16::String16()
     95     : mString(getEmptyString())
     96 {
     97 }
     98 
     99 String16::String16(const String16& o)
    100     : mString(o.mString)
    101 {
    102     SharedBuffer::bufferFromData(mString)->acquire();
    103 }
    104 
    105 String16::String16(const String16& o, size_t len, size_t begin)
    106     : mString(getEmptyString())
    107 {
    108     setTo(o, len, begin);
    109 }
    110 
    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 
    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 
    141 String16::String16(const String8& o)
    142     : mString(allocFromUTF8(o.string(), o.size()))
    143 {
    144 }
    145 
    146 String16::String16(const char* o)
    147     : mString(allocFromUTF8(o, strlen(o)))
    148 {
    149 }
    150 
    151 String16::String16(const char* o, size_t len)
    152     : mString(allocFromUTF8(o, len))
    153 {
    154 }
    155 
    156 String16::~String16()
    157 {
    158     SharedBuffer::bufferFromData(mString)->release();
    159 }
    160 
    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 
    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 
    189 status_t String16::setTo(const char16_t* other)
    190 {
    191     return setTo(other, strlen16(other));
    192 }
    193 
    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 
    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 
    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 
    252 status_t String16::insert(size_t pos, const char16_t* chrs)
    253 {
    254     return insert(pos, chrs, strlen16(chrs));
    255 }
    256 
    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 
    293 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 
    307 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 
    321 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 
    328 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 
    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 
    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 
    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 
    412 TextOutput& operator<<(TextOutput& to, const String16& val)
    413 {
    414     to << String8(val).string();
    415     return to;
    416 }
    417 
    418 }; // namespace android
    419