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