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