1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkString.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,650 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkString.h" 1.14 +#include "SkFixed.h" 1.15 +#include "SkThread.h" 1.16 +#include "SkUtils.h" 1.17 +#include <stdarg.h> 1.18 +#include <stdio.h> 1.19 + 1.20 +// number of bytes (on the stack) to receive the printf result 1.21 +static const size_t kBufferSize = 1024; 1.22 + 1.23 +#ifdef SK_BUILD_FOR_WIN 1.24 + #define VSNPRINTF(buffer, size, format, args) \ 1.25 + _vsnprintf_s(buffer, size, _TRUNCATE, format, args) 1.26 + #define SNPRINTF _snprintf 1.27 +#else 1.28 + #define VSNPRINTF vsnprintf 1.29 + #define SNPRINTF snprintf 1.30 +#endif 1.31 + 1.32 +#define ARGS_TO_BUFFER(format, buffer, size) \ 1.33 + do { \ 1.34 + va_list args; \ 1.35 + va_start(args, format); \ 1.36 + VSNPRINTF(buffer, size, format, args); \ 1.37 + va_end(args); \ 1.38 + } while (0) 1.39 + 1.40 +/////////////////////////////////////////////////////////////////////////////// 1.41 + 1.42 +bool SkStrEndsWith(const char string[], const char suffixStr[]) { 1.43 + SkASSERT(string); 1.44 + SkASSERT(suffixStr); 1.45 + size_t strLen = strlen(string); 1.46 + size_t suffixLen = strlen(suffixStr); 1.47 + return strLen >= suffixLen && 1.48 + !strncmp(string + strLen - suffixLen, suffixStr, suffixLen); 1.49 +} 1.50 + 1.51 +bool SkStrEndsWith(const char string[], const char suffixChar) { 1.52 + SkASSERT(string); 1.53 + size_t strLen = strlen(string); 1.54 + if (0 == strLen) { 1.55 + return false; 1.56 + } else { 1.57 + return (suffixChar == string[strLen-1]); 1.58 + } 1.59 +} 1.60 + 1.61 +int SkStrStartsWithOneOf(const char string[], const char prefixes[]) { 1.62 + int index = 0; 1.63 + do { 1.64 + const char* limit = strchr(prefixes, '\0'); 1.65 + if (!strncmp(string, prefixes, limit - prefixes)) { 1.66 + return index; 1.67 + } 1.68 + prefixes = limit + 1; 1.69 + index++; 1.70 + } while (prefixes[0]); 1.71 + return -1; 1.72 +} 1.73 + 1.74 +char* SkStrAppendU32(char string[], uint32_t dec) { 1.75 + SkDEBUGCODE(char* start = string;) 1.76 + 1.77 + char buffer[SkStrAppendU32_MaxSize]; 1.78 + char* p = buffer + sizeof(buffer); 1.79 + 1.80 + do { 1.81 + *--p = SkToU8('0' + dec % 10); 1.82 + dec /= 10; 1.83 + } while (dec != 0); 1.84 + 1.85 + SkASSERT(p >= buffer); 1.86 + char* stop = buffer + sizeof(buffer); 1.87 + while (p < stop) { 1.88 + *string++ = *p++; 1.89 + } 1.90 + SkASSERT(string - start <= SkStrAppendU32_MaxSize); 1.91 + return string; 1.92 +} 1.93 + 1.94 +char* SkStrAppendS32(char string[], int32_t dec) { 1.95 + if (dec < 0) { 1.96 + *string++ = '-'; 1.97 + dec = -dec; 1.98 + } 1.99 + return SkStrAppendU32(string, static_cast<uint32_t>(dec)); 1.100 +} 1.101 + 1.102 +char* SkStrAppendU64(char string[], uint64_t dec, int minDigits) { 1.103 + SkDEBUGCODE(char* start = string;) 1.104 + 1.105 + char buffer[SkStrAppendU64_MaxSize]; 1.106 + char* p = buffer + sizeof(buffer); 1.107 + 1.108 + do { 1.109 + *--p = SkToU8('0' + (int32_t) (dec % 10)); 1.110 + dec /= 10; 1.111 + minDigits--; 1.112 + } while (dec != 0); 1.113 + 1.114 + while (minDigits > 0) { 1.115 + *--p = '0'; 1.116 + minDigits--; 1.117 + } 1.118 + 1.119 + SkASSERT(p >= buffer); 1.120 + size_t cp_len = buffer + sizeof(buffer) - p; 1.121 + memcpy(string, p, cp_len); 1.122 + string += cp_len; 1.123 + 1.124 + SkASSERT(string - start <= SkStrAppendU64_MaxSize); 1.125 + return string; 1.126 +} 1.127 + 1.128 +char* SkStrAppendS64(char string[], int64_t dec, int minDigits) { 1.129 + if (dec < 0) { 1.130 + *string++ = '-'; 1.131 + dec = -dec; 1.132 + } 1.133 + return SkStrAppendU64(string, static_cast<uint64_t>(dec), minDigits); 1.134 +} 1.135 + 1.136 +char* SkStrAppendFloat(char string[], float value) { 1.137 + // since floats have at most 8 significant digits, we limit our %g to that. 1.138 + static const char gFormat[] = "%.8g"; 1.139 + // make it 1 larger for the terminating 0 1.140 + char buffer[SkStrAppendScalar_MaxSize + 1]; 1.141 + int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value); 1.142 + memcpy(string, buffer, len); 1.143 + SkASSERT(len <= SkStrAppendScalar_MaxSize); 1.144 + return string + len; 1.145 +} 1.146 + 1.147 +char* SkStrAppendFixed(char string[], SkFixed x) { 1.148 + SkDEBUGCODE(char* start = string;) 1.149 + if (x < 0) { 1.150 + *string++ = '-'; 1.151 + x = -x; 1.152 + } 1.153 + 1.154 + unsigned frac = x & 0xFFFF; 1.155 + x >>= 16; 1.156 + if (frac == 0xFFFF) { 1.157 + // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999 1.158 + x += 1; 1.159 + frac = 0; 1.160 + } 1.161 + string = SkStrAppendS32(string, x); 1.162 + 1.163 + // now handle the fractional part (if any) 1.164 + if (frac) { 1.165 + static const uint16_t gTens[] = { 1000, 100, 10, 1 }; 1.166 + const uint16_t* tens = gTens; 1.167 + 1.168 + x = SkFixedRoundToInt(frac * 10000); 1.169 + SkASSERT(x <= 10000); 1.170 + if (x == 10000) { 1.171 + x -= 1; 1.172 + } 1.173 + *string++ = '.'; 1.174 + do { 1.175 + unsigned powerOfTen = *tens++; 1.176 + *string++ = SkToU8('0' + x / powerOfTen); 1.177 + x %= powerOfTen; 1.178 + } while (x != 0); 1.179 + } 1.180 + 1.181 + SkASSERT(string - start <= SkStrAppendScalar_MaxSize); 1.182 + return string; 1.183 +} 1.184 + 1.185 +/////////////////////////////////////////////////////////////////////////////// 1.186 + 1.187 +// the 3 values are [length] [refcnt] [terminating zero data] 1.188 +const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 }; 1.189 + 1.190 +#define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec) 1.191 + 1.192 +static uint32_t trim_size_t_to_u32(size_t value) { 1.193 + if (sizeof(size_t) > sizeof(uint32_t)) { 1.194 + if (value > SK_MaxU32) { 1.195 + value = SK_MaxU32; 1.196 + } 1.197 + } 1.198 + return (uint32_t)value; 1.199 +} 1.200 + 1.201 +static size_t check_add32(size_t base, size_t extra) { 1.202 + SkASSERT(base <= SK_MaxU32); 1.203 + if (sizeof(size_t) > sizeof(uint32_t)) { 1.204 + if (base + extra > SK_MaxU32) { 1.205 + extra = SK_MaxU32 - base; 1.206 + } 1.207 + } 1.208 + return extra; 1.209 +} 1.210 + 1.211 +SkString::Rec* SkString::AllocRec(const char text[], size_t len) { 1.212 + Rec* rec; 1.213 + 1.214 + if (0 == len) { 1.215 + rec = const_cast<Rec*>(&gEmptyRec); 1.216 + } else { 1.217 + len = trim_size_t_to_u32(len); 1.218 + 1.219 + // add 1 for terminating 0, then align4 so we can have some slop when growing the string 1.220 + rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1)); 1.221 + rec->fLength = SkToU32(len); 1.222 + rec->fRefCnt = 1; 1.223 + if (text) { 1.224 + memcpy(rec->data(), text, len); 1.225 + } 1.226 + rec->data()[len] = 0; 1.227 + } 1.228 + return rec; 1.229 +} 1.230 + 1.231 +SkString::Rec* SkString::RefRec(Rec* src) { 1.232 + if (src != &gEmptyRec) { 1.233 + sk_atomic_inc(&src->fRefCnt); 1.234 + } 1.235 + return src; 1.236 +} 1.237 + 1.238 +#ifdef SK_DEBUG 1.239 +void SkString::validate() const { 1.240 + // make sure know one has written over our global 1.241 + SkASSERT(0 == gEmptyRec.fLength); 1.242 + SkASSERT(0 == gEmptyRec.fRefCnt); 1.243 + SkASSERT(0 == gEmptyRec.data()[0]); 1.244 + 1.245 + if (fRec != &gEmptyRec) { 1.246 + SkASSERT(fRec->fLength > 0); 1.247 + SkASSERT(fRec->fRefCnt > 0); 1.248 + SkASSERT(0 == fRec->data()[fRec->fLength]); 1.249 + } 1.250 + SkASSERT(fStr == c_str()); 1.251 +} 1.252 +#endif 1.253 + 1.254 +/////////////////////////////////////////////////////////////////////////////// 1.255 + 1.256 +SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) { 1.257 +#ifdef SK_DEBUG 1.258 + fStr = fRec->data(); 1.259 +#endif 1.260 +} 1.261 + 1.262 +SkString::SkString(size_t len) { 1.263 + fRec = AllocRec(NULL, len); 1.264 +#ifdef SK_DEBUG 1.265 + fStr = fRec->data(); 1.266 +#endif 1.267 +} 1.268 + 1.269 +SkString::SkString(const char text[]) { 1.270 + size_t len = text ? strlen(text) : 0; 1.271 + 1.272 + fRec = AllocRec(text, len); 1.273 +#ifdef SK_DEBUG 1.274 + fStr = fRec->data(); 1.275 +#endif 1.276 +} 1.277 + 1.278 +SkString::SkString(const char text[], size_t len) { 1.279 + fRec = AllocRec(text, len); 1.280 +#ifdef SK_DEBUG 1.281 + fStr = fRec->data(); 1.282 +#endif 1.283 +} 1.284 + 1.285 +SkString::SkString(const SkString& src) { 1.286 + src.validate(); 1.287 + 1.288 + fRec = RefRec(src.fRec); 1.289 +#ifdef SK_DEBUG 1.290 + fStr = fRec->data(); 1.291 +#endif 1.292 +} 1.293 + 1.294 +SkString::~SkString() { 1.295 + this->validate(); 1.296 + 1.297 + if (fRec->fLength) { 1.298 + SkASSERT(fRec->fRefCnt > 0); 1.299 + if (sk_atomic_dec(&fRec->fRefCnt) == 1) { 1.300 + sk_free(fRec); 1.301 + } 1.302 + } 1.303 +} 1.304 + 1.305 +bool SkString::equals(const SkString& src) const { 1.306 + return fRec == src.fRec || this->equals(src.c_str(), src.size()); 1.307 +} 1.308 + 1.309 +bool SkString::equals(const char text[]) const { 1.310 + return this->equals(text, text ? strlen(text) : 0); 1.311 +} 1.312 + 1.313 +bool SkString::equals(const char text[], size_t len) const { 1.314 + SkASSERT(len == 0 || text != NULL); 1.315 + 1.316 + return fRec->fLength == len && !memcmp(fRec->data(), text, len); 1.317 +} 1.318 + 1.319 +SkString& SkString::operator=(const SkString& src) { 1.320 + this->validate(); 1.321 + 1.322 + if (fRec != src.fRec) { 1.323 + SkString tmp(src); 1.324 + this->swap(tmp); 1.325 + } 1.326 + return *this; 1.327 +} 1.328 + 1.329 +SkString& SkString::operator=(const char text[]) { 1.330 + this->validate(); 1.331 + 1.332 + SkString tmp(text); 1.333 + this->swap(tmp); 1.334 + 1.335 + return *this; 1.336 +} 1.337 + 1.338 +void SkString::reset() { 1.339 + this->validate(); 1.340 + 1.341 + if (fRec->fLength) { 1.342 + SkASSERT(fRec->fRefCnt > 0); 1.343 + if (sk_atomic_dec(&fRec->fRefCnt) == 1) { 1.344 + sk_free(fRec); 1.345 + } 1.346 + } 1.347 + 1.348 + fRec = const_cast<Rec*>(&gEmptyRec); 1.349 +#ifdef SK_DEBUG 1.350 + fStr = fRec->data(); 1.351 +#endif 1.352 +} 1.353 + 1.354 +char* SkString::writable_str() { 1.355 + this->validate(); 1.356 + 1.357 + if (fRec->fLength) { 1.358 + if (fRec->fRefCnt > 1) { 1.359 + Rec* rec = AllocRec(fRec->data(), fRec->fLength); 1.360 + if (sk_atomic_dec(&fRec->fRefCnt) == 1) { 1.361 + // In this case after our check of fRecCnt > 1, we suddenly 1.362 + // did become the only owner, so now we have two copies of the 1.363 + // data (fRec and rec), so we need to delete one of them. 1.364 + sk_free(fRec); 1.365 + } 1.366 + fRec = rec; 1.367 + #ifdef SK_DEBUG 1.368 + fStr = fRec->data(); 1.369 + #endif 1.370 + } 1.371 + } 1.372 + return fRec->data(); 1.373 +} 1.374 + 1.375 +void SkString::set(const char text[]) { 1.376 + this->set(text, text ? strlen(text) : 0); 1.377 +} 1.378 + 1.379 +void SkString::set(const char text[], size_t len) { 1.380 + len = trim_size_t_to_u32(len); 1.381 + 1.382 + if (0 == len) { 1.383 + this->reset(); 1.384 + } else if (1 == fRec->fRefCnt && len <= fRec->fLength) { 1.385 + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))? 1.386 + // just use less of the buffer without allocating a smaller one 1.387 + char* p = this->writable_str(); 1.388 + if (text) { 1.389 + memcpy(p, text, len); 1.390 + } 1.391 + p[len] = 0; 1.392 + fRec->fLength = SkToU32(len); 1.393 + } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) { 1.394 + // we have spare room in the current allocation, so don't alloc a larger one 1.395 + char* p = this->writable_str(); 1.396 + if (text) { 1.397 + memcpy(p, text, len); 1.398 + } 1.399 + p[len] = 0; 1.400 + fRec->fLength = SkToU32(len); 1.401 + } else { 1.402 + SkString tmp(text, len); 1.403 + this->swap(tmp); 1.404 + } 1.405 +} 1.406 + 1.407 +void SkString::setUTF16(const uint16_t src[]) { 1.408 + int count = 0; 1.409 + 1.410 + while (src[count]) { 1.411 + count += 1; 1.412 + } 1.413 + this->setUTF16(src, count); 1.414 +} 1.415 + 1.416 +void SkString::setUTF16(const uint16_t src[], size_t count) { 1.417 + count = trim_size_t_to_u32(count); 1.418 + 1.419 + if (0 == count) { 1.420 + this->reset(); 1.421 + } else if (count <= fRec->fLength) { 1.422 + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) 1.423 + if (count < fRec->fLength) { 1.424 + this->resize(count); 1.425 + } 1.426 + char* p = this->writable_str(); 1.427 + for (size_t i = 0; i < count; i++) { 1.428 + p[i] = SkToU8(src[i]); 1.429 + } 1.430 + p[count] = 0; 1.431 + } else { 1.432 + SkString tmp(count); // puts a null terminator at the end of the string 1.433 + char* p = tmp.writable_str(); 1.434 + 1.435 + for (size_t i = 0; i < count; i++) { 1.436 + p[i] = SkToU8(src[i]); 1.437 + } 1.438 + this->swap(tmp); 1.439 + } 1.440 +} 1.441 + 1.442 +void SkString::insert(size_t offset, const char text[]) { 1.443 + this->insert(offset, text, text ? strlen(text) : 0); 1.444 +} 1.445 + 1.446 +void SkString::insert(size_t offset, const char text[], size_t len) { 1.447 + if (len) { 1.448 + size_t length = fRec->fLength; 1.449 + if (offset > length) { 1.450 + offset = length; 1.451 + } 1.452 + 1.453 + // Check if length + len exceeds 32bits, we trim len 1.454 + len = check_add32(length, len); 1.455 + if (0 == len) { 1.456 + return; 1.457 + } 1.458 + 1.459 + /* If we're the only owner, and we have room in our allocation for the insert, 1.460 + do it in place, rather than allocating a new buffer. 1.461 + 1.462 + To know we have room, compare the allocated sizes 1.463 + beforeAlloc = SkAlign4(length + 1) 1.464 + afterAlloc = SkAligh4(length + 1 + len) 1.465 + but SkAlign4(x) is (x + 3) >> 2 << 2 1.466 + which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 1.467 + and we can then eliminate the +1+3 since that doesn't affec the answer 1.468 + */ 1.469 + if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) { 1.470 + char* dst = this->writable_str(); 1.471 + 1.472 + if (offset < length) { 1.473 + memmove(dst + offset + len, dst + offset, length - offset); 1.474 + } 1.475 + memcpy(dst + offset, text, len); 1.476 + 1.477 + dst[length + len] = 0; 1.478 + fRec->fLength = SkToU32(length + len); 1.479 + } else { 1.480 + /* Seems we should use realloc here, since that is safe if it fails 1.481 + (we have the original data), and might be faster than alloc/copy/free. 1.482 + */ 1.483 + SkString tmp(fRec->fLength + len); 1.484 + char* dst = tmp.writable_str(); 1.485 + 1.486 + if (offset > 0) { 1.487 + memcpy(dst, fRec->data(), offset); 1.488 + } 1.489 + memcpy(dst + offset, text, len); 1.490 + if (offset < fRec->fLength) { 1.491 + memcpy(dst + offset + len, fRec->data() + offset, 1.492 + fRec->fLength - offset); 1.493 + } 1.494 + 1.495 + this->swap(tmp); 1.496 + } 1.497 + } 1.498 +} 1.499 + 1.500 +void SkString::insertUnichar(size_t offset, SkUnichar uni) { 1.501 + char buffer[kMaxBytesInUTF8Sequence]; 1.502 + size_t len = SkUTF8_FromUnichar(uni, buffer); 1.503 + 1.504 + if (len) { 1.505 + this->insert(offset, buffer, len); 1.506 + } 1.507 +} 1.508 + 1.509 +void SkString::insertS32(size_t offset, int32_t dec) { 1.510 + char buffer[SkStrAppendS32_MaxSize]; 1.511 + char* stop = SkStrAppendS32(buffer, dec); 1.512 + this->insert(offset, buffer, stop - buffer); 1.513 +} 1.514 + 1.515 +void SkString::insertS64(size_t offset, int64_t dec, int minDigits) { 1.516 + char buffer[SkStrAppendS64_MaxSize]; 1.517 + char* stop = SkStrAppendS64(buffer, dec, minDigits); 1.518 + this->insert(offset, buffer, stop - buffer); 1.519 +} 1.520 + 1.521 +void SkString::insertU32(size_t offset, uint32_t dec) { 1.522 + char buffer[SkStrAppendU32_MaxSize]; 1.523 + char* stop = SkStrAppendU32(buffer, dec); 1.524 + this->insert(offset, buffer, stop - buffer); 1.525 +} 1.526 + 1.527 +void SkString::insertU64(size_t offset, uint64_t dec, int minDigits) { 1.528 + char buffer[SkStrAppendU64_MaxSize]; 1.529 + char* stop = SkStrAppendU64(buffer, dec, minDigits); 1.530 + this->insert(offset, buffer, stop - buffer); 1.531 +} 1.532 + 1.533 +void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) { 1.534 + minDigits = SkPin32(minDigits, 0, 8); 1.535 + 1.536 + static const char gHex[] = "0123456789ABCDEF"; 1.537 + 1.538 + char buffer[8]; 1.539 + char* p = buffer + sizeof(buffer); 1.540 + 1.541 + do { 1.542 + *--p = gHex[hex & 0xF]; 1.543 + hex >>= 4; 1.544 + minDigits -= 1; 1.545 + } while (hex != 0); 1.546 + 1.547 + while (--minDigits >= 0) { 1.548 + *--p = '0'; 1.549 + } 1.550 + 1.551 + SkASSERT(p >= buffer); 1.552 + this->insert(offset, p, buffer + sizeof(buffer) - p); 1.553 +} 1.554 + 1.555 +void SkString::insertScalar(size_t offset, SkScalar value) { 1.556 + char buffer[SkStrAppendScalar_MaxSize]; 1.557 + char* stop = SkStrAppendScalar(buffer, value); 1.558 + this->insert(offset, buffer, stop - buffer); 1.559 +} 1.560 + 1.561 +void SkString::printf(const char format[], ...) { 1.562 + char buffer[kBufferSize]; 1.563 + ARGS_TO_BUFFER(format, buffer, kBufferSize); 1.564 + 1.565 + this->set(buffer, strlen(buffer)); 1.566 +} 1.567 + 1.568 +void SkString::appendf(const char format[], ...) { 1.569 + char buffer[kBufferSize]; 1.570 + ARGS_TO_BUFFER(format, buffer, kBufferSize); 1.571 + 1.572 + this->append(buffer, strlen(buffer)); 1.573 +} 1.574 + 1.575 +void SkString::appendVAList(const char format[], va_list args) { 1.576 + char buffer[kBufferSize]; 1.577 + VSNPRINTF(buffer, kBufferSize, format, args); 1.578 + 1.579 + this->append(buffer, strlen(buffer)); 1.580 +} 1.581 + 1.582 +void SkString::prependf(const char format[], ...) { 1.583 + char buffer[kBufferSize]; 1.584 + ARGS_TO_BUFFER(format, buffer, kBufferSize); 1.585 + 1.586 + this->prepend(buffer, strlen(buffer)); 1.587 +} 1.588 + 1.589 +/////////////////////////////////////////////////////////////////////////////// 1.590 + 1.591 +void SkString::remove(size_t offset, size_t length) { 1.592 + size_t size = this->size(); 1.593 + 1.594 + if (offset < size) { 1.595 + if (offset + length > size) { 1.596 + length = size - offset; 1.597 + } 1.598 + if (length > 0) { 1.599 + SkASSERT(size > length); 1.600 + SkString tmp(size - length); 1.601 + char* dst = tmp.writable_str(); 1.602 + const char* src = this->c_str(); 1.603 + 1.604 + if (offset) { 1.605 + SkASSERT(offset <= tmp.size()); 1.606 + memcpy(dst, src, offset); 1.607 + } 1.608 + size_t tail = size - offset - length; 1.609 + SkASSERT((int32_t)tail >= 0); 1.610 + if (tail) { 1.611 + // SkASSERT(offset + length <= tmp.size()); 1.612 + memcpy(dst + offset, src + offset + length, tail); 1.613 + } 1.614 + SkASSERT(dst[tmp.size()] == 0); 1.615 + this->swap(tmp); 1.616 + } 1.617 + } 1.618 +} 1.619 + 1.620 +void SkString::swap(SkString& other) { 1.621 + this->validate(); 1.622 + other.validate(); 1.623 + 1.624 + SkTSwap<Rec*>(fRec, other.fRec); 1.625 +#ifdef SK_DEBUG 1.626 + SkTSwap<const char*>(fStr, other.fStr); 1.627 +#endif 1.628 +} 1.629 + 1.630 +/////////////////////////////////////////////////////////////////////////////// 1.631 + 1.632 +SkString SkStringPrintf(const char* format, ...) { 1.633 + SkString formattedOutput; 1.634 + char buffer[kBufferSize]; 1.635 + ARGS_TO_BUFFER(format, buffer, kBufferSize); 1.636 + formattedOutput.set(buffer); 1.637 + return formattedOutput; 1.638 +} 1.639 + 1.640 +void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) { 1.641 + const char* end = str + strlen(str); 1.642 + while (str != end) { 1.643 + // Find a token. 1.644 + const size_t len = strcspn(str, delimiters); 1.645 + out->push_back().set(str, len); 1.646 + str += len; 1.647 + // Skip any delimiters. 1.648 + str += strspn(str, delimiters); 1.649 + } 1.650 +} 1.651 + 1.652 +#undef VSNPRINTF 1.653 +#undef SNPRINTF