gfx/skia/trunk/src/core/SkString.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkString.h"
michael@0 11 #include "SkFixed.h"
michael@0 12 #include "SkThread.h"
michael@0 13 #include "SkUtils.h"
michael@0 14 #include <stdarg.h>
michael@0 15 #include <stdio.h>
michael@0 16
michael@0 17 // number of bytes (on the stack) to receive the printf result
michael@0 18 static const size_t kBufferSize = 1024;
michael@0 19
michael@0 20 #ifdef SK_BUILD_FOR_WIN
michael@0 21 #define VSNPRINTF(buffer, size, format, args) \
michael@0 22 _vsnprintf_s(buffer, size, _TRUNCATE, format, args)
michael@0 23 #define SNPRINTF _snprintf
michael@0 24 #else
michael@0 25 #define VSNPRINTF vsnprintf
michael@0 26 #define SNPRINTF snprintf
michael@0 27 #endif
michael@0 28
michael@0 29 #define ARGS_TO_BUFFER(format, buffer, size) \
michael@0 30 do { \
michael@0 31 va_list args; \
michael@0 32 va_start(args, format); \
michael@0 33 VSNPRINTF(buffer, size, format, args); \
michael@0 34 va_end(args); \
michael@0 35 } while (0)
michael@0 36
michael@0 37 ///////////////////////////////////////////////////////////////////////////////
michael@0 38
michael@0 39 bool SkStrEndsWith(const char string[], const char suffixStr[]) {
michael@0 40 SkASSERT(string);
michael@0 41 SkASSERT(suffixStr);
michael@0 42 size_t strLen = strlen(string);
michael@0 43 size_t suffixLen = strlen(suffixStr);
michael@0 44 return strLen >= suffixLen &&
michael@0 45 !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
michael@0 46 }
michael@0 47
michael@0 48 bool SkStrEndsWith(const char string[], const char suffixChar) {
michael@0 49 SkASSERT(string);
michael@0 50 size_t strLen = strlen(string);
michael@0 51 if (0 == strLen) {
michael@0 52 return false;
michael@0 53 } else {
michael@0 54 return (suffixChar == string[strLen-1]);
michael@0 55 }
michael@0 56 }
michael@0 57
michael@0 58 int SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
michael@0 59 int index = 0;
michael@0 60 do {
michael@0 61 const char* limit = strchr(prefixes, '\0');
michael@0 62 if (!strncmp(string, prefixes, limit - prefixes)) {
michael@0 63 return index;
michael@0 64 }
michael@0 65 prefixes = limit + 1;
michael@0 66 index++;
michael@0 67 } while (prefixes[0]);
michael@0 68 return -1;
michael@0 69 }
michael@0 70
michael@0 71 char* SkStrAppendU32(char string[], uint32_t dec) {
michael@0 72 SkDEBUGCODE(char* start = string;)
michael@0 73
michael@0 74 char buffer[SkStrAppendU32_MaxSize];
michael@0 75 char* p = buffer + sizeof(buffer);
michael@0 76
michael@0 77 do {
michael@0 78 *--p = SkToU8('0' + dec % 10);
michael@0 79 dec /= 10;
michael@0 80 } while (dec != 0);
michael@0 81
michael@0 82 SkASSERT(p >= buffer);
michael@0 83 char* stop = buffer + sizeof(buffer);
michael@0 84 while (p < stop) {
michael@0 85 *string++ = *p++;
michael@0 86 }
michael@0 87 SkASSERT(string - start <= SkStrAppendU32_MaxSize);
michael@0 88 return string;
michael@0 89 }
michael@0 90
michael@0 91 char* SkStrAppendS32(char string[], int32_t dec) {
michael@0 92 if (dec < 0) {
michael@0 93 *string++ = '-';
michael@0 94 dec = -dec;
michael@0 95 }
michael@0 96 return SkStrAppendU32(string, static_cast<uint32_t>(dec));
michael@0 97 }
michael@0 98
michael@0 99 char* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
michael@0 100 SkDEBUGCODE(char* start = string;)
michael@0 101
michael@0 102 char buffer[SkStrAppendU64_MaxSize];
michael@0 103 char* p = buffer + sizeof(buffer);
michael@0 104
michael@0 105 do {
michael@0 106 *--p = SkToU8('0' + (int32_t) (dec % 10));
michael@0 107 dec /= 10;
michael@0 108 minDigits--;
michael@0 109 } while (dec != 0);
michael@0 110
michael@0 111 while (minDigits > 0) {
michael@0 112 *--p = '0';
michael@0 113 minDigits--;
michael@0 114 }
michael@0 115
michael@0 116 SkASSERT(p >= buffer);
michael@0 117 size_t cp_len = buffer + sizeof(buffer) - p;
michael@0 118 memcpy(string, p, cp_len);
michael@0 119 string += cp_len;
michael@0 120
michael@0 121 SkASSERT(string - start <= SkStrAppendU64_MaxSize);
michael@0 122 return string;
michael@0 123 }
michael@0 124
michael@0 125 char* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
michael@0 126 if (dec < 0) {
michael@0 127 *string++ = '-';
michael@0 128 dec = -dec;
michael@0 129 }
michael@0 130 return SkStrAppendU64(string, static_cast<uint64_t>(dec), minDigits);
michael@0 131 }
michael@0 132
michael@0 133 char* SkStrAppendFloat(char string[], float value) {
michael@0 134 // since floats have at most 8 significant digits, we limit our %g to that.
michael@0 135 static const char gFormat[] = "%.8g";
michael@0 136 // make it 1 larger for the terminating 0
michael@0 137 char buffer[SkStrAppendScalar_MaxSize + 1];
michael@0 138 int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
michael@0 139 memcpy(string, buffer, len);
michael@0 140 SkASSERT(len <= SkStrAppendScalar_MaxSize);
michael@0 141 return string + len;
michael@0 142 }
michael@0 143
michael@0 144 char* SkStrAppendFixed(char string[], SkFixed x) {
michael@0 145 SkDEBUGCODE(char* start = string;)
michael@0 146 if (x < 0) {
michael@0 147 *string++ = '-';
michael@0 148 x = -x;
michael@0 149 }
michael@0 150
michael@0 151 unsigned frac = x & 0xFFFF;
michael@0 152 x >>= 16;
michael@0 153 if (frac == 0xFFFF) {
michael@0 154 // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999
michael@0 155 x += 1;
michael@0 156 frac = 0;
michael@0 157 }
michael@0 158 string = SkStrAppendS32(string, x);
michael@0 159
michael@0 160 // now handle the fractional part (if any)
michael@0 161 if (frac) {
michael@0 162 static const uint16_t gTens[] = { 1000, 100, 10, 1 };
michael@0 163 const uint16_t* tens = gTens;
michael@0 164
michael@0 165 x = SkFixedRoundToInt(frac * 10000);
michael@0 166 SkASSERT(x <= 10000);
michael@0 167 if (x == 10000) {
michael@0 168 x -= 1;
michael@0 169 }
michael@0 170 *string++ = '.';
michael@0 171 do {
michael@0 172 unsigned powerOfTen = *tens++;
michael@0 173 *string++ = SkToU8('0' + x / powerOfTen);
michael@0 174 x %= powerOfTen;
michael@0 175 } while (x != 0);
michael@0 176 }
michael@0 177
michael@0 178 SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
michael@0 179 return string;
michael@0 180 }
michael@0 181
michael@0 182 ///////////////////////////////////////////////////////////////////////////////
michael@0 183
michael@0 184 // the 3 values are [length] [refcnt] [terminating zero data]
michael@0 185 const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
michael@0 186
michael@0 187 #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec)
michael@0 188
michael@0 189 static uint32_t trim_size_t_to_u32(size_t value) {
michael@0 190 if (sizeof(size_t) > sizeof(uint32_t)) {
michael@0 191 if (value > SK_MaxU32) {
michael@0 192 value = SK_MaxU32;
michael@0 193 }
michael@0 194 }
michael@0 195 return (uint32_t)value;
michael@0 196 }
michael@0 197
michael@0 198 static size_t check_add32(size_t base, size_t extra) {
michael@0 199 SkASSERT(base <= SK_MaxU32);
michael@0 200 if (sizeof(size_t) > sizeof(uint32_t)) {
michael@0 201 if (base + extra > SK_MaxU32) {
michael@0 202 extra = SK_MaxU32 - base;
michael@0 203 }
michael@0 204 }
michael@0 205 return extra;
michael@0 206 }
michael@0 207
michael@0 208 SkString::Rec* SkString::AllocRec(const char text[], size_t len) {
michael@0 209 Rec* rec;
michael@0 210
michael@0 211 if (0 == len) {
michael@0 212 rec = const_cast<Rec*>(&gEmptyRec);
michael@0 213 } else {
michael@0 214 len = trim_size_t_to_u32(len);
michael@0 215
michael@0 216 // add 1 for terminating 0, then align4 so we can have some slop when growing the string
michael@0 217 rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
michael@0 218 rec->fLength = SkToU32(len);
michael@0 219 rec->fRefCnt = 1;
michael@0 220 if (text) {
michael@0 221 memcpy(rec->data(), text, len);
michael@0 222 }
michael@0 223 rec->data()[len] = 0;
michael@0 224 }
michael@0 225 return rec;
michael@0 226 }
michael@0 227
michael@0 228 SkString::Rec* SkString::RefRec(Rec* src) {
michael@0 229 if (src != &gEmptyRec) {
michael@0 230 sk_atomic_inc(&src->fRefCnt);
michael@0 231 }
michael@0 232 return src;
michael@0 233 }
michael@0 234
michael@0 235 #ifdef SK_DEBUG
michael@0 236 void SkString::validate() const {
michael@0 237 // make sure know one has written over our global
michael@0 238 SkASSERT(0 == gEmptyRec.fLength);
michael@0 239 SkASSERT(0 == gEmptyRec.fRefCnt);
michael@0 240 SkASSERT(0 == gEmptyRec.data()[0]);
michael@0 241
michael@0 242 if (fRec != &gEmptyRec) {
michael@0 243 SkASSERT(fRec->fLength > 0);
michael@0 244 SkASSERT(fRec->fRefCnt > 0);
michael@0 245 SkASSERT(0 == fRec->data()[fRec->fLength]);
michael@0 246 }
michael@0 247 SkASSERT(fStr == c_str());
michael@0 248 }
michael@0 249 #endif
michael@0 250
michael@0 251 ///////////////////////////////////////////////////////////////////////////////
michael@0 252
michael@0 253 SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
michael@0 254 #ifdef SK_DEBUG
michael@0 255 fStr = fRec->data();
michael@0 256 #endif
michael@0 257 }
michael@0 258
michael@0 259 SkString::SkString(size_t len) {
michael@0 260 fRec = AllocRec(NULL, len);
michael@0 261 #ifdef SK_DEBUG
michael@0 262 fStr = fRec->data();
michael@0 263 #endif
michael@0 264 }
michael@0 265
michael@0 266 SkString::SkString(const char text[]) {
michael@0 267 size_t len = text ? strlen(text) : 0;
michael@0 268
michael@0 269 fRec = AllocRec(text, len);
michael@0 270 #ifdef SK_DEBUG
michael@0 271 fStr = fRec->data();
michael@0 272 #endif
michael@0 273 }
michael@0 274
michael@0 275 SkString::SkString(const char text[], size_t len) {
michael@0 276 fRec = AllocRec(text, len);
michael@0 277 #ifdef SK_DEBUG
michael@0 278 fStr = fRec->data();
michael@0 279 #endif
michael@0 280 }
michael@0 281
michael@0 282 SkString::SkString(const SkString& src) {
michael@0 283 src.validate();
michael@0 284
michael@0 285 fRec = RefRec(src.fRec);
michael@0 286 #ifdef SK_DEBUG
michael@0 287 fStr = fRec->data();
michael@0 288 #endif
michael@0 289 }
michael@0 290
michael@0 291 SkString::~SkString() {
michael@0 292 this->validate();
michael@0 293
michael@0 294 if (fRec->fLength) {
michael@0 295 SkASSERT(fRec->fRefCnt > 0);
michael@0 296 if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
michael@0 297 sk_free(fRec);
michael@0 298 }
michael@0 299 }
michael@0 300 }
michael@0 301
michael@0 302 bool SkString::equals(const SkString& src) const {
michael@0 303 return fRec == src.fRec || this->equals(src.c_str(), src.size());
michael@0 304 }
michael@0 305
michael@0 306 bool SkString::equals(const char text[]) const {
michael@0 307 return this->equals(text, text ? strlen(text) : 0);
michael@0 308 }
michael@0 309
michael@0 310 bool SkString::equals(const char text[], size_t len) const {
michael@0 311 SkASSERT(len == 0 || text != NULL);
michael@0 312
michael@0 313 return fRec->fLength == len && !memcmp(fRec->data(), text, len);
michael@0 314 }
michael@0 315
michael@0 316 SkString& SkString::operator=(const SkString& src) {
michael@0 317 this->validate();
michael@0 318
michael@0 319 if (fRec != src.fRec) {
michael@0 320 SkString tmp(src);
michael@0 321 this->swap(tmp);
michael@0 322 }
michael@0 323 return *this;
michael@0 324 }
michael@0 325
michael@0 326 SkString& SkString::operator=(const char text[]) {
michael@0 327 this->validate();
michael@0 328
michael@0 329 SkString tmp(text);
michael@0 330 this->swap(tmp);
michael@0 331
michael@0 332 return *this;
michael@0 333 }
michael@0 334
michael@0 335 void SkString::reset() {
michael@0 336 this->validate();
michael@0 337
michael@0 338 if (fRec->fLength) {
michael@0 339 SkASSERT(fRec->fRefCnt > 0);
michael@0 340 if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
michael@0 341 sk_free(fRec);
michael@0 342 }
michael@0 343 }
michael@0 344
michael@0 345 fRec = const_cast<Rec*>(&gEmptyRec);
michael@0 346 #ifdef SK_DEBUG
michael@0 347 fStr = fRec->data();
michael@0 348 #endif
michael@0 349 }
michael@0 350
michael@0 351 char* SkString::writable_str() {
michael@0 352 this->validate();
michael@0 353
michael@0 354 if (fRec->fLength) {
michael@0 355 if (fRec->fRefCnt > 1) {
michael@0 356 Rec* rec = AllocRec(fRec->data(), fRec->fLength);
michael@0 357 if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
michael@0 358 // In this case after our check of fRecCnt > 1, we suddenly
michael@0 359 // did become the only owner, so now we have two copies of the
michael@0 360 // data (fRec and rec), so we need to delete one of them.
michael@0 361 sk_free(fRec);
michael@0 362 }
michael@0 363 fRec = rec;
michael@0 364 #ifdef SK_DEBUG
michael@0 365 fStr = fRec->data();
michael@0 366 #endif
michael@0 367 }
michael@0 368 }
michael@0 369 return fRec->data();
michael@0 370 }
michael@0 371
michael@0 372 void SkString::set(const char text[]) {
michael@0 373 this->set(text, text ? strlen(text) : 0);
michael@0 374 }
michael@0 375
michael@0 376 void SkString::set(const char text[], size_t len) {
michael@0 377 len = trim_size_t_to_u32(len);
michael@0 378
michael@0 379 if (0 == len) {
michael@0 380 this->reset();
michael@0 381 } else if (1 == fRec->fRefCnt && len <= fRec->fLength) {
michael@0 382 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
michael@0 383 // just use less of the buffer without allocating a smaller one
michael@0 384 char* p = this->writable_str();
michael@0 385 if (text) {
michael@0 386 memcpy(p, text, len);
michael@0 387 }
michael@0 388 p[len] = 0;
michael@0 389 fRec->fLength = SkToU32(len);
michael@0 390 } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) {
michael@0 391 // we have spare room in the current allocation, so don't alloc a larger one
michael@0 392 char* p = this->writable_str();
michael@0 393 if (text) {
michael@0 394 memcpy(p, text, len);
michael@0 395 }
michael@0 396 p[len] = 0;
michael@0 397 fRec->fLength = SkToU32(len);
michael@0 398 } else {
michael@0 399 SkString tmp(text, len);
michael@0 400 this->swap(tmp);
michael@0 401 }
michael@0 402 }
michael@0 403
michael@0 404 void SkString::setUTF16(const uint16_t src[]) {
michael@0 405 int count = 0;
michael@0 406
michael@0 407 while (src[count]) {
michael@0 408 count += 1;
michael@0 409 }
michael@0 410 this->setUTF16(src, count);
michael@0 411 }
michael@0 412
michael@0 413 void SkString::setUTF16(const uint16_t src[], size_t count) {
michael@0 414 count = trim_size_t_to_u32(count);
michael@0 415
michael@0 416 if (0 == count) {
michael@0 417 this->reset();
michael@0 418 } else if (count <= fRec->fLength) {
michael@0 419 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
michael@0 420 if (count < fRec->fLength) {
michael@0 421 this->resize(count);
michael@0 422 }
michael@0 423 char* p = this->writable_str();
michael@0 424 for (size_t i = 0; i < count; i++) {
michael@0 425 p[i] = SkToU8(src[i]);
michael@0 426 }
michael@0 427 p[count] = 0;
michael@0 428 } else {
michael@0 429 SkString tmp(count); // puts a null terminator at the end of the string
michael@0 430 char* p = tmp.writable_str();
michael@0 431
michael@0 432 for (size_t i = 0; i < count; i++) {
michael@0 433 p[i] = SkToU8(src[i]);
michael@0 434 }
michael@0 435 this->swap(tmp);
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 void SkString::insert(size_t offset, const char text[]) {
michael@0 440 this->insert(offset, text, text ? strlen(text) : 0);
michael@0 441 }
michael@0 442
michael@0 443 void SkString::insert(size_t offset, const char text[], size_t len) {
michael@0 444 if (len) {
michael@0 445 size_t length = fRec->fLength;
michael@0 446 if (offset > length) {
michael@0 447 offset = length;
michael@0 448 }
michael@0 449
michael@0 450 // Check if length + len exceeds 32bits, we trim len
michael@0 451 len = check_add32(length, len);
michael@0 452 if (0 == len) {
michael@0 453 return;
michael@0 454 }
michael@0 455
michael@0 456 /* If we're the only owner, and we have room in our allocation for the insert,
michael@0 457 do it in place, rather than allocating a new buffer.
michael@0 458
michael@0 459 To know we have room, compare the allocated sizes
michael@0 460 beforeAlloc = SkAlign4(length + 1)
michael@0 461 afterAlloc = SkAligh4(length + 1 + len)
michael@0 462 but SkAlign4(x) is (x + 3) >> 2 << 2
michael@0 463 which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
michael@0 464 and we can then eliminate the +1+3 since that doesn't affec the answer
michael@0 465 */
michael@0 466 if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) {
michael@0 467 char* dst = this->writable_str();
michael@0 468
michael@0 469 if (offset < length) {
michael@0 470 memmove(dst + offset + len, dst + offset, length - offset);
michael@0 471 }
michael@0 472 memcpy(dst + offset, text, len);
michael@0 473
michael@0 474 dst[length + len] = 0;
michael@0 475 fRec->fLength = SkToU32(length + len);
michael@0 476 } else {
michael@0 477 /* Seems we should use realloc here, since that is safe if it fails
michael@0 478 (we have the original data), and might be faster than alloc/copy/free.
michael@0 479 */
michael@0 480 SkString tmp(fRec->fLength + len);
michael@0 481 char* dst = tmp.writable_str();
michael@0 482
michael@0 483 if (offset > 0) {
michael@0 484 memcpy(dst, fRec->data(), offset);
michael@0 485 }
michael@0 486 memcpy(dst + offset, text, len);
michael@0 487 if (offset < fRec->fLength) {
michael@0 488 memcpy(dst + offset + len, fRec->data() + offset,
michael@0 489 fRec->fLength - offset);
michael@0 490 }
michael@0 491
michael@0 492 this->swap(tmp);
michael@0 493 }
michael@0 494 }
michael@0 495 }
michael@0 496
michael@0 497 void SkString::insertUnichar(size_t offset, SkUnichar uni) {
michael@0 498 char buffer[kMaxBytesInUTF8Sequence];
michael@0 499 size_t len = SkUTF8_FromUnichar(uni, buffer);
michael@0 500
michael@0 501 if (len) {
michael@0 502 this->insert(offset, buffer, len);
michael@0 503 }
michael@0 504 }
michael@0 505
michael@0 506 void SkString::insertS32(size_t offset, int32_t dec) {
michael@0 507 char buffer[SkStrAppendS32_MaxSize];
michael@0 508 char* stop = SkStrAppendS32(buffer, dec);
michael@0 509 this->insert(offset, buffer, stop - buffer);
michael@0 510 }
michael@0 511
michael@0 512 void SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
michael@0 513 char buffer[SkStrAppendS64_MaxSize];
michael@0 514 char* stop = SkStrAppendS64(buffer, dec, minDigits);
michael@0 515 this->insert(offset, buffer, stop - buffer);
michael@0 516 }
michael@0 517
michael@0 518 void SkString::insertU32(size_t offset, uint32_t dec) {
michael@0 519 char buffer[SkStrAppendU32_MaxSize];
michael@0 520 char* stop = SkStrAppendU32(buffer, dec);
michael@0 521 this->insert(offset, buffer, stop - buffer);
michael@0 522 }
michael@0 523
michael@0 524 void SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
michael@0 525 char buffer[SkStrAppendU64_MaxSize];
michael@0 526 char* stop = SkStrAppendU64(buffer, dec, minDigits);
michael@0 527 this->insert(offset, buffer, stop - buffer);
michael@0 528 }
michael@0 529
michael@0 530 void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
michael@0 531 minDigits = SkPin32(minDigits, 0, 8);
michael@0 532
michael@0 533 static const char gHex[] = "0123456789ABCDEF";
michael@0 534
michael@0 535 char buffer[8];
michael@0 536 char* p = buffer + sizeof(buffer);
michael@0 537
michael@0 538 do {
michael@0 539 *--p = gHex[hex & 0xF];
michael@0 540 hex >>= 4;
michael@0 541 minDigits -= 1;
michael@0 542 } while (hex != 0);
michael@0 543
michael@0 544 while (--minDigits >= 0) {
michael@0 545 *--p = '0';
michael@0 546 }
michael@0 547
michael@0 548 SkASSERT(p >= buffer);
michael@0 549 this->insert(offset, p, buffer + sizeof(buffer) - p);
michael@0 550 }
michael@0 551
michael@0 552 void SkString::insertScalar(size_t offset, SkScalar value) {
michael@0 553 char buffer[SkStrAppendScalar_MaxSize];
michael@0 554 char* stop = SkStrAppendScalar(buffer, value);
michael@0 555 this->insert(offset, buffer, stop - buffer);
michael@0 556 }
michael@0 557
michael@0 558 void SkString::printf(const char format[], ...) {
michael@0 559 char buffer[kBufferSize];
michael@0 560 ARGS_TO_BUFFER(format, buffer, kBufferSize);
michael@0 561
michael@0 562 this->set(buffer, strlen(buffer));
michael@0 563 }
michael@0 564
michael@0 565 void SkString::appendf(const char format[], ...) {
michael@0 566 char buffer[kBufferSize];
michael@0 567 ARGS_TO_BUFFER(format, buffer, kBufferSize);
michael@0 568
michael@0 569 this->append(buffer, strlen(buffer));
michael@0 570 }
michael@0 571
michael@0 572 void SkString::appendVAList(const char format[], va_list args) {
michael@0 573 char buffer[kBufferSize];
michael@0 574 VSNPRINTF(buffer, kBufferSize, format, args);
michael@0 575
michael@0 576 this->append(buffer, strlen(buffer));
michael@0 577 }
michael@0 578
michael@0 579 void SkString::prependf(const char format[], ...) {
michael@0 580 char buffer[kBufferSize];
michael@0 581 ARGS_TO_BUFFER(format, buffer, kBufferSize);
michael@0 582
michael@0 583 this->prepend(buffer, strlen(buffer));
michael@0 584 }
michael@0 585
michael@0 586 ///////////////////////////////////////////////////////////////////////////////
michael@0 587
michael@0 588 void SkString::remove(size_t offset, size_t length) {
michael@0 589 size_t size = this->size();
michael@0 590
michael@0 591 if (offset < size) {
michael@0 592 if (offset + length > size) {
michael@0 593 length = size - offset;
michael@0 594 }
michael@0 595 if (length > 0) {
michael@0 596 SkASSERT(size > length);
michael@0 597 SkString tmp(size - length);
michael@0 598 char* dst = tmp.writable_str();
michael@0 599 const char* src = this->c_str();
michael@0 600
michael@0 601 if (offset) {
michael@0 602 SkASSERT(offset <= tmp.size());
michael@0 603 memcpy(dst, src, offset);
michael@0 604 }
michael@0 605 size_t tail = size - offset - length;
michael@0 606 SkASSERT((int32_t)tail >= 0);
michael@0 607 if (tail) {
michael@0 608 // SkASSERT(offset + length <= tmp.size());
michael@0 609 memcpy(dst + offset, src + offset + length, tail);
michael@0 610 }
michael@0 611 SkASSERT(dst[tmp.size()] == 0);
michael@0 612 this->swap(tmp);
michael@0 613 }
michael@0 614 }
michael@0 615 }
michael@0 616
michael@0 617 void SkString::swap(SkString& other) {
michael@0 618 this->validate();
michael@0 619 other.validate();
michael@0 620
michael@0 621 SkTSwap<Rec*>(fRec, other.fRec);
michael@0 622 #ifdef SK_DEBUG
michael@0 623 SkTSwap<const char*>(fStr, other.fStr);
michael@0 624 #endif
michael@0 625 }
michael@0 626
michael@0 627 ///////////////////////////////////////////////////////////////////////////////
michael@0 628
michael@0 629 SkString SkStringPrintf(const char* format, ...) {
michael@0 630 SkString formattedOutput;
michael@0 631 char buffer[kBufferSize];
michael@0 632 ARGS_TO_BUFFER(format, buffer, kBufferSize);
michael@0 633 formattedOutput.set(buffer);
michael@0 634 return formattedOutput;
michael@0 635 }
michael@0 636
michael@0 637 void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
michael@0 638 const char* end = str + strlen(str);
michael@0 639 while (str != end) {
michael@0 640 // Find a token.
michael@0 641 const size_t len = strcspn(str, delimiters);
michael@0 642 out->push_back().set(str, len);
michael@0 643 str += len;
michael@0 644 // Skip any delimiters.
michael@0 645 str += strspn(str, delimiters);
michael@0 646 }
michael@0 647 }
michael@0 648
michael@0 649 #undef VSNPRINTF
michael@0 650 #undef SNPRINTF

mercurial