• 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 "SkStreamPriv.h"
12 #include "SkData.h"
13 #include "SkFixed.h"
14 #include "SkString.h"
15 #include "SkOSFile.h"
16 #include "SkTypes.h"
17 
18 ///////////////////////////////////////////////////////////////////////////////
19 
20 
readS8()21 int8_t SkStream::readS8() {
22     int8_t value;
23     SkDEBUGCODE(size_t len =) this->read(&value, 1);
24     SkASSERT(1 == len);
25     return value;
26 }
27 
readS16()28 int16_t SkStream::readS16() {
29     int16_t value;
30     SkDEBUGCODE(size_t len =) this->read(&value, 2);
31     SkASSERT(2 == len);
32     return value;
33 }
34 
readS32()35 int32_t SkStream::readS32() {
36     int32_t value;
37     SkDEBUGCODE(size_t len =) this->read(&value, 4);
38     SkASSERT(4 == len);
39     return value;
40 }
41 
readScalar()42 SkScalar SkStream::readScalar() {
43     SkScalar value;
44     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
45     SkASSERT(sizeof(SkScalar) == len);
46     return value;
47 }
48 
49 #define SK_MAX_BYTE_FOR_U8          0xFD
50 #define SK_BYTE_SENTINEL_FOR_U16    0xFE
51 #define SK_BYTE_SENTINEL_FOR_U32    0xFF
52 
readPackedUInt()53 size_t SkStream::readPackedUInt() {
54     uint8_t byte;
55     if (!this->read(&byte, 1)) {
56         return 0;
57     }
58     if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
59         return this->readU16();
60     } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
61         return this->readU32();
62     } else {
63         return byte;
64     }
65 }
66 
67 //////////////////////////////////////////////////////////////////////////////////////
68 
~SkWStream()69 SkWStream::~SkWStream()
70 {
71 }
72 
newline()73 void SkWStream::newline()
74 {
75     this->write("\n", 1);
76 }
77 
flush()78 void SkWStream::flush()
79 {
80 }
81 
writeText(const char text[])82 bool SkWStream::writeText(const char text[])
83 {
84     SkASSERT(text);
85     return this->write(text, strlen(text));
86 }
87 
writeDecAsText(int32_t dec)88 bool SkWStream::writeDecAsText(int32_t dec)
89 {
90     SkString    tmp;
91     tmp.appendS32(dec);
92     return this->write(tmp.c_str(), tmp.size());
93 }
94 
writeBigDecAsText(int64_t dec,int minDigits)95 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
96 {
97     SkString    tmp;
98     tmp.appendS64(dec, minDigits);
99     return this->write(tmp.c_str(), tmp.size());
100 }
101 
writeHexAsText(uint32_t hex,int digits)102 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
103 {
104     SkString    tmp;
105     tmp.appendHex(hex, digits);
106     return this->write(tmp.c_str(), tmp.size());
107 }
108 
writeScalarAsText(SkScalar value)109 bool SkWStream::writeScalarAsText(SkScalar value)
110 {
111     SkString    tmp;
112     tmp.appendScalar(value);
113     return this->write(tmp.c_str(), tmp.size());
114 }
115 
write8(U8CPU value)116 bool SkWStream::write8(U8CPU value) {
117     uint8_t v = SkToU8(value);
118     return this->write(&v, 1);
119 }
120 
write16(U16CPU value)121 bool SkWStream::write16(U16CPU value) {
122     uint16_t v = SkToU16(value);
123     return this->write(&v, 2);
124 }
125 
write32(uint32_t value)126 bool SkWStream::write32(uint32_t value) {
127     return this->write(&value, 4);
128 }
129 
writeScalar(SkScalar value)130 bool SkWStream::writeScalar(SkScalar value) {
131     return this->write(&value, sizeof(value));
132 }
133 
SizeOfPackedUInt(size_t value)134 int SkWStream::SizeOfPackedUInt(size_t value) {
135     if (value <= SK_MAX_BYTE_FOR_U8) {
136         return 1;
137     } else if (value <= 0xFFFF) {
138         return 3;
139     }
140     return 5;
141 }
142 
writePackedUInt(size_t value)143 bool SkWStream::writePackedUInt(size_t value) {
144     uint8_t data[5];
145     size_t len = 1;
146     if (value <= SK_MAX_BYTE_FOR_U8) {
147         data[0] = value;
148         len = 1;
149     } else if (value <= 0xFFFF) {
150         uint16_t value16 = value;
151         data[0] = SK_BYTE_SENTINEL_FOR_U16;
152         memcpy(&data[1], &value16, 2);
153         len = 3;
154     } else {
155         uint32_t value32 = SkToU32(value);
156         data[0] = SK_BYTE_SENTINEL_FOR_U32;
157         memcpy(&data[1], &value32, 4);
158         len = 5;
159     }
160     return this->write(data, len);
161 }
162 
writeStream(SkStream * stream,size_t length)163 bool SkWStream::writeStream(SkStream* stream, size_t length) {
164     char scratch[1024];
165     const size_t MAX = sizeof(scratch);
166 
167     while (length != 0) {
168         size_t n = length;
169         if (n > MAX) {
170             n = MAX;
171         }
172         stream->read(scratch, n);
173         if (!this->write(scratch, n)) {
174             return false;
175         }
176         length -= n;
177     }
178     return true;
179 }
180 
181 ///////////////////////////////////////////////////////////////////////////////
182 
SkFILEStream(const char file[])183 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
184     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
185 }
186 
SkFILEStream(FILE * file,Ownership ownership)187 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
188     : fFILE((SkFILE*)file)
189     , fOwnership(ownership) {
190 }
191 
~SkFILEStream()192 SkFILEStream::~SkFILEStream() {
193     if (fFILE && fOwnership != kCallerRetains_Ownership) {
194         sk_fclose(fFILE);
195     }
196 }
197 
setPath(const char path[])198 void SkFILEStream::setPath(const char path[]) {
199     fName.set(path);
200     if (fFILE) {
201         sk_fclose(fFILE);
202         fFILE = NULL;
203     }
204     if (path) {
205         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
206     }
207 }
208 
read(void * buffer,size_t size)209 size_t SkFILEStream::read(void* buffer, size_t size) {
210     if (fFILE) {
211         return sk_fread(buffer, size, fFILE);
212     }
213     return 0;
214 }
215 
isAtEnd() const216 bool SkFILEStream::isAtEnd() const {
217     return sk_feof(fFILE);
218 }
219 
rewind()220 bool SkFILEStream::rewind() {
221     if (fFILE) {
222         if (sk_frewind(fFILE)) {
223             return true;
224         }
225         // we hit an error
226         sk_fclose(fFILE);
227         fFILE = NULL;
228     }
229     return false;
230 }
231 
duplicate() const232 SkStreamAsset* SkFILEStream::duplicate() const {
233     if (NULL == fFILE) {
234         return new SkMemoryStream();
235     }
236 
237     if (fData.get()) {
238         return new SkMemoryStream(fData);
239     }
240 
241     if (!fName.isEmpty()) {
242         SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
243         if (sk_fidentical(that->fFILE, this->fFILE)) {
244             return that.detach();
245         }
246     }
247 
248     fData.reset(SkData::NewFromFILE(fFILE));
249     if (NULL == fData.get()) {
250         return NULL;
251     }
252     return new SkMemoryStream(fData);
253 }
254 
getPosition() const255 size_t SkFILEStream::getPosition() const {
256     return sk_ftell(fFILE);
257 }
258 
seek(size_t position)259 bool SkFILEStream::seek(size_t position) {
260     return sk_fseek(fFILE, position);
261 }
262 
move(long offset)263 bool SkFILEStream::move(long offset) {
264     return sk_fmove(fFILE, offset);
265 }
266 
fork() const267 SkStreamAsset* SkFILEStream::fork() const {
268     SkAutoTUnref<SkStreamAsset> that(this->duplicate());
269     that->seek(this->getPosition());
270     return that.detach();
271 }
272 
getLength() const273 size_t SkFILEStream::getLength() const {
274     return sk_fgetsize(fFILE);
275 }
276 
getMemoryBase()277 const void* SkFILEStream::getMemoryBase() {
278     if (NULL == fData.get()) {
279         return NULL;
280     }
281     return fData->data();
282 }
283 
284 ///////////////////////////////////////////////////////////////////////////////
285 
newFromParams(const void * src,size_t size,bool copyData)286 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
287     if (copyData) {
288         return SkData::NewWithCopy(src, size);
289     } else {
290         return SkData::NewWithoutCopy(src, size);
291     }
292 }
293 
SkMemoryStream()294 SkMemoryStream::SkMemoryStream() {
295     fData = SkData::NewEmpty();
296     fOffset = 0;
297 }
298 
SkMemoryStream(size_t size)299 SkMemoryStream::SkMemoryStream(size_t size) {
300     fData = SkData::NewUninitialized(size);
301     fOffset = 0;
302 }
303 
SkMemoryStream(const void * src,size_t size,bool copyData)304 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
305     fData = newFromParams(src, size, copyData);
306     fOffset = 0;
307 }
308 
SkMemoryStream(SkData * data)309 SkMemoryStream::SkMemoryStream(SkData* data) {
310     if (NULL == data) {
311         fData = SkData::NewEmpty();
312     } else {
313         fData = data;
314         fData->ref();
315     }
316     fOffset = 0;
317 }
318 
~SkMemoryStream()319 SkMemoryStream::~SkMemoryStream() {
320     fData->unref();
321 }
322 
setMemoryOwned(const void * src,size_t size)323 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
324     fData->unref();
325     fData = SkData::NewFromMalloc(src, size);
326     fOffset = 0;
327 }
328 
setMemory(const void * src,size_t size,bool copyData)329 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
330     fData->unref();
331     fData = newFromParams(src, size, copyData);
332     fOffset = 0;
333 }
334 
copyToData() const335 SkData* SkMemoryStream::copyToData() const {
336     fData->ref();
337     return fData;
338 }
339 
setData(SkData * data)340 SkData* SkMemoryStream::setData(SkData* data) {
341     fData->unref();
342     if (NULL == data) {
343         fData = SkData::NewEmpty();
344     } else {
345         fData = data;
346         fData->ref();
347     }
348     fOffset = 0;
349     return data;
350 }
351 
skipToAlign4()352 void SkMemoryStream::skipToAlign4() {
353     // cast to remove unary-minus warning
354     fOffset += -(int)fOffset & 0x03;
355 }
356 
read(void * buffer,size_t size)357 size_t SkMemoryStream::read(void* buffer, size_t size) {
358     size_t dataSize = fData->size();
359 
360     if (size > dataSize - fOffset) {
361         size = dataSize - fOffset;
362     }
363     if (buffer) {
364         memcpy(buffer, fData->bytes() + fOffset, size);
365     }
366     fOffset += size;
367     return size;
368 }
369 
isAtEnd() const370 bool SkMemoryStream::isAtEnd() const {
371     return fOffset == fData->size();
372 }
373 
rewind()374 bool SkMemoryStream::rewind() {
375     fOffset = 0;
376     return true;
377 }
378 
duplicate() const379 SkMemoryStream* SkMemoryStream::duplicate() const {
380     return SkNEW_ARGS(SkMemoryStream, (fData));
381 }
382 
getPosition() const383 size_t SkMemoryStream::getPosition() const {
384     return fOffset;
385 }
386 
seek(size_t position)387 bool SkMemoryStream::seek(size_t position) {
388     fOffset = position > fData->size()
389             ? fData->size()
390             : position;
391     return true;
392 }
393 
move(long offset)394 bool SkMemoryStream::move(long offset) {
395     return this->seek(fOffset + offset);
396 }
397 
fork() const398 SkMemoryStream* SkMemoryStream::fork() const {
399     SkAutoTUnref<SkMemoryStream> that(this->duplicate());
400     that->seek(fOffset);
401     return that.detach();
402 }
403 
getLength() const404 size_t SkMemoryStream::getLength() const {
405     return fData->size();
406 }
407 
getMemoryBase()408 const void* SkMemoryStream::getMemoryBase() {
409     return fData->data();
410 }
411 
getAtPos()412 const void* SkMemoryStream::getAtPos() {
413     return fData->bytes() + fOffset;
414 }
415 
416 /////////////////////////////////////////////////////////////////////////////////////////////////////////
417 /////////////////////////////////////////////////////////////////////////////////////////////////////////
418 
SkFILEWStream(const char path[])419 SkFILEWStream::SkFILEWStream(const char path[])
420 {
421     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
422 }
423 
~SkFILEWStream()424 SkFILEWStream::~SkFILEWStream()
425 {
426     if (fFILE) {
427         sk_fclose(fFILE);
428     }
429 }
430 
bytesWritten() const431 size_t SkFILEWStream::bytesWritten() const {
432     return sk_ftell(fFILE);
433 }
434 
write(const void * buffer,size_t size)435 bool SkFILEWStream::write(const void* buffer, size_t size)
436 {
437     if (fFILE == NULL) {
438         return false;
439     }
440 
441     if (sk_fwrite(buffer, size, fFILE) != size)
442     {
443         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
444         sk_fclose(fFILE);
445         fFILE = NULL;
446         return false;
447     }
448     return true;
449 }
450 
flush()451 void SkFILEWStream::flush()
452 {
453     if (fFILE) {
454         sk_fflush(fFILE);
455     }
456 }
457 
458 ////////////////////////////////////////////////////////////////////////
459 
SkMemoryWStream(void * buffer,size_t size)460 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
461     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
462 {
463 }
464 
write(const void * buffer,size_t size)465 bool SkMemoryWStream::write(const void* buffer, size_t size) {
466     size = SkTMin(size, fMaxLength - fBytesWritten);
467     if (size > 0) {
468         memcpy(fBuffer + fBytesWritten, buffer, size);
469         fBytesWritten += size;
470         return true;
471     }
472     return false;
473 }
474 
475 ////////////////////////////////////////////////////////////////////////
476 
477 #define SkDynamicMemoryWStream_MinBlockSize   256
478 
479 struct SkDynamicMemoryWStream::Block {
480     Block*  fNext;
481     char*   fCurr;
482     char*   fStop;
483 
startSkDynamicMemoryWStream::Block484     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block485     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block486     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block487     size_t  written() const { return fCurr - this->start(); }
488 
initSkDynamicMemoryWStream::Block489     void init(size_t size)
490     {
491         fNext = NULL;
492         fCurr = this->start();
493         fStop = this->start() + size;
494     }
495 
appendSkDynamicMemoryWStream::Block496     const void* append(const void* data, size_t size)
497     {
498         SkASSERT((size_t)(fStop - fCurr) >= size);
499         memcpy(fCurr, data, size);
500         fCurr += size;
501         return (const void*)((const char*)data + size);
502     }
503 };
504 
SkDynamicMemoryWStream()505 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
506     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
507 {
508 }
509 
~SkDynamicMemoryWStream()510 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
511 {
512     reset();
513 }
514 
reset()515 void SkDynamicMemoryWStream::reset()
516 {
517     this->invalidateCopy();
518 
519     Block*  block = fHead;
520 
521     while (block != NULL) {
522         Block*  next = block->fNext;
523         sk_free(block);
524         block = next;
525     }
526     fHead = fTail = NULL;
527     fBytesWritten = 0;
528 }
529 
write(const void * buffer,size_t count)530 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
531 {
532     if (count > 0) {
533         this->invalidateCopy();
534 
535         fBytesWritten += count;
536 
537         size_t  size;
538 
539         if (fTail != NULL && fTail->avail() > 0) {
540             size = SkTMin(fTail->avail(), count);
541             buffer = fTail->append(buffer, size);
542             SkASSERT(count >= size);
543             count -= size;
544             if (count == 0)
545                 return true;
546         }
547 
548         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
549         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
550         block->init(size);
551         block->append(buffer, count);
552 
553         if (fTail != NULL)
554             fTail->fNext = block;
555         else
556             fHead = fTail = block;
557         fTail = block;
558     }
559     return true;
560 }
561 
write(const void * buffer,size_t offset,size_t count)562 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
563 {
564     if (offset + count > fBytesWritten) {
565         return false; // test does not partially modify
566     }
567 
568     this->invalidateCopy();
569 
570     Block* block = fHead;
571     while (block != NULL) {
572         size_t size = block->written();
573         if (offset < size) {
574             size_t part = offset + count > size ? size - offset : count;
575             memcpy(block->start() + offset, buffer, part);
576             if (count <= part)
577                 return true;
578             count -= part;
579             buffer = (const void*) ((char* ) buffer + part);
580         }
581         offset = offset > size ? offset - size : 0;
582         block = block->fNext;
583     }
584     return false;
585 }
586 
read(void * buffer,size_t offset,size_t count)587 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
588 {
589     if (offset + count > fBytesWritten)
590         return false; // test does not partially modify
591     Block* block = fHead;
592     while (block != NULL) {
593         size_t size = block->written();
594         if (offset < size) {
595             size_t part = offset + count > size ? size - offset : count;
596             memcpy(buffer, block->start() + offset, part);
597             if (count <= part)
598                 return true;
599             count -= part;
600             buffer = (void*) ((char* ) buffer + part);
601         }
602         offset = offset > size ? offset - size : 0;
603         block = block->fNext;
604     }
605     return false;
606 }
607 
copyTo(void * dst) const608 void SkDynamicMemoryWStream::copyTo(void* dst) const
609 {
610     if (fCopy) {
611         memcpy(dst, fCopy->data(), fBytesWritten);
612     } else {
613         Block* block = fHead;
614 
615         while (block != NULL) {
616             size_t size = block->written();
617             memcpy(dst, block->start(), size);
618             dst = (void*)((char*)dst + size);
619             block = block->fNext;
620         }
621     }
622 }
623 
padToAlign4()624 void SkDynamicMemoryWStream::padToAlign4()
625 {
626     // cast to remove unary-minus warning
627     int padBytes = -(int)fBytesWritten & 0x03;
628     if (padBytes == 0)
629         return;
630     int zero = 0;
631     write(&zero, padBytes);
632 }
633 
copyToData() const634 SkData* SkDynamicMemoryWStream::copyToData() const {
635     if (NULL == fCopy) {
636         SkData* data = SkData::NewUninitialized(fBytesWritten);
637         // be sure to call copyTo() before we assign to fCopy
638         this->copyTo(data->writable_data());
639         fCopy = data;
640     }
641     return SkRef(fCopy);
642 }
643 
invalidateCopy()644 void SkDynamicMemoryWStream::invalidateCopy() {
645     if (fCopy) {
646         fCopy->unref();
647         fCopy = NULL;
648     }
649 }
650 
651 class SkBlockMemoryRefCnt : public SkRefCnt {
652 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)653     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
654 
~SkBlockMemoryRefCnt()655     virtual ~SkBlockMemoryRefCnt() {
656         SkDynamicMemoryWStream::Block* block = fHead;
657         while (block != NULL) {
658             SkDynamicMemoryWStream::Block* next = block->fNext;
659             sk_free(block);
660             block = next;
661         }
662     }
663 
664     SkDynamicMemoryWStream::Block* const fHead;
665 };
666 
667 class SkBlockMemoryStream : public SkStreamAsset {
668 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)669     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
670         : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
671         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
672 
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)673     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
674         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
675         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
676 
read(void * buffer,size_t rawCount)677     virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
678         size_t count = rawCount;
679         if (fOffset + count > fSize) {
680             count = fSize - fOffset;
681         }
682         size_t bytesLeftToRead = count;
683         while (fCurrent != NULL) {
684             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
685             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
686             if (buffer) {
687                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
688                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
689             }
690             if (bytesLeftToRead <= bytesFromCurrent) {
691                 fCurrentOffset += bytesFromCurrent;
692                 fOffset += count;
693                 return count;
694             }
695             bytesLeftToRead -= bytesFromCurrent;
696             fCurrent = fCurrent->fNext;
697             fCurrentOffset = 0;
698         }
699         SkASSERT(false);
700         return 0;
701     }
702 
isAtEnd() const703     virtual bool isAtEnd() const SK_OVERRIDE {
704         return fOffset == fSize;
705     }
706 
rewind()707     virtual bool rewind() SK_OVERRIDE {
708         fCurrent = fBlockMemory->fHead;
709         fOffset = 0;
710         fCurrentOffset = 0;
711         return true;
712     }
713 
duplicate() const714     virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
715         return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
716     }
717 
getPosition() const718     virtual size_t getPosition() const SK_OVERRIDE {
719         return fOffset;
720     }
721 
seek(size_t position)722     virtual bool seek(size_t position) SK_OVERRIDE {
723         // If possible, skip forward.
724         if (position >= fOffset) {
725             size_t skipAmount = position - fOffset;
726             return this->skip(skipAmount) == skipAmount;
727         }
728         // If possible, move backward within the current block.
729         size_t moveBackAmount = fOffset - position;
730         if (moveBackAmount <= fCurrentOffset) {
731             fCurrentOffset -= moveBackAmount;
732             fOffset -= moveBackAmount;
733             return true;
734         }
735         // Otherwise rewind and move forward.
736         return this->rewind() && this->skip(position) == position;
737     }
738 
move(long offset)739     virtual bool move(long offset) SK_OVERRIDE {
740         return seek(fOffset + offset);
741     }
742 
fork() const743     virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
744         SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
745         that->fCurrent = this->fCurrent;
746         that->fOffset = this->fOffset;
747         that->fCurrentOffset = this->fCurrentOffset;
748         return that.detach();
749     }
750 
getLength() const751     virtual size_t getLength() const SK_OVERRIDE {
752         return fSize;
753     }
754 
getMemoryBase()755     virtual const void* getMemoryBase() SK_OVERRIDE {
756         if (NULL == fBlockMemory->fHead->fNext) {
757             return fBlockMemory->fHead->start();
758         }
759         return NULL;
760     }
761 
762 private:
763     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
764     SkDynamicMemoryWStream::Block const * fCurrent;
765     size_t const fSize;
766     size_t fOffset;
767     size_t fCurrentOffset;
768 };
769 
detachAsStream()770 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
771     if (fCopy) {
772         SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
773         this->reset();
774         return stream;
775     }
776     SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
777     fHead = 0;
778     this->reset();
779     return stream;
780 }
781 
782 ///////////////////////////////////////////////////////////////////////////////
783 
newline()784 void SkDebugWStream::newline()
785 {
786 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
787     SkDebugf("\n");
788     fBytesWritten++;
789 #endif
790 }
791 
write(const void * buffer,size_t size)792 bool SkDebugWStream::write(const void* buffer, size_t size)
793 {
794 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
795     char* s = new char[size+1];
796     memcpy(s, buffer, size);
797     s[size] = 0;
798     SkDebugf("%s", s);
799     delete[] s;
800     fBytesWritten += size;
801 #endif
802     return true;
803 }
804 
805 ///////////////////////////////////////////////////////////////////////////////
806 ///////////////////////////////////////////////////////////////////////////////
807 
808 
mmap_filename(const char path[])809 static SkData* mmap_filename(const char path[]) {
810     SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
811     if (NULL == file) {
812         return NULL;
813     }
814 
815     SkData* data = SkData::NewFromFILE(file);
816     sk_fclose(file);
817     return data;
818 }
819 
NewFromFile(const char path[])820 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
821     SkAutoTUnref<SkData> data(mmap_filename(path));
822     if (data.get()) {
823         return SkNEW_ARGS(SkMemoryStream, (data.get()));
824     }
825 
826     // If we get here, then our attempt at using mmap failed, so try normal
827     // file access.
828     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
829     if (!stream->isValid()) {
830         stream->unref();
831         stream = NULL;
832     }
833     return stream;
834 }
835 
836 // Declared in SkStreamPriv.h:
SkCopyStreamToStorage(SkAutoMalloc * storage,SkStream * stream)837 size_t SkCopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) {
838     SkASSERT(storage != NULL);
839     SkASSERT(stream != NULL);
840 
841     if (stream->hasLength()) {
842         const size_t length = stream->getLength();
843         void* dst = storage->reset(length);
844         if (stream->read(dst, length) != length) {
845             return 0;
846         }
847         return length;
848     }
849 
850     SkDynamicMemoryWStream tempStream;
851     // Arbitrary buffer size.
852     const size_t bufferSize = 256 * 1024; // 256KB
853     char buffer[bufferSize];
854     SkDEBUGCODE(size_t debugLength = 0;)
855     do {
856         size_t bytesRead = stream->read(buffer, bufferSize);
857         tempStream.write(buffer, bytesRead);
858         SkDEBUGCODE(debugLength += bytesRead);
859         SkASSERT(tempStream.bytesWritten() == debugLength);
860     } while (!stream->isAtEnd());
861     const size_t length = tempStream.bytesWritten();
862     void* dst = storage->reset(length);
863     tempStream.copyTo(dst);
864     return length;
865 }
866 
867 // Declared in SkStreamPriv.h:
SkCopyStreamToData(SkStream * stream)868 SkData* SkCopyStreamToData(SkStream* stream) {
869     SkASSERT(stream != NULL);
870 
871     if (stream->hasLength()) {
872         return SkData::NewFromStream(stream, stream->getLength());
873     }
874 
875     SkDynamicMemoryWStream tempStream;
876     const size_t bufferSize = 4096;
877     char buffer[bufferSize];
878     do {
879         size_t bytesRead = stream->read(buffer, bufferSize);
880         tempStream.write(buffer, bytesRead);
881     } while (!stream->isAtEnd());
882     return tempStream.copyToData();
883 }
884 
SkStreamRewindableFromSkStream(SkStream * stream)885 SkStreamRewindable* SkStreamRewindableFromSkStream(SkStream* stream) {
886     if (!stream) {
887         return NULL;
888     }
889     SkAutoTUnref<SkStreamRewindable> dupStream(stream->duplicate());
890     if (dupStream) {
891         return dupStream.detach();
892     }
893     stream->rewind();
894     if (stream->hasLength()) {
895         size_t length = stream->getLength();
896         if (stream->hasPosition()) {  // If stream has length, but can't rewind.
897             length -= stream->getPosition();
898         }
899         SkAutoTUnref<SkData> data(SkData::NewFromStream(stream, length));
900         return SkNEW_ARGS(SkMemoryStream, (data.get()));
901     }
902     SkDynamicMemoryWStream tempStream;
903     const size_t bufferSize = 4096;
904     char buffer[bufferSize];
905     do {
906         size_t bytesRead = stream->read(buffer, bufferSize);
907         tempStream.write(buffer, bytesRead);
908     } while (!stream->isAtEnd());
909     return tempStream.detachAsStream();  // returns a SkBlockMemoryStream,
910                                          // cheaper than copying to SkData
911 }
912