Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkStream.cpp
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
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
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
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
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
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
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
78 SkWStream::~SkWStream()
79 {
80 }
81
82 void SkWStream::newline()
83 {
84     this->write("\n", 1);
85 }
86
87 void SkWStream::flush()
88 {
89 }
90
91 bool SkWStream::writeText(const char text[])
92 {
93     SkASSERT(text);
94     return this->write(text, strlen(text));
95 }
96
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
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
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
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
125 bool SkWStream::write8(U8CPU value) {
126     uint8_t v = SkToU8(value);
127     return this->write(&v, 1);
128 }
129
130 bool SkWStream::write16(U16CPU value) {
131     uint16_t v = SkToU16(value);
132     return this->write(&v, 2);
133 }
134
135 bool SkWStream::write32(uint32_t value) {
136     return this->write(&value, 4);
137 }
138
139 bool SkWStream::writeScalar(SkScalar value) {
140     return this->write(&value, sizeof(value));
141 }
142
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
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
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
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
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
206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
207     : fFILE((SkFILE*)file)
208     , fOwnership(ownership) {
209 }
210
211 SkFILEStream::~SkFILEStream() {
212     if (fFILE && fOwnership != kCallerRetains_Ownership) {
213         sk_fclose(fFILE);
214     }
215 }
216
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
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
235 bool SkFILEStream::isAtEnd() const {
236     return sk_feof(fFILE);
237 }
238
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
251 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
274 size_t SkFILEStream::getPosition() const {
275     return sk_ftell(fFILE);
276 }
277
278 bool SkFILEStream::seek(size_t position) {
279     return sk_fseek(fFILE, position);
280 }
281
282 bool SkFILEStream::move(long offset) {
283     return sk_fmove(fFILE, offset);
284 }
285
286 SkStreamAsset* SkFILEStream::fork() const {
287     SkAutoTUnref<SkStreamAsset> that(this->duplicate());
288     that->seek(this->getPosition());
289     return that.detach();
290 }
291
292 size_t SkFILEStream::getLength() const {
293     return sk_fgetsize(fFILE);
294 }
295
296 const void* SkFILEStream::getMemoryBase() {
297     if (NULL == fData.get()) {
298         return NULL;
299     }
300     return fData->data();
301 }
302
303 ///////////////////////////////////////////////////////////////////////////////
304
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
313 SkMemoryStream::SkMemoryStream() {
314     fData = SkData::NewEmpty();
315     fOffset = 0;
316 }
317
318 SkMemoryStream::SkMemoryStream(size_t size) {
319     fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
320     fOffset = 0;
321 }
322
323 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
324     fData = newFromParams(src, size, copyData);
325     fOffset = 0;
326 }
327
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
338 SkMemoryStream::~SkMemoryStream() {
339     fData->unref();
340 }
341
342 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
343     fData->unref();
344     fData = SkData::NewFromMalloc(src, size);
345     fOffset = 0;
346 }
347
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
354 SkData* SkMemoryStream::copyToData() const {
355     fData->ref();
356     return fData;
357 }
358
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
371 void SkMemoryStream::skipToAlign4() {
372     // cast to remove unary-minus warning
373     fOffset += -(int)fOffset & 0x03;
374 }
375
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
389 bool SkMemoryStream::isAtEnd() const {
390     return fOffset == fData->size();
391 }
392
393 bool SkMemoryStream::rewind() {
394     fOffset = 0;
395     return true;
396 }
397
398 SkMemoryStream* SkMemoryStream::duplicate() const {
399     return SkNEW_ARGS(SkMemoryStream, (fData));
400 }
401
402 size_t SkMemoryStream::getPosition() const {
403     return fOffset;
404 }
405
406 bool SkMemoryStream::seek(size_t position) {
407     fOffset = position > fData->size()
408             ? fData->size()
409             : position;
410     return true;
411 }
412
413 bool SkMemoryStream::move(long offset) {
414     return this->seek(fOffset + offset);
415 }
416
417 SkMemoryStream* SkMemoryStream::fork() const {
418     SkAutoTUnref<SkMemoryStream> that(this->duplicate());
419     that->seek(fOffset);
420     return that.detach();
421 }
422
423 size_t SkMemoryStream::getLength() const {
424     return fData->size();
425 }
426
427 const void* SkMemoryStream::getMemoryBase() {
428     return fData->data();
429 }
430
431 const void* SkMemoryStream::getAtPos() {
432     return fData->bytes() + fOffset;
433 }
434
435 /////////////////////////////////////////////////////////////////////////////////////////////////////////
436 /////////////////////////////////////////////////////////////////////////////////////////////////////////
437
438 SkFILEWStream::SkFILEWStream(const char path[])
439 {
440     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
441 }
442
443 SkFILEWStream::~SkFILEWStream()
444 {
445     if (fFILE) {
446         sk_fclose(fFILE);
447     }
448 }
449
450 size_t SkFILEWStream::bytesWritten() const {
451     return sk_ftell(fFILE);
452 }
453
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
470 void SkFILEWStream::flush()
471 {
472     if (fFILE) {
473         sk_fflush(fFILE);
474     }
475 }
476
477 ////////////////////////////////////////////////////////////////////////
478
479 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
480     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
481 {
482 }
483
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
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
524 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
525     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
526 {
527 }
528
529 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
530 {
531     reset();
532 }
533
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
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
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
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
627 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
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
653 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
663 void SkDynamicMemoryWStream::invalidateCopy() {
664     if (fCopy) {
665         fCopy->unref();
666         fCopy = NULL;
667     }
668 }
669
670 class SkBlockMemoryRefCnt : public SkRefCnt {
671 public:
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
686 class SkBlockMemoryStream : public SkStreamAsset {
687 public:
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
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
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
803 void SkDebugWStream::newline()
804 {
805 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
806     SkDebugf("\n");
807     fBytesWritten++;
808 #endif
809 }
810
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
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
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 }