LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkStream.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 493 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 103 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13