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     SkString    tmp;
     91     tmp.appendS32(dec);
     92     return this->write(tmp.c_str(), tmp.size());
     93 }
     94 
     95 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
     96 {
     97     SkString    tmp;
     98     tmp.appendS64(dec, minDigits);
     99     return this->write(tmp.c_str(), tmp.size());
    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     SkString    tmp;
    112     tmp.appendScalar(value);
    113     return this->write(tmp.c_str(), tmp.size());
    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) : NULL;
    185 }
    186 
    187 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
    188     : fFILE((SkFILE*)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 = NULL;
    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 = NULL;
    228     }
    229     return false;
    230 }
    231 
    232 SkStreamAsset* SkFILEStream::duplicate() const {
    233     if (NULL == fFILE) {
    234         return new SkMemoryStream();
    235     }
    236 
    237     if (fData.get()) {
    238         return new SkMemoryStream(fData);
    239     }
    240 
    241     if (!fName.isEmpty()) {
    242         SkAutoTUnref<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 (NULL == fData.get()) {
    250         return NULL;
    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     SkAutoTUnref<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 (NULL == fData.get()) {
    279         return NULL;
    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 (NULL == 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 (NULL == 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 bool SkMemoryStream::isAtEnd() const {
    371     return fOffset == fData->size();
    372 }
    373 
    374 bool SkMemoryStream::rewind() {
    375     fOffset = 0;
    376     return true;
    377 }
    378 
    379 SkMemoryStream* SkMemoryStream::duplicate() const {
    380     return SkNEW_ARGS(SkMemoryStream, (fData));
    381 }
    382 
    383 size_t SkMemoryStream::getPosition() const {
    384     return fOffset;
    385 }
    386 
    387 bool SkMemoryStream::seek(size_t position) {
    388     fOffset = position > fData->size()
    389             ? fData->size()
    390             : position;
    391     return true;
    392 }
    393 
    394 bool SkMemoryStream::move(long offset) {
    395     return this->seek(fOffset + offset);
    396 }
    397 
    398 SkMemoryStream* SkMemoryStream::fork() const {
    399     SkAutoTUnref<SkMemoryStream> that(this->duplicate());
    400     that->seek(fOffset);
    401     return that.detach();
    402 }
    403 
    404 size_t SkMemoryStream::getLength() const {
    405     return fData->size();
    406 }
    407 
    408 const void* SkMemoryStream::getMemoryBase() {
    409     return fData->data();
    410 }
    411 
    412 const void* SkMemoryStream::getAtPos() {
    413     return fData->bytes() + fOffset;
    414 }
    415 
    416 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    417 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    418 
    419 SkFILEWStream::SkFILEWStream(const char path[])
    420 {
    421     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    422 }
    423 
    424 SkFILEWStream::~SkFILEWStream()
    425 {
    426     if (fFILE) {
    427         sk_fclose(fFILE);
    428     }
    429 }
    430 
    431 size_t SkFILEWStream::bytesWritten() const {
    432     return sk_ftell(fFILE);
    433 }
    434 
    435 bool SkFILEWStream::write(const void* buffer, size_t size)
    436 {
    437     if (fFILE == NULL) {
    438         return false;
    439     }
    440 
    441     if (sk_fwrite(buffer, size, fFILE) != size)
    442     {
    443         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    444         sk_fclose(fFILE);
    445         fFILE = NULL;
    446         return false;
    447     }
    448     return true;
    449 }
    450 
    451 void SkFILEWStream::flush()
    452 {
    453     if (fFILE) {
    454         sk_fflush(fFILE);
    455     }
    456 }
    457 
    458 ////////////////////////////////////////////////////////////////////////
    459 
    460 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    461     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    462 {
    463 }
    464 
    465 bool SkMemoryWStream::write(const void* buffer, size_t size) {
    466     size = SkTMin(size, fMaxLength - fBytesWritten);
    467     if (size > 0) {
    468         memcpy(fBuffer + fBytesWritten, buffer, size);
    469         fBytesWritten += size;
    470         return true;
    471     }
    472     return false;
    473 }
    474 
    475 ////////////////////////////////////////////////////////////////////////
    476 
    477 #define SkDynamicMemoryWStream_MinBlockSize   256
    478 
    479 struct SkDynamicMemoryWStream::Block {
    480     Block*  fNext;
    481     char*   fCurr;
    482     char*   fStop;
    483 
    484     const char* start() const { return (const char*)(this + 1); }
    485     char*   start() { return (char*)(this + 1); }
    486     size_t  avail() const { return fStop - fCurr; }
    487     size_t  written() const { return fCurr - this->start(); }
    488 
    489     void init(size_t size)
    490     {
    491         fNext = NULL;
    492         fCurr = this->start();
    493         fStop = this->start() + size;
    494     }
    495 
    496     const void* append(const void* data, size_t size)
    497     {
    498         SkASSERT((size_t)(fStop - fCurr) >= size);
    499         memcpy(fCurr, data, size);
    500         fCurr += size;
    501         return (const void*)((const char*)data + size);
    502     }
    503 };
    504 
    505 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
    506     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
    507 {
    508 }
    509 
    510 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    511 {
    512     reset();
    513 }
    514 
    515 void SkDynamicMemoryWStream::reset()
    516 {
    517     this->invalidateCopy();
    518 
    519     Block*  block = fHead;
    520 
    521     while (block != NULL) {
    522         Block*  next = block->fNext;
    523         sk_free(block);
    524         block = next;
    525     }
    526     fHead = fTail = NULL;
    527     fBytesWritten = 0;
    528 }
    529 
    530 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    531 {
    532     if (count > 0) {
    533         this->invalidateCopy();
    534 
    535         fBytesWritten += count;
    536 
    537         size_t  size;
    538 
    539         if (fTail != NULL && fTail->avail() > 0) {
    540             size = SkTMin(fTail->avail(), count);
    541             buffer = fTail->append(buffer, size);
    542             SkASSERT(count >= size);
    543             count -= size;
    544             if (count == 0)
    545                 return true;
    546         }
    547 
    548         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
    549         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    550         block->init(size);
    551         block->append(buffer, count);
    552 
    553         if (fTail != NULL)
    554             fTail->fNext = block;
    555         else
    556             fHead = fTail = block;
    557         fTail = block;
    558     }
    559     return true;
    560 }
    561 
    562 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    563 {
    564     if (offset + count > fBytesWritten) {
    565         return false; // test does not partially modify
    566     }
    567 
    568     this->invalidateCopy();
    569 
    570     Block* block = fHead;
    571     while (block != NULL) {
    572         size_t size = block->written();
    573         if (offset < size) {
    574             size_t part = offset + count > size ? size - offset : count;
    575             memcpy(block->start() + offset, buffer, part);
    576             if (count <= part)
    577                 return true;
    578             count -= part;
    579             buffer = (const void*) ((char* ) buffer + part);
    580         }
    581         offset = offset > size ? offset - size : 0;
    582         block = block->fNext;
    583     }
    584     return false;
    585 }
    586 
    587 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    588 {
    589     if (offset + count > fBytesWritten)
    590         return false; // test does not partially modify
    591     Block* block = fHead;
    592     while (block != NULL) {
    593         size_t size = block->written();
    594         if (offset < size) {
    595             size_t part = offset + count > size ? size - offset : count;
    596             memcpy(buffer, block->start() + offset, part);
    597             if (count <= part)
    598                 return true;
    599             count -= part;
    600             buffer = (void*) ((char* ) buffer + part);
    601         }
    602         offset = offset > size ? offset - size : 0;
    603         block = block->fNext;
    604     }
    605     return false;
    606 }
    607 
    608 void SkDynamicMemoryWStream::copyTo(void* dst) const
    609 {
    610     if (fCopy) {
    611         memcpy(dst, fCopy->data(), fBytesWritten);
    612     } else {
    613         Block* block = fHead;
    614 
    615         while (block != NULL) {
    616             size_t size = block->written();
    617             memcpy(dst, block->start(), size);
    618             dst = (void*)((char*)dst + size);
    619             block = block->fNext;
    620         }
    621     }
    622 }
    623 
    624 void SkDynamicMemoryWStream::padToAlign4()
    625 {
    626     // cast to remove unary-minus warning
    627     int padBytes = -(int)fBytesWritten & 0x03;
    628     if (padBytes == 0)
    629         return;
    630     int zero = 0;
    631     write(&zero, padBytes);
    632 }
    633 
    634 SkData* SkDynamicMemoryWStream::copyToData() const {
    635     if (NULL == fCopy) {
    636         SkData* data = SkData::NewUninitialized(fBytesWritten);
    637         // be sure to call copyTo() before we assign to fCopy
    638         this->copyTo(data->writable_data());
    639         fCopy = data;
    640     }
    641     return SkRef(fCopy);
    642 }
    643 
    644 void SkDynamicMemoryWStream::invalidateCopy() {
    645     if (fCopy) {
    646         fCopy->unref();
    647         fCopy = NULL;
    648     }
    649 }
    650 
    651 class SkBlockMemoryRefCnt : public SkRefCnt {
    652 public:
    653     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
    654 
    655     virtual ~SkBlockMemoryRefCnt() {
    656         SkDynamicMemoryWStream::Block* block = fHead;
    657         while (block != NULL) {
    658             SkDynamicMemoryWStream::Block* next = block->fNext;
    659             sk_free(block);
    660             block = next;
    661         }
    662     }
    663 
    664     SkDynamicMemoryWStream::Block* const fHead;
    665 };
    666 
    667 class SkBlockMemoryStream : public SkStreamAsset {
    668 public:
    669     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
    670         : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
    671         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
    672 
    673     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
    674         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
    675         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
    676 
    677     virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
    678         size_t count = rawCount;
    679         if (fOffset + count > fSize) {
    680             count = fSize - fOffset;
    681         }
    682         size_t bytesLeftToRead = count;
    683         while (fCurrent != NULL) {
    684             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
    685             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
    686             if (buffer) {
    687                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
    688                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
    689             }
    690             if (bytesLeftToRead <= bytesFromCurrent) {
    691                 fCurrentOffset += bytesFromCurrent;
    692                 fOffset += count;
    693                 return count;
    694             }
    695             bytesLeftToRead -= bytesFromCurrent;
    696             fCurrent = fCurrent->fNext;
    697             fCurrentOffset = 0;
    698         }
    699         SkASSERT(false);
    700         return 0;
    701     }
    702 
    703     virtual bool isAtEnd() const SK_OVERRIDE {
    704         return fOffset == fSize;
    705     }
    706 
    707     virtual bool rewind() SK_OVERRIDE {
    708         fCurrent = fBlockMemory->fHead;
    709         fOffset = 0;
    710         fCurrentOffset = 0;
    711         return true;
    712     }
    713 
    714     virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
    715         return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
    716     }
    717 
    718     virtual size_t getPosition() const SK_OVERRIDE {
    719         return fOffset;
    720     }
    721 
    722     virtual bool seek(size_t position) SK_OVERRIDE {
    723         // If possible, skip forward.
    724         if (position >= fOffset) {
    725             size_t skipAmount = position - fOffset;
    726             return this->skip(skipAmount) == skipAmount;
    727         }
    728         // If possible, move backward within the current block.
    729         size_t moveBackAmount = fOffset - position;
    730         if (moveBackAmount <= fCurrentOffset) {
    731             fCurrentOffset -= moveBackAmount;
    732             fOffset -= moveBackAmount;
    733             return true;
    734         }
    735         // Otherwise rewind and move forward.
    736         return this->rewind() && this->skip(position) == position;
    737     }
    738 
    739     virtual bool move(long offset) SK_OVERRIDE {
    740         return seek(fOffset + offset);
    741     }
    742 
    743     virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
    744         SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
    745         that->fCurrent = this->fCurrent;
    746         that->fOffset = this->fOffset;
    747         that->fCurrentOffset = this->fCurrentOffset;
    748         return that.detach();
    749     }
    750 
    751     virtual size_t getLength() const SK_OVERRIDE {
    752         return fSize;
    753     }
    754 
    755     virtual const void* getMemoryBase() SK_OVERRIDE {
    756         if (NULL == fBlockMemory->fHead->fNext) {
    757             return fBlockMemory->fHead->start();
    758         }
    759         return NULL;
    760     }
    761 
    762 private:
    763     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
    764     SkDynamicMemoryWStream::Block const * fCurrent;
    765     size_t const fSize;
    766     size_t fOffset;
    767     size_t fCurrentOffset;
    768 };
    769 
    770 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
    771     if (fCopy) {
    772         SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
    773         this->reset();
    774         return stream;
    775     }
    776     SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
    777     fHead = 0;
    778     this->reset();
    779     return stream;
    780 }
    781 
    782 ///////////////////////////////////////////////////////////////////////////////
    783 
    784 void SkDebugWStream::newline()
    785 {
    786 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
    787     SkDebugf("\n");
    788     fBytesWritten++;
    789 #endif
    790 }
    791 
    792 bool SkDebugWStream::write(const void* buffer, size_t size)
    793 {
    794 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
    795     char* s = new char[size+1];
    796     memcpy(s, buffer, size);
    797     s[size] = 0;
    798     SkDebugf("%s", s);
    799     delete[] s;
    800     fBytesWritten += size;
    801 #endif
    802     return true;
    803 }
    804 
    805 ///////////////////////////////////////////////////////////////////////////////
    806 ///////////////////////////////////////////////////////////////////////////////
    807 
    808 
    809 static SkData* mmap_filename(const char path[]) {
    810     SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
    811     if (NULL == file) {
    812         return NULL;
    813     }
    814 
    815     SkData* data = SkData::NewFromFILE(file);
    816     sk_fclose(file);
    817     return data;
    818 }
    819 
    820 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
    821     SkAutoTUnref<SkData> data(mmap_filename(path));
    822     if (data.get()) {
    823         return SkNEW_ARGS(SkMemoryStream, (data.get()));
    824     }
    825 
    826     // If we get here, then our attempt at using mmap failed, so try normal
    827     // file access.
    828     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
    829     if (!stream->isValid()) {
    830         stream->unref();
    831         stream = NULL;
    832     }
    833     return stream;
    834 }
    835 
    836 // Declared in SkStreamPriv.h:
    837 size_t SkCopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) {
    838     SkASSERT(storage != NULL);
    839     SkASSERT(stream != NULL);
    840 
    841     if (stream->hasLength()) {
    842         const size_t length = stream->getLength();
    843         void* dst = storage->reset(length);
    844         if (stream->read(dst, length) != length) {
    845             return 0;
    846         }
    847         return length;
    848     }
    849 
    850     SkDynamicMemoryWStream tempStream;
    851     // Arbitrary buffer size.
    852     const size_t bufferSize = 256 * 1024; // 256KB
    853     char buffer[bufferSize];
    854     SkDEBUGCODE(size_t debugLength = 0;)
    855     do {
    856         size_t bytesRead = stream->read(buffer, bufferSize);
    857         tempStream.write(buffer, bytesRead);
    858         SkDEBUGCODE(debugLength += bytesRead);
    859         SkASSERT(tempStream.bytesWritten() == debugLength);
    860     } while (!stream->isAtEnd());
    861     const size_t length = tempStream.bytesWritten();
    862     void* dst = storage->reset(length);
    863     tempStream.copyTo(dst);
    864     return length;
    865 }
    866 
    867 // Declared in SkStreamPriv.h:
    868 SkData* SkCopyStreamToData(SkStream* stream) {
    869     SkASSERT(stream != NULL);
    870 
    871     if (stream->hasLength()) {
    872         return SkData::NewFromStream(stream, stream->getLength());
    873     }
    874 
    875     SkDynamicMemoryWStream tempStream;
    876     const size_t bufferSize = 4096;
    877     char buffer[bufferSize];
    878     do {
    879         size_t bytesRead = stream->read(buffer, bufferSize);
    880         tempStream.write(buffer, bytesRead);
    881     } while (!stream->isAtEnd());
    882     return tempStream.copyToData();
    883 }
    884 
    885 SkStreamRewindable* SkStreamRewindableFromSkStream(SkStream* stream) {
    886     if (!stream) {
    887         return NULL;
    888     }
    889     SkAutoTUnref<SkStreamRewindable> dupStream(stream->duplicate());
    890     if (dupStream) {
    891         return dupStream.detach();
    892     }
    893     stream->rewind();
    894     if (stream->hasLength()) {
    895         size_t length = stream->getLength();
    896         if (stream->hasPosition()) {  // If stream has length, but can't rewind.
    897             length -= stream->getPosition();
    898         }
    899         SkAutoTUnref<SkData> data(SkData::NewFromStream(stream, length));
    900         return SkNEW_ARGS(SkMemoryStream, (data.get()));
    901     }
    902     SkDynamicMemoryWStream tempStream;
    903     const size_t bufferSize = 4096;
    904     char buffer[bufferSize];
    905     do {
    906         size_t bytesRead = stream->read(buffer, bufferSize);
    907         tempStream.write(buffer, bytesRead);
    908     } while (!stream->isAtEnd());
    909     return tempStream.detachAsStream();  // returns a SkBlockMemoryStream,
    910                                          // cheaper than copying to SkData
    911 }
    912