• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~SkStream()16 SkStream::~SkStream() {}
17 
getFileName()18 const char* SkStream::getFileName()
19 {
20     // override in subclass if you represent a file
21     return NULL;
22 }
23 
getMemoryBase()24 const void* SkStream::getMemoryBase()
25 {
26     // override in subclass if you represent a memory block
27     return NULL;
28 }
29 
skip(size_t size)30 size_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 
readS8()39 int8_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 
readS16()46 int16_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 
readS32()53 int32_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 
readScalar()60 SkScalar 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 
readPackedUInt()71 size_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 
~SkWStream()87 SkWStream::~SkWStream()
88 {
89 }
90 
newline()91 void SkWStream::newline()
92 {
93     this->write("\n", 1);
94 }
95 
flush()96 void SkWStream::flush()
97 {
98 }
99 
writeText(const char text[])100 bool SkWStream::writeText(const char text[])
101 {
102     SkASSERT(text);
103     return this->write(text, strlen(text));
104 }
105 
writeDecAsText(int32_t dec)106 bool SkWStream::writeDecAsText(int32_t dec)
107 {
108     SkString    tmp;
109     tmp.appendS32(dec);
110     return this->write(tmp.c_str(), tmp.size());
111 }
112 
writeBigDecAsText(int64_t dec,int minDigits)113 bool 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 
writeHexAsText(uint32_t hex,int digits)120 bool 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 
writeScalarAsText(SkScalar value)127 bool SkWStream::writeScalarAsText(SkScalar value)
128 {
129     SkString    tmp;
130     tmp.appendScalar(value);
131     return this->write(tmp.c_str(), tmp.size());
132 }
133 
write8(U8CPU value)134 bool SkWStream::write8(U8CPU value) {
135     uint8_t v = SkToU8(value);
136     return this->write(&v, 1);
137 }
138 
write16(U16CPU value)139 bool SkWStream::write16(U16CPU value) {
140     uint16_t v = SkToU16(value);
141     return this->write(&v, 2);
142 }
143 
write32(uint32_t value)144 bool SkWStream::write32(uint32_t value) {
145     return this->write(&value, 4);
146 }
147 
writeScalar(SkScalar value)148 bool SkWStream::writeScalar(SkScalar value) {
149     return this->write(&value, sizeof(value));
150 }
151 
writePackedUInt(size_t value)152 bool 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 
writeStream(SkStream * stream,size_t length)172 bool 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 
writeData(const SkData * data)190 bool SkWStream::writeData(const SkData* data) {
191     if (data) {
192         this->write(data->data(), data->size());
193     }
194     return true;
195 }
196 
197 ///////////////////////////////////////////////////////////////////////////////
198 
SkFILEStream(const char file[])199 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
200 {
201     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
202 }
203 
~SkFILEStream()204 SkFILEStream::~SkFILEStream()
205 {
206     if (fFILE)
207         sk_fclose(fFILE);
208 }
209 
setPath(const char path[])210 void 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 
getFileName()222 const char* SkFILEStream::getFileName()
223 {
224     return fName.c_str();
225 }
226 
rewind()227 bool 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 
read(void * buffer,size_t size)240 size_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 
newFromParams(const void * src,size_t size,bool copyData)254 static 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 
SkMemoryStream()262 SkMemoryStream::SkMemoryStream() {
263     fData = SkData::NewEmpty();
264     fOffset = 0;
265 }
266 
SkMemoryStream(size_t size)267 SkMemoryStream::SkMemoryStream(size_t size) {
268     fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
269     fOffset = 0;
270 }
271 
SkMemoryStream(const void * src,size_t size,bool copyData)272 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
273     fData = newFromParams(src, size, copyData);
274     fOffset = 0;
275 }
276 
~SkMemoryStream()277 SkMemoryStream::~SkMemoryStream() {
278     fData->unref();
279 }
280 
setMemoryOwned(const void * src,size_t size)281 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
282     fData->unref();
283     fData = SkData::NewFromMalloc(src, size);
284     fOffset = 0;
285 }
286 
setMemory(const void * src,size_t size,bool copyData)287 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
288     fData->unref();
289     fData = newFromParams(src, size, copyData);
290     fOffset = 0;
291 }
292 
copyToData() const293 SkData* SkMemoryStream::copyToData() const {
294     fData->ref();
295     return fData;
296 }
297 
setData(SkData * data)298 SkData* SkMemoryStream::setData(SkData* data) {
299     SkRefCnt_SafeAssign(fData, data);
300     return data;
301 }
302 
skipToAlign4()303 void SkMemoryStream::skipToAlign4() {
304     // cast to remove unary-minus warning
305     fOffset += -(int)fOffset & 0x03;
306 }
307 
rewind()308 bool SkMemoryStream::rewind() {
309     fOffset = 0;
310     return true;
311 }
312 
read(void * buffer,size_t size)313 size_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 
getMemoryBase()334 const void* SkMemoryStream::getMemoryBase() {
335     return fData->data();
336 }
337 
getAtPos()338 const void* SkMemoryStream::getAtPos() {
339     return fData->bytes() + fOffset;
340 }
341 
seek(size_t offset)342 size_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 
SkBufferStream(SkStream * proxy,size_t bufferSize)352 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
353     : fProxy(proxy)
354 {
355     SkASSERT(proxy != NULL);
356     proxy->ref();
357     this->init(NULL, bufferSize);
358 }
359 
SkBufferStream(SkStream * proxy,void * buffer,size_t bufferSize)360 SkBufferStream::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 
init(void * buffer,size_t bufferSize)369 void 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 
~SkBufferStream()390 SkBufferStream::~SkBufferStream()
391 {
392     fProxy->unref();
393     if (fWeOwnTheBuffer)
394         sk_free(fBuffer);
395 }
396 
rewind()397 bool SkBufferStream::rewind()
398 {
399     fBufferOffset = fBufferSize = fOrigBufferSize;
400     return fProxy->rewind();
401 }
402 
getFileName()403 const char* SkBufferStream::getFileName()
404 {
405     return fProxy->getFileName();
406 }
407 
408 #ifdef SK_DEBUG
409 //  #define SK_TRACE_BUFFERSTREAM
410 #endif
411 
read(void * buffer,size_t size)412 size_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 
getMemoryBase()496 const void* SkBufferStream::getMemoryBase()
497 {
498     return fProxy->getMemoryBase();
499 }
500 
501 /////////////////////////////////////////////////////////////////////////////////////////////////////////
502 /////////////////////////////////////////////////////////////////////////////////////////////////////////
503 
SkFILEWStream(const char path[])504 SkFILEWStream::SkFILEWStream(const char path[])
505 {
506     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
507 }
508 
~SkFILEWStream()509 SkFILEWStream::~SkFILEWStream()
510 {
511     if (fFILE)
512         sk_fclose(fFILE);
513 }
514 
write(const void * buffer,size_t size)515 bool 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 
flush()530 void SkFILEWStream::flush()
531 {
532     if (fFILE)
533         sk_fflush(fFILE);
534 }
535 
536 ////////////////////////////////////////////////////////////////////////
537 
SkMemoryWStream(void * buffer,size_t size)538 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
539     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
540 {
541 }
542 
write(const void * buffer,size_t size)543 bool 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 
559 struct SkDynamicMemoryWStream::Block {
560     Block*  fNext;
561     char*   fCurr;
562     char*   fStop;
563 
startSkDynamicMemoryWStream::Block564     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block565     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block566     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block567     size_t  written() const { return fCurr - this->start(); }
568 
initSkDynamicMemoryWStream::Block569     void init(size_t size)
570     {
571         fNext = NULL;
572         fCurr = this->start();
573         fStop = this->start() + size;
574     }
575 
appendSkDynamicMemoryWStream::Block576     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 
SkDynamicMemoryWStream()585 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
586     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
587 {
588 }
589 
~SkDynamicMemoryWStream()590 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
591 {
592     reset();
593 }
594 
reset()595 void 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 
write(const void * buffer,size_t count)610 bool 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 
write(const void * buffer,size_t offset,size_t count)642 bool 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 
read(void * buffer,size_t offset,size_t count)667 bool 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 
copyTo(void * dst) const688 void 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 
padToAlign4()704 void 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 
copyToData() const714 SkData* 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 
invalidateCopy()724 void SkDynamicMemoryWStream::invalidateCopy() {
725     if (fCopy) {
726         fCopy->unref();
727         fCopy = NULL;
728     }
729 }
730 
731 ///////////////////////////////////////////////////////////////////////////////
732 
newline()733 void SkDebugWStream::newline()
734 {
735 #ifdef SK_DEBUG
736     SkDebugf("\n");
737 #endif
738 }
739 
write(const void * buffer,size_t size)740 bool 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