Home | History | Annotate | Download | only in core
      1 #include "SkWriter32.h"
      2 
      3 struct SkWriter32::Block {
      4     Block*  fNext;
      5     size_t  fSize;
      6     size_t  fAllocated;
      7 
      8     size_t  available() const { return fSize - fAllocated; }
      9     char*   base() { return (char*)(this + 1); }
     10     const char* base() const { return (const char*)(this + 1); }
     11 
     12     uint32_t* alloc(size_t size)
     13     {
     14         SkASSERT(SkAlign4(size) == size);
     15         SkASSERT(this->available() >= size);
     16         void* ptr = this->base() + fAllocated;
     17         fAllocated += size;
     18         SkASSERT(fAllocated <= fSize);
     19         return (uint32_t*)ptr;
     20     }
     21 
     22     uint32_t* peek32(size_t offset)
     23     {
     24         SkASSERT(offset <= fAllocated + 4);
     25         void* ptr = this->base() + offset;
     26         return (uint32_t*)ptr;
     27     }
     28 
     29     static Block* Create(size_t size)
     30     {
     31         SkASSERT(SkAlign4(size) == size);
     32         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
     33         block->fNext = NULL;
     34         block->fSize = size;
     35         block->fAllocated = 0;
     36         return block;
     37     }
     38 };
     39 
     40 ///////////////////////////////////////////////////////////////////////////////
     41 
     42 SkWriter32::~SkWriter32()
     43 {
     44     this->reset();
     45 }
     46 
     47 void SkWriter32::reset()
     48 {
     49     Block* block = fHead;
     50     while (block)
     51     {
     52         Block* next = block->fNext;
     53         sk_free(block);
     54         block = next;
     55     }
     56     fHead = fTail = NULL;
     57     fSize = 0;
     58 }
     59 
     60 uint32_t* SkWriter32::reserve(size_t size)
     61 {
     62     SkASSERT(SkAlign4(size) == size);
     63 
     64     Block* block = fTail;
     65 
     66     if (NULL == block)
     67     {
     68         SkASSERT(NULL == fHead);
     69         fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
     70     }
     71     else if (block->available() < size)
     72     {
     73         fTail = Block::Create(SkMax32(size, fMinSize));
     74         block->fNext = fTail;
     75         block = fTail;
     76     }
     77 
     78     fSize += size;
     79 
     80     return block->alloc(size);
     81 }
     82 
     83 uint32_t* SkWriter32::peek32(size_t offset)
     84 {
     85     SkASSERT(SkAlign4(offset) == offset);
     86     SkASSERT(offset <= fSize);
     87 
     88     Block* block = fHead;
     89     SkASSERT(NULL != block);
     90 
     91     while (offset >= block->fAllocated)
     92     {
     93         offset -= block->fAllocated;
     94         block = block->fNext;
     95         SkASSERT(NULL != block);
     96     }
     97     return block->peek32(offset);
     98 }
     99 
    100 void SkWriter32::flatten(void* dst) const
    101 {
    102     const Block* block = fHead;
    103     SkDEBUGCODE(size_t total = 0;)
    104 
    105     while (block)
    106     {
    107         size_t allocated = block->fAllocated;
    108         memcpy(dst, block->base(), allocated);
    109         dst = (char*)dst + allocated;
    110         block = block->fNext;
    111 
    112         SkDEBUGCODE(total += allocated;)
    113         SkASSERT(total <= fSize);
    114     }
    115     SkASSERT(total == fSize);
    116 }
    117 
    118 void SkWriter32::writePad(const void* src, size_t size) {
    119     size_t alignedSize = SkAlign4(size);
    120     char* dst = (char*)this->reserve(alignedSize);
    121     memcpy(dst, src, size);
    122     dst += size;
    123     int n = alignedSize - size;
    124     while (--n >= 0) {
    125         *dst++ = 0;
    126     }
    127 }
    128 
    129 #include "SkStream.h"
    130 
    131 size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
    132     char scratch[1024];
    133     const size_t MAX = sizeof(scratch);
    134     size_t remaining = length;
    135 
    136     while (remaining != 0) {
    137         size_t n = remaining;
    138         if (n > MAX) {
    139             n = MAX;
    140         }
    141         size_t bytes = stream->read(scratch, n);
    142         this->writePad(scratch, bytes);
    143         remaining -= bytes;
    144         if (bytes != n) {
    145             break;
    146         }
    147     }
    148     return length - remaining;
    149 }
    150 
    151 bool SkWriter32::writeToStream(SkWStream* stream) {
    152     const Block* block = fHead;
    153     while (block) {
    154         if (!stream->write(block->base(), block->fAllocated)) {
    155             return false;
    156         }
    157         block = block->fNext;
    158     }
    159     return true;
    160 }
    161 
    162