SkStream.cpp revision 6cab1a4b6a68aa81237731308ff37a646d48f51c
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
16SK_DEFINE_INST_COUNT(SkStream)
17SK_DEFINE_INST_COUNT(SkWStream)
18SK_DEFINE_INST_COUNT(SkFILEStream)
19SK_DEFINE_INST_COUNT(SkMemoryStream)
20SK_DEFINE_INST_COUNT(SkFILEWStream)
21SK_DEFINE_INST_COUNT(SkMemoryWStream)
22SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream)
23SK_DEFINE_INST_COUNT(SkDebugWStream)
24
25///////////////////////////////////////////////////////////////////////////////
26
27
28int8_t SkStream::readS8() {
29    int8_t value;
30    SkDEBUGCODE(size_t len =) this->read(&value, 1);
31    SkASSERT(1 == len);
32    return value;
33}
34
35int16_t SkStream::readS16() {
36    int16_t value;
37    SkDEBUGCODE(size_t len =) this->read(&value, 2);
38    SkASSERT(2 == len);
39    return value;
40}
41
42int32_t SkStream::readS32() {
43    int32_t value;
44    SkDEBUGCODE(size_t len =) this->read(&value, 4);
45    SkASSERT(4 == len);
46    return value;
47}
48
49SkScalar SkStream::readScalar() {
50    SkScalar value;
51    SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
52    SkASSERT(sizeof(SkScalar) == len);
53    return value;
54}
55
56#define SK_MAX_BYTE_FOR_U8          0xFD
57#define SK_BYTE_SENTINEL_FOR_U16    0xFE
58#define SK_BYTE_SENTINEL_FOR_U32    0xFF
59
60size_t SkStream::readPackedUInt() {
61    uint8_t byte;
62    if (!this->read(&byte, 1)) {
63        return 0;
64    }
65    if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
66        return this->readU16();
67    } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
68        return this->readU32();
69    } else {
70        return byte;
71    }
72}
73
74SkData* SkStream::readData() {
75    size_t size = this->readU32();
76    if (0 == size) {
77        return SkData::NewEmpty();
78    } else {
79        void* buffer = sk_malloc_throw(size);
80        this->read(buffer, size);
81        return SkData::NewFromMalloc(buffer, size);
82    }
83}
84
85//////////////////////////////////////////////////////////////////////////////////////
86
87SkWStream::~SkWStream()
88{
89}
90
91void SkWStream::newline()
92{
93    this->write("\n", 1);
94}
95
96void SkWStream::flush()
97{
98}
99
100bool SkWStream::writeText(const char text[])
101{
102    SkASSERT(text);
103    return this->write(text, strlen(text));
104}
105
106bool SkWStream::writeDecAsText(int32_t dec)
107{
108    SkString    tmp;
109    tmp.appendS32(dec);
110    return this->write(tmp.c_str(), tmp.size());
111}
112
113bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
114{
115    SkString    tmp;
116    tmp.appendS64(dec, minDigits);
117    return this->write(tmp.c_str(), tmp.size());
118}
119
120bool SkWStream::writeHexAsText(uint32_t hex, int digits)
121{
122    SkString    tmp;
123    tmp.appendHex(hex, digits);
124    return this->write(tmp.c_str(), tmp.size());
125}
126
127bool SkWStream::writeScalarAsText(SkScalar value)
128{
129    SkString    tmp;
130    tmp.appendScalar(value);
131    return this->write(tmp.c_str(), tmp.size());
132}
133
134bool SkWStream::write8(U8CPU value) {
135    uint8_t v = SkToU8(value);
136    return this->write(&v, 1);
137}
138
139bool SkWStream::write16(U16CPU value) {
140    uint16_t v = SkToU16(value);
141    return this->write(&v, 2);
142}
143
144bool SkWStream::write32(uint32_t value) {
145    return this->write(&value, 4);
146}
147
148bool SkWStream::writeScalar(SkScalar value) {
149    return this->write(&value, sizeof(value));
150}
151
152bool SkWStream::writePackedUInt(size_t value) {
153    uint8_t data[5];
154    size_t len = 1;
155    if (value <= SK_MAX_BYTE_FOR_U8) {
156        data[0] = value;
157        len = 1;
158    } else if (value <= 0xFFFF) {
159        uint16_t value16 = value;
160        data[0] = SK_BYTE_SENTINEL_FOR_U16;
161        memcpy(&data[1], &value16, 2);
162        len = 3;
163    } else {
164        uint32_t value32 = value;
165        data[0] = SK_BYTE_SENTINEL_FOR_U32;
166        memcpy(&data[1], &value32, 4);
167        len = 5;
168    }
169    return this->write(data, len);
170}
171
172bool SkWStream::writeStream(SkStream* stream, size_t length) {
173    char scratch[1024];
174    const size_t MAX = sizeof(scratch);
175
176    while (length != 0) {
177        size_t n = length;
178        if (n > MAX) {
179            n = MAX;
180        }
181        stream->read(scratch, n);
182        if (!this->write(scratch, n)) {
183            return false;
184        }
185        length -= n;
186    }
187    return true;
188}
189
190bool SkWStream::writeData(const SkData* data) {
191    if (data) {
192        this->write32(data->size());
193        this->write(data->data(), data->size());
194    } else {
195        this->write32(0);
196    }
197    return true;
198}
199
200///////////////////////////////////////////////////////////////////////////////
201
202SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
203    fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
204}
205
206SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
207    : fFILE((SkFILE*)file)
208    , fOwnership(ownership) {
209}
210
211SkFILEStream::~SkFILEStream() {
212    if (fFILE && fOwnership != kCallerRetains_Ownership) {
213        sk_fclose(fFILE);
214    }
215}
216
217void SkFILEStream::setPath(const char path[]) {
218    fName.set(path);
219    if (fFILE) {
220        sk_fclose(fFILE);
221        fFILE = NULL;
222    }
223    if (path) {
224        fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
225    }
226}
227
228size_t SkFILEStream::read(void* buffer, size_t size) {
229    if (fFILE) {
230        return sk_fread(buffer, size, fFILE);
231    }
232    return 0;
233}
234
235bool SkFILEStream::isAtEnd() const {
236    return sk_feof(fFILE);
237}
238
239bool SkFILEStream::rewind() {
240    if (fFILE) {
241        if (sk_frewind(fFILE)) {
242            return true;
243        }
244        // we hit an error
245        sk_fclose(fFILE);
246        fFILE = NULL;
247    }
248    return false;
249}
250
251SkStreamAsset* SkFILEStream::duplicate() const {
252    if (NULL == fFILE) {
253        return new SkMemoryStream();
254    }
255
256    if (NULL != fData.get()) {
257        return new SkMemoryStream(fData);
258    }
259
260    if (!fName.isEmpty()) {
261        SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
262        if (sk_fidentical(that->fFILE, this->fFILE)) {
263            return that.detach();
264        }
265    }
266
267    fData.reset(SkData::NewFromFILE(fFILE));
268    if (NULL == fData.get()) {
269        return NULL;
270    }
271    return new SkMemoryStream(fData);
272}
273
274size_t SkFILEStream::getPosition() const {
275    return sk_ftell(fFILE);
276}
277
278bool SkFILEStream::seek(size_t position) {
279    return sk_fseek(fFILE, position);
280}
281
282bool SkFILEStream::move(long offset) {
283    return sk_fmove(fFILE, offset);
284}
285
286SkStreamAsset* SkFILEStream::fork() const {
287    SkAutoTUnref<SkStreamAsset> that(this->duplicate());
288    that->seek(this->getPosition());
289    return that.detach();
290}
291
292size_t SkFILEStream::getLength() const {
293    return sk_fgetsize(fFILE);
294}
295
296const void* SkFILEStream::getMemoryBase() {
297    if (NULL == fData.get()) {
298        return NULL;
299    }
300    return fData->data();
301}
302
303///////////////////////////////////////////////////////////////////////////////
304
305static SkData* newFromParams(const void* src, size_t size, bool copyData) {
306    if (copyData) {
307        return SkData::NewWithCopy(src, size);
308    } else {
309        return SkData::NewWithProc(src, size, NULL, NULL);
310    }
311}
312
313SkMemoryStream::SkMemoryStream() {
314    fData = SkData::NewEmpty();
315    fOffset = 0;
316}
317
318SkMemoryStream::SkMemoryStream(size_t size) {
319    fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
320    fOffset = 0;
321}
322
323SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
324    fData = newFromParams(src, size, copyData);
325    fOffset = 0;
326}
327
328SkMemoryStream::SkMemoryStream(SkData* data) {
329    if (NULL == data) {
330        fData = SkData::NewEmpty();
331    } else {
332        fData = data;
333        fData->ref();
334    }
335    fOffset = 0;
336}
337
338SkMemoryStream::~SkMemoryStream() {
339    fData->unref();
340}
341
342void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
343    fData->unref();
344    fData = SkData::NewFromMalloc(src, size);
345    fOffset = 0;
346}
347
348void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
349    fData->unref();
350    fData = newFromParams(src, size, copyData);
351    fOffset = 0;
352}
353
354SkData* SkMemoryStream::copyToData() const {
355    fData->ref();
356    return fData;
357}
358
359SkData* SkMemoryStream::setData(SkData* data) {
360    fData->unref();
361    if (NULL == data) {
362        fData = SkData::NewEmpty();
363    } else {
364        fData = data;
365        fData->ref();
366    }
367    return data;
368}
369
370void SkMemoryStream::skipToAlign4() {
371    // cast to remove unary-minus warning
372    fOffset += -(int)fOffset & 0x03;
373}
374
375size_t SkMemoryStream::read(void* buffer, size_t size) {
376    size_t dataSize = fData->size();
377
378    if (size > dataSize - fOffset) {
379        size = dataSize - fOffset;
380    }
381    if (buffer) {
382        memcpy(buffer, fData->bytes() + fOffset, size);
383    }
384    fOffset += size;
385    return size;
386}
387
388bool SkMemoryStream::isAtEnd() const {
389    return fOffset == fData->size();
390}
391
392bool SkMemoryStream::rewind() {
393    fOffset = 0;
394    return true;
395}
396
397SkMemoryStream* SkMemoryStream::duplicate() const {
398    return SkNEW_ARGS(SkMemoryStream, (fData));
399}
400
401size_t SkMemoryStream::getPosition() const {
402    return fOffset;
403}
404
405bool SkMemoryStream::seek(size_t position) {
406    fOffset = position > fData->size()
407            ? fData->size()
408            : position;
409    return true;
410}
411
412bool SkMemoryStream::move(long offset) {
413    return this->seek(fOffset + offset);
414}
415
416SkMemoryStream* SkMemoryStream::fork() const {
417    SkAutoTUnref<SkMemoryStream> that(this->duplicate());
418    that->seek(fOffset);
419    return that.detach();
420}
421
422size_t SkMemoryStream::getLength() const {
423    return fData->size();
424}
425
426const void* SkMemoryStream::getMemoryBase() {
427    return fData->data();
428}
429
430const void* SkMemoryStream::getAtPos() {
431    return fData->bytes() + fOffset;
432}
433
434/////////////////////////////////////////////////////////////////////////////////////////////////////////
435/////////////////////////////////////////////////////////////////////////////////////////////////////////
436
437SkFILEWStream::SkFILEWStream(const char path[])
438{
439    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
440}
441
442SkFILEWStream::~SkFILEWStream()
443{
444    if (fFILE)
445        sk_fclose(fFILE);
446}
447
448bool SkFILEWStream::write(const void* buffer, size_t size)
449{
450    if (fFILE == NULL)
451        return false;
452
453    if (sk_fwrite(buffer, size, fFILE) != size)
454    {
455        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
456        sk_fclose(fFILE);
457        fFILE = NULL;
458        return false;
459    }
460    return true;
461}
462
463void SkFILEWStream::flush()
464{
465    if (fFILE)
466        sk_fflush(fFILE);
467}
468
469////////////////////////////////////////////////////////////////////////
470
471SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
472    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
473{
474}
475
476bool SkMemoryWStream::write(const void* buffer, size_t size)
477{
478    size = SkMin32(size, fMaxLength - fBytesWritten);
479    if (size > 0)
480    {
481        memcpy(fBuffer + fBytesWritten, buffer, size);
482        fBytesWritten += size;
483        return true;
484    }
485    return false;
486}
487
488////////////////////////////////////////////////////////////////////////
489
490#define SkDynamicMemoryWStream_MinBlockSize   256
491
492struct SkDynamicMemoryWStream::Block {
493    Block*  fNext;
494    char*   fCurr;
495    char*   fStop;
496
497    const char* start() const { return (const char*)(this + 1); }
498    char*   start() { return (char*)(this + 1); }
499    size_t  avail() const { return fStop - fCurr; }
500    size_t  written() const { return fCurr - this->start(); }
501
502    void init(size_t size)
503    {
504        fNext = NULL;
505        fCurr = this->start();
506        fStop = this->start() + size;
507    }
508
509    const void* append(const void* data, size_t size)
510    {
511        SkASSERT((size_t)(fStop - fCurr) >= size);
512        memcpy(fCurr, data, size);
513        fCurr += size;
514        return (const void*)((const char*)data + size);
515    }
516};
517
518SkDynamicMemoryWStream::SkDynamicMemoryWStream()
519    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
520{
521}
522
523SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
524{
525    reset();
526}
527
528void SkDynamicMemoryWStream::reset()
529{
530    this->invalidateCopy();
531
532    Block*  block = fHead;
533
534    while (block != NULL) {
535        Block*  next = block->fNext;
536        sk_free(block);
537        block = next;
538    }
539    fHead = fTail = NULL;
540    fBytesWritten = 0;
541}
542
543bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
544{
545    if (count > 0) {
546        this->invalidateCopy();
547
548        fBytesWritten += count;
549
550        size_t  size;
551
552        if (fTail != NULL && fTail->avail() > 0) {
553            size = SkMin32(fTail->avail(), count);
554            buffer = fTail->append(buffer, size);
555            SkASSERT(count >= size);
556            count -= size;
557            if (count == 0)
558                return true;
559        }
560
561        size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
562        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
563        block->init(size);
564        block->append(buffer, count);
565
566        if (fTail != NULL)
567            fTail->fNext = block;
568        else
569            fHead = fTail = block;
570        fTail = block;
571    }
572    return true;
573}
574
575bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
576{
577    if (offset + count > fBytesWritten) {
578        return false; // test does not partially modify
579    }
580
581    this->invalidateCopy();
582
583    Block* block = fHead;
584    while (block != NULL) {
585        size_t size = block->written();
586        if (offset < size) {
587            size_t part = offset + count > size ? size - offset : count;
588            memcpy(block->start() + offset, buffer, part);
589            if (count <= part)
590                return true;
591            count -= part;
592            buffer = (const void*) ((char* ) buffer + part);
593        }
594        offset = offset > size ? offset - size : 0;
595        block = block->fNext;
596    }
597    return false;
598}
599
600bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
601{
602    if (offset + count > fBytesWritten)
603        return false; // test does not partially modify
604    Block* block = fHead;
605    while (block != NULL) {
606        size_t size = block->written();
607        if (offset < size) {
608            size_t part = offset + count > size ? size - offset : count;
609            memcpy(buffer, block->start() + offset, part);
610            if (count <= part)
611                return true;
612            count -= part;
613            buffer = (void*) ((char* ) buffer + part);
614        }
615        offset = offset > size ? offset - size : 0;
616        block = block->fNext;
617    }
618    return false;
619}
620
621void SkDynamicMemoryWStream::copyTo(void* dst) const
622{
623    if (fCopy) {
624        memcpy(dst, fCopy->data(), fBytesWritten);
625    } else {
626        Block* block = fHead;
627
628        while (block != NULL) {
629            size_t size = block->written();
630            memcpy(dst, block->start(), size);
631            dst = (void*)((char*)dst + size);
632            block = block->fNext;
633        }
634    }
635}
636
637void SkDynamicMemoryWStream::padToAlign4()
638{
639    // cast to remove unary-minus warning
640    int padBytes = -(int)fBytesWritten & 0x03;
641    if (padBytes == 0)
642        return;
643    int zero = 0;
644    write(&zero, padBytes);
645}
646
647SkData* SkDynamicMemoryWStream::copyToData() const {
648    if (NULL == fCopy) {
649        void* buffer = sk_malloc_throw(fBytesWritten);
650        this->copyTo(buffer);
651        fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
652    }
653    fCopy->ref();
654    return fCopy;
655}
656
657void SkDynamicMemoryWStream::invalidateCopy() {
658    if (fCopy) {
659        fCopy->unref();
660        fCopy = NULL;
661    }
662}
663
664///////////////////////////////////////////////////////////////////////////////
665
666void SkDebugWStream::newline()
667{
668#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
669    SkDebugf("\n");
670#endif
671}
672
673bool SkDebugWStream::write(const void* buffer, size_t size)
674{
675#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
676    char* s = new char[size+1];
677    memcpy(s, buffer, size);
678    s[size] = 0;
679    SkDebugf("%s", s);
680    delete[] s;
681#endif
682    return true;
683}
684
685///////////////////////////////////////////////////////////////////////////////
686///////////////////////////////////////////////////////////////////////////////
687
688
689static SkData* mmap_filename(const char path[]) {
690    SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
691    if (NULL == file) {
692        return NULL;
693    }
694
695    SkData* data = SkData::NewFromFILE(file);
696    sk_fclose(file);
697    return data;
698}
699
700SkStreamAsset* SkStream::NewFromFile(const char path[]) {
701    SkAutoTUnref<SkData> data(mmap_filename(path));
702    if (data.get()) {
703        return SkNEW_ARGS(SkMemoryStream, (data.get()));
704    }
705
706    // If we get here, then our attempt at using mmap failed, so try normal
707    // file access.
708    SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
709    if (!stream->isValid()) {
710        stream->unref();
711        stream = NULL;
712    }
713    return stream;
714}
715