• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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