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
19int8_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
26int16_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
33int32_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
40SkScalar 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
51size_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
65SkData* 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
78SkWStream::~SkWStream()
79{
80}
81
82void SkWStream::newline()
83{
84    this->write("\n", 1);
85}
86
87void SkWStream::flush()
88{
89}
90
91bool SkWStream::writeText(const char text[])
92{
93    SkASSERT(text);
94    return this->write(text, strlen(text));
95}
96
97bool SkWStream::writeDecAsText(int32_t dec)
98{
99    SkString    tmp;
100    tmp.appendS32(dec);
101    return this->write(tmp.c_str(), tmp.size());
102}
103
104bool 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
111bool 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
118bool SkWStream::writeScalarAsText(SkScalar value)
119{
120    SkString    tmp;
121    tmp.appendScalar(value);
122    return this->write(tmp.c_str(), tmp.size());
123}
124
125bool SkWStream::write8(U8CPU value) {
126    uint8_t v = SkToU8(value);
127    return this->write(&v, 1);
128}
129
130bool SkWStream::write16(U16CPU value) {
131    uint16_t v = SkToU16(value);
132    return this->write(&v, 2);
133}
134
135bool SkWStream::write32(uint32_t value) {
136    return this->write(&value, 4);
137}
138
139bool SkWStream::writeScalar(SkScalar value) {
140    return this->write(&value, sizeof(value));
141}
142
143int 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
152bool 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
172bool 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
190bool 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
202SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
203    fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
204}
205
206SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
207    : fFILE((SkFILE*)file)
208    , fOwnership(ownership) {
209}
210
211SkFILEStream::~SkFILEStream() {
212    if (fFILE && fOwnership != kCallerRetains_Ownership) {
213        sk_fclose(fFILE);
214    }
215}
216
217void 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
228size_t SkFILEStream::read(void* buffer, size_t size) {
229    if (fFILE) {
230        return sk_fread(buffer, size, fFILE);
231    }
232    return 0;
233}
234
235bool SkFILEStream::isAtEnd() const {
236    return sk_feof(fFILE);
237}
238
239bool 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
251SkStreamAsset* 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
274size_t SkFILEStream::getPosition() const {
275    return sk_ftell(fFILE);
276}
277
278bool SkFILEStream::seek(size_t position) {
279    return sk_fseek(fFILE, position);
280}
281
282bool SkFILEStream::move(long offset) {
283    return sk_fmove(fFILE, offset);
284}
285
286SkStreamAsset* SkFILEStream::fork() const {
287    SkAutoTUnref<SkStreamAsset> that(this->duplicate());
288    that->seek(this->getPosition());
289    return that.detach();
290}
291
292size_t SkFILEStream::getLength() const {
293    return sk_fgetsize(fFILE);
294}
295
296const void* SkFILEStream::getMemoryBase() {
297    if (NULL == fData.get()) {
298        return NULL;
299    }
300    return fData->data();
301}
302
303///////////////////////////////////////////////////////////////////////////////
304
305static 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
313SkMemoryStream::SkMemoryStream() {
314    fData = SkData::NewEmpty();
315    fOffset = 0;
316}
317
318SkMemoryStream::SkMemoryStream(size_t size) {
319    fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
320    fOffset = 0;
321}
322
323SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
324    fData = newFromParams(src, size, copyData);
325    fOffset = 0;
326}
327
328SkMemoryStream::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
338SkMemoryStream::~SkMemoryStream() {
339    fData->unref();
340}
341
342void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
343    fData->unref();
344    fData = SkData::NewFromMalloc(src, size);
345    fOffset = 0;
346}
347
348void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
349    fData->unref();
350    fData = newFromParams(src, size, copyData);
351    fOffset = 0;
352}
353
354SkData* SkMemoryStream::copyToData() const {
355    fData->ref();
356    return fData;
357}
358
359SkData* 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
371void SkMemoryStream::skipToAlign4() {
372    // cast to remove unary-minus warning
373    fOffset += -(int)fOffset & 0x03;
374}
375
376size_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
389bool SkMemoryStream::isAtEnd() const {
390    return fOffset == fData->size();
391}
392
393bool SkMemoryStream::rewind() {
394    fOffset = 0;
395    return true;
396}
397
398SkMemoryStream* SkMemoryStream::duplicate() const {
399    return SkNEW_ARGS(SkMemoryStream, (fData));
400}
401
402size_t SkMemoryStream::getPosition() const {
403    return fOffset;
404}
405
406bool SkMemoryStream::seek(size_t position) {
407    fOffset = position > fData->size()
408            ? fData->size()
409            : position;
410    return true;
411}
412
413bool SkMemoryStream::move(long offset) {
414    return this->seek(fOffset + offset);
415}
416
417SkMemoryStream* SkMemoryStream::fork() const {
418    SkAutoTUnref<SkMemoryStream> that(this->duplicate());
419    that->seek(fOffset);
420    return that.detach();
421}
422
423size_t SkMemoryStream::getLength() const {
424    return fData->size();
425}
426
427const void* SkMemoryStream::getMemoryBase() {
428    return fData->data();
429}
430
431const void* SkMemoryStream::getAtPos() {
432    return fData->bytes() + fOffset;
433}
434
435/////////////////////////////////////////////////////////////////////////////////////////////////////////
436/////////////////////////////////////////////////////////////////////////////////////////////////////////
437
438SkFILEWStream::SkFILEWStream(const char path[])
439{
440    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
441}
442
443SkFILEWStream::~SkFILEWStream()
444{
445    if (fFILE) {
446        sk_fclose(fFILE);
447    }
448}
449
450size_t SkFILEWStream::bytesWritten() const {
451    return sk_ftell(fFILE);
452}
453
454bool 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
470void SkFILEWStream::flush()
471{
472    if (fFILE) {
473        sk_fflush(fFILE);
474    }
475}
476
477////////////////////////////////////////////////////////////////////////
478
479SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
480    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
481{
482}
483
484bool 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
498struct SkDynamicMemoryWStream::Block {
499    Block*  fNext;
500    char*   fCurr;
501    char*   fStop;
502
503    const char* start() const { return (const char*)(this + 1); }
504    char*   start() { return (char*)(this + 1); }
505    size_t  avail() const { return fStop - fCurr; }
506    size_t  written() const { return fCurr - this->start(); }
507
508    void init(size_t size)
509    {
510        fNext = NULL;
511        fCurr = this->start();
512        fStop = this->start() + size;
513    }
514
515    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
524SkDynamicMemoryWStream::SkDynamicMemoryWStream()
525    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
526{
527}
528
529SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
530{
531    reset();
532}
533
534void 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
549bool 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
581bool 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
606bool 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
627void 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
643void 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
653SkData* 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
663void SkDynamicMemoryWStream::invalidateCopy() {
664    if (fCopy) {
665        fCopy->unref();
666        fCopy = NULL;
667    }
668}
669
670class SkBlockMemoryRefCnt : public SkRefCnt {
671public:
672    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
673
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
686class SkBlockMemoryStream : public SkStreamAsset {
687public:
688    SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
689        : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
690        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
691
692    SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
693        : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
694        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
695
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
722    virtual bool isAtEnd() const SK_OVERRIDE {
723        return fOffset == fSize;
724    }
725
726    virtual bool rewind() SK_OVERRIDE {
727        fCurrent = fBlockMemory->fHead;
728        fOffset = 0;
729        fCurrentOffset = 0;
730        return true;
731    }
732
733    virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
734        return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
735    }
736
737    virtual size_t getPosition() const SK_OVERRIDE {
738        return fOffset;
739    }
740
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
758    virtual bool move(long offset) SK_OVERRIDE {
759        return seek(fOffset + offset);
760    }
761
762    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
770    virtual size_t getLength() const SK_OVERRIDE {
771        return fSize;
772    }
773
774    virtual const void* getMemoryBase() SK_OVERRIDE {
775        if (NULL == fBlockMemory->fHead->fNext) {
776            return fBlockMemory->fHead->start();
777        }
778        return NULL;
779    }
780
781private:
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
789SkStreamAsset* 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
803void SkDebugWStream::newline()
804{
805#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
806    SkDebugf("\n");
807    fBytesWritten++;
808#endif
809}
810
811bool 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
828static 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
839SkStreamAsset* 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