Home | History | Annotate | Download | only in core
      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