• 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 
SizeOfPackedUInt(size_t value)143 int SkWStream::SizeOfPackedUInt(size_t value) {
144     if (value <= SK_MAX_BYTE_FOR_U8) {
145         return 1;
146     } else if (value <= 0xFFFF) {
147         return 3;
148     }
149     return 5;
150 }
151 
writePackedUInt(size_t value)152 bool SkWStream::writePackedUInt(size_t value) {
153     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;
163     } else {
164         uint32_t value32 = SkToU32(value);
165         data[0] = SK_BYTE_SENTINEL_FOR_U32;
166         memcpy(&data[1], &value32, 4);
167         len = 5;
168     }
169     return this->write(data, len);
170 }
171 
writeStream(SkStream * stream,size_t length)172 bool 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 
writeData(const SkData * data)190 bool SkWStream::writeData(const SkData* data) {
191     if (data) {
192         this->write32(SkToU32(data->size()));
193         this->write(data->data(), data->size());
194     } else {
195         this->write32(0);
196     }
197     return true;
198 }
199 
200 ///////////////////////////////////////////////////////////////////////////////
201 
SkFILEStream(const char file[])202 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
203     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
204 }
205 
SkFILEStream(FILE * file,Ownership ownership)206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
207     : fFILE((SkFILE*)file)
208     , fOwnership(ownership) {
209 }
210 
~SkFILEStream()211 SkFILEStream::~SkFILEStream() {
212     if (fFILE && fOwnership != kCallerRetains_Ownership) {
213         sk_fclose(fFILE);
214     }
215 }
216 
setPath(const char path[])217 void SkFILEStream::setPath(const char path[]) {
218     fName.set(path);
219     if (fFILE) {
220         sk_fclose(fFILE);
221         fFILE = NULL;
222     }
223     if (path) {
224         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
225     }
226 }
227 
read(void * buffer,size_t size)228 size_t SkFILEStream::read(void* buffer, size_t size) {
229     if (fFILE) {
230         return sk_fread(buffer, size, fFILE);
231     }
232     return 0;
233 }
234 
isAtEnd() const235 bool SkFILEStream::isAtEnd() const {
236     return sk_feof(fFILE);
237 }
238 
rewind()239 bool SkFILEStream::rewind() {
240     if (fFILE) {
241         if (sk_frewind(fFILE)) {
242             return true;
243         }
244         // we hit an error
245         sk_fclose(fFILE);
246         fFILE = NULL;
247     }
248     return false;
249 }
250 
duplicate() const251 SkStreamAsset* SkFILEStream::duplicate() const {
252     if (NULL == fFILE) {
253         return new SkMemoryStream();
254     }
255 
256     if (NULL != fData.get()) {
257         return new SkMemoryStream(fData);
258     }
259 
260     if (!fName.isEmpty()) {
261         SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
262         if (sk_fidentical(that->fFILE, this->fFILE)) {
263             return that.detach();
264         }
265     }
266 
267     fData.reset(SkData::NewFromFILE(fFILE));
268     if (NULL == fData.get()) {
269         return NULL;
270     }
271     return new SkMemoryStream(fData);
272 }
273 
getPosition() const274 size_t SkFILEStream::getPosition() const {
275     return sk_ftell(fFILE);
276 }
277 
seek(size_t position)278 bool SkFILEStream::seek(size_t position) {
279     return sk_fseek(fFILE, position);
280 }
281 
move(long offset)282 bool SkFILEStream::move(long offset) {
283     return sk_fmove(fFILE, offset);
284 }
285 
fork() const286 SkStreamAsset* SkFILEStream::fork() const {
287     SkAutoTUnref<SkStreamAsset> that(this->duplicate());
288     that->seek(this->getPosition());
289     return that.detach();
290 }
291 
getLength() const292 size_t SkFILEStream::getLength() const {
293     return sk_fgetsize(fFILE);
294 }
295 
getMemoryBase()296 const void* SkFILEStream::getMemoryBase() {
297     if (NULL == fData.get()) {
298         return NULL;
299     }
300     return fData->data();
301 }
302 
303 ///////////////////////////////////////////////////////////////////////////////
304 
newFromParams(const void * src,size_t size,bool copyData)305 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
306     if (copyData) {
307         return SkData::NewWithCopy(src, size);
308     } else {
309         return SkData::NewWithProc(src, size, NULL, NULL);
310     }
311 }
312 
SkMemoryStream()313 SkMemoryStream::SkMemoryStream() {
314     fData = SkData::NewEmpty();
315     fOffset = 0;
316 }
317 
SkMemoryStream(size_t size)318 SkMemoryStream::SkMemoryStream(size_t size) {
319     fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
320     fOffset = 0;
321 }
322 
SkMemoryStream(const void * src,size_t size,bool copyData)323 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
324     fData = newFromParams(src, size, copyData);
325     fOffset = 0;
326 }
327 
SkMemoryStream(SkData * data)328 SkMemoryStream::SkMemoryStream(SkData* data) {
329     if (NULL == data) {
330         fData = SkData::NewEmpty();
331     } else {
332         fData = data;
333         fData->ref();
334     }
335     fOffset = 0;
336 }
337 
~SkMemoryStream()338 SkMemoryStream::~SkMemoryStream() {
339     fData->unref();
340 }
341 
setMemoryOwned(const void * src,size_t size)342 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
343     fData->unref();
344     fData = SkData::NewFromMalloc(src, size);
345     fOffset = 0;
346 }
347 
setMemory(const void * src,size_t size,bool copyData)348 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
349     fData->unref();
350     fData = newFromParams(src, size, copyData);
351     fOffset = 0;
352 }
353 
copyToData() const354 SkData* SkMemoryStream::copyToData() const {
355     fData->ref();
356     return fData;
357 }
358 
setData(SkData * data)359 SkData* SkMemoryStream::setData(SkData* data) {
360     fData->unref();
361     if (NULL == data) {
362         fData = SkData::NewEmpty();
363     } else {
364         fData = data;
365         fData->ref();
366     }
367     fOffset = 0;
368     return data;
369 }
370 
skipToAlign4()371 void SkMemoryStream::skipToAlign4() {
372     // cast to remove unary-minus warning
373     fOffset += -(int)fOffset & 0x03;
374 }
375 
read(void * buffer,size_t size)376 size_t SkMemoryStream::read(void* buffer, size_t size) {
377     size_t dataSize = fData->size();
378 
379     if (size > dataSize - fOffset) {
380         size = dataSize - fOffset;
381     }
382     if (buffer) {
383         memcpy(buffer, fData->bytes() + fOffset, size);
384     }
385     fOffset += size;
386     return size;
387 }
388 
isAtEnd() const389 bool SkMemoryStream::isAtEnd() const {
390     return fOffset == fData->size();
391 }
392 
rewind()393 bool SkMemoryStream::rewind() {
394     fOffset = 0;
395     return true;
396 }
397 
duplicate() const398 SkMemoryStream* SkMemoryStream::duplicate() const {
399     return SkNEW_ARGS(SkMemoryStream, (fData));
400 }
401 
getPosition() const402 size_t SkMemoryStream::getPosition() const {
403     return fOffset;
404 }
405 
seek(size_t position)406 bool SkMemoryStream::seek(size_t position) {
407     fOffset = position > fData->size()
408             ? fData->size()
409             : position;
410     return true;
411 }
412 
move(long offset)413 bool SkMemoryStream::move(long offset) {
414     return this->seek(fOffset + offset);
415 }
416 
fork() const417 SkMemoryStream* SkMemoryStream::fork() const {
418     SkAutoTUnref<SkMemoryStream> that(this->duplicate());
419     that->seek(fOffset);
420     return that.detach();
421 }
422 
getLength() const423 size_t SkMemoryStream::getLength() const {
424     return fData->size();
425 }
426 
getMemoryBase()427 const void* SkMemoryStream::getMemoryBase() {
428     return fData->data();
429 }
430 
getAtPos()431 const void* SkMemoryStream::getAtPos() {
432     return fData->bytes() + fOffset;
433 }
434 
435 /////////////////////////////////////////////////////////////////////////////////////////////////////////
436 /////////////////////////////////////////////////////////////////////////////////////////////////////////
437 
SkFILEWStream(const char path[])438 SkFILEWStream::SkFILEWStream(const char path[])
439 {
440     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
441 }
442 
~SkFILEWStream()443 SkFILEWStream::~SkFILEWStream()
444 {
445     if (fFILE) {
446         sk_fclose(fFILE);
447     }
448 }
449 
bytesWritten() const450 size_t SkFILEWStream::bytesWritten() const {
451     return sk_ftell(fFILE);
452 }
453 
write(const void * buffer,size_t size)454 bool SkFILEWStream::write(const void* buffer, size_t size)
455 {
456     if (fFILE == NULL) {
457         return false;
458     }
459 
460     if (sk_fwrite(buffer, size, fFILE) != size)
461     {
462         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
463         sk_fclose(fFILE);
464         fFILE = NULL;
465         return false;
466     }
467     return true;
468 }
469 
flush()470 void SkFILEWStream::flush()
471 {
472     if (fFILE) {
473         sk_fflush(fFILE);
474     }
475 }
476 
477 ////////////////////////////////////////////////////////////////////////
478 
SkMemoryWStream(void * buffer,size_t size)479 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
480     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
481 {
482 }
483 
write(const void * buffer,size_t size)484 bool SkMemoryWStream::write(const void* buffer, size_t size) {
485     size = SkTMin(size, fMaxLength - fBytesWritten);
486     if (size > 0) {
487         memcpy(fBuffer + fBytesWritten, buffer, size);
488         fBytesWritten += size;
489         return true;
490     }
491     return false;
492 }
493 
494 ////////////////////////////////////////////////////////////////////////
495 
496 #define SkDynamicMemoryWStream_MinBlockSize   256
497 
498 struct SkDynamicMemoryWStream::Block {
499     Block*  fNext;
500     char*   fCurr;
501     char*   fStop;
502 
startSkDynamicMemoryWStream::Block503     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block504     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block505     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block506     size_t  written() const { return fCurr - this->start(); }
507 
initSkDynamicMemoryWStream::Block508     void init(size_t size)
509     {
510         fNext = NULL;
511         fCurr = this->start();
512         fStop = this->start() + size;
513     }
514 
appendSkDynamicMemoryWStream::Block515     const void* append(const void* data, size_t size)
516     {
517         SkASSERT((size_t)(fStop - fCurr) >= size);
518         memcpy(fCurr, data, size);
519         fCurr += size;
520         return (const void*)((const char*)data + size);
521     }
522 };
523 
SkDynamicMemoryWStream()524 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
525     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
526 {
527 }
528 
~SkDynamicMemoryWStream()529 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
530 {
531     reset();
532 }
533 
reset()534 void SkDynamicMemoryWStream::reset()
535 {
536     this->invalidateCopy();
537 
538     Block*  block = fHead;
539 
540     while (block != NULL) {
541         Block*  next = block->fNext;
542         sk_free(block);
543         block = next;
544     }
545     fHead = fTail = NULL;
546     fBytesWritten = 0;
547 }
548 
write(const void * buffer,size_t count)549 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
550 {
551     if (count > 0) {
552         this->invalidateCopy();
553 
554         fBytesWritten += count;
555 
556         size_t  size;
557 
558         if (fTail != NULL && fTail->avail() > 0) {
559             size = SkTMin(fTail->avail(), count);
560             buffer = fTail->append(buffer, size);
561             SkASSERT(count >= size);
562             count -= size;
563             if (count == 0)
564                 return true;
565         }
566 
567         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
568         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
569         block->init(size);
570         block->append(buffer, count);
571 
572         if (fTail != NULL)
573             fTail->fNext = block;
574         else
575             fHead = fTail = block;
576         fTail = block;
577     }
578     return true;
579 }
580 
write(const void * buffer,size_t offset,size_t count)581 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
582 {
583     if (offset + count > fBytesWritten) {
584         return false; // test does not partially modify
585     }
586 
587     this->invalidateCopy();
588 
589     Block* block = fHead;
590     while (block != NULL) {
591         size_t size = block->written();
592         if (offset < size) {
593             size_t part = offset + count > size ? size - offset : count;
594             memcpy(block->start() + offset, buffer, part);
595             if (count <= part)
596                 return true;
597             count -= part;
598             buffer = (const void*) ((char* ) buffer + part);
599         }
600         offset = offset > size ? offset - size : 0;
601         block = block->fNext;
602     }
603     return false;
604 }
605 
read(void * buffer,size_t offset,size_t count)606 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
607 {
608     if (offset + count > fBytesWritten)
609         return false; // test does not partially modify
610     Block* block = fHead;
611     while (block != NULL) {
612         size_t size = block->written();
613         if (offset < size) {
614             size_t part = offset + count > size ? size - offset : count;
615             memcpy(buffer, block->start() + offset, part);
616             if (count <= part)
617                 return true;
618             count -= part;
619             buffer = (void*) ((char* ) buffer + part);
620         }
621         offset = offset > size ? offset - size : 0;
622         block = block->fNext;
623     }
624     return false;
625 }
626 
copyTo(void * dst) const627 void SkDynamicMemoryWStream::copyTo(void* dst) const
628 {
629     if (fCopy) {
630         memcpy(dst, fCopy->data(), fBytesWritten);
631     } else {
632         Block* block = fHead;
633 
634         while (block != NULL) {
635             size_t size = block->written();
636             memcpy(dst, block->start(), size);
637             dst = (void*)((char*)dst + size);
638             block = block->fNext;
639         }
640     }
641 }
642 
padToAlign4()643 void SkDynamicMemoryWStream::padToAlign4()
644 {
645     // cast to remove unary-minus warning
646     int padBytes = -(int)fBytesWritten & 0x03;
647     if (padBytes == 0)
648         return;
649     int zero = 0;
650     write(&zero, padBytes);
651 }
652 
copyToData() const653 SkData* SkDynamicMemoryWStream::copyToData() const {
654     if (NULL == fCopy) {
655         void* buffer = sk_malloc_throw(fBytesWritten);
656         this->copyTo(buffer);
657         fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
658     }
659     fCopy->ref();
660     return fCopy;
661 }
662 
invalidateCopy()663 void SkDynamicMemoryWStream::invalidateCopy() {
664     if (fCopy) {
665         fCopy->unref();
666         fCopy = NULL;
667     }
668 }
669 
670 class SkBlockMemoryRefCnt : public SkRefCnt {
671 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)672     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
673 
~SkBlockMemoryRefCnt()674     virtual ~SkBlockMemoryRefCnt() {
675         SkDynamicMemoryWStream::Block* block = fHead;
676         while (block != NULL) {
677             SkDynamicMemoryWStream::Block* next = block->fNext;
678             sk_free(block);
679             block = next;
680         }
681     }
682 
683     SkDynamicMemoryWStream::Block* const fHead;
684 };
685 
686 class SkBlockMemoryStream : public SkStreamAsset {
687 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)688     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
689         : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
690         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
691 
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)692     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
693         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
694         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
695 
read(void * buffer,size_t rawCount)696     virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
697         size_t count = rawCount;
698         if (fOffset + count > fSize) {
699             count = fSize - fOffset;
700         }
701         size_t bytesLeftToRead = count;
702         while (fCurrent != NULL) {
703             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
704             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
705             if (buffer) {
706                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
707                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
708             }
709             if (bytesLeftToRead <= bytesFromCurrent) {
710                 fCurrentOffset += bytesFromCurrent;
711                 fOffset += count;
712                 return count;
713             }
714             bytesLeftToRead -= bytesFromCurrent;
715             fCurrent = fCurrent->fNext;
716             fCurrentOffset = 0;
717         }
718         SkASSERT(false);
719         return 0;
720     }
721 
isAtEnd() const722     virtual bool isAtEnd() const SK_OVERRIDE {
723         return fOffset == fSize;
724     }
725 
rewind()726     virtual bool rewind() SK_OVERRIDE {
727         fCurrent = fBlockMemory->fHead;
728         fOffset = 0;
729         fCurrentOffset = 0;
730         return true;
731     }
732 
duplicate() const733     virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
734         return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
735     }
736 
getPosition() const737     virtual size_t getPosition() const SK_OVERRIDE {
738         return fOffset;
739     }
740 
seek(size_t position)741     virtual bool seek(size_t position) SK_OVERRIDE {
742         // If possible, skip forward.
743         if (position >= fOffset) {
744             size_t skipAmount = position - fOffset;
745             return this->skip(skipAmount) == skipAmount;
746         }
747         // If possible, move backward within the current block.
748         size_t moveBackAmount = fOffset - position;
749         if (moveBackAmount <= fCurrentOffset) {
750             fCurrentOffset -= moveBackAmount;
751             fOffset -= moveBackAmount;
752             return true;
753         }
754         // Otherwise rewind and move forward.
755         return this->rewind() && this->skip(position) == position;
756     }
757 
move(long offset)758     virtual bool move(long offset) SK_OVERRIDE {
759         return seek(fOffset + offset);
760     }
761 
fork() const762     virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
763         SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
764         that->fCurrent = this->fCurrent;
765         that->fOffset = this->fOffset;
766         that->fCurrentOffset = this->fCurrentOffset;
767         return that.detach();
768     }
769 
getLength() const770     virtual size_t getLength() const SK_OVERRIDE {
771         return fSize;
772     }
773 
getMemoryBase()774     virtual const void* getMemoryBase() SK_OVERRIDE {
775         if (NULL == fBlockMemory->fHead->fNext) {
776             return fBlockMemory->fHead->start();
777         }
778         return NULL;
779     }
780 
781 private:
782     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
783     SkDynamicMemoryWStream::Block const * fCurrent;
784     size_t const fSize;
785     size_t fOffset;
786     size_t fCurrentOffset;
787 };
788 
detachAsStream()789 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
790     if (fCopy) {
791         SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
792         this->reset();
793         return stream;
794     }
795     SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
796     fHead = 0;
797     this->reset();
798     return stream;
799 }
800 
801 ///////////////////////////////////////////////////////////////////////////////
802 
newline()803 void SkDebugWStream::newline()
804 {
805 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
806     SkDebugf("\n");
807     fBytesWritten++;
808 #endif
809 }
810 
write(const void * buffer,size_t size)811 bool SkDebugWStream::write(const void* buffer, size_t size)
812 {
813 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
814     char* s = new char[size+1];
815     memcpy(s, buffer, size);
816     s[size] = 0;
817     SkDebugf("%s", s);
818     delete[] s;
819     fBytesWritten += size;
820 #endif
821     return true;
822 }
823 
824 ///////////////////////////////////////////////////////////////////////////////
825 ///////////////////////////////////////////////////////////////////////////////
826 
827 
mmap_filename(const char path[])828 static SkData* mmap_filename(const char path[]) {
829     SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
830     if (NULL == file) {
831         return NULL;
832     }
833 
834     SkData* data = SkData::NewFromFILE(file);
835     sk_fclose(file);
836     return data;
837 }
838 
NewFromFile(const char path[])839 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
840     SkAutoTUnref<SkData> data(mmap_filename(path));
841     if (data.get()) {
842         return SkNEW_ARGS(SkMemoryStream, (data.get()));
843     }
844 
845     // If we get here, then our attempt at using mmap failed, so try normal
846     // file access.
847     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
848     if (!stream->isValid()) {
849         stream->unref();
850         stream = NULL;
851     }
852     return stream;
853 }
854