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