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