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