blob: 8b712440e26a85ba4252e69edef479d296274833 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkStream.h"
reed@google.com8d0b5772011-06-24 13:07:31 +000011#include "SkData.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkFixed.h"
13#include "SkString.h"
14#include "SkOSFile.h"
15
16SkStream::~SkStream() {}
17
18const char* SkStream::getFileName()
19{
20 // override in subclass if you represent a file
21 return NULL;
22}
23
24const void* SkStream::getMemoryBase()
25{
26 // override in subclass if you represent a memory block
27 return NULL;
28}
29
30size_t SkStream::skip(size_t size)
31{
32 /* Check for size == 0, and just return 0. If we passed that
33 to read(), it would interpret it as a request for the entire
34 size of the stream.
35 */
36 return size ? this->read(NULL, size) : 0;
37}
38
39int8_t SkStream::readS8() {
40 int8_t value;
reed@android.com04225dc2009-03-20 04:59:37 +000041 SkDEBUGCODE(size_t len =) this->read(&value, 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 SkASSERT(1 == len);
43 return value;
44}
45
46int16_t SkStream::readS16() {
47 int16_t value;
reed@android.com04225dc2009-03-20 04:59:37 +000048 SkDEBUGCODE(size_t len =) this->read(&value, 2);
reed@android.com8a1c16f2008-12-17 15:59:43 +000049 SkASSERT(2 == len);
50 return value;
51}
52
53int32_t SkStream::readS32() {
54 int32_t value;
reed@android.com04225dc2009-03-20 04:59:37 +000055 SkDEBUGCODE(size_t len =) this->read(&value, 4);
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 SkASSERT(4 == len);
57 return value;
58}
59
60SkScalar SkStream::readScalar() {
61 SkScalar value;
reed@android.com04225dc2009-03-20 04:59:37 +000062 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 SkASSERT(sizeof(SkScalar) == len);
64 return value;
65}
66
reed@google.com19f286b2011-10-18 11:49:52 +000067#define SK_MAX_BYTE_FOR_U8 0xFD
68#define SK_BYTE_SENTINEL_FOR_U16 0xFE
69#define SK_BYTE_SENTINEL_FOR_U32 0xFF
70
reed@android.com8a1c16f2008-12-17 15:59:43 +000071size_t SkStream::readPackedUInt() {
72 uint8_t byte;
73 if (!this->read(&byte, 1)) {
74 return 0;
75 }
reed@google.com19f286b2011-10-18 11:49:52 +000076 if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
77 return this->readU16();
78 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
79 return this->readU32();
80 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 return byte;
82 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000083}
84
85//////////////////////////////////////////////////////////////////////////////////////
86
87SkWStream::~SkWStream()
88{
89}
90
91void SkWStream::newline()
92{
93 this->write("\n", 1);
94}
95
96void SkWStream::flush()
97{
98}
99
100bool SkWStream::writeText(const char text[])
101{
102 SkASSERT(text);
103 return this->write(text, strlen(text));
104}
105
106bool SkWStream::writeDecAsText(int32_t dec)
107{
108 SkString tmp;
109 tmp.appendS32(dec);
110 return this->write(tmp.c_str(), tmp.size());
111}
112
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000113bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
114{
115 SkString tmp;
116 tmp.appendS64(dec, minDigits);
117 return this->write(tmp.c_str(), tmp.size());
118}
119
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120bool SkWStream::writeHexAsText(uint32_t hex, int digits)
121{
122 SkString tmp;
123 tmp.appendHex(hex, digits);
124 return this->write(tmp.c_str(), tmp.size());
125}
126
127bool SkWStream::writeScalarAsText(SkScalar value)
128{
129 SkString tmp;
130 tmp.appendScalar(value);
131 return this->write(tmp.c_str(), tmp.size());
132}
133
134bool SkWStream::write8(U8CPU value) {
135 uint8_t v = SkToU8(value);
136 return this->write(&v, 1);
137}
138
139bool SkWStream::write16(U16CPU value) {
140 uint16_t v = SkToU16(value);
141 return this->write(&v, 2);
142}
143
144bool SkWStream::write32(uint32_t value) {
145 return this->write(&value, 4);
146}
147
148bool SkWStream::writeScalar(SkScalar value) {
149 return this->write(&value, sizeof(value));
150}
151
152bool SkWStream::writePackedUInt(size_t value) {
reed@google.com19f286b2011-10-18 11:49:52 +0000153 uint8_t data[5];
154 size_t len = 1;
155 if (value <= SK_MAX_BYTE_FOR_U8) {
156 data[0] = value;
157 len = 1;
158 } else if (value <= 0xFFFF) {
159 uint16_t value16 = value;
160 data[0] = SK_BYTE_SENTINEL_FOR_U16;
161 memcpy(&data[1], &value16, 2);
162 len = 3;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 } else {
reed@google.com19f286b2011-10-18 11:49:52 +0000164 uint32_t value32 = value;
165 data[0] = SK_BYTE_SENTINEL_FOR_U32;
166 memcpy(&data[1], &value32, 4);
167 len = 5;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 }
reed@google.com19f286b2011-10-18 11:49:52 +0000169 return this->write(data, len);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170}
171
172bool SkWStream::writeStream(SkStream* stream, size_t length) {
173 char scratch[1024];
174 const size_t MAX = sizeof(scratch);
175
176 while (length != 0) {
177 size_t n = length;
178 if (n > MAX) {
179 n = MAX;
180 }
181 stream->read(scratch, n);
182 if (!this->write(scratch, n)) {
183 return false;
184 }
185 length -= n;
186 }
187 return true;
188}
189
reed@google.com8a85d0c2011-06-24 19:12:12 +0000190bool SkWStream::writeData(const SkData* data) {
191 if (data) {
192 this->write(data->data(), data->size());
193 }
194 return true;
195}
196
197///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
199SkFILEStream::SkFILEStream(const char file[]) : fName(file)
200{
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
202}
203
204SkFILEStream::~SkFILEStream()
205{
206 if (fFILE)
207 sk_fclose(fFILE);
208}
209
210void SkFILEStream::setPath(const char path[])
211{
212 fName.set(path);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 if (fFILE)
214 {
215 sk_fclose(fFILE);
216 fFILE = NULL;
217 }
218 if (path)
219 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
220}
221
222const char* SkFILEStream::getFileName()
223{
224 return fName.c_str();
225}
226
227bool SkFILEStream::rewind()
228{
229 if (fFILE)
230 {
231 if (sk_frewind(fFILE))
232 return true;
233 // we hit an error
234 sk_fclose(fFILE);
235 fFILE = NULL;
236 }
237 return false;
238}
239
240size_t SkFILEStream::read(void* buffer, size_t size)
241{
242 if (fFILE)
243 {
244 if (buffer == NULL && size == 0) // special signature, they want the total size
245 return sk_fgetsize(fFILE);
246 else
247 return sk_fread(buffer, size, fFILE);
248 }
249 return 0;
250}
251
reed@google.com8a85d0c2011-06-24 19:12:12 +0000252///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253
reed@google.com67d0cff2011-06-24 20:06:36 +0000254static SkData* newFromParams(const void* src, size_t size, bool copyData) {
255 if (copyData) {
256 return SkData::NewWithCopy(src, size);
257 } else {
258 return SkData::NewWithProc(src, size, NULL, NULL);
259 }
260}
261
reed@google.com8a85d0c2011-06-24 19:12:12 +0000262SkMemoryStream::SkMemoryStream() {
263 fData = SkData::NewEmpty();
264 fOffset = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265}
266
267SkMemoryStream::SkMemoryStream(size_t size) {
reed@google.com8a85d0c2011-06-24 19:12:12 +0000268 fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269 fOffset = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270}
271
reed@google.com8a85d0c2011-06-24 19:12:12 +0000272SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
reed@google.com67d0cff2011-06-24 20:06:36 +0000273 fData = newFromParams(src, size, copyData);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000274 fOffset = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275}
276
reed@google.com8a85d0c2011-06-24 19:12:12 +0000277SkMemoryStream::~SkMemoryStream() {
278 fData->unref();
279}
280
281void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
282 fData->unref();
283 fData = SkData::NewFromMalloc(src, size);
284 fOffset = 0;
285}
286
287void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
288 fData->unref();
reed@google.com67d0cff2011-06-24 20:06:36 +0000289 fData = newFromParams(src, size, copyData);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000290 fOffset = 0;
291}
292
293SkData* SkMemoryStream::copyToData() const {
294 fData->ref();
295 return fData;
296}
297
298SkData* SkMemoryStream::setData(SkData* data) {
299 SkRefCnt_SafeAssign(fData, data);
300 return data;
301}
302
303void SkMemoryStream::skipToAlign4() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 // cast to remove unary-minus warning
305 fOffset += -(int)fOffset & 0x03;
306}
307
reed@google.com8a85d0c2011-06-24 19:12:12 +0000308bool SkMemoryStream::rewind() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 fOffset = 0;
310 return true;
311}
312
reed@google.com8a85d0c2011-06-24 19:12:12 +0000313size_t SkMemoryStream::read(void* buffer, size_t size) {
314 size_t dataSize = fData->size();
315
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316 if (buffer == NULL && size == 0) // special signature, they want the total size
reed@google.com8a85d0c2011-06-24 19:12:12 +0000317 return dataSize;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318
319 // if buffer is NULL, seek ahead by size
320
reed@google.com8a85d0c2011-06-24 19:12:12 +0000321 if (size == 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 return 0;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000323 }
324 if (size > dataSize - fOffset) {
325 size = dataSize - fOffset;
326 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327 if (buffer) {
reed@google.com8a85d0c2011-06-24 19:12:12 +0000328 memcpy(buffer, fData->bytes() + fOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000329 }
330 fOffset += size;
331 return size;
332}
333
reed@google.com8a85d0c2011-06-24 19:12:12 +0000334const void* SkMemoryStream::getMemoryBase() {
335 return fData->data();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336}
337
reed@google.com8a85d0c2011-06-24 19:12:12 +0000338const void* SkMemoryStream::getAtPos() {
339 return fData->bytes() + fOffset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340}
341
reed@google.com8a85d0c2011-06-24 19:12:12 +0000342size_t SkMemoryStream::seek(size_t offset) {
343 if (offset > fData->size()) {
344 offset = fData->size();
345 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 fOffset = offset;
347 return offset;
348}
349
reed@google.com8a85d0c2011-06-24 19:12:12 +0000350///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000351
352SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
353 : fProxy(proxy)
354{
355 SkASSERT(proxy != NULL);
356 proxy->ref();
357 this->init(NULL, bufferSize);
358}
359
360SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
361 : fProxy(proxy)
362{
363 SkASSERT(proxy != NULL);
364 SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no sense, we must know how big their buffer is
365 proxy->ref();
366 this->init(buffer, bufferSize);
367}
368
369void SkBufferStream::init(void* buffer, size_t bufferSize)
370{
371 if (bufferSize == 0)
372 bufferSize = kDefaultBufferSize;
373
374 fOrigBufferSize = bufferSize;
375 fBufferSize = bufferSize;
376 fBufferOffset = bufferSize; // to trigger a reload on the first read()
377
378 if (buffer == NULL)
379 {
380 fBuffer = (char*)sk_malloc_throw(fBufferSize);
381 fWeOwnTheBuffer = true;
382 }
383 else
384 {
385 fBuffer = (char*)buffer;
386 fWeOwnTheBuffer = false;
387 }
388}
389
390SkBufferStream::~SkBufferStream()
391{
392 fProxy->unref();
393 if (fWeOwnTheBuffer)
394 sk_free(fBuffer);
395}
396
397bool SkBufferStream::rewind()
398{
399 fBufferOffset = fBufferSize = fOrigBufferSize;
400 return fProxy->rewind();
401}
402
403const char* SkBufferStream::getFileName()
404{
405 return fProxy->getFileName();
406}
407
408#ifdef SK_DEBUG
409// #define SK_TRACE_BUFFERSTREAM
410#endif
411
412size_t SkBufferStream::read(void* buffer, size_t size) {
413#ifdef SK_TRACE_BUFFERSTREAM
414 SkDebugf("Request %d", size);
415#endif
416
417 if (buffer == NULL && size == 0) {
418 return fProxy->read(buffer, size); // requesting total size
419 }
420
421 if (0 == size) {
422 return 0;
423 }
424
425 // skip size bytes
426 if (NULL == buffer) {
427 size_t remaining = fBufferSize - fBufferOffset;
428 if (remaining >= size) {
429 fBufferOffset += size;
430 return size;
431 }
432 // if we get here, we are being asked to skip beyond our current buffer
433 // so reset our offset to force a read next time, and skip the diff
434 // in our proxy
435 fBufferOffset = fOrigBufferSize;
436 return remaining + fProxy->read(NULL, size - remaining);
437 }
438
439 size_t s = size;
440 size_t actuallyRead = 0;
441
442 // flush what we can from our fBuffer
443 if (fBufferOffset < fBufferSize)
444 {
445 if (s > fBufferSize - fBufferOffset)
446 s = fBufferSize - fBufferOffset;
447 memcpy(buffer, fBuffer + fBufferOffset, s);
448#ifdef SK_TRACE_BUFFERSTREAM
449 SkDebugf(" flush %d", s);
450#endif
451 size -= s;
452 fBufferOffset += s;
453 buffer = (char*)buffer + s;
454 actuallyRead = s;
455 }
456
457 // check if there is more to read
458 if (size)
459 {
460 SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
461
462 if (size < fBufferSize) // lets try to read more than the request
463 {
464 s = fProxy->read(fBuffer, fBufferSize);
465#ifdef SK_TRACE_BUFFERSTREAM
466 SkDebugf(" read %d into fBuffer", s);
467#endif
468 if (size > s) // they asked for too much
469 size = s;
470 if (size)
471 {
472 memcpy(buffer, fBuffer, size);
473 actuallyRead += size;
474#ifdef SK_TRACE_BUFFERSTREAM
475 SkDebugf(" memcpy %d into dst", size);
476#endif
477 }
478
479 fBufferOffset = size;
480 fBufferSize = s; // record the (possibly smaller) size for the buffer
481 }
482 else // just do a direct read
483 {
484 actuallyRead += fProxy->read(buffer, size);
485#ifdef SK_TRACE_BUFFERSTREAM
486 SkDebugf(" direct read %d", size);
487#endif
488 }
489 }
490#ifdef SK_TRACE_BUFFERSTREAM
491 SkDebugf("\n");
492#endif
493 return actuallyRead;
494}
495
496const void* SkBufferStream::getMemoryBase()
497{
498 return fProxy->getMemoryBase();
499}
500
501/////////////////////////////////////////////////////////////////////////////////////////////////////////
502/////////////////////////////////////////////////////////////////////////////////////////////////////////
503
504SkFILEWStream::SkFILEWStream(const char path[])
505{
506 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
507}
508
509SkFILEWStream::~SkFILEWStream()
510{
511 if (fFILE)
512 sk_fclose(fFILE);
513}
514
515bool SkFILEWStream::write(const void* buffer, size_t size)
516{
517 if (fFILE == NULL)
518 return false;
519
520 if (sk_fwrite(buffer, size, fFILE) != size)
521 {
522 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
523 sk_fclose(fFILE);
524 fFILE = NULL;
525 return false;
526 }
527 return true;
528}
529
530void SkFILEWStream::flush()
531{
532 if (fFILE)
533 sk_fflush(fFILE);
534}
535
536////////////////////////////////////////////////////////////////////////
537
538SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
539 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
540{
541}
542
543bool SkMemoryWStream::write(const void* buffer, size_t size)
544{
545 size = SkMin32(size, fMaxLength - fBytesWritten);
546 if (size > 0)
547 {
548 memcpy(fBuffer + fBytesWritten, buffer, size);
549 fBytesWritten += size;
550 return true;
551 }
552 return false;
553}
554
555////////////////////////////////////////////////////////////////////////
556
557#define SkDynamicMemoryWStream_MinBlockSize 256
558
559struct SkDynamicMemoryWStream::Block {
560 Block* fNext;
561 char* fCurr;
562 char* fStop;
563
564 const char* start() const { return (const char*)(this + 1); }
565 char* start() { return (char*)(this + 1); }
566 size_t avail() const { return fStop - fCurr; }
567 size_t written() const { return fCurr - this->start(); }
568
569 void init(size_t size)
570 {
571 fNext = NULL;
572 fCurr = this->start();
573 fStop = this->start() + size;
574 }
575
576 const void* append(const void* data, size_t size)
577 {
578 SkASSERT((size_t)(fStop - fCurr) >= size);
579 memcpy(fCurr, data, size);
580 fCurr += size;
581 return (const void*)((const char*)data + size);
582 }
583};
584
reed@google.com8a85d0c2011-06-24 19:12:12 +0000585SkDynamicMemoryWStream::SkDynamicMemoryWStream()
586 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587{
588}
589
590SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
591{
592 reset();
593}
594
reed@android.com8a1c16f2008-12-17 15:59:43 +0000595void SkDynamicMemoryWStream::reset()
596{
reed@google.com8a85d0c2011-06-24 19:12:12 +0000597 this->invalidateCopy();
598
reed@android.com8a1c16f2008-12-17 15:59:43 +0000599 Block* block = fHead;
600
601 while (block != NULL) {
602 Block* next = block->fNext;
603 sk_free(block);
604 block = next;
605 }
606 fHead = fTail = NULL;
607 fBytesWritten = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000608}
609
610bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
611{
612 if (count > 0) {
reed@google.com8a85d0c2011-06-24 19:12:12 +0000613 this->invalidateCopy();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000614
reed@android.com8a1c16f2008-12-17 15:59:43 +0000615 fBytesWritten += count;
616
617 size_t size;
618
619 if (fTail != NULL && fTail->avail() > 0) {
620 size = SkMin32(fTail->avail(), count);
621 buffer = fTail->append(buffer, size);
622 SkASSERT(count >= size);
623 count -= size;
624 if (count == 0)
625 return true;
626 }
627
628 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
629 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
630 block->init(size);
631 block->append(buffer, count);
632
633 if (fTail != NULL)
634 fTail->fNext = block;
635 else
636 fHead = fTail = block;
637 fTail = block;
638 }
639 return true;
640}
641
642bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
643{
reed@google.com8a85d0c2011-06-24 19:12:12 +0000644 if (offset + count > fBytesWritten) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645 return false; // test does not partially modify
reed@google.com8a85d0c2011-06-24 19:12:12 +0000646 }
647
648 this->invalidateCopy();
649
reed@android.com8a1c16f2008-12-17 15:59:43 +0000650 Block* block = fHead;
651 while (block != NULL) {
652 size_t size = block->written();
653 if (offset < size) {
654 size_t part = offset + count > size ? size - offset : count;
655 memcpy(block->start() + offset, buffer, part);
656 if (count <= part)
657 return true;
658 count -= part;
659 buffer = (const void*) ((char* ) buffer + part);
660 }
661 offset = offset > size ? offset - size : 0;
662 block = block->fNext;
663 }
664 return false;
665}
666
667bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
668{
669 if (offset + count > fBytesWritten)
670 return false; // test does not partially modify
671 Block* block = fHead;
672 while (block != NULL) {
673 size_t size = block->written();
674 if (offset < size) {
675 size_t part = offset + count > size ? size - offset : count;
676 memcpy(buffer, block->start() + offset, part);
677 if (count <= part)
678 return true;
679 count -= part;
680 buffer = (void*) ((char* ) buffer + part);
681 }
682 offset = offset > size ? offset - size : 0;
683 block = block->fNext;
684 }
685 return false;
686}
687
688void SkDynamicMemoryWStream::copyTo(void* dst) const
689{
reed@google.com8a85d0c2011-06-24 19:12:12 +0000690 if (fCopy) {
691 memcpy(dst, fCopy->data(), fBytesWritten);
692 } else {
693 Block* block = fHead;
694
695 while (block != NULL) {
696 size_t size = block->written();
697 memcpy(dst, block->start(), size);
698 dst = (void*)((char*)dst + size);
699 block = block->fNext;
700 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000701 }
702}
703
reed@android.com8a1c16f2008-12-17 15:59:43 +0000704void SkDynamicMemoryWStream::padToAlign4()
705{
706 // cast to remove unary-minus warning
707 int padBytes = -(int)fBytesWritten & 0x03;
708 if (padBytes == 0)
709 return;
710 int zero = 0;
711 write(&zero, padBytes);
712}
713
reed@google.com8d0b5772011-06-24 13:07:31 +0000714SkData* SkDynamicMemoryWStream::copyToData() const {
reed@google.com8a85d0c2011-06-24 19:12:12 +0000715 if (NULL == fCopy) {
716 void* buffer = sk_malloc_throw(fBytesWritten);
717 this->copyTo(buffer);
718 fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
719 }
720 fCopy->ref();
721 return fCopy;
reed@google.com70442a62011-06-23 21:48:04 +0000722}
723
reed@google.com8a85d0c2011-06-24 19:12:12 +0000724void SkDynamicMemoryWStream::invalidateCopy() {
725 if (fCopy) {
726 fCopy->unref();
727 fCopy = NULL;
728 }
729}
730
731///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000732
733void SkDebugWStream::newline()
734{
735#ifdef SK_DEBUG
736 SkDebugf("\n");
737#endif
738}
739
740bool SkDebugWStream::write(const void* buffer, size_t size)
741{
742#ifdef SK_DEBUG
743 char* s = new char[size+1];
744 memcpy(s, buffer, size);
745 s[size] = 0;
746 SkDebugf("%s", s);
747 delete[] s;
748#endif
749 return true;
750}