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 SkStream::~SkStream() {}
     17 
     18 const char* SkStream::getFileName()
     19 {
     20     // override in subclass if you represent a file
     21     return NULL;
     22 }
     23 
     24 const void* SkStream::getMemoryBase()
     25 {
     26     // override in subclass if you represent a memory block
     27     return NULL;
     28 }
     29 
     30 size_t SkStream::skip(size_t size)
     31 {
     32     /*  Check for size == 0, and just return 0. If we passed that
     33         to read(), it would interpret it as a request for the entire
     34         size of the stream.
     35     */
     36     return size ? this->read(NULL, size) : 0;
     37 }
     38 
     39 int8_t SkStream::readS8() {
     40     int8_t value;
     41     SkDEBUGCODE(size_t len =) this->read(&value, 1);
     42     SkASSERT(1 == len);
     43     return value;
     44 }
     45 
     46 int16_t SkStream::readS16() {
     47     int16_t value;
     48     SkDEBUGCODE(size_t len =) this->read(&value, 2);
     49     SkASSERT(2 == len);
     50     return value;
     51 }
     52 
     53 int32_t SkStream::readS32() {
     54     int32_t value;
     55     SkDEBUGCODE(size_t len =) this->read(&value, 4);
     56     SkASSERT(4 == len);
     57     return value;
     58 }
     59 
     60 SkScalar SkStream::readScalar() {
     61     SkScalar value;
     62     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
     63     SkASSERT(sizeof(SkScalar) == len);
     64     return value;
     65 }
     66 
     67 #define SK_MAX_BYTE_FOR_U8          0xFD
     68 #define SK_BYTE_SENTINEL_FOR_U16    0xFE
     69 #define SK_BYTE_SENTINEL_FOR_U32    0xFF
     70 
     71 size_t SkStream::readPackedUInt() {
     72     uint8_t byte;
     73     if (!this->read(&byte, 1)) {
     74         return 0;
     75     }
     76     if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
     77         return this->readU16();
     78     } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
     79         return this->readU32();
     80     } else {
     81         return byte;
     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->write(data->data(), data->size());
    193     }
    194     return true;
    195 }
    196 
    197 ///////////////////////////////////////////////////////////////////////////////
    198 
    199 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
    200 {
    201     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
    202 }
    203 
    204 SkFILEStream::~SkFILEStream()
    205 {
    206     if (fFILE)
    207         sk_fclose(fFILE);
    208 }
    209 
    210 void SkFILEStream::setPath(const char path[])
    211 {
    212     fName.set(path);
    213     if (fFILE)
    214     {
    215         sk_fclose(fFILE);
    216         fFILE = NULL;
    217     }
    218     if (path)
    219         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
    220 }
    221 
    222 const char* SkFILEStream::getFileName()
    223 {
    224     return fName.c_str();
    225 }
    226 
    227 bool SkFILEStream::rewind()
    228 {
    229     if (fFILE)
    230     {
    231         if (sk_frewind(fFILE))
    232             return true;
    233         // we hit an error
    234         sk_fclose(fFILE);
    235         fFILE = NULL;
    236     }
    237     return false;
    238 }
    239 
    240 size_t SkFILEStream::read(void* buffer, size_t size)
    241 {
    242     if (fFILE)
    243     {
    244         if (buffer == NULL && size == 0)    // special signature, they want the total size
    245             return sk_fgetsize(fFILE);
    246         else
    247             return sk_fread(buffer, size, fFILE);
    248     }
    249     return 0;
    250 }
    251 
    252 ///////////////////////////////////////////////////////////////////////////////
    253 
    254 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
    255     if (copyData) {
    256         return SkData::NewWithCopy(src, size);
    257     } else {
    258         return SkData::NewWithProc(src, size, NULL, NULL);
    259     }
    260 }
    261 
    262 SkMemoryStream::SkMemoryStream() {
    263     fData = SkData::NewEmpty();
    264     fOffset = 0;
    265 }
    266 
    267 SkMemoryStream::SkMemoryStream(size_t size) {
    268     fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
    269     fOffset = 0;
    270 }
    271 
    272 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
    273     fData = newFromParams(src, size, copyData);
    274     fOffset = 0;
    275 }
    276 
    277 SkMemoryStream::~SkMemoryStream() {
    278     fData->unref();
    279 }
    280 
    281 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
    282     fData->unref();
    283     fData = SkData::NewFromMalloc(src, size);
    284     fOffset = 0;
    285 }
    286 
    287 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
    288     fData->unref();
    289     fData = newFromParams(src, size, copyData);
    290     fOffset = 0;
    291 }
    292 
    293 SkData* SkMemoryStream::copyToData() const {
    294     fData->ref();
    295     return fData;
    296 }
    297 
    298 SkData* SkMemoryStream::setData(SkData* data) {
    299     SkRefCnt_SafeAssign(fData, data);
    300     return data;
    301 }
    302 
    303 void SkMemoryStream::skipToAlign4() {
    304     // cast to remove unary-minus warning
    305     fOffset += -(int)fOffset & 0x03;
    306 }
    307 
    308 bool SkMemoryStream::rewind() {
    309     fOffset = 0;
    310     return true;
    311 }
    312 
    313 size_t SkMemoryStream::read(void* buffer, size_t size) {
    314     size_t dataSize = fData->size();
    315 
    316     if (buffer == NULL && size == 0)    // special signature, they want the total size
    317         return dataSize;
    318 
    319     // if buffer is NULL, seek ahead by size
    320 
    321     if (size == 0) {
    322         return 0;
    323     }
    324     if (size > dataSize - fOffset) {
    325         size = dataSize - fOffset;
    326     }
    327     if (buffer) {
    328         memcpy(buffer, fData->bytes() + fOffset, size);
    329     }
    330     fOffset += size;
    331     return size;
    332 }
    333 
    334 const void* SkMemoryStream::getMemoryBase() {
    335     return fData->data();
    336 }
    337 
    338 const void* SkMemoryStream::getAtPos() {
    339     return fData->bytes() + fOffset;
    340 }
    341 
    342 size_t SkMemoryStream::seek(size_t offset) {
    343     if (offset > fData->size()) {
    344         offset = fData->size();
    345     }
    346     fOffset = offset;
    347     return offset;
    348 }
    349 
    350 ///////////////////////////////////////////////////////////////////////////////
    351 
    352 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
    353     : fProxy(proxy)
    354 {
    355     SkASSERT(proxy != NULL);
    356     proxy->ref();
    357     this->init(NULL, bufferSize);
    358 }
    359 
    360 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
    361     : fProxy(proxy)
    362 {
    363     SkASSERT(proxy != NULL);
    364     SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
    365     proxy->ref();
    366     this->init(buffer, bufferSize);
    367 }
    368 
    369 void SkBufferStream::init(void* buffer, size_t bufferSize)
    370 {
    371     if (bufferSize == 0)
    372         bufferSize = kDefaultBufferSize;
    373 
    374     fOrigBufferSize = bufferSize;
    375     fBufferSize = bufferSize;
    376     fBufferOffset = bufferSize; // to trigger a reload on the first read()
    377 
    378     if (buffer == NULL)
    379     {
    380         fBuffer = (char*)sk_malloc_throw(fBufferSize);
    381         fWeOwnTheBuffer = true;
    382     }
    383     else
    384     {
    385         fBuffer = (char*)buffer;
    386         fWeOwnTheBuffer = false;
    387     }
    388 }
    389 
    390 SkBufferStream::~SkBufferStream()
    391 {
    392     fProxy->unref();
    393     if (fWeOwnTheBuffer)
    394         sk_free(fBuffer);
    395 }
    396 
    397 bool SkBufferStream::rewind()
    398 {
    399     fBufferOffset = fBufferSize = fOrigBufferSize;
    400     return fProxy->rewind();
    401 }
    402 
    403 const char* SkBufferStream::getFileName()
    404 {
    405     return fProxy->getFileName();
    406 }
    407 
    408 #ifdef SK_DEBUG
    409 //  #define SK_TRACE_BUFFERSTREAM
    410 #endif
    411 
    412 size_t SkBufferStream::read(void* buffer, size_t size) {
    413 #ifdef SK_TRACE_BUFFERSTREAM
    414     SkDebugf("Request %d", size);
    415 #endif
    416 
    417     if (buffer == NULL && size == 0) {
    418         return fProxy->read(buffer, size);    // requesting total size
    419     }
    420 
    421     if (0 == size) {
    422         return 0;
    423     }
    424 
    425     // skip size bytes
    426     if (NULL == buffer) {
    427         size_t remaining = fBufferSize - fBufferOffset;
    428         if (remaining >= size) {
    429             fBufferOffset += size;
    430             return size;
    431         }
    432         // if we get here, we are being asked to skip beyond our current buffer
    433         // so reset our offset to force a read next time, and skip the diff
    434         // in our proxy
    435         fBufferOffset = fOrigBufferSize;
    436         return remaining + fProxy->read(NULL, size - remaining);
    437     }
    438 
    439     size_t s = size;
    440     size_t actuallyRead = 0;
    441 
    442     // flush what we can from our fBuffer
    443     if (fBufferOffset < fBufferSize)
    444     {
    445         if (s > fBufferSize - fBufferOffset)
    446             s = fBufferSize - fBufferOffset;
    447         memcpy(buffer, fBuffer + fBufferOffset, s);
    448 #ifdef SK_TRACE_BUFFERSTREAM
    449         SkDebugf(" flush %d", s);
    450 #endif
    451         size -= s;
    452         fBufferOffset += s;
    453         buffer = (char*)buffer + s;
    454         actuallyRead = s;
    455     }
    456 
    457     // check if there is more to read
    458     if (size)
    459     {
    460         SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
    461 
    462         if (size < fBufferSize) // lets try to read more than the request
    463         {
    464             s = fProxy->read(fBuffer, fBufferSize);
    465 #ifdef SK_TRACE_BUFFERSTREAM
    466             SkDebugf(" read %d into fBuffer", s);
    467 #endif
    468             if (size > s)   // they asked for too much
    469                 size = s;
    470             if (size)
    471             {
    472                 memcpy(buffer, fBuffer, size);
    473                 actuallyRead += size;
    474 #ifdef SK_TRACE_BUFFERSTREAM
    475                 SkDebugf(" memcpy %d into dst", size);
    476 #endif
    477             }
    478 
    479             fBufferOffset = size;
    480             fBufferSize = s;        // record the (possibly smaller) size for the buffer
    481         }
    482         else    // just do a direct read
    483         {
    484             actuallyRead += fProxy->read(buffer, size);
    485 #ifdef SK_TRACE_BUFFERSTREAM
    486             SkDebugf(" direct read %d", size);
    487 #endif
    488         }
    489     }
    490 #ifdef SK_TRACE_BUFFERSTREAM
    491     SkDebugf("\n");
    492 #endif
    493     return actuallyRead;
    494 }
    495 
    496 const void* SkBufferStream::getMemoryBase()
    497 {
    498     return fProxy->getMemoryBase();
    499 }
    500 
    501 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    502 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    503 
    504 SkFILEWStream::SkFILEWStream(const char path[])
    505 {
    506     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    507 }
    508 
    509 SkFILEWStream::~SkFILEWStream()
    510 {
    511     if (fFILE)
    512         sk_fclose(fFILE);
    513 }
    514 
    515 bool SkFILEWStream::write(const void* buffer, size_t size)
    516 {
    517     if (fFILE == NULL)
    518         return false;
    519 
    520     if (sk_fwrite(buffer, size, fFILE) != size)
    521     {
    522         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    523         sk_fclose(fFILE);
    524         fFILE = NULL;
    525         return false;
    526     }
    527     return true;
    528 }
    529 
    530 void SkFILEWStream::flush()
    531 {
    532     if (fFILE)
    533         sk_fflush(fFILE);
    534 }
    535 
    536 ////////////////////////////////////////////////////////////////////////
    537 
    538 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    539     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    540 {
    541 }
    542 
    543 bool SkMemoryWStream::write(const void* buffer, size_t size)
    544 {
    545     size = SkMin32(size, fMaxLength - fBytesWritten);
    546     if (size > 0)
    547     {
    548         memcpy(fBuffer + fBytesWritten, buffer, size);
    549         fBytesWritten += size;
    550         return true;
    551     }
    552     return false;
    553 }
    554 
    555 ////////////////////////////////////////////////////////////////////////
    556 
    557 #define SkDynamicMemoryWStream_MinBlockSize   256
    558 
    559 struct SkDynamicMemoryWStream::Block {
    560     Block*  fNext;
    561     char*   fCurr;
    562     char*   fStop;
    563 
    564     const char* start() const { return (const char*)(this + 1); }
    565     char*   start() { return (char*)(this + 1); }
    566     size_t  avail() const { return fStop - fCurr; }
    567     size_t  written() const { return fCurr - this->start(); }
    568 
    569     void init(size_t size)
    570     {
    571         fNext = NULL;
    572         fCurr = this->start();
    573         fStop = this->start() + size;
    574     }
    575 
    576     const void* append(const void* data, size_t size)
    577     {
    578         SkASSERT((size_t)(fStop - fCurr) >= size);
    579         memcpy(fCurr, data, size);
    580         fCurr += size;
    581         return (const void*)((const char*)data + size);
    582     }
    583 };
    584 
    585 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
    586     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
    587 {
    588 }
    589 
    590 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    591 {
    592     reset();
    593 }
    594 
    595 void SkDynamicMemoryWStream::reset()
    596 {
    597     this->invalidateCopy();
    598 
    599     Block*  block = fHead;
    600 
    601     while (block != NULL) {
    602         Block*  next = block->fNext;
    603         sk_free(block);
    604         block = next;
    605     }
    606     fHead = fTail = NULL;
    607     fBytesWritten = 0;
    608 }
    609 
    610 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    611 {
    612     if (count > 0) {
    613         this->invalidateCopy();
    614 
    615         fBytesWritten += count;
    616 
    617         size_t  size;
    618 
    619         if (fTail != NULL && fTail->avail() > 0) {
    620             size = SkMin32(fTail->avail(), count);
    621             buffer = fTail->append(buffer, size);
    622             SkASSERT(count >= size);
    623             count -= size;
    624             if (count == 0)
    625                 return true;
    626         }
    627 
    628         size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
    629         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    630         block->init(size);
    631         block->append(buffer, count);
    632 
    633         if (fTail != NULL)
    634             fTail->fNext = block;
    635         else
    636             fHead = fTail = block;
    637         fTail = block;
    638     }
    639     return true;
    640 }
    641 
    642 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    643 {
    644     if (offset + count > fBytesWritten) {
    645         return false; // test does not partially modify
    646     }
    647 
    648     this->invalidateCopy();
    649 
    650     Block* block = fHead;
    651     while (block != NULL) {
    652         size_t size = block->written();
    653         if (offset < size) {
    654             size_t part = offset + count > size ? size - offset : count;
    655             memcpy(block->start() + offset, buffer, part);
    656             if (count <= part)
    657                 return true;
    658             count -= part;
    659             buffer = (const void*) ((char* ) buffer + part);
    660         }
    661         offset = offset > size ? offset - size : 0;
    662         block = block->fNext;
    663     }
    664     return false;
    665 }
    666 
    667 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    668 {
    669     if (offset + count > fBytesWritten)
    670         return false; // test does not partially modify
    671     Block* block = fHead;
    672     while (block != NULL) {
    673         size_t size = block->written();
    674         if (offset < size) {
    675             size_t part = offset + count > size ? size - offset : count;
    676             memcpy(buffer, block->start() + offset, part);
    677             if (count <= part)
    678                 return true;
    679             count -= part;
    680             buffer = (void*) ((char* ) buffer + part);
    681         }
    682         offset = offset > size ? offset - size : 0;
    683         block = block->fNext;
    684     }
    685     return false;
    686 }
    687 
    688 void SkDynamicMemoryWStream::copyTo(void* dst) const
    689 {
    690     if (fCopy) {
    691         memcpy(dst, fCopy->data(), fBytesWritten);
    692     } else {
    693         Block* block = fHead;
    694 
    695         while (block != NULL) {
    696             size_t size = block->written();
    697             memcpy(dst, block->start(), size);
    698             dst = (void*)((char*)dst + size);
    699             block = block->fNext;
    700         }
    701     }
    702 }
    703 
    704 void SkDynamicMemoryWStream::padToAlign4()
    705 {
    706     // cast to remove unary-minus warning
    707     int padBytes = -(int)fBytesWritten & 0x03;
    708     if (padBytes == 0)
    709         return;
    710     int zero = 0;
    711     write(&zero, padBytes);
    712 }
    713 
    714 SkData* SkDynamicMemoryWStream::copyToData() const {
    715     if (NULL == fCopy) {
    716         void* buffer = sk_malloc_throw(fBytesWritten);
    717         this->copyTo(buffer);
    718         fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
    719     }
    720     fCopy->ref();
    721     return fCopy;
    722 }
    723 
    724 void SkDynamicMemoryWStream::invalidateCopy() {
    725     if (fCopy) {
    726         fCopy->unref();
    727         fCopy = NULL;
    728     }
    729 }
    730 
    731 ///////////////////////////////////////////////////////////////////////////////
    732 
    733 void SkDebugWStream::newline()
    734 {
    735 #ifdef SK_DEBUG
    736     SkDebugf("\n");
    737 #endif
    738 }
    739 
    740 bool SkDebugWStream::write(const void* buffer, size_t size)
    741 {
    742 #ifdef SK_DEBUG
    743     char* s = new char[size+1];
    744     memcpy(s, buffer, size);
    745     s[size] = 0;
    746     SkDebugf("%s", s);
    747     delete[] s;
    748 #endif
    749     return true;
    750 }
    751