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