1 /* 2 * Copyright (C) 2010 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 #define LOG_TAG "AString" 18 #include <utils/Log.h> 19 20 #include <ctype.h> 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include <binder/Parcel.h> 27 #include <utils/String8.h> 28 #include "ADebug.h" 29 #include "AString.h" 30 31 namespace android { 32 33 // static 34 const char *AString::kEmptyString = ""; 35 36 AString::AString() 37 : mData((char *)kEmptyString), 38 mSize(0), 39 mAllocSize(1) { 40 } 41 42 AString::AString(const char *s) 43 : mData(NULL), 44 mSize(0), 45 mAllocSize(1) { 46 if (!s) { 47 ALOGW("ctor got NULL, using empty string instead"); 48 clear(); 49 } else { 50 setTo(s); 51 } 52 } 53 54 AString::AString(const char *s, size_t size) 55 : mData(NULL), 56 mSize(0), 57 mAllocSize(1) { 58 if (!s) { 59 ALOGW("ctor got NULL, using empty string instead"); 60 clear(); 61 } else { 62 setTo(s, size); 63 } 64 } 65 66 AString::AString(const String8 &from) 67 : mData(NULL), 68 mSize(0), 69 mAllocSize(1) { 70 setTo(from.string(), from.length()); 71 } 72 73 AString::AString(const AString &from) 74 : mData(NULL), 75 mSize(0), 76 mAllocSize(1) { 77 setTo(from, 0, from.size()); 78 } 79 80 AString::AString(const AString &from, size_t offset, size_t n) 81 : mData(NULL), 82 mSize(0), 83 mAllocSize(1) { 84 setTo(from, offset, n); 85 } 86 87 AString::~AString() { 88 clear(); 89 } 90 91 AString &AString::operator=(const AString &from) { 92 if (&from != this) { 93 setTo(from, 0, from.size()); 94 } 95 96 return *this; 97 } 98 99 size_t AString::size() const { 100 return mSize; 101 } 102 103 const char *AString::c_str() const { 104 return mData; 105 } 106 107 bool AString::empty() const { 108 return mSize == 0; 109 } 110 111 void AString::setTo(const char *s) { 112 setTo(s, strlen(s)); 113 } 114 115 void AString::setTo(const char *s, size_t size) { 116 clear(); 117 append(s, size); 118 } 119 120 void AString::setTo(const AString &from, size_t offset, size_t n) { 121 CHECK(&from != this); 122 123 clear(); 124 setTo(from.mData + offset, n); 125 } 126 127 void AString::clear() { 128 if (mData && mData != kEmptyString) { 129 free(mData); 130 mData = NULL; 131 } 132 133 mData = (char *)kEmptyString; 134 mSize = 0; 135 mAllocSize = 1; 136 } 137 138 size_t AString::hash() const { 139 size_t x = 0; 140 for (size_t i = 0; i < mSize; ++i) { 141 x = (x * 31) + mData[i]; 142 } 143 144 return x; 145 } 146 147 bool AString::operator==(const AString &other) const { 148 return mSize == other.mSize && !memcmp(mData, other.mData, mSize); 149 } 150 151 void AString::trim() { 152 makeMutable(); 153 154 size_t i = 0; 155 while (i < mSize && isspace(mData[i])) { 156 ++i; 157 } 158 159 size_t j = mSize; 160 while (j > i && isspace(mData[j - 1])) { 161 --j; 162 } 163 164 memmove(mData, &mData[i], j - i); 165 mSize = j - i; 166 mData[mSize] = '\0'; 167 } 168 169 void AString::erase(size_t start, size_t n) { 170 CHECK_LT(start, mSize); 171 CHECK_LE(start + n, mSize); 172 173 makeMutable(); 174 175 memmove(&mData[start], &mData[start + n], mSize - start - n); 176 mSize -= n; 177 mData[mSize] = '\0'; 178 } 179 180 void AString::makeMutable() { 181 if (mData == kEmptyString) { 182 mData = strdup(kEmptyString); 183 } 184 } 185 186 void AString::append(const char *s) { 187 append(s, strlen(s)); 188 } 189 190 void AString::append(const char *s, size_t size) { 191 makeMutable(); 192 193 if (mSize + size + 1 > mAllocSize) { 194 mAllocSize = (mAllocSize + size + 31) & -32; 195 mData = (char *)realloc(mData, mAllocSize); 196 CHECK(mData != NULL); 197 } 198 199 memcpy(&mData[mSize], s, size); 200 mSize += size; 201 mData[mSize] = '\0'; 202 } 203 204 void AString::append(const AString &from) { 205 append(from.c_str(), from.size()); 206 } 207 208 void AString::append(const AString &from, size_t offset, size_t n) { 209 append(from.c_str() + offset, n); 210 } 211 212 void AString::append(int x) { 213 char s[16]; 214 int result = snprintf(s, sizeof(s), "%d", x); 215 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 216 append(s); 217 } 218 219 void AString::append(unsigned x) { 220 char s[16]; 221 int result = snprintf(s, sizeof(s), "%u", x); 222 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 223 append(s); 224 } 225 226 void AString::append(long x) { 227 char s[32]; 228 int result = snprintf(s, sizeof(s), "%ld", x); 229 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 230 append(s); 231 } 232 233 void AString::append(unsigned long x) { 234 char s[32]; 235 int result = snprintf(s, sizeof(s), "%lu", x); 236 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 237 append(s); 238 } 239 240 void AString::append(long long x) { 241 char s[32]; 242 int result = snprintf(s, sizeof(s), "%lld", x); 243 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 244 append(s); 245 } 246 247 void AString::append(unsigned long long x) { 248 char s[32]; 249 int result = snprintf(s, sizeof(s), "%llu", x); 250 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 251 append(s); 252 } 253 254 void AString::append(float x) { 255 char s[16]; 256 int result = snprintf(s, sizeof(s), "%f", x); 257 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 258 append(s); 259 } 260 261 void AString::append(double x) { 262 char s[16]; 263 int result = snprintf(s, sizeof(s), "%f", x); 264 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 265 append(s); 266 } 267 268 void AString::append(void *x) { 269 char s[32]; 270 int result = snprintf(s, sizeof(s), "%p", x); 271 CHECK((result > 0) && ((size_t) result) < sizeof(s)); 272 append(s); 273 } 274 275 ssize_t AString::find(const char *substring, size_t start) const { 276 CHECK_LE(start, size()); 277 278 const char *match = strstr(mData + start, substring); 279 280 if (match == NULL) { 281 return -1; 282 } 283 284 return match - mData; 285 } 286 287 void AString::insert(const AString &from, size_t insertionPos) { 288 insert(from.c_str(), from.size(), insertionPos); 289 } 290 291 void AString::insert(const char *from, size_t size, size_t insertionPos) { 292 CHECK_GE(insertionPos, 0u); 293 CHECK_LE(insertionPos, mSize); 294 295 makeMutable(); 296 297 if (mSize + size + 1 > mAllocSize) { 298 mAllocSize = (mAllocSize + size + 31) & -32; 299 mData = (char *)realloc(mData, mAllocSize); 300 CHECK(mData != NULL); 301 } 302 303 memmove(&mData[insertionPos + size], 304 &mData[insertionPos], mSize - insertionPos + 1); 305 306 memcpy(&mData[insertionPos], from, size); 307 308 mSize += size; 309 } 310 311 bool AString::operator<(const AString &other) const { 312 return compare(other) < 0; 313 } 314 315 bool AString::operator>(const AString &other) const { 316 return compare(other) > 0; 317 } 318 319 int AString::compare(const AString &other) const { 320 return strcmp(mData, other.mData); 321 } 322 323 int AString::compareIgnoreCase(const AString &other) const { 324 return strcasecmp(mData, other.mData); 325 } 326 327 bool AString::equalsIgnoreCase(const AString &other) const { 328 return compareIgnoreCase(other) == 0; 329 } 330 331 void AString::tolower() { 332 makeMutable(); 333 334 for (size_t i = 0; i < mSize; ++i) { 335 mData[i] = ::tolower(mData[i]); 336 } 337 } 338 339 bool AString::startsWith(const char *prefix) const { 340 return !strncmp(mData, prefix, strlen(prefix)); 341 } 342 343 bool AString::endsWith(const char *suffix) const { 344 size_t suffixLen = strlen(suffix); 345 346 if (mSize < suffixLen) { 347 return false; 348 } 349 350 return !strcmp(mData + mSize - suffixLen, suffix); 351 } 352 353 bool AString::startsWithIgnoreCase(const char *prefix) const { 354 return !strncasecmp(mData, prefix, strlen(prefix)); 355 } 356 357 bool AString::endsWithIgnoreCase(const char *suffix) const { 358 size_t suffixLen = strlen(suffix); 359 360 if (mSize < suffixLen) { 361 return false; 362 } 363 364 return !strcasecmp(mData + mSize - suffixLen, suffix); 365 } 366 367 // static 368 AString AString::FromParcel(const Parcel &parcel) { 369 size_t size = static_cast<size_t>(parcel.readInt32()); 370 return AString(static_cast<const char *>(parcel.readInplace(size)), size); 371 } 372 373 status_t AString::writeToParcel(Parcel *parcel) const { 374 CHECK_LE(mSize, static_cast<size_t>(INT32_MAX)); 375 status_t err = parcel->writeInt32(mSize); 376 if (err == OK) { 377 err = parcel->write(mData, mSize); 378 } 379 return err; 380 } 381 382 AString AStringPrintf(const char *format, ...) { 383 va_list ap; 384 va_start(ap, format); 385 386 char *buffer; 387 vasprintf(&buffer, format, ap); 388 389 va_end(ap); 390 391 AString result(buffer); 392 393 free(buffer); 394 buffer = NULL; 395 396 return result; 397 } 398 399 } // namespace android 400 401