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
21int8_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
28int16_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
35int32_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
42SkScalar 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
53size_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
69SkWStream::~SkWStream()
70{
71}
72
73void SkWStream::newline()
74{
75    this->write("\n", 1);
76}
77
78void SkWStream::flush()
79{
80}
81
82bool SkWStream::writeText(const char text[])
83{
84    SkASSERT(text);
85    return this->write(text, strlen(text));
86}
87
88bool 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
95bool 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
102bool 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
109bool 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
116bool SkWStream::write8(U8CPU value) {
117    uint8_t v = SkToU8(value);
118    return this->write(&v, 1);
119}
120
121bool SkWStream::write16(U16CPU value) {
122    uint16_t v = SkToU16(value);
123    return this->write(&v, 2);
124}
125
126bool SkWStream::write32(uint32_t value) {
127    return this->write(&value, 4);
128}
129
130bool SkWStream::writeScalar(SkScalar value) {
131    return this->write(&value, sizeof(value));
132}
133
134int 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
143bool 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
163bool 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
183SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
184    fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
185}
186
187SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
188    : fFILE((SkFILE*)file)
189    , fOwnership(ownership) {
190}
191
192SkFILEStream::~SkFILEStream() {
193    if (fFILE && fOwnership != kCallerRetains_Ownership) {
194        sk_fclose(fFILE);
195    }
196}
197
198void 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
209size_t SkFILEStream::read(void* buffer, size_t size) {
210    if (fFILE) {
211        return sk_fread(buffer, size, fFILE);
212    }
213    return 0;
214}
215
216bool SkFILEStream::isAtEnd() const {
217    return sk_feof(fFILE);
218}
219
220bool 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
232SkStreamAsset* 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
255size_t SkFILEStream::getPosition() const {
256    return sk_ftell(fFILE);
257}
258
259bool SkFILEStream::seek(size_t position) {
260    return sk_fseek(fFILE, position);
261}
262
263bool SkFILEStream::move(long offset) {
264    return sk_fmove(fFILE, offset);
265}
266
267SkStreamAsset* SkFILEStream::fork() const {
268    SkAutoTDelete<SkStreamAsset> that(this->duplicate());
269    that->seek(this->getPosition());
270    return that.detach();
271}
272
273size_t SkFILEStream::getLength() const {
274    return sk_fgetsize(fFILE);
275}
276
277const void* SkFILEStream::getMemoryBase() {
278    if (NULL == fData.get()) {
279        return NULL;
280    }
281    return fData->data();
282}
283
284///////////////////////////////////////////////////////////////////////////////
285
286static 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
294SkMemoryStream::SkMemoryStream() {
295    fData = SkData::NewEmpty();
296    fOffset = 0;
297}
298
299SkMemoryStream::SkMemoryStream(size_t size) {
300    fData = SkData::NewUninitialized(size);
301    fOffset = 0;
302}
303
304SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
305    fData = newFromParams(src, size, copyData);
306    fOffset = 0;
307}
308
309SkMemoryStream::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
319SkMemoryStream::~SkMemoryStream() {
320    fData->unref();
321}
322
323void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
324    fData->unref();
325    fData = SkData::NewFromMalloc(src, size);
326    fOffset = 0;
327}
328
329void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
330    fData->unref();
331    fData = newFromParams(src, size, copyData);
332    fOffset = 0;
333}
334
335SkData* SkMemoryStream::copyToData() const {
336    fData->ref();
337    return fData;
338}
339
340SkData* 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
352void SkMemoryStream::skipToAlign4() {
353    // cast to remove unary-minus warning
354    fOffset += -(int)fOffset & 0x03;
355}
356
357size_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
370bool 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
384bool SkMemoryStream::isAtEnd() const {
385    return fOffset == fData->size();
386}
387
388bool SkMemoryStream::rewind() {
389    fOffset = 0;
390    return true;
391}
392
393SkMemoryStream* SkMemoryStream::duplicate() const {
394    return SkNEW_ARGS(SkMemoryStream, (fData));
395}
396
397size_t SkMemoryStream::getPosition() const {
398    return fOffset;
399}
400
401bool SkMemoryStream::seek(size_t position) {
402    fOffset = position > fData->size()
403            ? fData->size()
404            : position;
405    return true;
406}
407
408bool SkMemoryStream::move(long offset) {
409    return this->seek(fOffset + offset);
410}
411
412SkMemoryStream* SkMemoryStream::fork() const {
413    SkAutoTDelete<SkMemoryStream> that(this->duplicate());
414    that->seek(fOffset);
415    return that.detach();
416}
417
418size_t SkMemoryStream::getLength() const {
419    return fData->size();
420}
421
422const void* SkMemoryStream::getMemoryBase() {
423    return fData->data();
424}
425
426const void* SkMemoryStream::getAtPos() {
427    return fData->bytes() + fOffset;
428}
429
430/////////////////////////////////////////////////////////////////////////////////////////////////////////
431/////////////////////////////////////////////////////////////////////////////////////////////////////////
432
433SkFILEWStream::SkFILEWStream(const char path[])
434{
435    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
436}
437
438SkFILEWStream::~SkFILEWStream()
439{
440    if (fFILE) {
441        sk_fclose(fFILE);
442    }
443}
444
445size_t SkFILEWStream::bytesWritten() const {
446    return sk_ftell(fFILE);
447}
448
449bool 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
465void SkFILEWStream::flush()
466{
467    if (fFILE) {
468        sk_fflush(fFILE);
469    }
470}
471
472////////////////////////////////////////////////////////////////////////
473
474SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
475    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
476{
477}
478
479bool 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
493struct SkDynamicMemoryWStream::Block {
494    Block*  fNext;
495    char*   fCurr;
496    char*   fStop;
497
498    const char* start() const { return (const char*)(this + 1); }
499    char*   start() { return (char*)(this + 1); }
500    size_t  avail() const { return fStop - fCurr; }
501    size_t  written() const { return fCurr - this->start(); }
502
503    void init(size_t size)
504    {
505        fNext = NULL;
506        fCurr = this->start();
507        fStop = this->start() + size;
508    }
509
510    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
519SkDynamicMemoryWStream::SkDynamicMemoryWStream()
520    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
521{
522}
523
524SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
525{
526    reset();
527}
528
529void 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
544bool 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
576bool 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
601bool 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
622void 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
638void 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
644void 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
654SkData* 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
664void SkDynamicMemoryWStream::invalidateCopy() {
665    if (fCopy) {
666        fCopy->unref();
667        fCopy = NULL;
668    }
669}
670
671class SkBlockMemoryRefCnt : public SkRefCnt {
672public:
673    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
674
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
687class SkBlockMemoryStream : public SkStreamAsset {
688public:
689    SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
690        : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
691        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
692
693    SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
694        : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
695        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
696
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
723    bool isAtEnd() const override {
724        return fOffset == fSize;
725    }
726
727    bool rewind() override {
728        fCurrent = fBlockMemory->fHead;
729        fOffset = 0;
730        fCurrentOffset = 0;
731        return true;
732    }
733
734    SkBlockMemoryStream* duplicate() const override {
735        return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
736    }
737
738    size_t getPosition() const override {
739        return fOffset;
740    }
741
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
759    bool move(long offset) override {
760        return seek(fOffset + offset);
761    }
762
763    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
771    size_t getLength() const override {
772        return fSize;
773    }
774
775    const void* getMemoryBase() override {
776        if (NULL == fBlockMemory->fHead->fNext) {
777            return fBlockMemory->fHead->start();
778        }
779        return NULL;
780    }
781
782private:
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
790SkStreamAsset* 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
804void SkDebugWStream::newline()
805{
806#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
807    SkDebugf("\n");
808    fBytesWritten++;
809#endif
810}
811
812bool 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
829static 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
840SkStreamAsset* 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:
857size_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:
888SkData* 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
905SkStreamRewindable* 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