Home | History | Annotate | Download | only in base
      1 // Copyright 2014 The Android Open Source Project
      2 //
      3 // This software is licensed under the terms of the GNU General Public
      4 // License version 2, as published by the Free Software Foundation, and
      5 // may be copied, distributed, and modified under those terms.
      6 //
      7 // This program is distributed in the hope that it will be useful,
      8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 // GNU General Public License for more details.
     11 
     12 #include "android/base/String.h"
     13 
     14 #include "android/base/Limits.h"
     15 #include "android/base/Log.h"
     16 #include "android/base/memory/MallocUsableSize.h"
     17 #include "android/base/StringView.h"
     18 
     19 #include <limits.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 
     23 namespace android {
     24 namespace base {
     25 
     26 String::String() : mStr(mStorage), mSize(0) {
     27     mStorage[0] = '\0';
     28 }
     29 
     30 
     31 String::String(const char* str) : mStr(mStorage), mSize(0) {
     32     assign(str, ::strlen(str));
     33 }
     34 
     35 
     36 String::String(const char* str, size_t len) : mStr(mStorage), mSize(0) {
     37     assign(str, len);
     38 }
     39 
     40 
     41 String::String(const String& other) : mStr(mStorage), mSize(0) {
     42     assign(other);
     43 }
     44 
     45 
     46 String::String(const StringView& other) : mStr(mStorage), mSize(0) {
     47     assign(other);
     48 }
     49 
     50 
     51 String::String(size_t count, char fill) : mStr(mStorage), mSize(0) {
     52     this->assign(count, fill);
     53 }
     54 
     55 
     56 String::~String() {
     57     reserve(0U);
     58     // Prevent misuse from dangling pointers.
     59     mStr = NULL;
     60     mSize = 0;
     61     mCapacity = 0;
     62 }
     63 
     64 String& String::assign(const char* str) {
     65     return this->assign(str, ::strlen(str));
     66 }
     67 
     68 
     69 String& String::assign(const char* str, size_t len) {
     70     this->resize(len);
     71     ::memmove(mStr, str, len);
     72     return *this;
     73 }
     74 
     75 
     76 String& String::assign(const String& other) {
     77     return this->assign(other.c_str(), other.size());
     78 }
     79 
     80 
     81 String& String::assign(const StringView& other) {
     82     return this->assign(other.str(), other.size());
     83 }
     84 
     85 
     86 String& String::assign(char ch) {
     87     return this->assign(&ch, 1U);
     88 }
     89 
     90 
     91 String& String::assign(size_t count, char fill) {
     92     this->resize(count);
     93     ::memset(mStr, fill, count);
     94     return *this;
     95 }
     96 
     97 
     98 String& String::append(const char* str, size_t len) {
     99     size_t oldSize = mSize;
    100     this->resize(mSize + len);
    101     ::memmove(mStr + oldSize, str, len);
    102     return *this;
    103 }
    104 
    105 
    106 String& String::append(const char* str) {
    107     return this->append(str, ::strlen(str));
    108 }
    109 
    110 
    111 String& String::append(const String& other) {
    112     return this->append(other.c_str(), other.size());
    113 }
    114 
    115 
    116 String& String::append(const StringView& other) {
    117     return this->append(other.str(), other.size());
    118 }
    119 
    120 
    121 String& String::append(char ch) {
    122     return this->append(&ch, 1U);
    123 }
    124 
    125 
    126 int String::compare(const char* str, size_t len) const {
    127     if (mSize == 0)
    128         return (len == 0) ? 0 : -1;
    129 
    130     if (len == 0)
    131         return +1;
    132 
    133     int ret = ::strncmp(mStr, str, len);
    134     if (ret < 0)
    135         return -1;
    136     if (ret > 0)
    137         return +1;
    138 
    139     if (mSize < len)
    140         return -1;
    141     if (mSize > len)
    142         return +1;
    143     return 0;
    144 }
    145 
    146 
    147 int String::compare(const char* str) const {
    148     return compare(str, ::strlen(str));
    149 }
    150 
    151 
    152 int String::compare(const String& other) const {
    153     return compare(other.c_str(), other.size());
    154 }
    155 
    156 
    157 int String::compare(const StringView& other) const {
    158     return compare(other.str(), other.size());
    159 }
    160 
    161 
    162 int String::compare(char ch) const {
    163     return compare(&ch, 1U);
    164 }
    165 
    166 
    167 bool String::equals(const char* str, size_t len) const {
    168     if (mSize == 0)
    169         return (len == 0);
    170 
    171     if (len != mSize)
    172         return false;
    173 
    174     return !::memcmp(mStr, str, len);
    175 }
    176 
    177 
    178 bool String::equals(const char* str) const {
    179     return equals(str, ::strlen(str));
    180 }
    181 
    182 
    183 bool String::equals(const String& other) const {
    184     return equals(other.c_str(), other.size());
    185 }
    186 
    187 
    188 bool String::equals(const StringView& other) const {
    189     return equals(other.str(), other.size());
    190 }
    191 
    192 
    193 bool String::equals(char ch) const {
    194     return equals(&ch, 1U);
    195 }
    196 
    197 
    198 void String::resize(size_t newSize) {
    199     if (!mStr)
    200         mStr = mStorage;
    201 
    202     size_t oldCapacity = capacity();
    203     if (newSize < oldCapacity) {
    204         if (oldCapacity >= 256U && newSize < oldCapacity / 2) {
    205             reserve(newSize);
    206         }
    207     } else if (newSize > oldCapacity) {
    208         const size_t kMaxCapacity = SIZE_MAX - 1U;
    209         CHECK(newSize < kMaxCapacity);
    210 
    211         size_t newCapacity = oldCapacity;
    212         while (newCapacity < newSize) {
    213             size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8;
    214             newCapacity = (newCapacity2 < newCapacity)
    215                     ? kMaxCapacity : newCapacity2;
    216         }
    217         reserve(newCapacity);
    218     }
    219     DCHECK(newSize <= capacity());
    220     mSize = newSize;
    221     mStr[newSize] = '\0';
    222 }
    223 
    224 
    225 void String::reserve(size_t newSize) {
    226     size_t minSize = (newSize < kMinCapacity) ? kMinCapacity : newSize;
    227 
    228     if (!mStr)
    229         mStr = mStorage;
    230 
    231     if (minSize == kMinCapacity) {
    232         if (mStr != mStorage) {
    233             // Copy the first bytes to mStorage, then free the heap
    234             // allocated buffer.
    235             ::memcpy(mStorage, mStr, newSize);
    236             ::free(mStr);
    237             mStr = mStorage;
    238         }
    239     } else /* newSize > kMinCapacity */ {
    240         char* oldStorage = (mStr == mStorage) ? NULL : mStr;
    241         size_t newStorageSize = newSize + 1U;
    242         mStr = static_cast<char*>(::realloc(oldStorage, newStorageSize));
    243 #if xxxUSE_MALLOC_USABLE_SIZE
    244         size_t usableSize = malloc_usable_size(mStr);
    245         if (usableSize > newStorageSize)
    246             newStorageSize = usableSize;
    247 #endif
    248         if (!oldStorage) {
    249             ::memcpy(mStr, mStorage, mSize);
    250         }
    251         if (newSize > mSize) {
    252             ::memset(mStr + mSize, 0, newSize - mSize);
    253         }
    254         mCapacity = newStorageSize - 1U;
    255     }
    256     mStr[newSize] = '\0';
    257 }
    258 
    259 void String::swap(String* other) {
    260     if (this == other)
    261         return;
    262 
    263     char* myStr = mStr;
    264     size_t mySize = mSize;
    265     size_t myCapacity = capacity();
    266 
    267     char* theirStr = other->mStr;
    268     size_t theirSize = other->mSize;
    269     size_t theirCapacity = other->capacity();
    270 
    271     if (myStr == mStorage) {
    272         if (theirStr == other->mStorage) {
    273             // Two small strings, swap buffer contents, no need to swap
    274             // pointers or capacities.
    275             for (size_t n = 0; n < kMinCapacity + 1U; ++n) {
    276                 char tmp = myStr[n];
    277                 myStr[n] = theirStr[n];
    278                 theirStr[n] = tmp;
    279             }
    280         } else {
    281             // |this| is a small string, |other| is a long one.
    282             ::memcpy(other->mStorage, mStorage, mySize + 1U);
    283             other->mStr = other->mStorage;
    284             mStr = theirStr;
    285             mCapacity = theirCapacity;
    286         }
    287     } else if (theirStr == other->mStorage) {
    288         // |this| is a long string, |other| is a short string.
    289         ::memcpy(mStorage, other->mStorage, theirSize + 1U);
    290         other->mStr = myStr;
    291         other->mCapacity = myCapacity;
    292         mStr = mStorage;
    293     } else {
    294         // Both |this| and |other| are long strings.
    295         mStr = theirStr;
    296         mCapacity = theirCapacity;
    297         other->mStr = myStr;
    298         other->mCapacity = myCapacity;
    299     }
    300     // Always swap the sizes.
    301     mSize = theirSize;
    302     other->mSize = mySize;
    303 }
    304 
    305 // static
    306 void String::adjustMovedSlice(String* fromStrings,
    307                               String* toStrings,
    308                               size_t count) {
    309     for (size_t n = 0; n < count; ++n) {
    310         if (toStrings[n].mStr == fromStrings[n].mStorage) {
    311             toStrings[n].mStr = toStrings[n].mStorage;
    312         }
    313     }
    314 }
    315 
    316 // static
    317 void String::moveSlice(String* strings,
    318                        size_t from,
    319                        size_t to,
    320                        size_t count) {
    321     // First, move all slice items with ::memmove().
    322     ::memmove(strings + to, strings + from, count * sizeof(String));
    323     // Second, adjust mStorage pointers.
    324     adjustMovedSlice(strings + from, strings + to, count);
    325 }
    326 
    327 void String::finalizeSlice(String* strings, size_t count) {
    328     for (size_t n = count; n > 0; --n) {
    329         strings[n - 1U].reserve(0U);
    330     }
    331 }
    332 
    333 }  // namespace base
    334 }  // namespace android
    335