1 :
2 : /*
3 : * Copyright 2011 Google Inc.
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 : #include "SkWriter32.h"
9 :
10 : struct SkWriter32::Block {
11 : Block* fNext;
12 : size_t fSize;
13 : size_t fAllocated;
14 :
15 0 : size_t available() const { return fSize - fAllocated; }
16 0 : char* base() { return (char*)(this + 1); }
17 0 : const char* base() const { return (const char*)(this + 1); }
18 :
19 0 : uint32_t* alloc(size_t size) {
20 0 : SkASSERT(SkAlign4(size) == size);
21 0 : SkASSERT(this->available() >= size);
22 0 : void* ptr = this->base() + fAllocated;
23 0 : fAllocated += size;
24 0 : SkASSERT(fAllocated <= fSize);
25 0 : return (uint32_t*)ptr;
26 : }
27 :
28 0 : uint32_t* peek32(size_t offset) {
29 0 : SkASSERT(offset <= fAllocated + 4);
30 0 : void* ptr = this->base() + offset;
31 0 : return (uint32_t*)ptr;
32 : }
33 :
34 0 : static Block* Create(size_t size) {
35 0 : SkASSERT(SkAlign4(size) == size);
36 0 : Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
37 0 : block->fNext = NULL;
38 0 : block->fSize = size;
39 0 : block->fAllocated = 0;
40 0 : return block;
41 : }
42 : };
43 :
44 : ///////////////////////////////////////////////////////////////////////////////
45 :
46 0 : SkWriter32::~SkWriter32() {
47 0 : this->reset();
48 0 : }
49 :
50 0 : void SkWriter32::reset() {
51 0 : Block* block = fHead;
52 0 : while (block) {
53 0 : Block* next = block->fNext;
54 0 : sk_free(block);
55 0 : block = next;
56 : }
57 :
58 0 : fSize = 0;
59 0 : fHead = fTail = NULL;
60 0 : fSingleBlock = NULL;
61 0 : }
62 :
63 0 : void SkWriter32::reset(void* block, size_t size) {
64 0 : this->reset();
65 0 : SkASSERT(0 == ((fSingleBlock - (char*)0) & 3)); // need 4-byte alignment
66 0 : fSingleBlock = (char*)block;
67 0 : fSingleBlockSize = (size & ~3);
68 0 : }
69 :
70 0 : uint32_t* SkWriter32::reserve(size_t size) {
71 0 : SkASSERT(SkAlign4(size) == size);
72 :
73 0 : if (fSingleBlock) {
74 0 : uint32_t* ptr = (uint32_t*)(fSingleBlock + fSize);
75 0 : fSize += size;
76 0 : SkASSERT(fSize <= fSingleBlockSize);
77 0 : return ptr;
78 : }
79 :
80 0 : Block* block = fTail;
81 :
82 0 : if (NULL == block) {
83 0 : SkASSERT(NULL == fHead);
84 0 : fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
85 0 : } else if (block->available() < size) {
86 0 : fTail = Block::Create(SkMax32(size, fMinSize));
87 0 : block->fNext = fTail;
88 0 : block = fTail;
89 : }
90 :
91 0 : fSize += size;
92 :
93 0 : return block->alloc(size);
94 : }
95 :
96 0 : uint32_t* SkWriter32::peek32(size_t offset) {
97 0 : SkASSERT(SkAlign4(offset) == offset);
98 0 : SkASSERT(offset <= fSize);
99 :
100 0 : if (fSingleBlock) {
101 0 : return (uint32_t*)(fSingleBlock + offset);
102 : }
103 :
104 0 : Block* block = fHead;
105 0 : SkASSERT(NULL != block);
106 :
107 0 : while (offset >= block->fAllocated) {
108 0 : offset -= block->fAllocated;
109 0 : block = block->fNext;
110 0 : SkASSERT(NULL != block);
111 : }
112 0 : return block->peek32(offset);
113 : }
114 :
115 0 : void SkWriter32::flatten(void* dst) const {
116 0 : if (fSingleBlock) {
117 0 : memcpy(dst, fSingleBlock, fSize);
118 0 : return;
119 : }
120 :
121 0 : const Block* block = fHead;
122 0 : SkDEBUGCODE(size_t total = 0;)
123 :
124 0 : while (block) {
125 0 : size_t allocated = block->fAllocated;
126 0 : memcpy(dst, block->base(), allocated);
127 0 : dst = (char*)dst + allocated;
128 0 : block = block->fNext;
129 :
130 0 : SkDEBUGCODE(total += allocated;)
131 0 : SkASSERT(total <= fSize);
132 : }
133 0 : SkASSERT(total == fSize);
134 : }
135 :
136 0 : void SkWriter32::writePad(const void* src, size_t size) {
137 0 : size_t alignedSize = SkAlign4(size);
138 0 : char* dst = (char*)this->reserve(alignedSize);
139 0 : memcpy(dst, src, size);
140 0 : dst += size;
141 0 : int n = alignedSize - size;
142 0 : while (--n >= 0) {
143 0 : *dst++ = 0;
144 : }
145 0 : }
146 :
147 : #include "SkStream.h"
148 :
149 0 : size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
150 0 : if (fSingleBlock) {
151 0 : SkASSERT(fSingleBlockSize >= fSize);
152 0 : size_t remaining = fSingleBlockSize - fSize;
153 0 : if (length > remaining) {
154 0 : length = remaining;
155 : }
156 0 : stream->read(fSingleBlock + fSize, length);
157 0 : fSize += length;
158 0 : return length;
159 : }
160 :
161 : char scratch[1024];
162 0 : const size_t MAX = sizeof(scratch);
163 0 : size_t remaining = length;
164 :
165 0 : while (remaining != 0) {
166 0 : size_t n = remaining;
167 0 : if (n > MAX) {
168 0 : n = MAX;
169 : }
170 0 : size_t bytes = stream->read(scratch, n);
171 0 : this->writePad(scratch, bytes);
172 0 : remaining -= bytes;
173 0 : if (bytes != n) {
174 0 : break;
175 : }
176 : }
177 0 : return length - remaining;
178 : }
179 :
180 0 : bool SkWriter32::writeToStream(SkWStream* stream) {
181 0 : if (fSingleBlock) {
182 0 : return stream->write(fSingleBlock, fSize);
183 : }
184 :
185 0 : const Block* block = fHead;
186 0 : while (block) {
187 0 : if (!stream->write(block->base(), block->fAllocated)) {
188 0 : return false;
189 : }
190 0 : block = block->fNext;
191 : }
192 0 : return true;
193 : }
194 :
195 : ///////////////////////////////////////////////////////////////////////////////
196 :
197 : #include "SkReader32.h"
198 : #include "SkString.h"
199 :
200 : /*
201 : * Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
202 : */
203 :
204 0 : const char* SkReader32::readString(size_t* outLen) {
205 0 : size_t len = this->readInt();
206 0 : const void* ptr = this->peek();
207 :
208 : // skip over teh string + '\0' and then pad to a multiple of 4
209 0 : size_t alignedSize = SkAlign4(len + 1);
210 0 : this->skip(alignedSize);
211 :
212 0 : if (outLen) {
213 0 : *outLen = len;
214 : }
215 0 : return (const char*)ptr;
216 : }
217 :
218 0 : size_t SkReader32::readIntoString(SkString* copy) {
219 : size_t len;
220 0 : const char* ptr = this->readString(&len);
221 0 : if (copy) {
222 0 : copy->set(ptr, len);
223 : }
224 0 : return len;
225 : }
226 :
227 0 : void SkWriter32::writeString(const char str[], size_t len) {
228 0 : if ((long)len < 0) {
229 0 : SkASSERT(str);
230 0 : len = strlen(str);
231 : }
232 0 : this->write32(len);
233 : // add 1 since we also write a terminating 0
234 0 : size_t alignedLen = SkAlign4(len + 1);
235 0 : char* ptr = (char*)this->reserve(alignedLen);
236 0 : memcpy(ptr, str, len);
237 0 : ptr[len] = 0;
238 : // we may have left 0,1,2,3 bytes uninitialized, since we reserved align4
239 : // number of bytes. That's ok, since the reader will know to skip those
240 0 : }
241 :
242 0 : size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
243 0 : if ((long)len < 0) {
244 0 : SkASSERT(str);
245 0 : len = strlen(str);
246 : }
247 0 : const size_t lenBytes = 4; // we use 4 bytes to record the length
248 : // add 1 since we also write a terminating 0
249 0 : return SkAlign4(lenBytes + len + 1);
250 : }
251 :
252 :
|