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