OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkData.h" | |
9 #include "SkRWBuffer.h" | |
10 #include "SkStream.h" | |
11 | |
12 struct SkBufferBlock { | |
13 SkBufferBlock* fNext; | |
14 size_t fUsed; | |
15 size_t fCapacity; | |
16 | |
17 const void* startData() const { return this + 1; }; | |
18 | |
19 static SkBufferBlock* Alloc(size_t length) { | |
20 size_t capacity = LengthToCapacity(length); | |
21 SkBufferBlock* block = (SkBufferBlock*)sk_malloc_throw(sizeof(SkBufferBl ock) + capacity); | |
22 block->fNext = NULL; | |
23 block->fUsed = 0; | |
24 block->fCapacity = capacity; | |
25 return block; | |
26 } | |
27 | |
28 // Return number of bytes actually appended | |
29 size_t append(const void* src, size_t length) { | |
30 this->validate(); | |
31 size_t avail = SkTMin(fCapacity - fUsed, length); | |
32 memcpy((char*)(this + 1) + fUsed, src, avail); | |
33 fUsed += avail; | |
34 this->validate(); | |
35 return avail; | |
36 } | |
37 | |
38 void validate() const { | |
39 #ifdef SK_DEBUG | |
40 SkASSERT(fCapacity > 0); | |
41 SkASSERT(fUsed <= fCapacity); | |
42 #endif | |
43 } | |
44 | |
45 private: | |
46 static size_t LengthToCapacity(size_t length) { | |
47 const size_t minSize = 4096 - sizeof(SkBufferBlock); | |
48 return SkTMax(length, minSize); | |
49 } | |
50 }; | |
51 | |
52 struct SkBufferHead { | |
53 mutable int32_t fRefCnt; | |
54 SkBufferBlock fBlock; | |
55 | |
56 static size_t LengthToCapacity(size_t length) { | |
57 const size_t minSize = 4096 - sizeof(SkBufferHead); | |
58 return SkTMax(length, minSize); | |
59 } | |
60 | |
61 static SkBufferHead* Alloc(size_t length) { | |
62 size_t capacity = LengthToCapacity(length); | |
63 size_t size = sizeof(SkBufferHead) + capacity; | |
64 SkBufferHead* head = (SkBufferHead*)sk_malloc_throw(size); | |
65 head->fRefCnt = 1; | |
66 head->fBlock.fNext = NULL; | |
67 head->fBlock.fUsed = 0; | |
68 head->fBlock.fCapacity = capacity; | |
69 return head; | |
70 } | |
71 | |
72 void ref() const { | |
73 SkASSERT(fRefCnt > 0); | |
74 sk_atomic_inc(&fRefCnt); | |
75 } | |
76 | |
77 void unref() const { | |
78 SkASSERT(fRefCnt > 0); | |
79 // A release here acts in place of all releases we "should" have been do ing in ref(). | |
80 if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { | |
81 // Like unique(), the acquire is only needed on success. | |
82 SkBufferBlock* block = fBlock.fNext; | |
83 sk_free((void*)this); | |
84 while (block) { | |
85 SkBufferBlock* next = block->fNext; | |
86 sk_free(block); | |
87 block = next; | |
88 } | |
89 SkDebugf("done\n"); | |
90 } | |
91 } | |
92 | |
93 void validate(size_t minUsed, SkBufferBlock* tail = NULL) const { | |
94 #ifdef SK_DEBUG | |
95 SkASSERT(fRefCnt > 0); | |
96 size_t totalUsed = 0; | |
97 const SkBufferBlock* block = &fBlock; | |
98 const SkBufferBlock* lastBlock = block; | |
99 while (block) { | |
100 block->validate(); | |
101 totalUsed += block->fUsed; | |
102 lastBlock = block; | |
103 block = block->fNext; | |
104 } | |
105 SkASSERT(minUsed <= totalUsed); | |
106 if (tail) { | |
107 SkASSERT(tail == lastBlock); | |
108 } | |
109 #endif | |
110 } | |
111 }; | |
112 | |
113 SkRBuffer::SkRBuffer(const SkBufferHead* head, size_t used) : fHead(SkRef(head)) , fUsed(used) { | |
114 if (head) { | |
115 SkASSERT(used > 0); | |
116 head->validate(used); | |
117 } else { | |
118 SkASSERT(0 == used); | |
119 } | |
120 } | |
121 | |
122 SkRBuffer::~SkRBuffer() { | |
123 if (fHead) { | |
124 fHead->validate(fUsed); | |
125 fHead->unref(); | |
126 } | |
127 } | |
128 | |
129 SkRBuffer::Iter::Iter(const SkRBuffer* buffer) { | |
130 this->reset(buffer); | |
131 } | |
132 | |
133 void SkRBuffer::Iter::reset(const SkRBuffer* buffer) { | |
134 if (buffer) { | |
135 fBlock = &buffer->fHead->fBlock; | |
136 fRemaining = buffer->fUsed; | |
137 } else { | |
138 fBlock = NULL; | |
139 fRemaining = 0; | |
140 } | |
141 } | |
142 | |
143 const void* SkRBuffer::Iter::data() const { | |
144 return fRemaining ? fBlock->startData() : NULL; | |
145 } | |
146 | |
147 size_t SkRBuffer::Iter::size() const { | |
148 return SkTMin(fBlock->fUsed, fRemaining); | |
149 } | |
150 | |
151 bool SkRBuffer::Iter::next() { | |
152 if (fRemaining) { | |
153 fRemaining -= this->size(); | |
154 fBlock = fBlock->fNext; | |
155 } | |
156 return fRemaining != 0; | |
157 } | |
158 | |
159 SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(NULL), fTail(NULL), fTota lUsed(0) {} | |
160 | |
161 SkRWBuffer::~SkRWBuffer() { | |
162 this->validate(); | |
163 fHead->unref(); | |
164 } | |
165 | |
166 void SkRWBuffer::append(const void* src, size_t length) { | |
167 this->validate(); | |
168 if (0 == length) { | |
169 return; | |
170 } | |
171 | |
172 fTotalUsed += length; | |
173 | |
174 if (NULL == fHead) { | |
175 fHead = SkBufferHead::Alloc(length); | |
176 fTail = &fHead->fBlock; | |
177 } | |
178 | |
179 size_t written = fTail->append(src, length); | |
180 SkASSERT(written <= length); | |
181 src = (const char*)src + written; | |
182 length -= written; | |
183 | |
184 if (length) { | |
185 SkBufferBlock* block = SkBufferBlock::Alloc(length); | |
186 fTail->fNext = block; | |
187 fTail = block; | |
188 written = fTail->append(src, length); | |
189 SkASSERT(written == length); | |
190 } | |
191 this->validate(); | |
192 } | |
193 | |
194 #ifdef SK_DEBUG | |
195 void SkRWBuffer::validate() const { | |
196 if (fHead) { | |
197 fHead->validate(fTotalUsed, fTail); | |
198 } else { | |
199 SkASSERT(NULL == fTail); | |
200 SkASSERT(0 == fTotalUsed); | |
201 } | |
202 } | |
203 #endif | |
204 | |
205 SkRBuffer* SkRWBuffer::newRBufferSnapshot() const { | |
206 return SkNEW_ARGS(SkRBuffer, (fHead, fTotalUsed)); | |
207 } | |
208 | |
209 SkData* SkRWBuffer::newDataSnapshot() const { | |
210 SkData* data = SkData::NewUninitialized(fTotalUsed); | |
211 | |
212 const SkBufferBlock* block = &fHead->fBlock; | |
213 char* dst = (char*)data->writable_data(); | |
214 while (block) { | |
215 memcpy(dst, block->startData(), block->fUsed); | |
216 dst += block->fUsed; | |
217 block = block->fNext; | |
218 } | |
219 return data; | |
220 } | |
221 | |
222 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
223 | |
224 class SkRBufferStreamAsset : public SkStreamAsset { | |
bungeman-skia
2015/04/27 14:52:42
You may want to take a look at SkBlockMemoryStream
reed2
2015/04/28 02:25:00
Acknowledged.
| |
225 void validate() const { | |
226 #ifdef SK_DEBUG | |
227 SkASSERT(fGlobalOffset <= fBuffer->size()); | |
228 SkASSERT(fLocalOffset <= fIter.size()); | |
229 SkASSERT(fLocalOffset <= fGlobalOffset); | |
230 #endif | |
231 } | |
232 | |
233 class AutoValidate { | |
234 SkRBufferStreamAsset* fStream; | |
235 public: | |
236 AutoValidate(SkRBufferStreamAsset* stream) : fStream(stream) { stream->v alidate(); } | |
237 ~AutoValidate() { fStream->validate(); } | |
238 }; | |
239 | |
240 #ifdef SK_DEBUG | |
241 #define AUTO_VALIDATE AutoValidate av(this); | |
242 #else | |
243 #define AUTO_VALIDATE | |
244 #endif | |
245 | |
246 public: | |
247 SkRBufferStreamAsset(const SkRBuffer* buffer) : fBuffer(SkRef(buffer)), fIte r(buffer) { | |
248 fGlobalOffset = fLocalOffset = 0; | |
249 } | |
250 | |
251 virtual ~SkRBufferStreamAsset() { fBuffer->unref(); } | |
252 | |
253 size_t getLength() const override { return fBuffer->size(); } | |
254 | |
255 bool rewind() override { | |
256 AUTO_VALIDATE | |
257 fIter.reset(fBuffer); | |
258 fGlobalOffset = fLocalOffset = 0; | |
259 return true; | |
260 } | |
261 | |
262 size_t read(void* dst, size_t request) override { | |
263 AUTO_VALIDATE | |
264 size_t bytesRead = 0; | |
265 for (;;) { | |
266 size_t size = fIter.size(); | |
267 SkASSERT(fLocalOffset <= size); | |
268 size_t avail = SkTMin(size - fLocalOffset, request - bytesRead); | |
269 if (dst) { | |
270 memcpy(dst, (const char*)fIter.data() + fLocalOffset, avail); | |
271 dst = (char*)dst + avail; | |
272 } | |
273 bytesRead += avail; | |
274 fLocalOffset += avail; | |
275 SkASSERT(bytesRead <= request); | |
276 if (bytesRead == request) { | |
277 break; | |
278 } | |
279 // If we get here, we've exhausted the current iter | |
280 SkASSERT(fLocalOffset == size); | |
281 fLocalOffset = 0; | |
282 if (!fIter.next()) { | |
283 break; // ran out of data | |
284 } | |
285 } | |
286 fGlobalOffset += bytesRead; | |
287 SkASSERT(fGlobalOffset <= fBuffer->size()); | |
288 return bytesRead; | |
289 } | |
290 | |
291 bool isAtEnd() const override { | |
292 return fBuffer->size() == fGlobalOffset; | |
293 } | |
294 | |
295 SkStreamAsset* duplicate() const override { | |
296 return SkNEW_ARGS(SkRBufferStreamAsset, (fBuffer)); | |
297 } | |
298 | |
299 size_t getPosition() const { | |
300 return fGlobalOffset; | |
301 } | |
302 | |
303 bool seek(size_t position) { | |
304 AUTO_VALIDATE | |
305 if (position < fGlobalOffset) { | |
306 this->rewind(); | |
307 } | |
308 (void)this->skip(position - fGlobalOffset); | |
309 return true; | |
310 } | |
311 | |
312 bool move(long offset) { | |
313 AUTO_VALIDATE | |
314 offset += fGlobalOffset; | |
315 if (offset <= 0) { | |
316 this->rewind(); | |
317 } else { | |
318 (void)this->seek(SkToSizeT(offset)); | |
319 } | |
320 return true; | |
321 } | |
322 | |
323 SkStreamAsset* fork() const override { | |
324 SkStreamAsset* clone = this->duplicate(); | |
325 clone->seek(this->getPosition()); | |
326 return clone; | |
327 } | |
328 | |
329 | |
330 private: | |
331 const SkRBuffer* fBuffer; | |
332 SkRBuffer::Iter fIter; | |
333 size_t fLocalOffset; | |
334 size_t fGlobalOffset; | |
335 }; | |
336 | |
337 SkStreamAsset* SkRWBuffer::newStreamSnapshot() const { | |
338 SkAutoTUnref<SkRBuffer> buffer(this->newRBufferSnapshot()); | |
339 return SkNEW_ARGS(SkRBufferStreamAsset, (buffer)); | |
340 } | |
OLD | NEW |