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