• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~SkStream()23 SkStream::~SkStream() {}
24 
getFileName()25 const char* SkStream::getFileName()
26 {
27     // override in subclass if you represent a file
28     return NULL;
29 }
30 
getMemoryBase()31 const void* SkStream::getMemoryBase()
32 {
33     // override in subclass if you represent a memory block
34     return NULL;
35 }
36 
skip(size_t size)37 size_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 
readS8()46 int8_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 
readS16()53 int16_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 
readS32()60 int32_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 
readScalar()67 SkScalar 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 
readPackedUInt()74 size_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 
~SkWStream()100 SkWStream::~SkWStream()
101 {
102 }
103 
newline()104 void SkWStream::newline()
105 {
106     this->write("\n", 1);
107 }
108 
flush()109 void SkWStream::flush()
110 {
111 }
112 
writeText(const char text[])113 bool SkWStream::writeText(const char text[])
114 {
115     SkASSERT(text);
116     return this->write(text, strlen(text));
117 }
118 
writeDecAsText(int32_t dec)119 bool SkWStream::writeDecAsText(int32_t dec)
120 {
121     SkString    tmp;
122     tmp.appendS32(dec);
123     return this->write(tmp.c_str(), tmp.size());
124 }
125 
writeHexAsText(uint32_t hex,int digits)126 bool 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 
writeScalarAsText(SkScalar value)133 bool SkWStream::writeScalarAsText(SkScalar value)
134 {
135     SkString    tmp;
136     tmp.appendScalar(value);
137     return this->write(tmp.c_str(), tmp.size());
138 }
139 
write8(U8CPU value)140 bool SkWStream::write8(U8CPU value) {
141     uint8_t v = SkToU8(value);
142     return this->write(&v, 1);
143 }
144 
write16(U16CPU value)145 bool SkWStream::write16(U16CPU value) {
146     uint16_t v = SkToU16(value);
147     return this->write(&v, 2);
148 }
149 
write32(uint32_t value)150 bool SkWStream::write32(uint32_t value) {
151     return this->write(&value, 4);
152 }
153 
writeScalar(SkScalar value)154 bool SkWStream::writeScalar(SkScalar value) {
155     return this->write(&value, sizeof(value));
156 }
157 
writePackedUInt(size_t value)158 bool 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 
writeStream(SkStream * stream,size_t length)168 bool 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 
SkFILEStream(const char file[])188 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
189 {
190     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
191 }
192 
~SkFILEStream()193 SkFILEStream::~SkFILEStream()
194 {
195     if (fFILE)
196         sk_fclose(fFILE);
197 }
198 
setPath(const char path[])199 void 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 
getFileName()211 const char* SkFILEStream::getFileName()
212 {
213     return fName.c_str();
214 }
215 
rewind()216 bool 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 
read(void * buffer,size_t size)229 size_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 
SkMemoryStream()243 SkMemoryStream::SkMemoryStream()
244 {
245     fWeOwnTheData = false;
246     this->setMemory(NULL, 0);
247 }
248 
SkMemoryStream(size_t size)249 SkMemoryStream::SkMemoryStream(size_t size) {
250     fWeOwnTheData = true;
251     fOffset = 0;
252     fSize = size;
253     fSrc = sk_malloc_throw(size);
254 }
255 
SkMemoryStream(const void * src,size_t size,bool copyData)256 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
257 {
258     fWeOwnTheData = false;
259     this->setMemory(src, size, copyData);
260 }
261 
~SkMemoryStream()262 SkMemoryStream::~SkMemoryStream()
263 {
264     if (fWeOwnTheData)
265         sk_free((void*)fSrc);
266 }
267 
setMemoryOwned(const void * src,size_t size)268 void 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 
setMemory(const void * src,size_t size,bool copyData)280 void 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 
skipToAlign4()298 void SkMemoryStream::skipToAlign4()
299 {
300     // cast to remove unary-minus warning
301     fOffset += -(int)fOffset & 0x03;
302 }
303 
rewind()304 bool SkMemoryStream::rewind()
305 {
306     fOffset = 0;
307     return true;
308 }
309 
read(void * buffer,size_t size)310 size_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 
getMemoryBase()328 const void* SkMemoryStream::getMemoryBase()
329 {
330     return fSrc;
331 }
332 
getAtPos()333 const void* SkMemoryStream::getAtPos()
334 {
335     return (const char*)fSrc + fOffset;
336 }
337 
seek(size_t offset)338 size_t SkMemoryStream::seek(size_t offset)
339 {
340     if (offset > fSize)
341         offset = fSize;
342     fOffset = offset;
343     return offset;
344 }
345 
346 /////////////////////////////////////////////////////////////////////////////////////////////////////////
347 
SkBufferStream(SkStream * proxy,size_t bufferSize)348 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
349     : fProxy(proxy)
350 {
351     SkASSERT(proxy != NULL);
352     proxy->ref();
353     this->init(NULL, bufferSize);
354 }
355 
SkBufferStream(SkStream * proxy,void * buffer,size_t bufferSize)356 SkBufferStream::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 
init(void * buffer,size_t bufferSize)365 void 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 
~SkBufferStream()386 SkBufferStream::~SkBufferStream()
387 {
388     fProxy->unref();
389     if (fWeOwnTheBuffer)
390         sk_free(fBuffer);
391 }
392 
rewind()393 bool SkBufferStream::rewind()
394 {
395     fBufferOffset = fBufferSize = fOrigBufferSize;
396     return fProxy->rewind();
397 }
398 
getFileName()399 const char* SkBufferStream::getFileName()
400 {
401     return fProxy->getFileName();
402 }
403 
404 #ifdef SK_DEBUG
405 //  #define SK_TRACE_BUFFERSTREAM
406 #endif
407 
read(void * buffer,size_t size)408 size_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 
getMemoryBase()492 const void* SkBufferStream::getMemoryBase()
493 {
494     return fProxy->getMemoryBase();
495 }
496 
497 /////////////////////////////////////////////////////////////////////////////////////////////////////////
498 /////////////////////////////////////////////////////////////////////////////////////////////////////////
499 
SkFILEWStream(const char path[])500 SkFILEWStream::SkFILEWStream(const char path[])
501 {
502     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
503 }
504 
~SkFILEWStream()505 SkFILEWStream::~SkFILEWStream()
506 {
507     if (fFILE)
508         sk_fclose(fFILE);
509 }
510 
write(const void * buffer,size_t size)511 bool 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 
flush()526 void SkFILEWStream::flush()
527 {
528     if (fFILE)
529         sk_fflush(fFILE);
530 }
531 
532 ////////////////////////////////////////////////////////////////////////
533 
SkMemoryWStream(void * buffer,size_t size)534 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
535     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
536 {
537 }
538 
write(const void * buffer,size_t size)539 bool 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 
555 struct SkDynamicMemoryWStream::Block {
556     Block*  fNext;
557     char*   fCurr;
558     char*   fStop;
559 
startSkDynamicMemoryWStream::Block560     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block561     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block562     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block563     size_t  written() const { return fCurr - this->start(); }
564 
initSkDynamicMemoryWStream::Block565     void init(size_t size)
566     {
567         fNext = NULL;
568         fCurr = this->start();
569         fStop = this->start() + size;
570     }
571 
appendSkDynamicMemoryWStream::Block572     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 
SkDynamicMemoryWStream()581 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
582 {
583 }
584 
~SkDynamicMemoryWStream()585 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
586 {
587     reset();
588 }
589 
detach()590 const char* SkDynamicMemoryWStream::detach()
591 {
592     const char* result = getStream();
593     fCopyToCache = NULL;
594     return result;
595 }
596 
reset()597 void 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 
write(const void * buffer,size_t count)612 bool 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 
write(const void * buffer,size_t offset,size_t count)647 bool 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 
read(void * buffer,size_t offset,size_t count)668 bool 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 
copyTo(void * dst) const689 void 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 
getStream() const701 const 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 
padToAlign4()710 void 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 
newline()722 void SkDebugWStream::newline()
723 {
724 #ifdef SK_DEBUG
725     SkDebugf("\n");
726 #endif
727 }
728 
write(const void * buffer,size_t size)729 bool 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