• 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     char buffer[SkStrAppendS32_MaxSize];
91     char* stop = SkStrAppendS32(buffer, dec);
92     return this->write(buffer, stop - buffer);
93 }
94 
writeBigDecAsText(int64_t dec,int minDigits)95 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
96 {
97     char buffer[SkStrAppendU64_MaxSize];
98     char* stop = SkStrAppendU64(buffer, dec, minDigits);
99     return this->write(buffer, stop - buffer);
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     char buffer[SkStrAppendScalar_MaxSize];
112     char* stop = SkStrAppendScalar(buffer, value);
113     return this->write(buffer, stop - buffer);
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) : nullptr;
185 }
186 
SkFILEStream(FILE * file,Ownership ownership)187 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
188     : fFILE(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 = nullptr;
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 = nullptr;
228     }
229     return false;
230 }
231 
duplicate() const232 SkStreamAsset* SkFILEStream::duplicate() const {
233     if (nullptr == fFILE) {
234         return new SkMemoryStream();
235     }
236 
237     if (fData.get()) {
238         return new SkMemoryStream(fData);
239     }
240 
241     if (!fName.isEmpty()) {
242         SkAutoTDelete<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 (nullptr == fData.get()) {
250         return nullptr;
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     SkAutoTDelete<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 (nullptr == fData.get()) {
279         return nullptr;
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 (nullptr == 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 (nullptr == 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 
peek(void * buffer,size_t size) const370 size_t SkMemoryStream::peek(void* buffer, size_t size) const {
371     SkASSERT(buffer != nullptr);
372 
373     const size_t currentOffset = fOffset;
374     SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
375     const size_t bytesRead = nonConstThis->read(buffer, size);
376     nonConstThis->fOffset = currentOffset;
377     return bytesRead;
378 }
379 
isAtEnd() const380 bool SkMemoryStream::isAtEnd() const {
381     return fOffset == fData->size();
382 }
383 
rewind()384 bool SkMemoryStream::rewind() {
385     fOffset = 0;
386     return true;
387 }
388 
duplicate() const389 SkMemoryStream* SkMemoryStream::duplicate() const { return new SkMemoryStream(fData); }
390 
getPosition() const391 size_t SkMemoryStream::getPosition() const {
392     return fOffset;
393 }
394 
seek(size_t position)395 bool SkMemoryStream::seek(size_t position) {
396     fOffset = position > fData->size()
397             ? fData->size()
398             : position;
399     return true;
400 }
401 
move(long offset)402 bool SkMemoryStream::move(long offset) {
403     return this->seek(fOffset + offset);
404 }
405 
fork() const406 SkMemoryStream* SkMemoryStream::fork() const {
407     SkAutoTDelete<SkMemoryStream> that(this->duplicate());
408     that->seek(fOffset);
409     return that.detach();
410 }
411 
getLength() const412 size_t SkMemoryStream::getLength() const {
413     return fData->size();
414 }
415 
getMemoryBase()416 const void* SkMemoryStream::getMemoryBase() {
417     return fData->data();
418 }
419 
getAtPos()420 const void* SkMemoryStream::getAtPos() {
421     return fData->bytes() + fOffset;
422 }
423 
424 /////////////////////////////////////////////////////////////////////////////////////////////////////////
425 /////////////////////////////////////////////////////////////////////////////////////////////////////////
426 
SkFILEWStream(const char path[])427 SkFILEWStream::SkFILEWStream(const char path[])
428 {
429     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
430 }
431 
~SkFILEWStream()432 SkFILEWStream::~SkFILEWStream()
433 {
434     if (fFILE) {
435         sk_fclose(fFILE);
436     }
437 }
438 
bytesWritten() const439 size_t SkFILEWStream::bytesWritten() const {
440     return sk_ftell(fFILE);
441 }
442 
write(const void * buffer,size_t size)443 bool SkFILEWStream::write(const void* buffer, size_t size)
444 {
445     if (fFILE == nullptr) {
446         return false;
447     }
448 
449     if (sk_fwrite(buffer, size, fFILE) != size)
450     {
451         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
452         sk_fclose(fFILE);
453         fFILE = nullptr;
454         return false;
455     }
456     return true;
457 }
458 
flush()459 void SkFILEWStream::flush()
460 {
461     if (fFILE) {
462         sk_fflush(fFILE);
463     }
464 }
465 
fsync()466 void SkFILEWStream::fsync()
467 {
468     flush();
469     if (fFILE) {
470         sk_fsync(fFILE);
471     }
472 }
473 
474 ////////////////////////////////////////////////////////////////////////
475 
SkMemoryWStream(void * buffer,size_t size)476 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
477     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
478 {
479 }
480 
write(const void * buffer,size_t size)481 bool SkMemoryWStream::write(const void* buffer, size_t size) {
482     size = SkTMin(size, fMaxLength - fBytesWritten);
483     if (size > 0) {
484         memcpy(fBuffer + fBytesWritten, buffer, size);
485         fBytesWritten += size;
486         return true;
487     }
488     return false;
489 }
490 
491 ////////////////////////////////////////////////////////////////////////
492 
493 #define SkDynamicMemoryWStream_MinBlockSize   256
494 
495 struct SkDynamicMemoryWStream::Block {
496     Block*  fNext;
497     char*   fCurr;
498     char*   fStop;
499 
startSkDynamicMemoryWStream::Block500     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block501     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block502     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block503     size_t  written() const { return fCurr - this->start(); }
504 
initSkDynamicMemoryWStream::Block505     void init(size_t size)
506     {
507         fNext = nullptr;
508         fCurr = this->start();
509         fStop = this->start() + size;
510     }
511 
appendSkDynamicMemoryWStream::Block512     const void* append(const void* data, size_t size)
513     {
514         SkASSERT((size_t)(fStop - fCurr) >= size);
515         memcpy(fCurr, data, size);
516         fCurr += size;
517         return (const void*)((const char*)data + size);
518     }
519 };
520 
SkDynamicMemoryWStream()521 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
522     : fHead(nullptr), fTail(nullptr), fBytesWritten(0), fCopy(nullptr)
523 {
524 }
525 
~SkDynamicMemoryWStream()526 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
527 {
528     reset();
529 }
530 
reset()531 void SkDynamicMemoryWStream::reset()
532 {
533     this->invalidateCopy();
534 
535     Block*  block = fHead;
536 
537     while (block != nullptr) {
538         Block*  next = block->fNext;
539         sk_free(block);
540         block = next;
541     }
542     fHead = fTail = nullptr;
543     fBytesWritten = 0;
544 }
545 
write(const void * buffer,size_t count)546 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
547 {
548     if (count > 0) {
549         this->invalidateCopy();
550 
551         fBytesWritten += count;
552 
553         size_t  size;
554 
555         if (fTail != nullptr && fTail->avail() > 0) {
556             size = SkTMin(fTail->avail(), count);
557             buffer = fTail->append(buffer, size);
558             SkASSERT(count >= size);
559             count -= size;
560             if (count == 0)
561                 return true;
562         }
563 
564         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
565         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
566         block->init(size);
567         block->append(buffer, count);
568 
569         if (fTail != nullptr)
570             fTail->fNext = block;
571         else
572             fHead = fTail = block;
573         fTail = block;
574     }
575     return true;
576 }
577 
write(const void * buffer,size_t offset,size_t count)578 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
579 {
580     if (offset + count > fBytesWritten) {
581         return false; // test does not partially modify
582     }
583 
584     this->invalidateCopy();
585 
586     Block* block = fHead;
587     while (block != nullptr) {
588         size_t size = block->written();
589         if (offset < size) {
590             size_t part = offset + count > size ? size - offset : count;
591             memcpy(block->start() + offset, buffer, part);
592             if (count <= part)
593                 return true;
594             count -= part;
595             buffer = (const void*) ((char* ) buffer + part);
596         }
597         offset = offset > size ? offset - size : 0;
598         block = block->fNext;
599     }
600     return false;
601 }
602 
read(void * buffer,size_t offset,size_t count)603 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
604 {
605     if (offset + count > fBytesWritten)
606         return false; // test does not partially modify
607     Block* block = fHead;
608     while (block != nullptr) {
609         size_t size = block->written();
610         if (offset < size) {
611             size_t part = offset + count > size ? size - offset : count;
612             memcpy(buffer, block->start() + offset, part);
613             if (count <= part)
614                 return true;
615             count -= part;
616             buffer = (void*) ((char* ) buffer + part);
617         }
618         offset = offset > size ? offset - size : 0;
619         block = block->fNext;
620     }
621     return false;
622 }
623 
copyTo(void * dst) const624 void SkDynamicMemoryWStream::copyTo(void* dst) const
625 {
626     if (fCopy) {
627         memcpy(dst, fCopy->data(), fBytesWritten);
628     } else {
629         Block* block = fHead;
630 
631         while (block != nullptr) {
632             size_t size = block->written();
633             memcpy(dst, block->start(), size);
634             dst = (void*)((char*)dst + size);
635             block = block->fNext;
636         }
637     }
638 }
639 
writeToStream(SkWStream * dst) const640 void SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
641     for (Block* block = fHead; block != nullptr; block = block->fNext) {
642         dst->write(block->start(), block->written());
643     }
644 }
645 
padToAlign4()646 void SkDynamicMemoryWStream::padToAlign4()
647 {
648     // cast to remove unary-minus warning
649     int padBytes = -(int)fBytesWritten & 0x03;
650     if (padBytes == 0)
651         return;
652     int zero = 0;
653     write(&zero, padBytes);
654 }
655 
copyToData() const656 SkData* SkDynamicMemoryWStream::copyToData() const {
657     if (nullptr == fCopy) {
658         SkData* data = SkData::NewUninitialized(fBytesWritten);
659         // be sure to call copyTo() before we assign to fCopy
660         this->copyTo(data->writable_data());
661         fCopy = data;
662     }
663     return SkRef(fCopy);
664 }
665 
invalidateCopy()666 void SkDynamicMemoryWStream::invalidateCopy() {
667     if (fCopy) {
668         fCopy->unref();
669         fCopy = nullptr;
670     }
671 }
672 
673 class SkBlockMemoryRefCnt : public SkRefCnt {
674 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)675     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
676 
~SkBlockMemoryRefCnt()677     virtual ~SkBlockMemoryRefCnt() {
678         SkDynamicMemoryWStream::Block* block = fHead;
679         while (block != nullptr) {
680             SkDynamicMemoryWStream::Block* next = block->fNext;
681             sk_free(block);
682             block = next;
683         }
684     }
685 
686     SkDynamicMemoryWStream::Block* const fHead;
687 };
688 
689 class SkBlockMemoryStream : public SkStreamAsset {
690 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)691     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
692         : fBlockMemory(new SkBlockMemoryRefCnt(head))
693         , fCurrent(head)
694         , fSize(size)
695         , fOffset(0)
696         , fCurrentOffset(0) {}
697 
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)698     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
699         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
700         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
701 
read(void * buffer,size_t rawCount)702     size_t read(void* buffer, size_t rawCount) override {
703         size_t count = rawCount;
704         if (fOffset + count > fSize) {
705             count = fSize - fOffset;
706         }
707         size_t bytesLeftToRead = count;
708         while (fCurrent != nullptr) {
709             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
710             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
711             if (buffer) {
712                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
713                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
714             }
715             if (bytesLeftToRead <= bytesFromCurrent) {
716                 fCurrentOffset += bytesFromCurrent;
717                 fOffset += count;
718                 return count;
719             }
720             bytesLeftToRead -= bytesFromCurrent;
721             fCurrent = fCurrent->fNext;
722             fCurrentOffset = 0;
723         }
724         SkASSERT(false);
725         return 0;
726     }
727 
isAtEnd() const728     bool isAtEnd() const override {
729         return fOffset == fSize;
730     }
731 
peek(void * buff,size_t bytesToPeek) const732     size_t peek(void* buff, size_t bytesToPeek) const override {
733         SkASSERT(buff != nullptr);
734 
735         bytesToPeek = SkTMin(bytesToPeek, fSize - fOffset);
736 
737         size_t bytesLeftToPeek = bytesToPeek;
738         char* buffer = static_cast<char*>(buff);
739         const SkDynamicMemoryWStream::Block* current = fCurrent;
740         size_t currentOffset = fCurrentOffset;
741         while (bytesLeftToPeek) {
742             SkASSERT(current);
743             size_t bytesFromCurrent =
744                     SkTMin(current->written() - currentOffset, bytesLeftToPeek);
745             memcpy(buffer, current->start() + currentOffset, bytesFromCurrent);
746             bytesLeftToPeek -= bytesFromCurrent;
747             buffer += bytesFromCurrent;
748             current = current->fNext;
749             currentOffset = 0;
750         }
751         return bytesToPeek;
752     }
753 
rewind()754     bool rewind() override {
755         fCurrent = fBlockMemory->fHead;
756         fOffset = 0;
757         fCurrentOffset = 0;
758         return true;
759     }
760 
duplicate() const761     SkBlockMemoryStream* duplicate() const override {
762         return new SkBlockMemoryStream(fBlockMemory.get(), fSize);
763     }
764 
getPosition() const765     size_t getPosition() const override {
766         return fOffset;
767     }
768 
seek(size_t position)769     bool seek(size_t position) override {
770         // If possible, skip forward.
771         if (position >= fOffset) {
772             size_t skipAmount = position - fOffset;
773             return this->skip(skipAmount) == skipAmount;
774         }
775         // If possible, move backward within the current block.
776         size_t moveBackAmount = fOffset - position;
777         if (moveBackAmount <= fCurrentOffset) {
778             fCurrentOffset -= moveBackAmount;
779             fOffset -= moveBackAmount;
780             return true;
781         }
782         // Otherwise rewind and move forward.
783         return this->rewind() && this->skip(position) == position;
784     }
785 
move(long offset)786     bool move(long offset) override {
787         return seek(fOffset + offset);
788     }
789 
fork() const790     SkBlockMemoryStream* fork() const override {
791         SkAutoTDelete<SkBlockMemoryStream> that(this->duplicate());
792         that->fCurrent = this->fCurrent;
793         that->fOffset = this->fOffset;
794         that->fCurrentOffset = this->fCurrentOffset;
795         return that.detach();
796     }
797 
getLength() const798     size_t getLength() const override {
799         return fSize;
800     }
801 
getMemoryBase()802     const void* getMemoryBase() override {
803         if (nullptr != fBlockMemory->fHead &&
804             nullptr == fBlockMemory->fHead->fNext) {
805             return fBlockMemory->fHead->start();
806         }
807         return nullptr;
808     }
809 
810 private:
811     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
812     SkDynamicMemoryWStream::Block const * fCurrent;
813     size_t const fSize;
814     size_t fOffset;
815     size_t fCurrentOffset;
816 };
817 
detachAsStream()818 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
819     if (fCopy) {
820         SkMemoryStream* stream = new SkMemoryStream(fCopy);
821         this->reset();
822         return stream;
823     }
824     SkBlockMemoryStream* stream = new SkBlockMemoryStream(fHead, fBytesWritten);
825     fHead = 0;
826     this->reset();
827     return stream;
828 }
829 
830 ///////////////////////////////////////////////////////////////////////////////
831 
newline()832 void SkDebugWStream::newline()
833 {
834 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
835     SkDebugf("\n");
836     fBytesWritten++;
837 #endif
838 }
839 
write(const void * buffer,size_t size)840 bool SkDebugWStream::write(const void* buffer, size_t size)
841 {
842 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
843     char* s = new char[size+1];
844     memcpy(s, buffer, size);
845     s[size] = 0;
846     SkDebugf("%s", s);
847     delete[] s;
848     fBytesWritten += size;
849 #endif
850     return true;
851 }
852 
853 ///////////////////////////////////////////////////////////////////////////////
854 ///////////////////////////////////////////////////////////////////////////////
855 
856 
mmap_filename(const char path[])857 static SkData* mmap_filename(const char path[]) {
858     FILE* file = sk_fopen(path, kRead_SkFILE_Flag);
859     if (nullptr == file) {
860         return nullptr;
861     }
862 
863     SkData* data = SkData::NewFromFILE(file);
864     sk_fclose(file);
865     return data;
866 }
867 
NewFromFile(const char path[])868 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
869     SkAutoTUnref<SkData> data(mmap_filename(path));
870     if (data.get()) {
871         return new SkMemoryStream(data.get());
872     }
873 
874     // If we get here, then our attempt at using mmap failed, so try normal
875     // file access.
876     SkFILEStream* stream = new SkFILEStream(path);
877     if (!stream->isValid()) {
878         delete stream;
879         stream = nullptr;
880     }
881     return stream;
882 }
883 
884 // Declared in SkStreamPriv.h:
SkCopyStreamToData(SkStream * stream)885 SkData* SkCopyStreamToData(SkStream* stream) {
886     SkASSERT(stream != nullptr);
887 
888     if (stream->hasLength()) {
889         return SkData::NewFromStream(stream, stream->getLength());
890     }
891 
892     SkDynamicMemoryWStream tempStream;
893     const size_t bufferSize = 4096;
894     char buffer[bufferSize];
895     do {
896         size_t bytesRead = stream->read(buffer, bufferSize);
897         tempStream.write(buffer, bytesRead);
898     } while (!stream->isAtEnd());
899     return tempStream.copyToData();
900 }
901 
SkStreamCopy(SkWStream * out,SkStream * input)902 bool SkStreamCopy(SkWStream* out, SkStream* input) {
903     const char* base = static_cast<const char*>(input->getMemoryBase());
904     if (base && input->hasPosition() && input->hasLength()) {
905         // Shortcut that avoids the while loop.
906         size_t position = input->getPosition();
907         size_t length = input->getLength();
908         SkASSERT(length >= position);
909         return out->write(&base[position], length - position);
910     }
911     char scratch[4096];
912     size_t count;
913     while (true) {
914         count = input->read(scratch, sizeof(scratch));
915         if (0 == count) {
916             return true;
917         }
918         if (!out->write(scratch, count)) {
919             return false;
920         }
921     }
922 }
923