AString.cpp revision 89b2a0ad367cdff5ff4e70036311ecf82921a829
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 31namespace android { 32 33// static 34const char *AString::kEmptyString = ""; 35 36AString::AString() 37 : mData((char *)kEmptyString), 38 mSize(0), 39 mAllocSize(1) { 40} 41 42AString::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 54AString::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 66AString::AString(const String8 &from) 67 : mData(NULL), 68 mSize(0), 69 mAllocSize(1) { 70 setTo(from.string(), from.length()); 71} 72 73AString::AString(const AString &from) 74 : mData(NULL), 75 mSize(0), 76 mAllocSize(1) { 77 setTo(from, 0, from.size()); 78} 79 80AString::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 87AString::~AString() { 88 clear(); 89} 90 91AString &AString::operator=(const AString &from) { 92 if (&from != this) { 93 setTo(from, 0, from.size()); 94 } 95 96 return *this; 97} 98 99size_t AString::size() const { 100 return mSize; 101} 102 103const char *AString::c_str() const { 104 return mData; 105} 106 107bool AString::empty() const { 108 return mSize == 0; 109} 110 111void AString::setTo(const char *s) { 112 setTo(s, strlen(s)); 113} 114 115void AString::setTo(const char *s, size_t size) { 116 clear(); 117 append(s, size); 118} 119 120void 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 127void 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 138size_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 147bool AString::operator==(const AString &other) const { 148 return mSize == other.mSize && !memcmp(mData, other.mData, mSize); 149} 150 151void 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 169void 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 180void AString::makeMutable() { 181 if (mData == kEmptyString) { 182 mData = strdup(kEmptyString); 183 } 184} 185 186void AString::append(const char *s) { 187 append(s, strlen(s)); 188} 189 190void 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 204void AString::append(const AString &from) { 205 append(from.c_str(), from.size()); 206} 207 208void AString::append(const AString &from, size_t offset, size_t n) { 209 append(from.c_str() + offset, n); 210} 211 212void 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 219void 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 226void 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 233void 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 240void 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 247void 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 254void 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 261void 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 268void 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 275ssize_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 287void AString::insert(const AString &from, size_t insertionPos) { 288 insert(from.c_str(), from.size(), insertionPos); 289} 290 291void 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 311bool AString::operator<(const AString &other) const { 312 return compare(other) < 0; 313} 314 315bool AString::operator>(const AString &other) const { 316 return compare(other) > 0; 317} 318 319int AString::compare(const AString &other) const { 320 return strcmp(mData, other.mData); 321} 322 323int AString::compareIgnoreCase(const AString &other) const { 324 return strcasecmp(mData, other.mData); 325} 326 327bool AString::equalsIgnoreCase(const AString &other) const { 328 return compareIgnoreCase(other) == 0; 329} 330 331void AString::tolower() { 332 makeMutable(); 333 334 for (size_t i = 0; i < mSize; ++i) { 335 mData[i] = ::tolower(mData[i]); 336 } 337} 338 339bool AString::startsWith(const char *prefix) const { 340 return !strncmp(mData, prefix, strlen(prefix)); 341} 342 343bool 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 353bool AString::startsWithIgnoreCase(const char *prefix) const { 354 return !strncasecmp(mData, prefix, strlen(prefix)); 355} 356 357bool 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 368AString 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 373status_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 382AString 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