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