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