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