SkWriter32.cpp revision 76692c34c7e2d69f4e43133e516c580f08caed99
1#include "SkWriter32.h"
2
3struct 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
42SkWriter32::~SkWriter32()
43{
44    this->reset();
45}
46
47void 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
60uint32_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
83uint32_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
100void 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
118void 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
131size_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
151bool 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