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    SkString    tmp;
91    tmp.appendS32(dec);
92    return this->write(tmp.c_str(), tmp.size());
93}
94
95bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
96{
97    SkString    tmp;
98    tmp.appendS64(dec, minDigits);
99    return this->write(tmp.c_str(), tmp.size());
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    SkString    tmp;
112    tmp.appendScalar(value);
113    return this->write(tmp.c_str(), tmp.size());
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        SkAutoTUnref<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    SkAutoTUnref<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::isAtEnd() const {
371    return fOffset == fData->size();
372}
373
374bool SkMemoryStream::rewind() {
375    fOffset = 0;
376    return true;
377}
378
379SkMemoryStream* SkMemoryStream::duplicate() const {
380    return SkNEW_ARGS(SkMemoryStream, (fData));
381}
382
383size_t SkMemoryStream::getPosition() const {
384    return fOffset;
385}
386
387bool SkMemoryStream::seek(size_t position) {
388    fOffset = position > fData->size()
389            ? fData->size()
390            : position;
391    return true;
392}
393
394bool SkMemoryStream::move(long offset) {
395    return this->seek(fOffset + offset);
396}
397
398SkMemoryStream* SkMemoryStream::fork() const {
399    SkAutoTUnref<SkMemoryStream> that(this->duplicate());
400    that->seek(fOffset);
401    return that.detach();
402}
403
404size_t SkMemoryStream::getLength() const {
405    return fData->size();
406}
407
408const void* SkMemoryStream::getMemoryBase() {
409    return fData->data();
410}
411
412const void* SkMemoryStream::getAtPos() {
413    return fData->bytes() + fOffset;
414}
415
416/////////////////////////////////////////////////////////////////////////////////////////////////////////
417/////////////////////////////////////////////////////////////////////////////////////////////////////////
418
419SkFILEWStream::SkFILEWStream(const char path[])
420{
421    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
422}
423
424SkFILEWStream::~SkFILEWStream()
425{
426    if (fFILE) {
427        sk_fclose(fFILE);
428    }
429}
430
431size_t SkFILEWStream::bytesWritten() const {
432    return sk_ftell(fFILE);
433}
434
435bool SkFILEWStream::write(const void* buffer, size_t size)
436{
437    if (fFILE == NULL) {
438        return false;
439    }
440
441    if (sk_fwrite(buffer, size, fFILE) != size)
442    {
443        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
444        sk_fclose(fFILE);
445        fFILE = NULL;
446        return false;
447    }
448    return true;
449}
450
451void SkFILEWStream::flush()
452{
453    if (fFILE) {
454        sk_fflush(fFILE);
455    }
456}
457
458////////////////////////////////////////////////////////////////////////
459
460SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
461    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
462{
463}
464
465bool SkMemoryWStream::write(const void* buffer, size_t size) {
466    size = SkTMin(size, fMaxLength - fBytesWritten);
467    if (size > 0) {
468        memcpy(fBuffer + fBytesWritten, buffer, size);
469        fBytesWritten += size;
470        return true;
471    }
472    return false;
473}
474
475////////////////////////////////////////////////////////////////////////
476
477#define SkDynamicMemoryWStream_MinBlockSize   256
478
479struct SkDynamicMemoryWStream::Block {
480    Block*  fNext;
481    char*   fCurr;
482    char*   fStop;
483
484    const char* start() const { return (const char*)(this + 1); }
485    char*   start() { return (char*)(this + 1); }
486    size_t  avail() const { return fStop - fCurr; }
487    size_t  written() const { return fCurr - this->start(); }
488
489    void init(size_t size)
490    {
491        fNext = NULL;
492        fCurr = this->start();
493        fStop = this->start() + size;
494    }
495
496    const void* append(const void* data, size_t size)
497    {
498        SkASSERT((size_t)(fStop - fCurr) >= size);
499        memcpy(fCurr, data, size);
500        fCurr += size;
501        return (const void*)((const char*)data + size);
502    }
503};
504
505SkDynamicMemoryWStream::SkDynamicMemoryWStream()
506    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
507{
508}
509
510SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
511{
512    reset();
513}
514
515void SkDynamicMemoryWStream::reset()
516{
517    this->invalidateCopy();
518
519    Block*  block = fHead;
520
521    while (block != NULL) {
522        Block*  next = block->fNext;
523        sk_free(block);
524        block = next;
525    }
526    fHead = fTail = NULL;
527    fBytesWritten = 0;
528}
529
530bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
531{
532    if (count > 0) {
533        this->invalidateCopy();
534
535        fBytesWritten += count;
536
537        size_t  size;
538
539        if (fTail != NULL && fTail->avail() > 0) {
540            size = SkTMin(fTail->avail(), count);
541            buffer = fTail->append(buffer, size);
542            SkASSERT(count >= size);
543            count -= size;
544            if (count == 0)
545                return true;
546        }
547
548        size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
549        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
550        block->init(size);
551        block->append(buffer, count);
552
553        if (fTail != NULL)
554            fTail->fNext = block;
555        else
556            fHead = fTail = block;
557        fTail = block;
558    }
559    return true;
560}
561
562bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
563{
564    if (offset + count > fBytesWritten) {
565        return false; // test does not partially modify
566    }
567
568    this->invalidateCopy();
569
570    Block* block = fHead;
571    while (block != NULL) {
572        size_t size = block->written();
573        if (offset < size) {
574            size_t part = offset + count > size ? size - offset : count;
575            memcpy(block->start() + offset, buffer, part);
576            if (count <= part)
577                return true;
578            count -= part;
579            buffer = (const void*) ((char* ) buffer + part);
580        }
581        offset = offset > size ? offset - size : 0;
582        block = block->fNext;
583    }
584    return false;
585}
586
587bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
588{
589    if (offset + count > fBytesWritten)
590        return false; // test does not partially modify
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(buffer, block->start() + offset, part);
597            if (count <= part)
598                return true;
599            count -= part;
600            buffer = (void*) ((char* ) buffer + part);
601        }
602        offset = offset > size ? offset - size : 0;
603        block = block->fNext;
604    }
605    return false;
606}
607
608void SkDynamicMemoryWStream::copyTo(void* dst) const
609{
610    if (fCopy) {
611        memcpy(dst, fCopy->data(), fBytesWritten);
612    } else {
613        Block* block = fHead;
614
615        while (block != NULL) {
616            size_t size = block->written();
617            memcpy(dst, block->start(), size);
618            dst = (void*)((char*)dst + size);
619            block = block->fNext;
620        }
621    }
622}
623
624void SkDynamicMemoryWStream::padToAlign4()
625{
626    // cast to remove unary-minus warning
627    int padBytes = -(int)fBytesWritten & 0x03;
628    if (padBytes == 0)
629        return;
630    int zero = 0;
631    write(&zero, padBytes);
632}
633
634SkData* SkDynamicMemoryWStream::copyToData() const {
635    if (NULL == fCopy) {
636        SkData* data = SkData::NewUninitialized(fBytesWritten);
637        // be sure to call copyTo() before we assign to fCopy
638        this->copyTo(data->writable_data());
639        fCopy = data;
640    }
641    return SkRef(fCopy);
642}
643
644void SkDynamicMemoryWStream::invalidateCopy() {
645    if (fCopy) {
646        fCopy->unref();
647        fCopy = NULL;
648    }
649}
650
651class SkBlockMemoryRefCnt : public SkRefCnt {
652public:
653    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
654
655    virtual ~SkBlockMemoryRefCnt() {
656        SkDynamicMemoryWStream::Block* block = fHead;
657        while (block != NULL) {
658            SkDynamicMemoryWStream::Block* next = block->fNext;
659            sk_free(block);
660            block = next;
661        }
662    }
663
664    SkDynamicMemoryWStream::Block* const fHead;
665};
666
667class SkBlockMemoryStream : public SkStreamAsset {
668public:
669    SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
670        : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
671        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
672
673    SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
674        : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
675        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
676
677    virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
678        size_t count = rawCount;
679        if (fOffset + count > fSize) {
680            count = fSize - fOffset;
681        }
682        size_t bytesLeftToRead = count;
683        while (fCurrent != NULL) {
684            size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
685            size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
686            if (buffer) {
687                memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
688                buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
689            }
690            if (bytesLeftToRead <= bytesFromCurrent) {
691                fCurrentOffset += bytesFromCurrent;
692                fOffset += count;
693                return count;
694            }
695            bytesLeftToRead -= bytesFromCurrent;
696            fCurrent = fCurrent->fNext;
697            fCurrentOffset = 0;
698        }
699        SkASSERT(false);
700        return 0;
701    }
702
703    virtual bool isAtEnd() const SK_OVERRIDE {
704        return fOffset == fSize;
705    }
706
707    virtual bool rewind() SK_OVERRIDE {
708        fCurrent = fBlockMemory->fHead;
709        fOffset = 0;
710        fCurrentOffset = 0;
711        return true;
712    }
713
714    virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
715        return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
716    }
717
718    virtual size_t getPosition() const SK_OVERRIDE {
719        return fOffset;
720    }
721
722    virtual bool seek(size_t position) SK_OVERRIDE {
723        // If possible, skip forward.
724        if (position >= fOffset) {
725            size_t skipAmount = position - fOffset;
726            return this->skip(skipAmount) == skipAmount;
727        }
728        // If possible, move backward within the current block.
729        size_t moveBackAmount = fOffset - position;
730        if (moveBackAmount <= fCurrentOffset) {
731            fCurrentOffset -= moveBackAmount;
732            fOffset -= moveBackAmount;
733            return true;
734        }
735        // Otherwise rewind and move forward.
736        return this->rewind() && this->skip(position) == position;
737    }
738
739    virtual bool move(long offset) SK_OVERRIDE {
740        return seek(fOffset + offset);
741    }
742
743    virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
744        SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
745        that->fCurrent = this->fCurrent;
746        that->fOffset = this->fOffset;
747        that->fCurrentOffset = this->fCurrentOffset;
748        return that.detach();
749    }
750
751    virtual size_t getLength() const SK_OVERRIDE {
752        return fSize;
753    }
754
755    virtual const void* getMemoryBase() SK_OVERRIDE {
756        if (NULL == fBlockMemory->fHead->fNext) {
757            return fBlockMemory->fHead->start();
758        }
759        return NULL;
760    }
761
762private:
763    SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
764    SkDynamicMemoryWStream::Block const * fCurrent;
765    size_t const fSize;
766    size_t fOffset;
767    size_t fCurrentOffset;
768};
769
770SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
771    if (fCopy) {
772        SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
773        this->reset();
774        return stream;
775    }
776    SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
777    fHead = 0;
778    this->reset();
779    return stream;
780}
781
782///////////////////////////////////////////////////////////////////////////////
783
784void SkDebugWStream::newline()
785{
786#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
787    SkDebugf("\n");
788    fBytesWritten++;
789#endif
790}
791
792bool SkDebugWStream::write(const void* buffer, size_t size)
793{
794#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
795    char* s = new char[size+1];
796    memcpy(s, buffer, size);
797    s[size] = 0;
798    SkDebugf("%s", s);
799    delete[] s;
800    fBytesWritten += size;
801#endif
802    return true;
803}
804
805///////////////////////////////////////////////////////////////////////////////
806///////////////////////////////////////////////////////////////////////////////
807
808
809static SkData* mmap_filename(const char path[]) {
810    SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
811    if (NULL == file) {
812        return NULL;
813    }
814
815    SkData* data = SkData::NewFromFILE(file);
816    sk_fclose(file);
817    return data;
818}
819
820SkStreamAsset* SkStream::NewFromFile(const char path[]) {
821    SkAutoTUnref<SkData> data(mmap_filename(path));
822    if (data.get()) {
823        return SkNEW_ARGS(SkMemoryStream, (data.get()));
824    }
825
826    // If we get here, then our attempt at using mmap failed, so try normal
827    // file access.
828    SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
829    if (!stream->isValid()) {
830        stream->unref();
831        stream = NULL;
832    }
833    return stream;
834}
835
836// Declared in SkStreamPriv.h:
837size_t SkCopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) {
838    SkASSERT(storage != NULL);
839    SkASSERT(stream != NULL);
840
841    if (stream->hasLength()) {
842        const size_t length = stream->getLength();
843        void* dst = storage->reset(length);
844        if (stream->read(dst, length) != length) {
845            return 0;
846        }
847        return length;
848    }
849
850    SkDynamicMemoryWStream tempStream;
851    // Arbitrary buffer size.
852    const size_t bufferSize = 256 * 1024; // 256KB
853    char buffer[bufferSize];
854    SkDEBUGCODE(size_t debugLength = 0;)
855    do {
856        size_t bytesRead = stream->read(buffer, bufferSize);
857        tempStream.write(buffer, bytesRead);
858        SkDEBUGCODE(debugLength += bytesRead);
859        SkASSERT(tempStream.bytesWritten() == debugLength);
860    } while (!stream->isAtEnd());
861    const size_t length = tempStream.bytesWritten();
862    void* dst = storage->reset(length);
863    tempStream.copyTo(dst);
864    return length;
865}
866
867// Declared in SkStreamPriv.h:
868SkData* SkCopyStreamToData(SkStream* stream) {
869    SkASSERT(stream != NULL);
870
871    if (stream->hasLength()) {
872        return SkData::NewFromStream(stream, stream->getLength());
873    }
874
875    SkDynamicMemoryWStream tempStream;
876    const size_t bufferSize = 4096;
877    char buffer[bufferSize];
878    do {
879        size_t bytesRead = stream->read(buffer, bufferSize);
880        tempStream.write(buffer, bytesRead);
881    } while (!stream->isAtEnd());
882    return tempStream.copyToData();
883}
884
885SkStreamRewindable* SkStreamRewindableFromSkStream(SkStream* stream) {
886    if (!stream) {
887        return NULL;
888    }
889    SkAutoTUnref<SkStreamRewindable> dupStream(stream->duplicate());
890    if (dupStream) {
891        return dupStream.detach();
892    }
893    stream->rewind();
894    if (stream->hasLength()) {
895        size_t length = stream->getLength();
896        if (stream->hasPosition()) {  // If stream has length, but can't rewind.
897            length -= stream->getPosition();
898        }
899        SkAutoTUnref<SkData> data(SkData::NewFromStream(stream, length));
900        return SkNEW_ARGS(SkMemoryStream, (data.get()));
901    }
902    SkDynamicMemoryWStream tempStream;
903    const size_t bufferSize = 4096;
904    char buffer[bufferSize];
905    do {
906        size_t bytesRead = stream->read(buffer, bufferSize);
907        tempStream.write(buffer, bytesRead);
908    } while (!stream->isAtEnd());
909    return tempStream.detachAsStream();  // returns a SkBlockMemoryStream,
910                                         // cheaper than copying to SkData
911}
912