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