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