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
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 = 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
181bool SkWStream::writeData(const SkData* data) {
182    if (data) {
183        this->write32(data->size());
184        this->write(data->data(), data->size());
185    } else {
186        this->write32(0);
187    }
188    return true;
189}
190
191///////////////////////////////////////////////////////////////////////////////
192
193SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
194    fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
195}
196
197SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
198    : fFILE((SkFILE*)file)
199    , fOwnership(ownership) {
200}
201
202SkFILEStream::~SkFILEStream() {
203    if (fFILE && fOwnership != kCallerRetains_Ownership) {
204        sk_fclose(fFILE);
205    }
206}
207
208void SkFILEStream::setPath(const char path[]) {
209    fName.set(path);
210    if (fFILE) {
211        sk_fclose(fFILE);
212        fFILE = NULL;
213    }
214    if (path) {
215        fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
216    }
217}
218
219size_t SkFILEStream::read(void* buffer, size_t size) {
220    if (fFILE) {
221        return sk_fread(buffer, size, fFILE);
222    }
223    return 0;
224}
225
226bool SkFILEStream::isAtEnd() const {
227    return sk_feof(fFILE);
228}
229
230bool SkFILEStream::rewind() {
231    if (fFILE) {
232        if (sk_frewind(fFILE)) {
233            return true;
234        }
235        // we hit an error
236        sk_fclose(fFILE);
237        fFILE = NULL;
238    }
239    return false;
240}
241
242SkStreamAsset* SkFILEStream::duplicate() const {
243    if (NULL == fFILE) {
244        return new SkMemoryStream();
245    }
246
247    if (NULL != fData.get()) {
248        return new SkMemoryStream(fData);
249    }
250
251    if (!fName.isEmpty()) {
252        SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
253        if (sk_fidentical(that->fFILE, this->fFILE)) {
254            return that.detach();
255        }
256    }
257
258    fData.reset(SkData::NewFromFILE(fFILE));
259    if (NULL == fData.get()) {
260        return NULL;
261    }
262    return new SkMemoryStream(fData);
263}
264
265size_t SkFILEStream::getPosition() const {
266    return sk_ftell(fFILE);
267}
268
269bool SkFILEStream::seek(size_t position) {
270    return sk_fseek(fFILE, position);
271}
272
273bool SkFILEStream::move(long offset) {
274    return sk_fmove(fFILE, offset);
275}
276
277SkStreamAsset* SkFILEStream::fork() const {
278    SkAutoTUnref<SkStreamAsset> that(this->duplicate());
279    that->seek(this->getPosition());
280    return that.detach();
281}
282
283size_t SkFILEStream::getLength() const {
284    return sk_fgetsize(fFILE);
285}
286
287const void* SkFILEStream::getMemoryBase() {
288    if (NULL == fData.get()) {
289        return NULL;
290    }
291    return fData->data();
292}
293
294///////////////////////////////////////////////////////////////////////////////
295
296static SkData* newFromParams(const void* src, size_t size, bool copyData) {
297    if (copyData) {
298        return SkData::NewWithCopy(src, size);
299    } else {
300        return SkData::NewWithProc(src, size, NULL, NULL);
301    }
302}
303
304SkMemoryStream::SkMemoryStream() {
305    fData = SkData::NewEmpty();
306    fOffset = 0;
307}
308
309SkMemoryStream::SkMemoryStream(size_t size) {
310    fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
311    fOffset = 0;
312}
313
314SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
315    fData = newFromParams(src, size, copyData);
316    fOffset = 0;
317}
318
319SkMemoryStream::SkMemoryStream(SkData* data) {
320    if (NULL == data) {
321        fData = SkData::NewEmpty();
322    } else {
323        fData = data;
324        fData->ref();
325    }
326    fOffset = 0;
327}
328
329SkMemoryStream::~SkMemoryStream() {
330    fData->unref();
331}
332
333void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
334    fData->unref();
335    fData = SkData::NewFromMalloc(src, size);
336    fOffset = 0;
337}
338
339void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
340    fData->unref();
341    fData = newFromParams(src, size, copyData);
342    fOffset = 0;
343}
344
345SkData* SkMemoryStream::copyToData() const {
346    fData->ref();
347    return fData;
348}
349
350SkData* SkMemoryStream::setData(SkData* data) {
351    fData->unref();
352    if (NULL == data) {
353        fData = SkData::NewEmpty();
354    } else {
355        fData = data;
356        fData->ref();
357    }
358    fOffset = 0;
359    return data;
360}
361
362void SkMemoryStream::skipToAlign4() {
363    // cast to remove unary-minus warning
364    fOffset += -(int)fOffset & 0x03;
365}
366
367size_t SkMemoryStream::read(void* buffer, size_t size) {
368    size_t dataSize = fData->size();
369
370    if (size > dataSize - fOffset) {
371        size = dataSize - fOffset;
372    }
373    if (buffer) {
374        memcpy(buffer, fData->bytes() + fOffset, size);
375    }
376    fOffset += size;
377    return size;
378}
379
380bool SkMemoryStream::isAtEnd() const {
381    return fOffset == fData->size();
382}
383
384bool SkMemoryStream::rewind() {
385    fOffset = 0;
386    return true;
387}
388
389SkMemoryStream* SkMemoryStream::duplicate() const {
390    return SkNEW_ARGS(SkMemoryStream, (fData));
391}
392
393size_t SkMemoryStream::getPosition() const {
394    return fOffset;
395}
396
397bool SkMemoryStream::seek(size_t position) {
398    fOffset = position > fData->size()
399            ? fData->size()
400            : position;
401    return true;
402}
403
404bool SkMemoryStream::move(long offset) {
405    return this->seek(fOffset + offset);
406}
407
408SkMemoryStream* SkMemoryStream::fork() const {
409    SkAutoTUnref<SkMemoryStream> that(this->duplicate());
410    that->seek(fOffset);
411    return that.detach();
412}
413
414size_t SkMemoryStream::getLength() const {
415    return fData->size();
416}
417
418const void* SkMemoryStream::getMemoryBase() {
419    return fData->data();
420}
421
422const void* SkMemoryStream::getAtPos() {
423    return fData->bytes() + fOffset;
424}
425
426/////////////////////////////////////////////////////////////////////////////////////////////////////////
427/////////////////////////////////////////////////////////////////////////////////////////////////////////
428
429SkFILEWStream::SkFILEWStream(const char path[])
430{
431    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
432}
433
434SkFILEWStream::~SkFILEWStream()
435{
436    if (fFILE)
437        sk_fclose(fFILE);
438}
439
440bool SkFILEWStream::write(const void* buffer, size_t size)
441{
442    if (fFILE == NULL)
443        return false;
444
445    if (sk_fwrite(buffer, size, fFILE) != size)
446    {
447        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
448        sk_fclose(fFILE);
449        fFILE = NULL;
450        return false;
451    }
452    return true;
453}
454
455void SkFILEWStream::flush()
456{
457    if (fFILE)
458        sk_fflush(fFILE);
459}
460
461////////////////////////////////////////////////////////////////////////
462
463SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
464    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
465{
466}
467
468bool SkMemoryWStream::write(const void* buffer, size_t size)
469{
470    size = SkMin32(size, fMaxLength - fBytesWritten);
471    if (size > 0)
472    {
473        memcpy(fBuffer + fBytesWritten, buffer, size);
474        fBytesWritten += size;
475        return true;
476    }
477    return false;
478}
479
480////////////////////////////////////////////////////////////////////////
481
482#define SkDynamicMemoryWStream_MinBlockSize   256
483
484struct SkDynamicMemoryWStream::Block {
485    Block*  fNext;
486    char*   fCurr;
487    char*   fStop;
488
489    const char* start() const { return (const char*)(this + 1); }
490    char*   start() { return (char*)(this + 1); }
491    size_t  avail() const { return fStop - fCurr; }
492    size_t  written() const { return fCurr - this->start(); }
493
494    void init(size_t size)
495    {
496        fNext = NULL;
497        fCurr = this->start();
498        fStop = this->start() + size;
499    }
500
501    const void* append(const void* data, size_t size)
502    {
503        SkASSERT((size_t)(fStop - fCurr) >= size);
504        memcpy(fCurr, data, size);
505        fCurr += size;
506        return (const void*)((const char*)data + size);
507    }
508};
509
510SkDynamicMemoryWStream::SkDynamicMemoryWStream()
511    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
512{
513}
514
515SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
516{
517    reset();
518}
519
520void SkDynamicMemoryWStream::reset()
521{
522    this->invalidateCopy();
523
524    Block*  block = fHead;
525
526    while (block != NULL) {
527        Block*  next = block->fNext;
528        sk_free(block);
529        block = next;
530    }
531    fHead = fTail = NULL;
532    fBytesWritten = 0;
533}
534
535bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
536{
537    if (count > 0) {
538        this->invalidateCopy();
539
540        fBytesWritten += count;
541
542        size_t  size;
543
544        if (fTail != NULL && fTail->avail() > 0) {
545            size = SkMin32(fTail->avail(), count);
546            buffer = fTail->append(buffer, size);
547            SkASSERT(count >= size);
548            count -= size;
549            if (count == 0)
550                return true;
551        }
552
553        size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
554        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
555        block->init(size);
556        block->append(buffer, count);
557
558        if (fTail != NULL)
559            fTail->fNext = block;
560        else
561            fHead = fTail = block;
562        fTail = block;
563    }
564    return true;
565}
566
567bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
568{
569    if (offset + count > fBytesWritten) {
570        return false; // test does not partially modify
571    }
572
573    this->invalidateCopy();
574
575    Block* block = fHead;
576    while (block != NULL) {
577        size_t size = block->written();
578        if (offset < size) {
579            size_t part = offset + count > size ? size - offset : count;
580            memcpy(block->start() + offset, buffer, part);
581            if (count <= part)
582                return true;
583            count -= part;
584            buffer = (const void*) ((char* ) buffer + part);
585        }
586        offset = offset > size ? offset - size : 0;
587        block = block->fNext;
588    }
589    return false;
590}
591
592bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
593{
594    if (offset + count > fBytesWritten)
595        return false; // test does not partially modify
596    Block* block = fHead;
597    while (block != NULL) {
598        size_t size = block->written();
599        if (offset < size) {
600            size_t part = offset + count > size ? size - offset : count;
601            memcpy(buffer, block->start() + offset, part);
602            if (count <= part)
603                return true;
604            count -= part;
605            buffer = (void*) ((char* ) buffer + part);
606        }
607        offset = offset > size ? offset - size : 0;
608        block = block->fNext;
609    }
610    return false;
611}
612
613void SkDynamicMemoryWStream::copyTo(void* dst) const
614{
615    if (fCopy) {
616        memcpy(dst, fCopy->data(), fBytesWritten);
617    } else {
618        Block* block = fHead;
619
620        while (block != NULL) {
621            size_t size = block->written();
622            memcpy(dst, block->start(), size);
623            dst = (void*)((char*)dst + size);
624            block = block->fNext;
625        }
626    }
627}
628
629void SkDynamicMemoryWStream::padToAlign4()
630{
631    // cast to remove unary-minus warning
632    int padBytes = -(int)fBytesWritten & 0x03;
633    if (padBytes == 0)
634        return;
635    int zero = 0;
636    write(&zero, padBytes);
637}
638
639SkData* SkDynamicMemoryWStream::copyToData() const {
640    if (NULL == fCopy) {
641        void* buffer = sk_malloc_throw(fBytesWritten);
642        this->copyTo(buffer);
643        fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
644    }
645    fCopy->ref();
646    return fCopy;
647}
648
649void SkDynamicMemoryWStream::invalidateCopy() {
650    if (fCopy) {
651        fCopy->unref();
652        fCopy = NULL;
653    }
654}
655
656class SkBlockMemoryRefCnt : public SkRefCnt {
657public:
658    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
659
660    virtual ~SkBlockMemoryRefCnt() {
661        SkDynamicMemoryWStream::Block* block = fHead;
662        while (block != NULL) {
663            SkDynamicMemoryWStream::Block* next = block->fNext;
664            sk_free(block);
665            block = next;
666        }
667    }
668
669    SkDynamicMemoryWStream::Block* const fHead;
670};
671
672class SkBlockMemoryStream : public SkStreamAsset {
673public:
674    SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
675        : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
676        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
677
678    SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
679        : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
680        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
681
682    virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
683        size_t count = rawCount;
684        if (fOffset + count > fSize) {
685            count = fSize - fOffset;
686        }
687        size_t bytesLeftToRead = count;
688        while (fCurrent != NULL) {
689            size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
690            size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent
691                                    ? bytesLeftToRead  : bytesLeftInCurrent;
692            if (buffer) {
693                memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
694            }
695            if (bytesLeftToRead <= bytesFromCurrent) {
696                fCurrentOffset += bytesFromCurrent;
697                fOffset += count;
698                return count;
699            }
700            bytesLeftToRead -= bytesFromCurrent;
701            buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
702            fCurrent = fCurrent->fNext;
703            fCurrentOffset = 0;
704        }
705        SkASSERT(false);
706        return 0;
707    }
708
709    virtual bool isAtEnd() const SK_OVERRIDE {
710        return fOffset == fSize;
711    }
712
713    virtual bool rewind() SK_OVERRIDE {
714        fCurrent = fBlockMemory->fHead;
715        fOffset = 0;
716        fCurrentOffset = 0;
717        return true;
718    }
719
720    virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
721        return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
722    }
723
724    virtual size_t getPosition() const SK_OVERRIDE {
725        return fOffset;
726    }
727
728    virtual bool seek(size_t position) SK_OVERRIDE {
729        // If possible, skip forward.
730        if (position >= fOffset) {
731            size_t skipAmount = position - fOffset;
732            return this->skip(skipAmount) == skipAmount;
733        }
734        // If possible, move backward within the current block.
735        size_t moveBackAmount = fOffset - position;
736        if (moveBackAmount <= fCurrentOffset) {
737            fCurrentOffset -= moveBackAmount;
738            fOffset -= moveBackAmount;
739            return true;
740        }
741        // Otherwise rewind and move forward.
742        return this->rewind() && this->skip(position) == position;
743    }
744
745    virtual bool move(long offset) SK_OVERRIDE {
746        return seek(fOffset + offset);
747    }
748
749    virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
750        SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
751        that->fCurrent = this->fCurrent;
752        that->fOffset = this->fOffset;
753        that->fCurrentOffset = this->fCurrentOffset;
754        return that.detach();
755    }
756
757    virtual size_t getLength() const SK_OVERRIDE {
758        return fSize;
759    }
760
761    virtual const void* getMemoryBase() SK_OVERRIDE {
762        if (NULL == fBlockMemory->fHead->fNext) {
763            return fBlockMemory->fHead->start();
764        }
765        return NULL;
766    }
767
768private:
769    SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
770    SkDynamicMemoryWStream::Block const * fCurrent;
771    size_t const fSize;
772    size_t fOffset;
773    size_t fCurrentOffset;
774};
775
776SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
777    if (fCopy) {
778        SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
779        this->reset();
780        return stream;
781    }
782    SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
783    fHead = 0;
784    this->reset();
785    return stream;
786}
787
788///////////////////////////////////////////////////////////////////////////////
789
790void SkDebugWStream::newline()
791{
792#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
793    SkDebugf("\n");
794#endif
795}
796
797bool SkDebugWStream::write(const void* buffer, size_t size)
798{
799#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
800    char* s = new char[size+1];
801    memcpy(s, buffer, size);
802    s[size] = 0;
803    SkDebugf("%s", s);
804    delete[] s;
805#endif
806    return true;
807}
808
809///////////////////////////////////////////////////////////////////////////////
810///////////////////////////////////////////////////////////////////////////////
811
812
813static SkData* mmap_filename(const char path[]) {
814    SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
815    if (NULL == file) {
816        return NULL;
817    }
818
819    SkData* data = SkData::NewFromFILE(file);
820    sk_fclose(file);
821    return data;
822}
823
824SkStreamAsset* SkStream::NewFromFile(const char path[]) {
825    SkAutoTUnref<SkData> data(mmap_filename(path));
826    if (data.get()) {
827        return SkNEW_ARGS(SkMemoryStream, (data.get()));
828    }
829
830    // If we get here, then our attempt at using mmap failed, so try normal
831    // file access.
832    SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
833    if (!stream->isValid()) {
834        stream->unref();
835        stream = NULL;
836    }
837    return stream;
838}
839