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 "SkStreamPriv.h"
12 #include "SkData.h"
13 #include "SkFixed.h"
14 #include "SkString.h"
15 #include "SkOSFile.h"
16 #include "SkTypes.h"
17 
18 ///////////////////////////////////////////////////////////////////////////////
19 
20 
readS8()21 int8_t SkStream::readS8() {
22     int8_t value;
23     SkDEBUGCODE(size_t len =) this->read(&value, 1);
24     SkASSERT(1 == len);
25     return value;
26 }
27 
readS16()28 int16_t SkStream::readS16() {
29     int16_t value;
30     SkDEBUGCODE(size_t len =) this->read(&value, 2);
31     SkASSERT(2 == len);
32     return value;
33 }
34 
readS32()35 int32_t SkStream::readS32() {
36     int32_t value;
37     SkDEBUGCODE(size_t len =) this->read(&value, 4);
38     SkASSERT(4 == len);
39     return value;
40 }
41 
readScalar()42 SkScalar SkStream::readScalar() {
43     SkScalar value;
44     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
45     SkASSERT(sizeof(SkScalar) == len);
46     return value;
47 }
48 
49 #define SK_MAX_BYTE_FOR_U8          0xFD
50 #define SK_BYTE_SENTINEL_FOR_U16    0xFE
51 #define SK_BYTE_SENTINEL_FOR_U32    0xFF
52 
readPackedUInt()53 size_t SkStream::readPackedUInt() {
54     uint8_t byte;
55     if (!this->read(&byte, 1)) {
56         return 0;
57     }
58     if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
59         return this->readU16();
60     } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
61         return this->readU32();
62     } else {
63         return byte;
64     }
65 }
66 
67 //////////////////////////////////////////////////////////////////////////////////////
68 
~SkWStream()69 SkWStream::~SkWStream()
70 {
71 }
72 
newline()73 void SkWStream::newline()
74 {
75     this->write("\n", 1);
76 }
77 
flush()78 void SkWStream::flush()
79 {
80 }
81 
writeText(const char text[])82 bool SkWStream::writeText(const char text[])
83 {
84     SkASSERT(text);
85     return this->write(text, strlen(text));
86 }
87 
writeDecAsText(int32_t dec)88 bool SkWStream::writeDecAsText(int32_t dec)
89 {
90     char buffer[SkStrAppendS32_MaxSize];
91     char* stop = SkStrAppendS32(buffer, dec);
92     return this->write(buffer, stop - buffer);
93 }
94 
writeBigDecAsText(int64_t dec,int minDigits)95 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
96 {
97     char buffer[SkStrAppendU64_MaxSize];
98     char* stop = SkStrAppendU64(buffer, dec, minDigits);
99     return this->write(buffer, stop - buffer);
100 }
101 
writeHexAsText(uint32_t hex,int digits)102 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
103 {
104     SkString    tmp;
105     tmp.appendHex(hex, digits);
106     return this->write(tmp.c_str(), tmp.size());
107 }
108 
writeScalarAsText(SkScalar value)109 bool SkWStream::writeScalarAsText(SkScalar value)
110 {
111     char buffer[SkStrAppendScalar_MaxSize];
112     char* stop = SkStrAppendScalar(buffer, value);
113     return this->write(buffer, stop - buffer);
114 }
115 
write8(U8CPU value)116 bool SkWStream::write8(U8CPU value) {
117     uint8_t v = SkToU8(value);
118     return this->write(&v, 1);
119 }
120 
write16(U16CPU value)121 bool SkWStream::write16(U16CPU value) {
122     uint16_t v = SkToU16(value);
123     return this->write(&v, 2);
124 }
125 
write32(uint32_t value)126 bool SkWStream::write32(uint32_t value) {
127     return this->write(&value, 4);
128 }
129 
writeScalar(SkScalar value)130 bool SkWStream::writeScalar(SkScalar value) {
131     return this->write(&value, sizeof(value));
132 }
133 
SizeOfPackedUInt(size_t value)134 int SkWStream::SizeOfPackedUInt(size_t value) {
135     if (value <= SK_MAX_BYTE_FOR_U8) {
136         return 1;
137     } else if (value <= 0xFFFF) {
138         return 3;
139     }
140     return 5;
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 = SkToU32(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 
181 ///////////////////////////////////////////////////////////////////////////////
182 
SkFILEStream(const char file[])183 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
184     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
185 }
186 
SkFILEStream(FILE * file,Ownership ownership)187 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
188     : fFILE((SkFILE*)file)
189     , fOwnership(ownership) {
190 }
191 
~SkFILEStream()192 SkFILEStream::~SkFILEStream() {
193     if (fFILE && fOwnership != kCallerRetains_Ownership) {
194         sk_fclose(fFILE);
195     }
196 }
197 
setPath(const char path[])198 void SkFILEStream::setPath(const char path[]) {
199     fName.set(path);
200     if (fFILE) {
201         sk_fclose(fFILE);
202         fFILE = NULL;
203     }
204     if (path) {
205         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
206     }
207 }
208 
read(void * buffer,size_t size)209 size_t SkFILEStream::read(void* buffer, size_t size) {
210     if (fFILE) {
211         return sk_fread(buffer, size, fFILE);
212     }
213     return 0;
214 }
215 
isAtEnd() const216 bool SkFILEStream::isAtEnd() const {
217     return sk_feof(fFILE);
218 }
219 
rewind()220 bool SkFILEStream::rewind() {
221     if (fFILE) {
222         if (sk_frewind(fFILE)) {
223             return true;
224         }
225         // we hit an error
226         sk_fclose(fFILE);
227         fFILE = NULL;
228     }
229     return false;
230 }
231 
duplicate() const232 SkStreamAsset* SkFILEStream::duplicate() const {
233     if (NULL == fFILE) {
234         return new SkMemoryStream();
235     }
236 
237     if (fData.get()) {
238         return new SkMemoryStream(fData);
239     }
240 
241     if (!fName.isEmpty()) {
242         SkAutoTDelete<SkFILEStream> that(new SkFILEStream(fName.c_str()));
243         if (sk_fidentical(that->fFILE, this->fFILE)) {
244             return that.detach();
245         }
246     }
247 
248     fData.reset(SkData::NewFromFILE(fFILE));
249     if (NULL == fData.get()) {
250         return NULL;
251     }
252     return new SkMemoryStream(fData);
253 }
254 
getPosition() const255 size_t SkFILEStream::getPosition() const {
256     return sk_ftell(fFILE);
257 }
258 
seek(size_t position)259 bool SkFILEStream::seek(size_t position) {
260     return sk_fseek(fFILE, position);
261 }
262 
move(long offset)263 bool SkFILEStream::move(long offset) {
264     return sk_fmove(fFILE, offset);
265 }
266 
fork() const267 SkStreamAsset* SkFILEStream::fork() const {
268     SkAutoTDelete<SkStreamAsset> that(this->duplicate());
269     that->seek(this->getPosition());
270     return that.detach();
271 }
272 
getLength() const273 size_t SkFILEStream::getLength() const {
274     return sk_fgetsize(fFILE);
275 }
276 
getMemoryBase()277 const void* SkFILEStream::getMemoryBase() {
278     if (NULL == fData.get()) {
279         return NULL;
280     }
281     return fData->data();
282 }
283 
284 ///////////////////////////////////////////////////////////////////////////////
285 
newFromParams(const void * src,size_t size,bool copyData)286 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
287     if (copyData) {
288         return SkData::NewWithCopy(src, size);
289     } else {
290         return SkData::NewWithoutCopy(src, size);
291     }
292 }
293 
SkMemoryStream()294 SkMemoryStream::SkMemoryStream() {
295     fData = SkData::NewEmpty();
296     fOffset = 0;
297 }
298 
SkMemoryStream(size_t size)299 SkMemoryStream::SkMemoryStream(size_t size) {
300     fData = SkData::NewUninitialized(size);
301     fOffset = 0;
302 }
303 
SkMemoryStream(const void * src,size_t size,bool copyData)304 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
305     fData = newFromParams(src, size, copyData);
306     fOffset = 0;
307 }
308 
SkMemoryStream(SkData * data)309 SkMemoryStream::SkMemoryStream(SkData* data) {
310     if (NULL == data) {
311         fData = SkData::NewEmpty();
312     } else {
313         fData = data;
314         fData->ref();
315     }
316     fOffset = 0;
317 }
318 
~SkMemoryStream()319 SkMemoryStream::~SkMemoryStream() {
320     fData->unref();
321 }
322 
setMemoryOwned(const void * src,size_t size)323 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
324     fData->unref();
325     fData = SkData::NewFromMalloc(src, size);
326     fOffset = 0;
327 }
328 
setMemory(const void * src,size_t size,bool copyData)329 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
330     fData->unref();
331     fData = newFromParams(src, size, copyData);
332     fOffset = 0;
333 }
334 
copyToData() const335 SkData* SkMemoryStream::copyToData() const {
336     fData->ref();
337     return fData;
338 }
339 
setData(SkData * data)340 SkData* SkMemoryStream::setData(SkData* data) {
341     fData->unref();
342     if (NULL == data) {
343         fData = SkData::NewEmpty();
344     } else {
345         fData = data;
346         fData->ref();
347     }
348     fOffset = 0;
349     return data;
350 }
351 
skipToAlign4()352 void SkMemoryStream::skipToAlign4() {
353     // cast to remove unary-minus warning
354     fOffset += -(int)fOffset & 0x03;
355 }
356 
read(void * buffer,size_t size)357 size_t SkMemoryStream::read(void* buffer, size_t size) {
358     size_t dataSize = fData->size();
359 
360     if (size > dataSize - fOffset) {
361         size = dataSize - fOffset;
362     }
363     if (buffer) {
364         memcpy(buffer, fData->bytes() + fOffset, size);
365     }
366     fOffset += size;
367     return size;
368 }
369 
peek(void * buffer,size_t size) const370 bool SkMemoryStream::peek(void* buffer, size_t size) const {
371     SkASSERT(buffer != NULL);
372     const size_t position = fOffset;
373     if (size > fData->size() - position) {
374         // The stream is not large enough to satisfy this request.
375         return false;
376     }
377     SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
378     SkDEBUGCODE(const size_t bytesRead =) nonConstThis->read(buffer, size);
379     SkASSERT(bytesRead == size);
380     nonConstThis->fOffset = position;
381     return true;
382 }
383 
isAtEnd() const384 bool SkMemoryStream::isAtEnd() const {
385     return fOffset == fData->size();
386 }
387 
rewind()388 bool SkMemoryStream::rewind() {
389     fOffset = 0;
390     return true;
391 }
392 
duplicate() const393 SkMemoryStream* SkMemoryStream::duplicate() const {
394     return SkNEW_ARGS(SkMemoryStream, (fData));
395 }
396 
getPosition() const397 size_t SkMemoryStream::getPosition() const {
398     return fOffset;
399 }
400 
seek(size_t position)401 bool SkMemoryStream::seek(size_t position) {
402     fOffset = position > fData->size()
403             ? fData->size()
404             : position;
405     return true;
406 }
407 
move(long offset)408 bool SkMemoryStream::move(long offset) {
409     return this->seek(fOffset + offset);
410 }
411 
fork() const412 SkMemoryStream* SkMemoryStream::fork() const {
413     SkAutoTDelete<SkMemoryStream> that(this->duplicate());
414     that->seek(fOffset);
415     return that.detach();
416 }
417 
getLength() const418 size_t SkMemoryStream::getLength() const {
419     return fData->size();
420 }
421 
getMemoryBase()422 const void* SkMemoryStream::getMemoryBase() {
423     return fData->data();
424 }
425 
getAtPos()426 const void* SkMemoryStream::getAtPos() {
427     return fData->bytes() + fOffset;
428 }
429 
430 /////////////////////////////////////////////////////////////////////////////////////////////////////////
431 /////////////////////////////////////////////////////////////////////////////////////////////////////////
432 
SkFILEWStream(const char path[])433 SkFILEWStream::SkFILEWStream(const char path[])
434 {
435     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
436 }
437 
~SkFILEWStream()438 SkFILEWStream::~SkFILEWStream()
439 {
440     if (fFILE) {
441         sk_fclose(fFILE);
442     }
443 }
444 
bytesWritten() const445 size_t SkFILEWStream::bytesWritten() const {
446     return sk_ftell(fFILE);
447 }
448 
write(const void * buffer,size_t size)449 bool SkFILEWStream::write(const void* buffer, size_t size)
450 {
451     if (fFILE == NULL) {
452         return false;
453     }
454 
455     if (sk_fwrite(buffer, size, fFILE) != size)
456     {
457         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
458         sk_fclose(fFILE);
459         fFILE = NULL;
460         return false;
461     }
462     return true;
463 }
464 
flush()465 void SkFILEWStream::flush()
466 {
467     if (fFILE) {
468         sk_fflush(fFILE);
469     }
470 }
471 
472 ////////////////////////////////////////////////////////////////////////
473 
SkMemoryWStream(void * buffer,size_t size)474 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
475     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
476 {
477 }
478 
write(const void * buffer,size_t size)479 bool SkMemoryWStream::write(const void* buffer, size_t size) {
480     size = SkTMin(size, fMaxLength - fBytesWritten);
481     if (size > 0) {
482         memcpy(fBuffer + fBytesWritten, buffer, size);
483         fBytesWritten += size;
484         return true;
485     }
486     return false;
487 }
488 
489 ////////////////////////////////////////////////////////////////////////
490 
491 #define SkDynamicMemoryWStream_MinBlockSize   256
492 
493 struct SkDynamicMemoryWStream::Block {
494     Block*  fNext;
495     char*   fCurr;
496     char*   fStop;
497 
startSkDynamicMemoryWStream::Block498     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block499     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block500     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block501     size_t  written() const { return fCurr - this->start(); }
502 
initSkDynamicMemoryWStream::Block503     void init(size_t size)
504     {
505         fNext = NULL;
506         fCurr = this->start();
507         fStop = this->start() + size;
508     }
509 
appendSkDynamicMemoryWStream::Block510     const void* append(const void* data, size_t size)
511     {
512         SkASSERT((size_t)(fStop - fCurr) >= size);
513         memcpy(fCurr, data, size);
514         fCurr += size;
515         return (const void*)((const char*)data + size);
516     }
517 };
518 
SkDynamicMemoryWStream()519 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
520     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
521 {
522 }
523 
~SkDynamicMemoryWStream()524 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
525 {
526     reset();
527 }
528 
reset()529 void SkDynamicMemoryWStream::reset()
530 {
531     this->invalidateCopy();
532 
533     Block*  block = fHead;
534 
535     while (block != NULL) {
536         Block*  next = block->fNext;
537         sk_free(block);
538         block = next;
539     }
540     fHead = fTail = NULL;
541     fBytesWritten = 0;
542 }
543 
write(const void * buffer,size_t count)544 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
545 {
546     if (count > 0) {
547         this->invalidateCopy();
548 
549         fBytesWritten += count;
550 
551         size_t  size;
552 
553         if (fTail != NULL && fTail->avail() > 0) {
554             size = SkTMin(fTail->avail(), count);
555             buffer = fTail->append(buffer, size);
556             SkASSERT(count >= size);
557             count -= size;
558             if (count == 0)
559                 return true;
560         }
561 
562         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
563         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
564         block->init(size);
565         block->append(buffer, count);
566 
567         if (fTail != NULL)
568             fTail->fNext = block;
569         else
570             fHead = fTail = block;
571         fTail = block;
572     }
573     return true;
574 }
575 
write(const void * buffer,size_t offset,size_t count)576 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
577 {
578     if (offset + count > fBytesWritten) {
579         return false; // test does not partially modify
580     }
581 
582     this->invalidateCopy();
583 
584     Block* block = fHead;
585     while (block != NULL) {
586         size_t size = block->written();
587         if (offset < size) {
588             size_t part = offset + count > size ? size - offset : count;
589             memcpy(block->start() + offset, buffer, part);
590             if (count <= part)
591                 return true;
592             count -= part;
593             buffer = (const void*) ((char* ) buffer + part);
594         }
595         offset = offset > size ? offset - size : 0;
596         block = block->fNext;
597     }
598     return false;
599 }
600 
read(void * buffer,size_t offset,size_t count)601 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
602 {
603     if (offset + count > fBytesWritten)
604         return false; // test does not partially modify
605     Block* block = fHead;
606     while (block != NULL) {
607         size_t size = block->written();
608         if (offset < size) {
609             size_t part = offset + count > size ? size - offset : count;
610             memcpy(buffer, block->start() + offset, part);
611             if (count <= part)
612                 return true;
613             count -= part;
614             buffer = (void*) ((char* ) buffer + part);
615         }
616         offset = offset > size ? offset - size : 0;
617         block = block->fNext;
618     }
619     return false;
620 }
621 
copyTo(void * dst) const622 void SkDynamicMemoryWStream::copyTo(void* dst) const
623 {
624     if (fCopy) {
625         memcpy(dst, fCopy->data(), fBytesWritten);
626     } else {
627         Block* block = fHead;
628 
629         while (block != NULL) {
630             size_t size = block->written();
631             memcpy(dst, block->start(), size);
632             dst = (void*)((char*)dst + size);
633             block = block->fNext;
634         }
635     }
636 }
637 
writeToStream(SkWStream * dst) const638 void SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
639     for (Block* block = fHead; block != NULL; block = block->fNext) {
640         dst->write(block->start(), block->written());
641     }
642 }
643 
padToAlign4()644 void SkDynamicMemoryWStream::padToAlign4()
645 {
646     // cast to remove unary-minus warning
647     int padBytes = -(int)fBytesWritten & 0x03;
648     if (padBytes == 0)
649         return;
650     int zero = 0;
651     write(&zero, padBytes);
652 }
653 
copyToData() const654 SkData* SkDynamicMemoryWStream::copyToData() const {
655     if (NULL == fCopy) {
656         SkData* data = SkData::NewUninitialized(fBytesWritten);
657         // be sure to call copyTo() before we assign to fCopy
658         this->copyTo(data->writable_data());
659         fCopy = data;
660     }
661     return SkRef(fCopy);
662 }
663 
invalidateCopy()664 void SkDynamicMemoryWStream::invalidateCopy() {
665     if (fCopy) {
666         fCopy->unref();
667         fCopy = NULL;
668     }
669 }
670 
671 class SkBlockMemoryRefCnt : public SkRefCnt {
672 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)673     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
674 
~SkBlockMemoryRefCnt()675     virtual ~SkBlockMemoryRefCnt() {
676         SkDynamicMemoryWStream::Block* block = fHead;
677         while (block != NULL) {
678             SkDynamicMemoryWStream::Block* next = block->fNext;
679             sk_free(block);
680             block = next;
681         }
682     }
683 
684     SkDynamicMemoryWStream::Block* const fHead;
685 };
686 
687 class SkBlockMemoryStream : public SkStreamAsset {
688 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)689     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
690         : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
691         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
692 
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)693     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
694         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
695         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
696 
read(void * buffer,size_t rawCount)697     size_t read(void* buffer, size_t rawCount) override {
698         size_t count = rawCount;
699         if (fOffset + count > fSize) {
700             count = fSize - fOffset;
701         }
702         size_t bytesLeftToRead = count;
703         while (fCurrent != NULL) {
704             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
705             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
706             if (buffer) {
707                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
708                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
709             }
710             if (bytesLeftToRead <= bytesFromCurrent) {
711                 fCurrentOffset += bytesFromCurrent;
712                 fOffset += count;
713                 return count;
714             }
715             bytesLeftToRead -= bytesFromCurrent;
716             fCurrent = fCurrent->fNext;
717             fCurrentOffset = 0;
718         }
719         SkASSERT(false);
720         return 0;
721     }
722 
isAtEnd() const723     bool isAtEnd() const override {
724         return fOffset == fSize;
725     }
726 
rewind()727     bool rewind() override {
728         fCurrent = fBlockMemory->fHead;
729         fOffset = 0;
730         fCurrentOffset = 0;
731         return true;
732     }
733 
duplicate() const734     SkBlockMemoryStream* duplicate() const override {
735         return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
736     }
737 
getPosition() const738     size_t getPosition() const override {
739         return fOffset;
740     }
741 
seek(size_t position)742     bool seek(size_t position) override {
743         // If possible, skip forward.
744         if (position >= fOffset) {
745             size_t skipAmount = position - fOffset;
746             return this->skip(skipAmount) == skipAmount;
747         }
748         // If possible, move backward within the current block.
749         size_t moveBackAmount = fOffset - position;
750         if (moveBackAmount <= fCurrentOffset) {
751             fCurrentOffset -= moveBackAmount;
752             fOffset -= moveBackAmount;
753             return true;
754         }
755         // Otherwise rewind and move forward.
756         return this->rewind() && this->skip(position) == position;
757     }
758 
move(long offset)759     bool move(long offset) override {
760         return seek(fOffset + offset);
761     }
762 
fork() const763     SkBlockMemoryStream* fork() const override {
764         SkAutoTDelete<SkBlockMemoryStream> that(this->duplicate());
765         that->fCurrent = this->fCurrent;
766         that->fOffset = this->fOffset;
767         that->fCurrentOffset = this->fCurrentOffset;
768         return that.detach();
769     }
770 
getLength() const771     size_t getLength() const override {
772         return fSize;
773     }
774 
getMemoryBase()775     const void* getMemoryBase() override {
776         if (NULL == fBlockMemory->fHead->fNext) {
777             return fBlockMemory->fHead->start();
778         }
779         return NULL;
780     }
781 
782 private:
783     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
784     SkDynamicMemoryWStream::Block const * fCurrent;
785     size_t const fSize;
786     size_t fOffset;
787     size_t fCurrentOffset;
788 };
789 
detachAsStream()790 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
791     if (fCopy) {
792         SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
793         this->reset();
794         return stream;
795     }
796     SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
797     fHead = 0;
798     this->reset();
799     return stream;
800 }
801 
802 ///////////////////////////////////////////////////////////////////////////////
803 
newline()804 void SkDebugWStream::newline()
805 {
806 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
807     SkDebugf("\n");
808     fBytesWritten++;
809 #endif
810 }
811 
write(const void * buffer,size_t size)812 bool SkDebugWStream::write(const void* buffer, size_t size)
813 {
814 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
815     char* s = new char[size+1];
816     memcpy(s, buffer, size);
817     s[size] = 0;
818     SkDebugf("%s", s);
819     delete[] s;
820     fBytesWritten += size;
821 #endif
822     return true;
823 }
824 
825 ///////////////////////////////////////////////////////////////////////////////
826 ///////////////////////////////////////////////////////////////////////////////
827 
828 
mmap_filename(const char path[])829 static SkData* mmap_filename(const char path[]) {
830     SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
831     if (NULL == file) {
832         return NULL;
833     }
834 
835     SkData* data = SkData::NewFromFILE(file);
836     sk_fclose(file);
837     return data;
838 }
839 
NewFromFile(const char path[])840 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
841     SkAutoTUnref<SkData> data(mmap_filename(path));
842     if (data.get()) {
843         return SkNEW_ARGS(SkMemoryStream, (data.get()));
844     }
845 
846     // If we get here, then our attempt at using mmap failed, so try normal
847     // file access.
848     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
849     if (!stream->isValid()) {
850         SkDELETE(stream);
851         stream = NULL;
852     }
853     return stream;
854 }
855 
856 // Declared in SkStreamPriv.h:
SkCopyStreamToStorage(SkAutoMalloc * storage,SkStream * stream)857 size_t SkCopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) {
858     SkASSERT(storage != NULL);
859     SkASSERT(stream != NULL);
860 
861     if (stream->hasLength()) {
862         const size_t length = stream->getLength();
863         void* dst = storage->reset(length);
864         if (stream->read(dst, length) != length) {
865             return 0;
866         }
867         return length;
868     }
869 
870     SkDynamicMemoryWStream tempStream;
871     // Arbitrary buffer size.
872     const size_t bufferSize = 256 * 1024; // 256KB
873     char buffer[bufferSize];
874     SkDEBUGCODE(size_t debugLength = 0;)
875     do {
876         size_t bytesRead = stream->read(buffer, bufferSize);
877         tempStream.write(buffer, bytesRead);
878         SkDEBUGCODE(debugLength += bytesRead);
879         SkASSERT(tempStream.bytesWritten() == debugLength);
880     } while (!stream->isAtEnd());
881     const size_t length = tempStream.bytesWritten();
882     void* dst = storage->reset(length);
883     tempStream.copyTo(dst);
884     return length;
885 }
886 
887 // Declared in SkStreamPriv.h:
SkCopyStreamToData(SkStream * stream)888 SkData* SkCopyStreamToData(SkStream* stream) {
889     SkASSERT(stream != NULL);
890 
891     if (stream->hasLength()) {
892         return SkData::NewFromStream(stream, stream->getLength());
893     }
894 
895     SkDynamicMemoryWStream tempStream;
896     const size_t bufferSize = 4096;
897     char buffer[bufferSize];
898     do {
899         size_t bytesRead = stream->read(buffer, bufferSize);
900         tempStream.write(buffer, bytesRead);
901     } while (!stream->isAtEnd());
902     return tempStream.copyToData();
903 }
904 
SkStreamRewindableFromSkStream(SkStream * stream)905 SkStreamRewindable* SkStreamRewindableFromSkStream(SkStream* stream) {
906     if (!stream) {
907         return NULL;
908     }
909     SkAutoTDelete<SkStreamRewindable> dupStream(stream->duplicate());
910     if (dupStream) {
911         return dupStream.detach();
912     }
913     stream->rewind();
914     if (stream->hasLength()) {
915         size_t length = stream->getLength();
916         if (stream->hasPosition()) {  // If stream has length, but can't rewind.
917             length -= stream->getPosition();
918         }
919         SkAutoTUnref<SkData> data(SkData::NewFromStream(stream, length));
920         return SkNEW_ARGS(SkMemoryStream, (data.get()));
921     }
922     SkDynamicMemoryWStream tempStream;
923     const size_t bufferSize = 4096;
924     char buffer[bufferSize];
925     do {
926         size_t bytesRead = stream->read(buffer, bufferSize);
927         tempStream.write(buffer, bytesRead);
928     } while (!stream->isAtEnd());
929     return tempStream.detachAsStream();  // returns a SkBlockMemoryStream,
930                                          // cheaper than copying to SkData
931 }
932