1
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
9
10 #include "SkStream.h"
11 #include "SkData.h"
12 #include "SkFixed.h"
13 #include "SkString.h"
14 #include "SkOSFile.h"
15
16 ///////////////////////////////////////////////////////////////////////////////
17
18
readS8()19 int8_t SkStream::readS8() {
20 int8_t value;
21 SkDEBUGCODE(size_t len =) this->read(&value, 1);
22 SkASSERT(1 == len);
23 return value;
24 }
25
readS16()26 int16_t SkStream::readS16() {
27 int16_t value;
28 SkDEBUGCODE(size_t len =) this->read(&value, 2);
29 SkASSERT(2 == len);
30 return value;
31 }
32
readS32()33 int32_t SkStream::readS32() {
34 int32_t value;
35 SkDEBUGCODE(size_t len =) this->read(&value, 4);
36 SkASSERT(4 == len);
37 return value;
38 }
39
readScalar()40 SkScalar SkStream::readScalar() {
41 SkScalar value;
42 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
43 SkASSERT(sizeof(SkScalar) == len);
44 return value;
45 }
46
47 #define SK_MAX_BYTE_FOR_U8 0xFD
48 #define SK_BYTE_SENTINEL_FOR_U16 0xFE
49 #define SK_BYTE_SENTINEL_FOR_U32 0xFF
50
readPackedUInt()51 size_t SkStream::readPackedUInt() {
52 uint8_t byte;
53 if (!this->read(&byte, 1)) {
54 return 0;
55 }
56 if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
57 return this->readU16();
58 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
59 return this->readU32();
60 } else {
61 return byte;
62 }
63 }
64
readData()65 SkData* SkStream::readData() {
66 size_t size = this->readU32();
67 if (0 == size) {
68 return SkData::NewEmpty();
69 } else {
70 void* buffer = sk_malloc_throw(size);
71 this->read(buffer, size);
72 return SkData::NewFromMalloc(buffer, size);
73 }
74 }
75
76 //////////////////////////////////////////////////////////////////////////////////////
77
~SkWStream()78 SkWStream::~SkWStream()
79 {
80 }
81
newline()82 void SkWStream::newline()
83 {
84 this->write("\n", 1);
85 }
86
flush()87 void SkWStream::flush()
88 {
89 }
90
writeText(const char text[])91 bool SkWStream::writeText(const char text[])
92 {
93 SkASSERT(text);
94 return this->write(text, strlen(text));
95 }
96
writeDecAsText(int32_t dec)97 bool SkWStream::writeDecAsText(int32_t dec)
98 {
99 SkString tmp;
100 tmp.appendS32(dec);
101 return this->write(tmp.c_str(), tmp.size());
102 }
103
writeBigDecAsText(int64_t dec,int minDigits)104 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
105 {
106 SkString tmp;
107 tmp.appendS64(dec, minDigits);
108 return this->write(tmp.c_str(), tmp.size());
109 }
110
writeHexAsText(uint32_t hex,int digits)111 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
112 {
113 SkString tmp;
114 tmp.appendHex(hex, digits);
115 return this->write(tmp.c_str(), tmp.size());
116 }
117
writeScalarAsText(SkScalar value)118 bool SkWStream::writeScalarAsText(SkScalar value)
119 {
120 SkString tmp;
121 tmp.appendScalar(value);
122 return this->write(tmp.c_str(), tmp.size());
123 }
124
write8(U8CPU value)125 bool SkWStream::write8(U8CPU value) {
126 uint8_t v = SkToU8(value);
127 return this->write(&v, 1);
128 }
129
write16(U16CPU value)130 bool SkWStream::write16(U16CPU value) {
131 uint16_t v = SkToU16(value);
132 return this->write(&v, 2);
133 }
134
write32(uint32_t value)135 bool SkWStream::write32(uint32_t value) {
136 return this->write(&value, 4);
137 }
138
writeScalar(SkScalar value)139 bool SkWStream::writeScalar(SkScalar value) {
140 return this->write(&value, sizeof(value));
141 }
142
writePackedUInt(size_t value)143 bool SkWStream::writePackedUInt(size_t value) {
144 uint8_t data[5];
145 size_t len = 1;
146 if (value <= SK_MAX_BYTE_FOR_U8) {
147 data[0] = value;
148 len = 1;
149 } else if (value <= 0xFFFF) {
150 uint16_t value16 = value;
151 data[0] = SK_BYTE_SENTINEL_FOR_U16;
152 memcpy(&data[1], &value16, 2);
153 len = 3;
154 } else {
155 uint32_t value32 = value;
156 data[0] = SK_BYTE_SENTINEL_FOR_U32;
157 memcpy(&data[1], &value32, 4);
158 len = 5;
159 }
160 return this->write(data, len);
161 }
162
writeStream(SkStream * stream,size_t length)163 bool SkWStream::writeStream(SkStream* stream, size_t length) {
164 char scratch[1024];
165 const size_t MAX = sizeof(scratch);
166
167 while (length != 0) {
168 size_t n = length;
169 if (n > MAX) {
170 n = MAX;
171 }
172 stream->read(scratch, n);
173 if (!this->write(scratch, n)) {
174 return false;
175 }
176 length -= n;
177 }
178 return true;
179 }
180
writeData(const SkData * data)181 bool SkWStream::writeData(const SkData* data) {
182 if (data) {
183 this->write32(data->size());
184 this->write(data->data(), data->size());
185 } else {
186 this->write32(0);
187 }
188 return true;
189 }
190
191 ///////////////////////////////////////////////////////////////////////////////
192
SkFILEStream(const char file[])193 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
194 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
195 }
196
SkFILEStream(FILE * file,Ownership ownership)197 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
198 : fFILE((SkFILE*)file)
199 , fOwnership(ownership) {
200 }
201
~SkFILEStream()202 SkFILEStream::~SkFILEStream() {
203 if (fFILE && fOwnership != kCallerRetains_Ownership) {
204 sk_fclose(fFILE);
205 }
206 }
207
setPath(const char path[])208 void SkFILEStream::setPath(const char path[]) {
209 fName.set(path);
210 if (fFILE) {
211 sk_fclose(fFILE);
212 fFILE = NULL;
213 }
214 if (path) {
215 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
216 }
217 }
218
read(void * buffer,size_t size)219 size_t SkFILEStream::read(void* buffer, size_t size) {
220 if (fFILE) {
221 return sk_fread(buffer, size, fFILE);
222 }
223 return 0;
224 }
225
isAtEnd() const226 bool SkFILEStream::isAtEnd() const {
227 return sk_feof(fFILE);
228 }
229
rewind()230 bool SkFILEStream::rewind() {
231 if (fFILE) {
232 if (sk_frewind(fFILE)) {
233 return true;
234 }
235 // we hit an error
236 sk_fclose(fFILE);
237 fFILE = NULL;
238 }
239 return false;
240 }
241
duplicate() const242 SkStreamAsset* SkFILEStream::duplicate() const {
243 if (NULL == fFILE) {
244 return new SkMemoryStream();
245 }
246
247 if (NULL != fData.get()) {
248 return new SkMemoryStream(fData);
249 }
250
251 if (!fName.isEmpty()) {
252 SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
253 if (sk_fidentical(that->fFILE, this->fFILE)) {
254 return that.detach();
255 }
256 }
257
258 fData.reset(SkData::NewFromFILE(fFILE));
259 if (NULL == fData.get()) {
260 return NULL;
261 }
262 return new SkMemoryStream(fData);
263 }
264
getPosition() const265 size_t SkFILEStream::getPosition() const {
266 return sk_ftell(fFILE);
267 }
268
seek(size_t position)269 bool SkFILEStream::seek(size_t position) {
270 return sk_fseek(fFILE, position);
271 }
272
move(long offset)273 bool SkFILEStream::move(long offset) {
274 return sk_fmove(fFILE, offset);
275 }
276
fork() const277 SkStreamAsset* SkFILEStream::fork() const {
278 SkAutoTUnref<SkStreamAsset> that(this->duplicate());
279 that->seek(this->getPosition());
280 return that.detach();
281 }
282
getLength() const283 size_t SkFILEStream::getLength() const {
284 return sk_fgetsize(fFILE);
285 }
286
getMemoryBase()287 const void* SkFILEStream::getMemoryBase() {
288 if (NULL == fData.get()) {
289 return NULL;
290 }
291 return fData->data();
292 }
293
294 ///////////////////////////////////////////////////////////////////////////////
295
newFromParams(const void * src,size_t size,bool copyData)296 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
297 if (copyData) {
298 return SkData::NewWithCopy(src, size);
299 } else {
300 return SkData::NewWithProc(src, size, NULL, NULL);
301 }
302 }
303
SkMemoryStream()304 SkMemoryStream::SkMemoryStream() {
305 fData = SkData::NewEmpty();
306 fOffset = 0;
307 }
308
SkMemoryStream(size_t size)309 SkMemoryStream::SkMemoryStream(size_t size) {
310 fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
311 fOffset = 0;
312 }
313
SkMemoryStream(const void * src,size_t size,bool copyData)314 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
315 fData = newFromParams(src, size, copyData);
316 fOffset = 0;
317 }
318
SkMemoryStream(SkData * data)319 SkMemoryStream::SkMemoryStream(SkData* data) {
320 if (NULL == data) {
321 fData = SkData::NewEmpty();
322 } else {
323 fData = data;
324 fData->ref();
325 }
326 fOffset = 0;
327 }
328
~SkMemoryStream()329 SkMemoryStream::~SkMemoryStream() {
330 fData->unref();
331 }
332
setMemoryOwned(const void * src,size_t size)333 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
334 fData->unref();
335 fData = SkData::NewFromMalloc(src, size);
336 fOffset = 0;
337 }
338
setMemory(const void * src,size_t size,bool copyData)339 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
340 fData->unref();
341 fData = newFromParams(src, size, copyData);
342 fOffset = 0;
343 }
344
copyToData() const345 SkData* SkMemoryStream::copyToData() const {
346 fData->ref();
347 return fData;
348 }
349
setData(SkData * data)350 SkData* SkMemoryStream::setData(SkData* data) {
351 fData->unref();
352 if (NULL == data) {
353 fData = SkData::NewEmpty();
354 } else {
355 fData = data;
356 fData->ref();
357 }
358 fOffset = 0;
359 return data;
360 }
361
skipToAlign4()362 void SkMemoryStream::skipToAlign4() {
363 // cast to remove unary-minus warning
364 fOffset += -(int)fOffset & 0x03;
365 }
366
read(void * buffer,size_t size)367 size_t SkMemoryStream::read(void* buffer, size_t size) {
368 size_t dataSize = fData->size();
369
370 if (size > dataSize - fOffset) {
371 size = dataSize - fOffset;
372 }
373 if (buffer) {
374 memcpy(buffer, fData->bytes() + fOffset, size);
375 }
376 fOffset += size;
377 return size;
378 }
379
isAtEnd() const380 bool SkMemoryStream::isAtEnd() const {
381 return fOffset == fData->size();
382 }
383
rewind()384 bool SkMemoryStream::rewind() {
385 fOffset = 0;
386 return true;
387 }
388
duplicate() const389 SkMemoryStream* SkMemoryStream::duplicate() const {
390 return SkNEW_ARGS(SkMemoryStream, (fData));
391 }
392
getPosition() const393 size_t SkMemoryStream::getPosition() const {
394 return fOffset;
395 }
396
seek(size_t position)397 bool SkMemoryStream::seek(size_t position) {
398 fOffset = position > fData->size()
399 ? fData->size()
400 : position;
401 return true;
402 }
403
move(long offset)404 bool SkMemoryStream::move(long offset) {
405 return this->seek(fOffset + offset);
406 }
407
fork() const408 SkMemoryStream* SkMemoryStream::fork() const {
409 SkAutoTUnref<SkMemoryStream> that(this->duplicate());
410 that->seek(fOffset);
411 return that.detach();
412 }
413
getLength() const414 size_t SkMemoryStream::getLength() const {
415 return fData->size();
416 }
417
getMemoryBase()418 const void* SkMemoryStream::getMemoryBase() {
419 return fData->data();
420 }
421
getAtPos()422 const void* SkMemoryStream::getAtPos() {
423 return fData->bytes() + fOffset;
424 }
425
426 /////////////////////////////////////////////////////////////////////////////////////////////////////////
427 /////////////////////////////////////////////////////////////////////////////////////////////////////////
428
SkFILEWStream(const char path[])429 SkFILEWStream::SkFILEWStream(const char path[])
430 {
431 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
432 }
433
~SkFILEWStream()434 SkFILEWStream::~SkFILEWStream()
435 {
436 if (fFILE)
437 sk_fclose(fFILE);
438 }
439
write(const void * buffer,size_t size)440 bool SkFILEWStream::write(const void* buffer, size_t size)
441 {
442 if (fFILE == NULL)
443 return false;
444
445 if (sk_fwrite(buffer, size, fFILE) != size)
446 {
447 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
448 sk_fclose(fFILE);
449 fFILE = NULL;
450 return false;
451 }
452 return true;
453 }
454
flush()455 void SkFILEWStream::flush()
456 {
457 if (fFILE)
458 sk_fflush(fFILE);
459 }
460
461 ////////////////////////////////////////////////////////////////////////
462
SkMemoryWStream(void * buffer,size_t size)463 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
464 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
465 {
466 }
467
write(const void * buffer,size_t size)468 bool SkMemoryWStream::write(const void* buffer, size_t size)
469 {
470 size = SkMin32(size, fMaxLength - fBytesWritten);
471 if (size > 0)
472 {
473 memcpy(fBuffer + fBytesWritten, buffer, size);
474 fBytesWritten += size;
475 return true;
476 }
477 return false;
478 }
479
480 ////////////////////////////////////////////////////////////////////////
481
482 #define SkDynamicMemoryWStream_MinBlockSize 256
483
484 struct SkDynamicMemoryWStream::Block {
485 Block* fNext;
486 char* fCurr;
487 char* fStop;
488
startSkDynamicMemoryWStream::Block489 const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block490 char* start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block491 size_t avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block492 size_t written() const { return fCurr - this->start(); }
493
initSkDynamicMemoryWStream::Block494 void init(size_t size)
495 {
496 fNext = NULL;
497 fCurr = this->start();
498 fStop = this->start() + size;
499 }
500
appendSkDynamicMemoryWStream::Block501 const void* append(const void* data, size_t size)
502 {
503 SkASSERT((size_t)(fStop - fCurr) >= size);
504 memcpy(fCurr, data, size);
505 fCurr += size;
506 return (const void*)((const char*)data + size);
507 }
508 };
509
SkDynamicMemoryWStream()510 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
511 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
512 {
513 }
514
~SkDynamicMemoryWStream()515 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
516 {
517 reset();
518 }
519
reset()520 void SkDynamicMemoryWStream::reset()
521 {
522 this->invalidateCopy();
523
524 Block* block = fHead;
525
526 while (block != NULL) {
527 Block* next = block->fNext;
528 sk_free(block);
529 block = next;
530 }
531 fHead = fTail = NULL;
532 fBytesWritten = 0;
533 }
534
write(const void * buffer,size_t count)535 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
536 {
537 if (count > 0) {
538 this->invalidateCopy();
539
540 fBytesWritten += count;
541
542 size_t size;
543
544 if (fTail != NULL && fTail->avail() > 0) {
545 size = SkMin32(fTail->avail(), count);
546 buffer = fTail->append(buffer, size);
547 SkASSERT(count >= size);
548 count -= size;
549 if (count == 0)
550 return true;
551 }
552
553 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
554 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
555 block->init(size);
556 block->append(buffer, count);
557
558 if (fTail != NULL)
559 fTail->fNext = block;
560 else
561 fHead = fTail = block;
562 fTail = block;
563 }
564 return true;
565 }
566
write(const void * buffer,size_t offset,size_t count)567 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
568 {
569 if (offset + count > fBytesWritten) {
570 return false; // test does not partially modify
571 }
572
573 this->invalidateCopy();
574
575 Block* block = fHead;
576 while (block != NULL) {
577 size_t size = block->written();
578 if (offset < size) {
579 size_t part = offset + count > size ? size - offset : count;
580 memcpy(block->start() + offset, buffer, part);
581 if (count <= part)
582 return true;
583 count -= part;
584 buffer = (const void*) ((char* ) buffer + part);
585 }
586 offset = offset > size ? offset - size : 0;
587 block = block->fNext;
588 }
589 return false;
590 }
591
read(void * buffer,size_t offset,size_t count)592 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
593 {
594 if (offset + count > fBytesWritten)
595 return false; // test does not partially modify
596 Block* block = fHead;
597 while (block != NULL) {
598 size_t size = block->written();
599 if (offset < size) {
600 size_t part = offset + count > size ? size - offset : count;
601 memcpy(buffer, block->start() + offset, part);
602 if (count <= part)
603 return true;
604 count -= part;
605 buffer = (void*) ((char* ) buffer + part);
606 }
607 offset = offset > size ? offset - size : 0;
608 block = block->fNext;
609 }
610 return false;
611 }
612
copyTo(void * dst) const613 void SkDynamicMemoryWStream::copyTo(void* dst) const
614 {
615 if (fCopy) {
616 memcpy(dst, fCopy->data(), fBytesWritten);
617 } else {
618 Block* block = fHead;
619
620 while (block != NULL) {
621 size_t size = block->written();
622 memcpy(dst, block->start(), size);
623 dst = (void*)((char*)dst + size);
624 block = block->fNext;
625 }
626 }
627 }
628
padToAlign4()629 void SkDynamicMemoryWStream::padToAlign4()
630 {
631 // cast to remove unary-minus warning
632 int padBytes = -(int)fBytesWritten & 0x03;
633 if (padBytes == 0)
634 return;
635 int zero = 0;
636 write(&zero, padBytes);
637 }
638
copyToData() const639 SkData* SkDynamicMemoryWStream::copyToData() const {
640 if (NULL == fCopy) {
641 void* buffer = sk_malloc_throw(fBytesWritten);
642 this->copyTo(buffer);
643 fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
644 }
645 fCopy->ref();
646 return fCopy;
647 }
648
invalidateCopy()649 void SkDynamicMemoryWStream::invalidateCopy() {
650 if (fCopy) {
651 fCopy->unref();
652 fCopy = NULL;
653 }
654 }
655
656 class SkBlockMemoryRefCnt : public SkRefCnt {
657 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)658 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
659
~SkBlockMemoryRefCnt()660 virtual ~SkBlockMemoryRefCnt() {
661 SkDynamicMemoryWStream::Block* block = fHead;
662 while (block != NULL) {
663 SkDynamicMemoryWStream::Block* next = block->fNext;
664 sk_free(block);
665 block = next;
666 }
667 }
668
669 SkDynamicMemoryWStream::Block* const fHead;
670 };
671
672 class SkBlockMemoryStream : public SkStreamAsset {
673 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)674 SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
675 : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
676 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
677
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)678 SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
679 : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
680 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
681
read(void * buffer,size_t rawCount)682 virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
683 size_t count = rawCount;
684 if (fOffset + count > fSize) {
685 count = fSize - fOffset;
686 }
687 size_t bytesLeftToRead = count;
688 while (fCurrent != NULL) {
689 size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
690 size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent
691 ? bytesLeftToRead : bytesLeftInCurrent;
692 if (buffer) {
693 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
694 }
695 if (bytesLeftToRead <= bytesFromCurrent) {
696 fCurrentOffset += bytesFromCurrent;
697 fOffset += count;
698 return count;
699 }
700 bytesLeftToRead -= bytesFromCurrent;
701 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
702 fCurrent = fCurrent->fNext;
703 fCurrentOffset = 0;
704 }
705 SkASSERT(false);
706 return 0;
707 }
708
isAtEnd() const709 virtual bool isAtEnd() const SK_OVERRIDE {
710 return fOffset == fSize;
711 }
712
rewind()713 virtual bool rewind() SK_OVERRIDE {
714 fCurrent = fBlockMemory->fHead;
715 fOffset = 0;
716 fCurrentOffset = 0;
717 return true;
718 }
719
duplicate() const720 virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
721 return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
722 }
723
getPosition() const724 virtual size_t getPosition() const SK_OVERRIDE {
725 return fOffset;
726 }
727
seek(size_t position)728 virtual bool seek(size_t position) SK_OVERRIDE {
729 // If possible, skip forward.
730 if (position >= fOffset) {
731 size_t skipAmount = position - fOffset;
732 return this->skip(skipAmount) == skipAmount;
733 }
734 // If possible, move backward within the current block.
735 size_t moveBackAmount = fOffset - position;
736 if (moveBackAmount <= fCurrentOffset) {
737 fCurrentOffset -= moveBackAmount;
738 fOffset -= moveBackAmount;
739 return true;
740 }
741 // Otherwise rewind and move forward.
742 return this->rewind() && this->skip(position) == position;
743 }
744
move(long offset)745 virtual bool move(long offset) SK_OVERRIDE {
746 return seek(fOffset + offset);
747 }
748
fork() const749 virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
750 SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
751 that->fCurrent = this->fCurrent;
752 that->fOffset = this->fOffset;
753 that->fCurrentOffset = this->fCurrentOffset;
754 return that.detach();
755 }
756
getLength() const757 virtual size_t getLength() const SK_OVERRIDE {
758 return fSize;
759 }
760
getMemoryBase()761 virtual const void* getMemoryBase() SK_OVERRIDE {
762 if (NULL == fBlockMemory->fHead->fNext) {
763 return fBlockMemory->fHead->start();
764 }
765 return NULL;
766 }
767
768 private:
769 SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
770 SkDynamicMemoryWStream::Block const * fCurrent;
771 size_t const fSize;
772 size_t fOffset;
773 size_t fCurrentOffset;
774 };
775
detachAsStream()776 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
777 if (fCopy) {
778 SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
779 this->reset();
780 return stream;
781 }
782 SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
783 fHead = 0;
784 this->reset();
785 return stream;
786 }
787
788 ///////////////////////////////////////////////////////////////////////////////
789
newline()790 void SkDebugWStream::newline()
791 {
792 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
793 SkDebugf("\n");
794 #endif
795 }
796
write(const void * buffer,size_t size)797 bool SkDebugWStream::write(const void* buffer, size_t size)
798 {
799 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
800 char* s = new char[size+1];
801 memcpy(s, buffer, size);
802 s[size] = 0;
803 SkDebugf("%s", s);
804 delete[] s;
805 #endif
806 return true;
807 }
808
809 ///////////////////////////////////////////////////////////////////////////////
810 ///////////////////////////////////////////////////////////////////////////////
811
812
mmap_filename(const char path[])813 static SkData* mmap_filename(const char path[]) {
814 SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
815 if (NULL == file) {
816 return NULL;
817 }
818
819 SkData* data = SkData::NewFromFILE(file);
820 sk_fclose(file);
821 return data;
822 }
823
NewFromFile(const char path[])824 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
825 SkAutoTUnref<SkData> data(mmap_filename(path));
826 if (data.get()) {
827 return SkNEW_ARGS(SkMemoryStream, (data.get()));
828 }
829
830 // If we get here, then our attempt at using mmap failed, so try normal
831 // file access.
832 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
833 if (!stream->isValid()) {
834 stream->unref();
835 stream = NULL;
836 }
837 return stream;
838 }
839