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