1/* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkStream.h" 9#include "SkStreamPriv.h" 10#include "SkData.h" 11#include "SkFixed.h" 12#include "SkMakeUnique.h" 13#include "SkSafeMath.h" 14#include "SkString.h" 15#include "SkOSFile.h" 16#include "SkTypes.h" 17#include "SkTFitsIn.h" 18 19#include <limits> 20 21/////////////////////////////////////////////////////////////////////////////// 22 23int8_t SkStream::readS8() { 24 int8_t value; 25 SkDEBUGCODE(size_t len =) this->read(&value, 1); 26 SkASSERT(1 == len); 27 return value; 28} 29 30int16_t SkStream::readS16() { 31 int16_t value; 32 SkDEBUGCODE(size_t len =) this->read(&value, 2); 33 SkASSERT(2 == len); 34 return value; 35} 36 37int32_t SkStream::readS32() { 38 int32_t value; 39 SkDEBUGCODE(size_t len =) this->read(&value, 4); 40 SkASSERT(4 == len); 41 return value; 42} 43 44SkScalar SkStream::readScalar() { 45 SkScalar value; 46 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar)); 47 SkASSERT(sizeof(SkScalar) == len); 48 return value; 49} 50 51#define SK_MAX_BYTE_FOR_U8 0xFD 52#define SK_BYTE_SENTINEL_FOR_U16 0xFE 53#define SK_BYTE_SENTINEL_FOR_U32 0xFF 54 55size_t SkStream::readPackedUInt() { 56 uint8_t byte; 57 if (!this->read(&byte, 1)) { 58 return 0; 59 } 60 if (SK_BYTE_SENTINEL_FOR_U16 == byte) { 61 return this->readU16(); 62 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) { 63 return this->readU32(); 64 } else { 65 return byte; 66 } 67} 68 69////////////////////////////////////////////////////////////////////////////////////// 70 71SkWStream::~SkWStream() 72{ 73} 74 75void SkWStream::flush() 76{ 77} 78 79bool SkWStream::writeDecAsText(int32_t dec) 80{ 81 char buffer[SkStrAppendS32_MaxSize]; 82 char* stop = SkStrAppendS32(buffer, dec); 83 return this->write(buffer, stop - buffer); 84} 85 86bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits) 87{ 88 char buffer[SkStrAppendU64_MaxSize]; 89 char* stop = SkStrAppendU64(buffer, dec, minDigits); 90 return this->write(buffer, stop - buffer); 91} 92 93bool SkWStream::writeHexAsText(uint32_t hex, int digits) 94{ 95 SkString tmp; 96 tmp.appendHex(hex, digits); 97 return this->write(tmp.c_str(), tmp.size()); 98} 99 100bool SkWStream::writeScalarAsText(SkScalar value) 101{ 102 char buffer[SkStrAppendScalar_MaxSize]; 103 char* stop = SkStrAppendScalar(buffer, value); 104 return this->write(buffer, stop - buffer); 105} 106 107bool SkWStream::writeScalar(SkScalar value) { 108 return this->write(&value, sizeof(value)); 109} 110 111int SkWStream::SizeOfPackedUInt(size_t value) { 112 if (value <= SK_MAX_BYTE_FOR_U8) { 113 return 1; 114 } else if (value <= 0xFFFF) { 115 return 3; 116 } 117 return 5; 118} 119 120bool SkWStream::writePackedUInt(size_t value) { 121 uint8_t data[5]; 122 size_t len = 1; 123 if (value <= SK_MAX_BYTE_FOR_U8) { 124 data[0] = value; 125 len = 1; 126 } else if (value <= 0xFFFF) { 127 uint16_t value16 = value; 128 data[0] = SK_BYTE_SENTINEL_FOR_U16; 129 memcpy(&data[1], &value16, 2); 130 len = 3; 131 } else { 132 uint32_t value32 = SkToU32(value); 133 data[0] = SK_BYTE_SENTINEL_FOR_U32; 134 memcpy(&data[1], &value32, 4); 135 len = 5; 136 } 137 return this->write(data, len); 138} 139 140bool SkWStream::writeStream(SkStream* stream, size_t length) { 141 char scratch[1024]; 142 const size_t MAX = sizeof(scratch); 143 144 while (length != 0) { 145 size_t n = length; 146 if (n > MAX) { 147 n = MAX; 148 } 149 stream->read(scratch, n); 150 if (!this->write(scratch, n)) { 151 return false; 152 } 153 length -= n; 154 } 155 return true; 156} 157 158/////////////////////////////////////////////////////////////////////////////// 159 160SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size, 161 size_t offset, size_t originalOffset) 162 : fFILE(std::move(file)) 163 , fSize(size) 164 , fOffset(SkTMin(offset, fSize)) 165 , fOriginalOffset(SkTMin(originalOffset, fSize)) 166{ } 167 168SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size, size_t offset) 169 : SkFILEStream(std::move(file), size, offset, offset) 170{ } 171 172SkFILEStream::SkFILEStream(FILE* file) 173 : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose), 174 file ? sk_fgetsize(file) : 0, 175 file ? sk_ftell(file) : 0) 176{ } 177 178 179SkFILEStream::SkFILEStream(const char path[]) 180 : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr) 181{ } 182 183SkFILEStream::~SkFILEStream() { 184 this->close(); 185} 186 187void SkFILEStream::close() { 188 fFILE.reset(); 189 fSize = 0; 190 fOffset = 0; 191} 192 193size_t SkFILEStream::read(void* buffer, size_t size) { 194 if (size > fSize - fOffset) { 195 size = fSize - fOffset; 196 } 197 size_t bytesRead = size; 198 if (buffer) { 199 bytesRead = sk_qread(fFILE.get(), buffer, size, fOffset); 200 } 201 if (bytesRead == SIZE_MAX) { 202 return 0; 203 } 204 fOffset += bytesRead; 205 return bytesRead; 206} 207 208bool SkFILEStream::isAtEnd() const { 209 if (fOffset == fSize) { 210 return true; 211 } 212 return fOffset >= sk_fgetsize(fFILE.get()); 213} 214 215bool SkFILEStream::rewind() { 216 fOffset = fOriginalOffset; 217 return true; 218} 219 220SkStreamAsset* SkFILEStream::onDuplicate() const { 221 return new SkFILEStream(fFILE, fSize, fOriginalOffset, fOriginalOffset); 222} 223 224size_t SkFILEStream::getPosition() const { 225 SkASSERT(fOffset >= fOriginalOffset); 226 return fOffset - fOriginalOffset; 227} 228 229bool SkFILEStream::seek(size_t position) { 230 fOffset = SkTMin(SkSafeMath::Add(position, fOriginalOffset), fSize); 231 return true; 232} 233 234bool SkFILEStream::move(long offset) { 235 if (offset < 0) { 236 if (offset == std::numeric_limits<long>::min() 237 || !SkTFitsIn<size_t>(-offset) 238 || (size_t) (-offset) >= this->getPosition()) { 239 fOffset = fOriginalOffset; 240 } else { 241 fOffset += offset; 242 } 243 } else if (!SkTFitsIn<size_t>(offset)) { 244 fOffset = fSize; 245 } else { 246 fOffset = SkTMin(SkSafeMath::Add(fOffset, (size_t) offset), fSize); 247 } 248 249 SkASSERT(fOffset >= fOriginalOffset && fOffset <= fSize); 250 return true; 251} 252 253SkStreamAsset* SkFILEStream::onFork() const { 254 return new SkFILEStream(fFILE, fSize, fOffset, fOriginalOffset); 255} 256 257size_t SkFILEStream::getLength() const { 258 return fSize - fOriginalOffset; 259} 260 261/////////////////////////////////////////////////////////////////////////////// 262 263static sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) { 264 if (copyData) { 265 return SkData::MakeWithCopy(src, size); 266 } else { 267 return SkData::MakeWithoutCopy(src, size); 268 } 269} 270 271SkMemoryStream::SkMemoryStream() { 272 fData = SkData::MakeEmpty(); 273 fOffset = 0; 274} 275 276SkMemoryStream::SkMemoryStream(size_t size) { 277 fData = SkData::MakeUninitialized(size); 278 fOffset = 0; 279} 280 281SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) { 282 fData = newFromParams(src, size, copyData); 283 fOffset = 0; 284} 285 286SkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) { 287 if (nullptr == fData) { 288 fData = SkData::MakeEmpty(); 289 } 290 fOffset = 0; 291} 292 293std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) { 294 return skstd::make_unique<SkMemoryStream>(data, length, true); 295} 296 297std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) { 298 return skstd::make_unique<SkMemoryStream>(data, length, false); 299} 300 301std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) { 302 return skstd::make_unique<SkMemoryStream>(std::move(data)); 303} 304 305void SkMemoryStream::setMemoryOwned(const void* src, size_t size) { 306 fData = SkData::MakeFromMalloc(src, size); 307 fOffset = 0; 308} 309 310void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) { 311 fData = newFromParams(src, size, copyData); 312 fOffset = 0; 313} 314 315void SkMemoryStream::setData(sk_sp<SkData> data) { 316 if (nullptr == data) { 317 fData = SkData::MakeEmpty(); 318 } else { 319 fData = data; 320 } 321 fOffset = 0; 322} 323 324void SkMemoryStream::skipToAlign4() { 325 // cast to remove unary-minus warning 326 fOffset += -(int)fOffset & 0x03; 327} 328 329size_t SkMemoryStream::read(void* buffer, size_t size) { 330 size_t dataSize = fData->size(); 331 332 if (size > dataSize - fOffset) { 333 size = dataSize - fOffset; 334 } 335 if (buffer) { 336 memcpy(buffer, fData->bytes() + fOffset, size); 337 } 338 fOffset += size; 339 return size; 340} 341 342size_t SkMemoryStream::peek(void* buffer, size_t size) const { 343 SkASSERT(buffer != nullptr); 344 345 const size_t currentOffset = fOffset; 346 SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this); 347 const size_t bytesRead = nonConstThis->read(buffer, size); 348 nonConstThis->fOffset = currentOffset; 349 return bytesRead; 350} 351 352bool SkMemoryStream::isAtEnd() const { 353 return fOffset == fData->size(); 354} 355 356bool SkMemoryStream::rewind() { 357 fOffset = 0; 358 return true; 359} 360 361SkMemoryStream* SkMemoryStream::onDuplicate() const { 362 return new SkMemoryStream(fData); 363} 364 365size_t SkMemoryStream::getPosition() const { 366 return fOffset; 367} 368 369bool SkMemoryStream::seek(size_t position) { 370 fOffset = position > fData->size() 371 ? fData->size() 372 : position; 373 return true; 374} 375 376bool SkMemoryStream::move(long offset) { 377 return this->seek(fOffset + offset); 378} 379 380SkMemoryStream* SkMemoryStream::onFork() const { 381 std::unique_ptr<SkMemoryStream> that(this->duplicate()); 382 that->seek(fOffset); 383 return that.release(); 384} 385 386size_t SkMemoryStream::getLength() const { 387 return fData->size(); 388} 389 390const void* SkMemoryStream::getMemoryBase() { 391 return fData->data(); 392} 393 394const void* SkMemoryStream::getAtPos() { 395 return fData->bytes() + fOffset; 396} 397 398///////////////////////////////////////////////////////////////////////////////////////////////////////// 399///////////////////////////////////////////////////////////////////////////////////////////////////////// 400 401SkFILEWStream::SkFILEWStream(const char path[]) 402{ 403 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 404} 405 406SkFILEWStream::~SkFILEWStream() 407{ 408 if (fFILE) { 409 sk_fclose(fFILE); 410 } 411} 412 413size_t SkFILEWStream::bytesWritten() const { 414 return sk_ftell(fFILE); 415} 416 417bool SkFILEWStream::write(const void* buffer, size_t size) 418{ 419 if (fFILE == nullptr) { 420 return false; 421 } 422 423 if (sk_fwrite(buffer, size, fFILE) != size) 424 { 425 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);) 426 sk_fclose(fFILE); 427 fFILE = nullptr; 428 return false; 429 } 430 return true; 431} 432 433void SkFILEWStream::flush() 434{ 435 if (fFILE) { 436 sk_fflush(fFILE); 437 } 438} 439 440void SkFILEWStream::fsync() 441{ 442 flush(); 443 if (fFILE) { 444 sk_fsync(fFILE); 445 } 446} 447 448//////////////////////////////////////////////////////////////////////// 449 450static inline void sk_memcpy_4bytes(void* dst, const void* src, size_t size) { 451 if (size == 4) { 452 memcpy(dst, src, 4); 453 } else { 454 memcpy(dst, src, size); 455 } 456} 457 458#define SkDynamicMemoryWStream_MinBlockSize 4096 459 460struct SkDynamicMemoryWStream::Block { 461 Block* fNext; 462 char* fCurr; 463 char* fStop; 464 465 const char* start() const { return (const char*)(this + 1); } 466 char* start() { return (char*)(this + 1); } 467 size_t avail() const { return fStop - fCurr; } 468 size_t written() const { return fCurr - this->start(); } 469 470 void init(size_t size) { 471 fNext = nullptr; 472 fCurr = this->start(); 473 fStop = this->start() + size; 474 } 475 476 const void* append(const void* data, size_t size) { 477 SkASSERT((size_t)(fStop - fCurr) >= size); 478 sk_memcpy_4bytes(fCurr, data, size); 479 fCurr += size; 480 return (const void*)((const char*)data + size); 481 } 482}; 483 484SkDynamicMemoryWStream::SkDynamicMemoryWStream() 485 : fHead(nullptr), fTail(nullptr), fBytesWrittenBeforeTail(0) 486{} 487 488SkDynamicMemoryWStream::~SkDynamicMemoryWStream() { 489 this->reset(); 490} 491 492void SkDynamicMemoryWStream::reset() { 493 Block* block = fHead; 494 while (block != nullptr) { 495 Block* next = block->fNext; 496 sk_free(block); 497 block = next; 498 } 499 fHead = fTail = nullptr; 500 fBytesWrittenBeforeTail = 0; 501} 502 503size_t SkDynamicMemoryWStream::bytesWritten() const { 504 this->validate(); 505 506 if (fTail) { 507 return fBytesWrittenBeforeTail + fTail->written(); 508 } 509 return 0; 510} 511 512bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) { 513 if (count > 0) { 514 size_t size; 515 516 if (fTail) { 517 if (fTail->avail() > 0) { 518 size = SkTMin(fTail->avail(), count); 519 buffer = fTail->append(buffer, size); 520 SkASSERT(count >= size); 521 count -= size; 522 if (count == 0) { 523 return true; 524 } 525 } 526 // If we get here, we've just exhausted fTail, so update our tracker 527 fBytesWrittenBeforeTail += fTail->written(); 528 } 529 530 size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block)); 531 size = SkAlign4(size); // ensure we're always a multiple of 4 (see padToAlign4()) 532 533 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 534 block->init(size); 535 block->append(buffer, count); 536 537 if (fTail != nullptr) 538 fTail->fNext = block; 539 else 540 fHead = fTail = block; 541 fTail = block; 542 this->validate(); 543 } 544 return true; 545} 546 547bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) { 548 if (offset + count > this->bytesWritten()) { 549 return false; // test does not partially modify 550 } 551 Block* block = fHead; 552 while (block != nullptr) { 553 size_t size = block->written(); 554 if (offset < size) { 555 size_t part = offset + count > size ? size - offset : count; 556 memcpy(buffer, block->start() + offset, part); 557 if (count <= part) 558 return true; 559 count -= part; 560 buffer = (void*) ((char* ) buffer + part); 561 } 562 offset = offset > size ? offset - size : 0; 563 block = block->fNext; 564 } 565 return false; 566} 567 568void SkDynamicMemoryWStream::copyTo(void* dst) const { 569 Block* block = fHead; 570 while (block != nullptr) { 571 size_t size = block->written(); 572 memcpy(dst, block->start(), size); 573 dst = (void*)((char*)dst + size); 574 block = block->fNext; 575 } 576} 577 578bool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const { 579 for (Block* block = fHead; block != nullptr; block = block->fNext) { 580 if (!dst->write(block->start(), block->written())) { 581 return false; 582 } 583 } 584 return true; 585} 586 587void SkDynamicMemoryWStream::padToAlign4() { 588 // The contract is to write zeros until the entire stream has written a multiple of 4 bytes. 589 // Our Blocks are guaranteed always be (a) full (except the tail) and (b) a multiple of 4 590 // so it is sufficient to just examine the tail (if present). 591 592 if (fTail) { 593 // cast to remove unary-minus warning 594 int padBytes = -(int)fTail->written() & 0x03; 595 if (padBytes) { 596 int zero = 0; 597 fTail->append(&zero, padBytes); 598 } 599 } 600} 601 602 603void SkDynamicMemoryWStream::copyToAndReset(void* ptr) { 604 // By looping through the source and freeing as we copy, we 605 // can reduce real memory use with large streams. 606 char* dst = reinterpret_cast<char*>(ptr); 607 Block* block = fHead; 608 while (block != nullptr) { 609 size_t len = block->written(); 610 memcpy(dst, block->start(), len); 611 dst += len; 612 Block* next = block->fNext; 613 sk_free(block); 614 block = next; 615 } 616 fHead = fTail = nullptr; 617 fBytesWrittenBeforeTail = 0; 618} 619 620bool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) { 621 // By looping through the source and freeing as we copy, we 622 // can reduce real memory use with large streams. 623 bool dstStreamGood = true; 624 for (Block* block = fHead; block != nullptr; ) { 625 if (dstStreamGood && !dst->write(block->start(), block->written())) { 626 dstStreamGood = false; 627 } 628 Block* next = block->fNext; 629 sk_free(block); 630 block = next; 631 } 632 fHead = fTail = nullptr; 633 fBytesWrittenBeforeTail = 0; 634 return dstStreamGood; 635} 636 637sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() { 638 const size_t size = this->bytesWritten(); 639 if (0 == size) { 640 return SkData::MakeEmpty(); 641 } 642 sk_sp<SkData> data = SkData::MakeUninitialized(size); 643 this->copyToAndReset(data->writable_data()); 644 return data; 645} 646 647#ifdef SK_DEBUG 648void SkDynamicMemoryWStream::validate() const { 649 if (!fHead) { 650 SkASSERT(!fTail); 651 SkASSERT(fBytesWrittenBeforeTail == 0); 652 return; 653 } 654 SkASSERT(fTail); 655 656 size_t bytes = 0; 657 const Block* block = fHead; 658 while (block) { 659 if (block->fNext) { 660 SkASSERT(block->avail() == 0); 661 bytes += block->written(); 662 SkASSERT(bytes == SkAlign4(bytes)); // see padToAlign4() 663 } 664 block = block->fNext; 665 } 666 SkASSERT(bytes == fBytesWrittenBeforeTail); 667} 668#endif 669 670//////////////////////////////////////////////////////////////////////////////////////////////// 671 672class SkBlockMemoryRefCnt : public SkRefCnt { 673public: 674 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { } 675 676 virtual ~SkBlockMemoryRefCnt() { 677 SkDynamicMemoryWStream::Block* block = fHead; 678 while (block != nullptr) { 679 SkDynamicMemoryWStream::Block* next = block->fNext; 680 sk_free(block); 681 block = next; 682 } 683 } 684 685 SkDynamicMemoryWStream::Block* const fHead; 686}; 687 688class SkBlockMemoryStream : public SkStreamAsset { 689public: 690 SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef, size_t size) 691 : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead) 692 , fSize(size) , fOffset(0), fCurrentOffset(0) { } 693 694 size_t read(void* buffer, size_t rawCount) override { 695 size_t count = rawCount; 696 if (fOffset + count > fSize) { 697 count = fSize - fOffset; 698 } 699 size_t bytesLeftToRead = count; 700 while (fCurrent != nullptr) { 701 size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset; 702 size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent); 703 if (buffer) { 704 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent); 705 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent); 706 } 707 if (bytesLeftToRead <= bytesFromCurrent) { 708 fCurrentOffset += bytesFromCurrent; 709 fOffset += count; 710 return count; 711 } 712 bytesLeftToRead -= bytesFromCurrent; 713 fCurrent = fCurrent->fNext; 714 fCurrentOffset = 0; 715 } 716 SkASSERT(false); 717 return 0; 718 } 719 720 bool isAtEnd() const override { 721 return fOffset == fSize; 722 } 723 724 size_t peek(void* buff, size_t bytesToPeek) const override { 725 SkASSERT(buff != nullptr); 726 727 bytesToPeek = SkTMin(bytesToPeek, fSize - fOffset); 728 729 size_t bytesLeftToPeek = bytesToPeek; 730 char* buffer = static_cast<char*>(buff); 731 const SkDynamicMemoryWStream::Block* current = fCurrent; 732 size_t currentOffset = fCurrentOffset; 733 while (bytesLeftToPeek) { 734 SkASSERT(current); 735 size_t bytesFromCurrent = SkTMin(current->written() - currentOffset, bytesLeftToPeek); 736 memcpy(buffer, current->start() + currentOffset, bytesFromCurrent); 737 bytesLeftToPeek -= bytesFromCurrent; 738 buffer += bytesFromCurrent; 739 current = current->fNext; 740 currentOffset = 0; 741 } 742 return bytesToPeek; 743 } 744 745 bool rewind() override { 746 fCurrent = fBlockMemory->fHead; 747 fOffset = 0; 748 fCurrentOffset = 0; 749 return true; 750 } 751 752 SkBlockMemoryStream* onDuplicate() const override { 753 return new SkBlockMemoryStream(fBlockMemory, fSize); 754 } 755 756 size_t getPosition() const override { 757 return fOffset; 758 } 759 760 bool seek(size_t position) override { 761 // If possible, skip forward. 762 if (position >= fOffset) { 763 size_t skipAmount = position - fOffset; 764 return this->skip(skipAmount) == skipAmount; 765 } 766 // If possible, move backward within the current block. 767 size_t moveBackAmount = fOffset - position; 768 if (moveBackAmount <= fCurrentOffset) { 769 fCurrentOffset -= moveBackAmount; 770 fOffset -= moveBackAmount; 771 return true; 772 } 773 // Otherwise rewind and move forward. 774 return this->rewind() && this->skip(position) == position; 775 } 776 777 bool move(long offset) override { 778 return seek(fOffset + offset); 779 } 780 781 SkBlockMemoryStream* onFork() const override { 782 SkBlockMemoryStream* that = this->onDuplicate(); 783 that->fCurrent = this->fCurrent; 784 that->fOffset = this->fOffset; 785 that->fCurrentOffset = this->fCurrentOffset; 786 return that; 787 } 788 789 size_t getLength() const override { 790 return fSize; 791 } 792 793 const void* getMemoryBase() override { 794 if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) { 795 return fBlockMemory->fHead->start(); 796 } 797 return nullptr; 798 } 799 800private: 801 sk_sp<SkBlockMemoryRefCnt> const fBlockMemory; 802 SkDynamicMemoryWStream::Block const * fCurrent; 803 size_t const fSize; 804 size_t fOffset; 805 size_t fCurrentOffset; 806}; 807 808std::unique_ptr<SkStreamAsset> SkDynamicMemoryWStream::detachAsStream() { 809 std::unique_ptr<SkStreamAsset> stream 810 = skstd::make_unique<SkBlockMemoryStream>(sk_make_sp<SkBlockMemoryRefCnt>(fHead), 811 this->bytesWritten()); 812 fHead = nullptr; // signal reset() to not free anything 813 this->reset(); 814 return stream; 815} 816 817/////////////////////////////////////////////////////////////////////////////// 818/////////////////////////////////////////////////////////////////////////////// 819 820static sk_sp<SkData> mmap_filename(const char path[]) { 821 FILE* file = sk_fopen(path, kRead_SkFILE_Flag); 822 if (nullptr == file) { 823 return nullptr; 824 } 825 826 auto data = SkData::MakeFromFILE(file); 827 sk_fclose(file); 828 return data; 829} 830 831std::unique_ptr<SkStreamAsset> SkStream::MakeFromFile(const char path[]) { 832 auto data(mmap_filename(path)); 833 if (data) { 834 return skstd::make_unique<SkMemoryStream>(std::move(data)); 835 } 836 837 // If we get here, then our attempt at using mmap failed, so try normal file access. 838 auto stream = skstd::make_unique<SkFILEStream>(path); 839 if (!stream->isValid()) { 840 return nullptr; 841 } 842 return std::move(stream); 843} 844 845// Declared in SkStreamPriv.h: 846sk_sp<SkData> SkCopyStreamToData(SkStream* stream) { 847 SkASSERT(stream != nullptr); 848 849 if (stream->hasLength()) { 850 return SkData::MakeFromStream(stream, stream->getLength()); 851 } 852 853 SkDynamicMemoryWStream tempStream; 854 const size_t bufferSize = 4096; 855 char buffer[bufferSize]; 856 do { 857 size_t bytesRead = stream->read(buffer, bufferSize); 858 tempStream.write(buffer, bytesRead); 859 } while (!stream->isAtEnd()); 860 return tempStream.detachAsData(); 861} 862 863bool SkStreamCopy(SkWStream* out, SkStream* input) { 864 const char* base = static_cast<const char*>(input->getMemoryBase()); 865 if (base && input->hasPosition() && input->hasLength()) { 866 // Shortcut that avoids the while loop. 867 size_t position = input->getPosition(); 868 size_t length = input->getLength(); 869 SkASSERT(length >= position); 870 return out->write(&base[position], length - position); 871 } 872 char scratch[4096]; 873 size_t count; 874 while (true) { 875 count = input->read(scratch, sizeof(scratch)); 876 if (0 == count) { 877 return true; 878 } 879 if (!out->write(scratch, count)) { 880 return false; 881 } 882 } 883} 884