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