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 23 int8_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 30 int16_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 37 int32_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 44 SkScalar 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 55 size_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 71 SkWStream::~SkWStream() 72 { 73 } 74 75 void SkWStream::flush() 76 { 77 } 78 79 bool 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 86 bool 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 93 bool 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 100 bool 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 107 bool SkWStream::writeScalar(SkScalar value) { 108 return this->write(&value, sizeof(value)); 109 } 110 111 int 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 120 bool 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 140 bool 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 160 SkFILEStream::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 168 SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size, size_t offset) 169 : SkFILEStream(std::move(file), size, offset, offset) 170 { } 171 172 SkFILEStream::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 179 SkFILEStream::SkFILEStream(const char path[]) 180 : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr) 181 { } 182 183 SkFILEStream::~SkFILEStream() { 184 this->close(); 185 } 186 187 void SkFILEStream::close() { 188 fFILE.reset(); 189 fSize = 0; 190 fOffset = 0; 191 } 192 193 size_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 208 bool SkFILEStream::isAtEnd() const { 209 if (fOffset == fSize) { 210 return true; 211 } 212 return fOffset >= sk_fgetsize(fFILE.get()); 213 } 214 215 bool SkFILEStream::rewind() { 216 fOffset = fOriginalOffset; 217 return true; 218 } 219 220 SkStreamAsset* SkFILEStream::onDuplicate() const { 221 return new SkFILEStream(fFILE, fSize, fOriginalOffset, fOriginalOffset); 222 } 223 224 size_t SkFILEStream::getPosition() const { 225 SkASSERT(fOffset >= fOriginalOffset); 226 return fOffset - fOriginalOffset; 227 } 228 229 bool SkFILEStream::seek(size_t position) { 230 fOffset = SkTMin(SkSafeMath::Add(position, fOriginalOffset), fSize); 231 return true; 232 } 233 234 bool 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 253 SkStreamAsset* SkFILEStream::onFork() const { 254 return new SkFILEStream(fFILE, fSize, fOffset, fOriginalOffset); 255 } 256 257 size_t SkFILEStream::getLength() const { 258 return fSize - fOriginalOffset; 259 } 260 261 /////////////////////////////////////////////////////////////////////////////// 262 263 static 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 271 SkMemoryStream::SkMemoryStream() { 272 fData = SkData::MakeEmpty(); 273 fOffset = 0; 274 } 275 276 SkMemoryStream::SkMemoryStream(size_t size) { 277 fData = SkData::MakeUninitialized(size); 278 fOffset = 0; 279 } 280 281 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) { 282 fData = newFromParams(src, size, copyData); 283 fOffset = 0; 284 } 285 286 SkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) { 287 if (nullptr == fData) { 288 fData = SkData::MakeEmpty(); 289 } 290 fOffset = 0; 291 } 292 293 std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) { 294 return skstd::make_unique<SkMemoryStream>(data, length, true); 295 } 296 297 std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) { 298 return skstd::make_unique<SkMemoryStream>(data, length, false); 299 } 300 301 std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) { 302 return skstd::make_unique<SkMemoryStream>(std::move(data)); 303 } 304 305 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) { 306 fData = SkData::MakeFromMalloc(src, size); 307 fOffset = 0; 308 } 309 310 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) { 311 fData = newFromParams(src, size, copyData); 312 fOffset = 0; 313 } 314 315 void 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 324 void SkMemoryStream::skipToAlign4() { 325 // cast to remove unary-minus warning 326 fOffset += -(int)fOffset & 0x03; 327 } 328 329 size_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 342 size_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 352 bool SkMemoryStream::isAtEnd() const { 353 return fOffset == fData->size(); 354 } 355 356 bool SkMemoryStream::rewind() { 357 fOffset = 0; 358 return true; 359 } 360 361 SkMemoryStream* SkMemoryStream::onDuplicate() const { 362 return new SkMemoryStream(fData); 363 } 364 365 size_t SkMemoryStream::getPosition() const { 366 return fOffset; 367 } 368 369 bool SkMemoryStream::seek(size_t position) { 370 fOffset = position > fData->size() 371 ? fData->size() 372 : position; 373 return true; 374 } 375 376 bool SkMemoryStream::move(long offset) { 377 return this->seek(fOffset + offset); 378 } 379 380 SkMemoryStream* SkMemoryStream::onFork() const { 381 std::unique_ptr<SkMemoryStream> that(this->duplicate()); 382 that->seek(fOffset); 383 return that.release(); 384 } 385 386 size_t SkMemoryStream::getLength() const { 387 return fData->size(); 388 } 389 390 const void* SkMemoryStream::getMemoryBase() { 391 return fData->data(); 392 } 393 394 const void* SkMemoryStream::getAtPos() { 395 return fData->bytes() + fOffset; 396 } 397 398 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 399 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 400 401 SkFILEWStream::SkFILEWStream(const char path[]) 402 { 403 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 404 } 405 406 SkFILEWStream::~SkFILEWStream() 407 { 408 if (fFILE) { 409 sk_fclose(fFILE); 410 } 411 } 412 413 size_t SkFILEWStream::bytesWritten() const { 414 return sk_ftell(fFILE); 415 } 416 417 bool 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 433 void SkFILEWStream::flush() 434 { 435 if (fFILE) { 436 sk_fflush(fFILE); 437 } 438 } 439 440 void SkFILEWStream::fsync() 441 { 442 flush(); 443 if (fFILE) { 444 sk_fsync(fFILE); 445 } 446 } 447 448 //////////////////////////////////////////////////////////////////////// 449 450 static 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 460 struct 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 484 SkDynamicMemoryWStream::SkDynamicMemoryWStream() 485 : fHead(nullptr), fTail(nullptr), fBytesWrittenBeforeTail(0) 486 {} 487 488 SkDynamicMemoryWStream::~SkDynamicMemoryWStream() { 489 this->reset(); 490 } 491 492 void 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 503 size_t SkDynamicMemoryWStream::bytesWritten() const { 504 this->validate(); 505 506 if (fTail) { 507 return fBytesWrittenBeforeTail + fTail->written(); 508 } 509 return 0; 510 } 511 512 bool 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 547 bool 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 568 void 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 578 bool 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 587 void 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 603 void 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 620 bool 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 637 sk_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 648 void 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 672 class SkBlockMemoryRefCnt : public SkRefCnt { 673 public: 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 688 class SkBlockMemoryStream : public SkStreamAsset { 689 public: 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 800 private: 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 808 std::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 820 static 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 831 std::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: 846 sk_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 863 bool 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