1 #include "SkWriter32.h"
2
3 struct SkWriter32::Block {
4 Block* fNext;
5 size_t fSize;
6 size_t fAllocated;
7
availableSkWriter32::Block8 size_t available() const { return fSize - fAllocated; }
baseSkWriter32::Block9 char* base() { return (char*)(this + 1); }
baseSkWriter32::Block10 const char* base() const { return (const char*)(this + 1); }
11
allocSkWriter32::Block12 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
peek32SkWriter32::Block22 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
CreateSkWriter32::Block29 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
~SkWriter32()42 SkWriter32::~SkWriter32()
43 {
44 this->reset();
45 }
46
reset()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
reserve(size_t size)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
peek32(size_t offset)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
flatten(void * dst) const100 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
writePad(const void * src,size_t size)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
readFromStream(SkStream * stream,size_t length)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
writeToStream(SkWStream * stream)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