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