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