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 26 namespace android { 27 28 // static 29 const char *AString::kEmptyString = ""; 30 31 AString::AString() 32 : mData((char *)kEmptyString), 33 mSize(0), 34 mAllocSize(1) { 35 } 36 37 AString::AString(const char *s) 38 : mData(NULL), 39 mSize(0), 40 mAllocSize(1) { 41 setTo(s); 42 } 43 44 AString::AString(const char *s, size_t size) 45 : mData(NULL), 46 mSize(0), 47 mAllocSize(1) { 48 setTo(s, size); 49 } 50 51 AString::AString(const AString &from) 52 : mData(NULL), 53 mSize(0), 54 mAllocSize(1) { 55 setTo(from, 0, from.size()); 56 } 57 58 AString::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 65 AString::~AString() { 66 clear(); 67 } 68 69 AString &AString::operator=(const AString &from) { 70 if (&from != this) { 71 setTo(from, 0, from.size()); 72 } 73 74 return *this; 75 } 76 77 size_t AString::size() const { 78 return mSize; 79 } 80 81 const char *AString::c_str() const { 82 return mData; 83 } 84 85 bool AString::empty() const { 86 return mSize == 0; 87 } 88 89 void AString::setTo(const char *s) { 90 setTo(s, strlen(s)); 91 } 92 93 void AString::setTo(const char *s, size_t size) { 94 clear(); 95 append(s, size); 96 } 97 98 void 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 105 void 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 116 size_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 125 bool AString::operator==(const AString &other) const { 126 return mSize == other.mSize && !memcmp(mData, other.mData, mSize); 127 } 128 129 void 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 147 void 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 158 void AString::makeMutable() { 159 if (mData == kEmptyString) { 160 mData = strdup(kEmptyString); 161 } 162 } 163 164 void AString::append(const char *s) { 165 append(s, strlen(s)); 166 } 167 168 void 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 182 void AString::append(const AString &from) { 183 append(from.c_str(), from.size()); 184 } 185 186 void AString::append(const AString &from, size_t offset, size_t n) { 187 append(from.c_str() + offset, n); 188 } 189 190 void AString::append(int x) { 191 char s[16]; 192 sprintf(s, "%d", x); 193 194 append(s); 195 } 196 197 void AString::append(unsigned x) { 198 char s[16]; 199 sprintf(s, "%u", x); 200 201 append(s); 202 } 203 204 void AString::append(long x) { 205 char s[16]; 206 sprintf(s, "%ld", x); 207 208 append(s); 209 } 210 211 void AString::append(unsigned long x) { 212 char s[16]; 213 sprintf(s, "%lu", x); 214 215 append(s); 216 } 217 218 void AString::append(long long x) { 219 char s[32]; 220 sprintf(s, "%lld", x); 221 222 append(s); 223 } 224 225 void AString::append(unsigned long long x) { 226 char s[32]; 227 sprintf(s, "%llu", x); 228 229 append(s); 230 } 231 232 void AString::append(float x) { 233 char s[16]; 234 sprintf(s, "%f", x); 235 236 append(s); 237 } 238 239 void AString::append(double x) { 240 char s[16]; 241 sprintf(s, "%f", x); 242 243 append(s); 244 } 245 246 void AString::append(void *x) { 247 char s[16]; 248 sprintf(s, "%p", x); 249 250 append(s); 251 } 252 253 ssize_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 265 void AString::insert(const AString &from, size_t insertionPos) { 266 insert(from.c_str(), from.size(), insertionPos); 267 } 268 269 void 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 289 bool AString::operator<(const AString &other) const { 290 return compare(other) < 0; 291 } 292 293 bool AString::operator>(const AString &other) const { 294 return compare(other) > 0; 295 } 296 297 int AString::compare(const AString &other) const { 298 return strcmp(mData, other.mData); 299 } 300 301 void AString::tolower() { 302 makeMutable(); 303 304 for (size_t i = 0; i < mSize; ++i) { 305 mData[i] = ::tolower(mData[i]); 306 } 307 } 308 309 bool AString::startsWith(const char *prefix) const { 310 return !strncmp(mData, prefix, strlen(prefix)); 311 } 312 313 bool 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 323 AString 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