SkStream.cpp revision 2e07942f42937b87f82a16e11b1bb26acd09896e
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::readStream() {
97    size_t size = this->readU32();
98    if (0 == size) {
99        return SkData::NewEmpty();
100    } else {
101        void* buffer = sk_malloc_throw(size);
102        stream->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() {
303    fData->unref();
304}
305
306void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
307    fData->unref();
308    fData = SkData::NewFromMalloc(src, size);
309    fOffset = 0;
310}
311
312void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
313    fData->unref();
314    fData = newFromParams(src, size, copyData);
315    fOffset = 0;
316}
317
318SkData* SkMemoryStream::copyToData() const {
319    fData->ref();
320    return fData;
321}
322
323SkData* SkMemoryStream::setData(SkData* data) {
324    SkRefCnt_SafeAssign(fData, data);
325    return data;
326}
327
328void SkMemoryStream::skipToAlign4() {
329    // cast to remove unary-minus warning
330    fOffset += -(int)fOffset & 0x03;
331}
332
333bool SkMemoryStream::rewind() {
334    fOffset = 0;
335    return true;
336}
337
338size_t SkMemoryStream::read(void* buffer, size_t size) {
339    size_t dataSize = fData->size();
340
341    if (buffer == NULL && size == 0)    // special signature, they want the total size
342        return dataSize;
343
344    // if buffer is NULL, seek ahead by size
345
346    if (size == 0) {
347        return 0;
348    }
349    if (size > dataSize - fOffset) {
350        size = dataSize - fOffset;
351    }
352    if (buffer) {
353        memcpy(buffer, fData->bytes() + fOffset, size);
354    }
355    fOffset += size;
356    return size;
357}
358
359const void* SkMemoryStream::getMemoryBase() {
360    return fData->data();
361}
362
363const void* SkMemoryStream::getAtPos() {
364    return fData->bytes() + fOffset;
365}
366
367size_t SkMemoryStream::seek(size_t offset) {
368    if (offset > fData->size()) {
369        offset = fData->size();
370    }
371    fOffset = offset;
372    return offset;
373}
374
375///////////////////////////////////////////////////////////////////////////////
376
377SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
378    : fProxy(proxy)
379{
380    SkASSERT(proxy != NULL);
381    proxy->ref();
382    this->init(NULL, bufferSize);
383}
384
385SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
386    : fProxy(proxy)
387{
388    SkASSERT(proxy != NULL);
389    SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
390    proxy->ref();
391    this->init(buffer, bufferSize);
392}
393
394void SkBufferStream::init(void* buffer, size_t bufferSize)
395{
396    if (bufferSize == 0)
397        bufferSize = kDefaultBufferSize;
398
399    fOrigBufferSize = bufferSize;
400    fBufferSize = bufferSize;
401    fBufferOffset = bufferSize; // to trigger a reload on the first read()
402
403    if (buffer == NULL)
404    {
405        fBuffer = (char*)sk_malloc_throw(fBufferSize);
406        fWeOwnTheBuffer = true;
407    }
408    else
409    {
410        fBuffer = (char*)buffer;
411        fWeOwnTheBuffer = false;
412    }
413}
414
415SkBufferStream::~SkBufferStream()
416{
417    fProxy->unref();
418    if (fWeOwnTheBuffer)
419        sk_free(fBuffer);
420}
421
422bool SkBufferStream::rewind()
423{
424    fBufferOffset = fBufferSize = fOrigBufferSize;
425    return fProxy->rewind();
426}
427
428const char* SkBufferStream::getFileName()
429{
430    return fProxy->getFileName();
431}
432
433#ifdef SK_DEBUG
434//  #define SK_TRACE_BUFFERSTREAM
435#endif
436
437size_t SkBufferStream::read(void* buffer, size_t size) {
438#ifdef SK_TRACE_BUFFERSTREAM
439    SkDebugf("Request %d", size);
440#endif
441
442    if (buffer == NULL && size == 0) {
443        return fProxy->read(buffer, size);    // requesting total size
444    }
445
446    if (0 == size) {
447        return 0;
448    }
449
450    // skip size bytes
451    if (NULL == buffer) {
452        size_t remaining = fBufferSize - fBufferOffset;
453        if (remaining >= size) {
454            fBufferOffset += size;
455            return size;
456        }
457        // if we get here, we are being asked to skip beyond our current buffer
458        // so reset our offset to force a read next time, and skip the diff
459        // in our proxy
460        fBufferOffset = fOrigBufferSize;
461        return remaining + fProxy->read(NULL, size - remaining);
462    }
463
464    size_t s = size;
465    size_t actuallyRead = 0;
466
467    // flush what we can from our fBuffer
468    if (fBufferOffset < fBufferSize)
469    {
470        if (s > fBufferSize - fBufferOffset)
471            s = fBufferSize - fBufferOffset;
472        memcpy(buffer, fBuffer + fBufferOffset, s);
473#ifdef SK_TRACE_BUFFERSTREAM
474        SkDebugf(" flush %d", s);
475#endif
476        size -= s;
477        fBufferOffset += s;
478        buffer = (char*)buffer + s;
479        actuallyRead = s;
480    }
481
482    // check if there is more to read
483    if (size)
484    {
485        SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
486
487        if (size < fBufferSize) // lets try to read more than the request
488        {
489            s = fProxy->read(fBuffer, fBufferSize);
490#ifdef SK_TRACE_BUFFERSTREAM
491            SkDebugf(" read %d into fBuffer", s);
492#endif
493            if (size > s)   // they asked for too much
494                size = s;
495            if (size)
496            {
497                memcpy(buffer, fBuffer, size);
498                actuallyRead += size;
499#ifdef SK_TRACE_BUFFERSTREAM
500                SkDebugf(" memcpy %d into dst", size);
501#endif
502            }
503
504            fBufferOffset = size;
505            fBufferSize = s;        // record the (possibly smaller) size for the buffer
506        }
507        else    // just do a direct read
508        {
509            actuallyRead += fProxy->read(buffer, size);
510#ifdef SK_TRACE_BUFFERSTREAM
511            SkDebugf(" direct read %d", size);
512#endif
513        }
514    }
515#ifdef SK_TRACE_BUFFERSTREAM
516    SkDebugf("\n");
517#endif
518    return actuallyRead;
519}
520
521const void* SkBufferStream::getMemoryBase()
522{
523    return fProxy->getMemoryBase();
524}
525
526/////////////////////////////////////////////////////////////////////////////////////////////////////////
527/////////////////////////////////////////////////////////////////////////////////////////////////////////
528
529SkFILEWStream::SkFILEWStream(const char path[])
530{
531    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
532}
533
534SkFILEWStream::~SkFILEWStream()
535{
536    if (fFILE)
537        sk_fclose(fFILE);
538}
539
540bool SkFILEWStream::write(const void* buffer, size_t size)
541{
542    if (fFILE == NULL)
543        return false;
544
545    if (sk_fwrite(buffer, size, fFILE) != size)
546    {
547        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
548        sk_fclose(fFILE);
549        fFILE = NULL;
550        return false;
551    }
552    return true;
553}
554
555void SkFILEWStream::flush()
556{
557    if (fFILE)
558        sk_fflush(fFILE);
559}
560
561////////////////////////////////////////////////////////////////////////
562
563SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
564    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
565{
566}
567
568bool SkMemoryWStream::write(const void* buffer, size_t size)
569{
570    size = SkMin32(size, fMaxLength - fBytesWritten);
571    if (size > 0)
572    {
573        memcpy(fBuffer + fBytesWritten, buffer, size);
574        fBytesWritten += size;
575        return true;
576    }
577    return false;
578}
579
580////////////////////////////////////////////////////////////////////////
581
582#define SkDynamicMemoryWStream_MinBlockSize   256
583
584struct SkDynamicMemoryWStream::Block {
585    Block*  fNext;
586    char*   fCurr;
587    char*   fStop;
588
589    const char* start() const { return (const char*)(this + 1); }
590    char*   start() { return (char*)(this + 1); }
591    size_t  avail() const { return fStop - fCurr; }
592    size_t  written() const { return fCurr - this->start(); }
593
594    void init(size_t size)
595    {
596        fNext = NULL;
597        fCurr = this->start();
598        fStop = this->start() + size;
599    }
600
601    const void* append(const void* data, size_t size)
602    {
603        SkASSERT((size_t)(fStop - fCurr) >= size);
604        memcpy(fCurr, data, size);
605        fCurr += size;
606        return (const void*)((const char*)data + size);
607    }
608};
609
610SkDynamicMemoryWStream::SkDynamicMemoryWStream()
611    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
612{
613}
614
615SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
616{
617    reset();
618}
619
620void SkDynamicMemoryWStream::reset()
621{
622    this->invalidateCopy();
623
624    Block*  block = fHead;
625
626    while (block != NULL) {
627        Block*  next = block->fNext;
628        sk_free(block);
629        block = next;
630    }
631    fHead = fTail = NULL;
632    fBytesWritten = 0;
633}
634
635bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
636{
637    if (count > 0) {
638        this->invalidateCopy();
639
640        fBytesWritten += count;
641
642        size_t  size;
643
644        if (fTail != NULL && fTail->avail() > 0) {
645            size = SkMin32(fTail->avail(), count);
646            buffer = fTail->append(buffer, size);
647            SkASSERT(count >= size);
648            count -= size;
649            if (count == 0)
650                return true;
651        }
652
653        size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
654        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
655        block->init(size);
656        block->append(buffer, count);
657
658        if (fTail != NULL)
659            fTail->fNext = block;
660        else
661            fHead = fTail = block;
662        fTail = block;
663    }
664    return true;
665}
666
667bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
668{
669    if (offset + count > fBytesWritten) {
670        return false; // test does not partially modify
671    }
672
673    this->invalidateCopy();
674
675    Block* block = fHead;
676    while (block != NULL) {
677        size_t size = block->written();
678        if (offset < size) {
679            size_t part = offset + count > size ? size - offset : count;
680            memcpy(block->start() + offset, buffer, part);
681            if (count <= part)
682                return true;
683            count -= part;
684            buffer = (const void*) ((char* ) buffer + part);
685        }
686        offset = offset > size ? offset - size : 0;
687        block = block->fNext;
688    }
689    return false;
690}
691
692bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
693{
694    if (offset + count > fBytesWritten)
695        return false; // test does not partially modify
696    Block* block = fHead;
697    while (block != NULL) {
698        size_t size = block->written();
699        if (offset < size) {
700            size_t part = offset + count > size ? size - offset : count;
701            memcpy(buffer, block->start() + offset, part);
702            if (count <= part)
703                return true;
704            count -= part;
705            buffer = (void*) ((char* ) buffer + part);
706        }
707        offset = offset > size ? offset - size : 0;
708        block = block->fNext;
709    }
710    return false;
711}
712
713void SkDynamicMemoryWStream::copyTo(void* dst) const
714{
715    if (fCopy) {
716        memcpy(dst, fCopy->data(), fBytesWritten);
717    } else {
718        Block* block = fHead;
719
720        while (block != NULL) {
721            size_t size = block->written();
722            memcpy(dst, block->start(), size);
723            dst = (void*)((char*)dst + size);
724            block = block->fNext;
725        }
726    }
727}
728
729void SkDynamicMemoryWStream::padToAlign4()
730{
731    // cast to remove unary-minus warning
732    int padBytes = -(int)fBytesWritten & 0x03;
733    if (padBytes == 0)
734        return;
735    int zero = 0;
736    write(&zero, padBytes);
737}
738
739SkData* SkDynamicMemoryWStream::copyToData() const {
740    if (NULL == fCopy) {
741        void* buffer = sk_malloc_throw(fBytesWritten);
742        this->copyTo(buffer);
743        fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
744    }
745    fCopy->ref();
746    return fCopy;
747}
748
749void SkDynamicMemoryWStream::invalidateCopy() {
750    if (fCopy) {
751        fCopy->unref();
752        fCopy = NULL;
753    }
754}
755
756///////////////////////////////////////////////////////////////////////////////
757
758void SkDebugWStream::newline()
759{
760#ifdef SK_DEBUG
761    SkDebugf("\n");
762#endif
763}
764
765bool SkDebugWStream::write(const void* buffer, size_t size)
766{
767#ifdef SK_DEBUG
768    char* s = new char[size+1];
769    memcpy(s, buffer, size);
770    s[size] = 0;
771    SkDebugf("%s", s);
772    delete[] s;
773#endif
774    return true;
775}
776