Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkString.h" | 10 #include "SkString.h" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 return string; | 182 return string; |
| 183 } | 183 } |
| 184 | 184 |
| 185 /////////////////////////////////////////////////////////////////////////////// | 185 /////////////////////////////////////////////////////////////////////////////// |
| 186 | 186 |
| 187 // the 3 values are [length] [refcnt] [terminating zero data] | 187 // the 3 values are [length] [refcnt] [terminating zero data] |
| 188 const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 }; | 188 const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 }; |
| 189 | 189 |
| 190 #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec) | 190 #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec) |
| 191 | 191 |
| 192 static uint32_t trim_size_t_to_u32(size_t value) { | |
| 193 if (sizeof(size_t) > sizeof(uint32_t)) { | |
|
bungeman-skia
2013/06/04 15:30:45
I just added SkTFitsIn<T> for exactly this kind of
| |
| 194 if (value > SK_MaxU32) { | |
| 195 value = SK_MaxU32; | |
| 196 } | |
| 197 } | |
| 198 return (uint32_t)value; | |
| 199 } | |
| 200 | |
| 201 static size_t check_add32(size_t base, size_t extra) { | |
| 202 SkASSERT(base <= SK_MaxU32); | |
| 203 if (sizeof(size_t) > sizeof(uint32_t)) { | |
| 204 if (base + extra > SK_MaxU32) { | |
| 205 extra = SK_MaxU32 - base; | |
| 206 } | |
| 207 } | |
| 208 return extra; | |
| 209 } | |
| 210 | |
| 192 SkString::Rec* SkString::AllocRec(const char text[], size_t len) { | 211 SkString::Rec* SkString::AllocRec(const char text[], size_t len) { |
| 193 Rec* rec; | 212 Rec* rec; |
| 194 | 213 |
| 195 if (0 == len) { | 214 if (0 == len) { |
| 196 rec = const_cast<Rec*>(&gEmptyRec); | 215 rec = const_cast<Rec*>(&gEmptyRec); |
| 197 } else { | 216 } else { |
| 217 len = trim_size_t_to_u32(len); | |
| 218 | |
| 198 // add 1 for terminating 0, then align4 so we can have some slop when gr owing the string | 219 // add 1 for terminating 0, then align4 so we can have some slop when gr owing the string |
| 199 rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1)); | 220 rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1)); |
| 200 rec->fLength = len; | 221 rec->fLength = SkToU32(len); |
| 201 rec->fRefCnt = 1; | 222 rec->fRefCnt = 1; |
| 202 if (text) { | 223 if (text) { |
| 203 memcpy(rec->data(), text, len); | 224 memcpy(rec->data(), text, len); |
| 204 } | 225 } |
| 205 rec->data()[len] = 0; | 226 rec->data()[len] = 0; |
| 206 } | 227 } |
| 207 return rec; | 228 return rec; |
| 208 } | 229 } |
| 209 | 230 |
| 210 SkString::Rec* SkString::RefRec(Rec* src) { | 231 SkString::Rec* SkString::RefRec(Rec* src) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 } | 370 } |
| 350 } | 371 } |
| 351 return fRec->data(); | 372 return fRec->data(); |
| 352 } | 373 } |
| 353 | 374 |
| 354 void SkString::set(const char text[]) { | 375 void SkString::set(const char text[]) { |
| 355 this->set(text, text ? strlen(text) : 0); | 376 this->set(text, text ? strlen(text) : 0); |
| 356 } | 377 } |
| 357 | 378 |
| 358 void SkString::set(const char text[], size_t len) { | 379 void SkString::set(const char text[], size_t len) { |
| 380 len = trim_size_t_to_u32(len); | |
| 381 | |
| 359 if (0 == len) { | 382 if (0 == len) { |
| 360 this->reset(); | 383 this->reset(); |
| 361 } else if (1 == fRec->fRefCnt && len <= fRec->fLength) { | 384 } else if (1 == fRec->fRefCnt && len <= fRec->fLength) { |
| 362 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLeng th>>1))? | 385 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLeng th>>1))? |
| 363 // just use less of the buffer without allocating a smaller one | 386 // just use less of the buffer without allocating a smaller one |
| 364 char* p = this->writable_str(); | 387 char* p = this->writable_str(); |
| 365 if (text) { | 388 if (text) { |
| 366 memcpy(p, text, len); | 389 memcpy(p, text, len); |
| 367 } | 390 } |
| 368 p[len] = 0; | 391 p[len] = 0; |
| 369 fRec->fLength = len; | 392 fRec->fLength = SkToU32(len); |
| 370 } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) { | 393 } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) { |
| 371 // we have spare room in the current allocation, so don't alloc a larger one | 394 // we have spare room in the current allocation, so don't alloc a larger one |
| 372 char* p = this->writable_str(); | 395 char* p = this->writable_str(); |
| 373 if (text) { | 396 if (text) { |
| 374 memcpy(p, text, len); | 397 memcpy(p, text, len); |
| 375 } | 398 } |
| 376 p[len] = 0; | 399 p[len] = 0; |
| 377 fRec->fLength = len; | 400 fRec->fLength = SkToU32(len); |
| 378 } else { | 401 } else { |
| 379 SkString tmp(text, len); | 402 SkString tmp(text, len); |
| 380 this->swap(tmp); | 403 this->swap(tmp); |
| 381 } | 404 } |
| 382 } | 405 } |
| 383 | 406 |
| 384 void SkString::setUTF16(const uint16_t src[]) { | 407 void SkString::setUTF16(const uint16_t src[]) { |
| 385 int count = 0; | 408 int count = 0; |
| 386 | 409 |
| 387 while (src[count]) { | 410 while (src[count]) { |
| 388 count += 1; | 411 count += 1; |
| 389 } | 412 } |
| 390 setUTF16(src, count); | 413 this->setUTF16(src, count); |
| 391 } | 414 } |
| 392 | 415 |
| 393 void SkString::setUTF16(const uint16_t src[], size_t count) { | 416 void SkString::setUTF16(const uint16_t src[], size_t count) { |
| 417 count = trim_size_t_to_u32(count); | |
| 418 | |
| 394 if (0 == count) { | 419 if (0 == count) { |
| 395 this->reset(); | 420 this->reset(); |
| 396 } else if (count <= fRec->fLength) { | 421 } else if (count <= fRec->fLength) { |
| 397 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLeng th>>1)) | 422 // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLeng th>>1)) |
| 398 if (count < fRec->fLength) { | 423 if (count < fRec->fLength) { |
| 399 this->resize(count); | 424 this->resize(count); |
| 400 } | 425 } |
| 401 char* p = this->writable_str(); | 426 char* p = this->writable_str(); |
| 402 for (size_t i = 0; i < count; i++) { | 427 for (size_t i = 0; i < count; i++) { |
| 403 p[i] = SkToU8(src[i]); | 428 p[i] = SkToU8(src[i]); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 417 void SkString::insert(size_t offset, const char text[]) { | 442 void SkString::insert(size_t offset, const char text[]) { |
| 418 this->insert(offset, text, text ? strlen(text) : 0); | 443 this->insert(offset, text, text ? strlen(text) : 0); |
| 419 } | 444 } |
| 420 | 445 |
| 421 void SkString::insert(size_t offset, const char text[], size_t len) { | 446 void SkString::insert(size_t offset, const char text[], size_t len) { |
| 422 if (len) { | 447 if (len) { |
| 423 size_t length = fRec->fLength; | 448 size_t length = fRec->fLength; |
| 424 if (offset > length) { | 449 if (offset > length) { |
| 425 offset = length; | 450 offset = length; |
| 426 } | 451 } |
| 452 | |
| 453 // Check if length + len exceeds 32bits, we trim len | |
| 454 len = check_add32(length, len); | |
| 455 if (0 == len) { | |
| 456 return; | |
| 457 } | |
| 427 | 458 |
| 428 /* If we're the only owner, and we have room in our allocation for the insert, | 459 /* If we're the only owner, and we have room in our allocation for the insert, |
| 429 do it in place, rather than allocating a new buffer. | 460 do it in place, rather than allocating a new buffer. |
| 430 | 461 |
| 431 To know we have room, compare the allocated sizes | 462 To know we have room, compare the allocated sizes |
| 432 beforeAlloc = SkAlign4(length + 1) | 463 beforeAlloc = SkAlign4(length + 1) |
| 433 afterAlloc = SkAligh4(length + 1 + len) | 464 afterAlloc = SkAligh4(length + 1 + len) |
| 434 but SkAlign4(x) is (x + 3) >> 2 << 2 | 465 but SkAlign4(x) is (x + 3) >> 2 << 2 |
| 435 which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 | 466 which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 |
| 436 and we can then eliminate the +1+3 since that doesn't affec the answ er | 467 and we can then eliminate the +1+3 since that doesn't affec the answ er |
| 437 */ | 468 */ |
| 438 if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) { | 469 if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) { |
| 439 char* dst = this->writable_str(); | 470 char* dst = this->writable_str(); |
| 440 | 471 |
| 441 if (offset < length) { | 472 if (offset < length) { |
| 442 memmove(dst + offset + len, dst + offset, length - offset); | 473 memmove(dst + offset + len, dst + offset, length - offset); |
| 443 } | 474 } |
| 444 memcpy(dst + offset, text, len); | 475 memcpy(dst + offset, text, len); |
| 445 | 476 |
| 446 dst[length + len] = 0; | 477 dst[length + len] = 0; |
| 447 fRec->fLength = length + len; | 478 fRec->fLength = SkToU32(length + len); |
| 448 } else { | 479 } else { |
| 449 /* Seems we should use realloc here, since that is safe if it fails | 480 /* Seems we should use realloc here, since that is safe if it fails |
| 450 (we have the original data), and might be faster than alloc/copy /free. | 481 (we have the original data), and might be faster than alloc/copy /free. |
| 451 */ | 482 */ |
| 452 SkString tmp(fRec->fLength + len); | 483 SkString tmp(fRec->fLength + len); |
| 453 char* dst = tmp.writable_str(); | 484 char* dst = tmp.writable_str(); |
| 454 | 485 |
| 455 if (offset > 0) { | 486 if (offset > 0) { |
| 456 memcpy(dst, fRec->data(), offset); | 487 memcpy(dst, fRec->data(), offset); |
| 457 } | 488 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 SkString SkStringPrintf(const char* format, ...) { | 641 SkString SkStringPrintf(const char* format, ...) { |
| 611 SkString formattedOutput; | 642 SkString formattedOutput; |
| 612 char buffer[kBufferSize]; | 643 char buffer[kBufferSize]; |
| 613 ARGS_TO_BUFFER(format, buffer, kBufferSize); | 644 ARGS_TO_BUFFER(format, buffer, kBufferSize); |
| 614 formattedOutput.set(buffer); | 645 formattedOutput.set(buffer); |
| 615 return formattedOutput; | 646 return formattedOutput; |
| 616 } | 647 } |
| 617 | 648 |
| 618 #undef VSNPRINTF | 649 #undef VSNPRINTF |
| 619 #undef SNPRINTF | 650 #undef SNPRINTF |
| OLD | NEW |