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 |