• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkStream.h"
9 #include "SkStreamPriv.h"
10 #include "SkData.h"
11 #include "SkFixed.h"
12 #include "SkMakeUnique.h"
13 #include "SkSafeMath.h"
14 #include "SkString.h"
15 #include "SkOSFile.h"
16 #include "SkTypes.h"
17 #include "SkTFitsIn.h"
18 
19 #include <limits>
20 
21 ///////////////////////////////////////////////////////////////////////////////
22 
readS8()23 int8_t SkStream::readS8() {
24     int8_t value;
25     SkDEBUGCODE(size_t len =) this->read(&value, 1);
26     SkASSERT(1 == len);
27     return value;
28 }
29 
readS16()30 int16_t SkStream::readS16() {
31     int16_t value;
32     SkDEBUGCODE(size_t len =) this->read(&value, 2);
33     SkASSERT(2 == len);
34     return value;
35 }
36 
readS32()37 int32_t SkStream::readS32() {
38     int32_t value;
39     SkDEBUGCODE(size_t len =) this->read(&value, 4);
40     SkASSERT(4 == len);
41     return value;
42 }
43 
readScalar()44 SkScalar SkStream::readScalar() {
45     SkScalar value;
46     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
47     SkASSERT(sizeof(SkScalar) == len);
48     return value;
49 }
50 
51 #define SK_MAX_BYTE_FOR_U8          0xFD
52 #define SK_BYTE_SENTINEL_FOR_U16    0xFE
53 #define SK_BYTE_SENTINEL_FOR_U32    0xFF
54 
readPackedUInt()55 size_t SkStream::readPackedUInt() {
56     uint8_t byte;
57     if (!this->read(&byte, 1)) {
58         return 0;
59     }
60     if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
61         return this->readU16();
62     } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
63         return this->readU32();
64     } else {
65         return byte;
66     }
67 }
68 
69 //////////////////////////////////////////////////////////////////////////////////////
70 
~SkWStream()71 SkWStream::~SkWStream()
72 {
73 }
74 
flush()75 void SkWStream::flush()
76 {
77 }
78 
writeDecAsText(int32_t dec)79 bool SkWStream::writeDecAsText(int32_t dec)
80 {
81     char buffer[SkStrAppendS32_MaxSize];
82     char* stop = SkStrAppendS32(buffer, dec);
83     return this->write(buffer, stop - buffer);
84 }
85 
writeBigDecAsText(int64_t dec,int minDigits)86 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
87 {
88     char buffer[SkStrAppendU64_MaxSize];
89     char* stop = SkStrAppendU64(buffer, dec, minDigits);
90     return this->write(buffer, stop - buffer);
91 }
92 
writeHexAsText(uint32_t hex,int digits)93 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
94 {
95     SkString    tmp;
96     tmp.appendHex(hex, digits);
97     return this->write(tmp.c_str(), tmp.size());
98 }
99 
writeScalarAsText(SkScalar value)100 bool SkWStream::writeScalarAsText(SkScalar value)
101 {
102     char buffer[SkStrAppendScalar_MaxSize];
103     char* stop = SkStrAppendScalar(buffer, value);
104     return this->write(buffer, stop - buffer);
105 }
106 
writeScalar(SkScalar value)107 bool SkWStream::writeScalar(SkScalar value) {
108     return this->write(&value, sizeof(value));
109 }
110 
SizeOfPackedUInt(size_t value)111 int SkWStream::SizeOfPackedUInt(size_t value) {
112     if (value <= SK_MAX_BYTE_FOR_U8) {
113         return 1;
114     } else if (value <= 0xFFFF) {
115         return 3;
116     }
117     return 5;
118 }
119 
writePackedUInt(size_t value)120 bool SkWStream::writePackedUInt(size_t value) {
121     uint8_t data[5];
122     size_t len = 1;
123     if (value <= SK_MAX_BYTE_FOR_U8) {
124         data[0] = value;
125         len = 1;
126     } else if (value <= 0xFFFF) {
127         uint16_t value16 = value;
128         data[0] = SK_BYTE_SENTINEL_FOR_U16;
129         memcpy(&data[1], &value16, 2);
130         len = 3;
131     } else {
132         uint32_t value32 = SkToU32(value);
133         data[0] = SK_BYTE_SENTINEL_FOR_U32;
134         memcpy(&data[1], &value32, 4);
135         len = 5;
136     }
137     return this->write(data, len);
138 }
139 
writeStream(SkStream * stream,size_t length)140 bool SkWStream::writeStream(SkStream* stream, size_t length) {
141     char scratch[1024];
142     const size_t MAX = sizeof(scratch);
143 
144     while (length != 0) {
145         size_t n = length;
146         if (n > MAX) {
147             n = MAX;
148         }
149         stream->read(scratch, n);
150         if (!this->write(scratch, n)) {
151             return false;
152         }
153         length -= n;
154     }
155     return true;
156 }
157 
158 ///////////////////////////////////////////////////////////////////////////////
159 
SkFILEStream(std::shared_ptr<FILE> file,size_t size,size_t offset,size_t originalOffset)160 SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size,
161                            size_t offset, size_t originalOffset)
162     : fFILE(std::move(file))
163     , fSize(size)
164     , fOffset(SkTMin(offset, fSize))
165     , fOriginalOffset(SkTMin(originalOffset, fSize))
166 { }
167 
SkFILEStream(std::shared_ptr<FILE> file,size_t size,size_t offset)168 SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size, size_t offset)
169     : SkFILEStream(std::move(file), size, offset, offset)
170 { }
171 
SkFILEStream(FILE * file)172 SkFILEStream::SkFILEStream(FILE* file)
173     : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose),
174                    file ? sk_fgetsize(file) : 0,
175                    file ? sk_ftell(file) : 0)
176 { }
177 
178 
SkFILEStream(const char path[])179 SkFILEStream::SkFILEStream(const char path[])
180     : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr)
181 { }
182 
~SkFILEStream()183 SkFILEStream::~SkFILEStream() {
184     this->close();
185 }
186 
close()187 void SkFILEStream::close() {
188     fFILE.reset();
189     fSize = 0;
190     fOffset = 0;
191 }
192 
read(void * buffer,size_t size)193 size_t SkFILEStream::read(void* buffer, size_t size) {
194     if (size > fSize - fOffset) {
195         size = fSize - fOffset;
196     }
197     size_t bytesRead = size;
198     if (buffer) {
199         bytesRead = sk_qread(fFILE.get(), buffer, size, fOffset);
200     }
201     if (bytesRead == SIZE_MAX) {
202         return 0;
203     }
204     fOffset += bytesRead;
205     return bytesRead;
206 }
207 
isAtEnd() const208 bool SkFILEStream::isAtEnd() const {
209     if (fOffset == fSize) {
210         return true;
211     }
212     return fOffset >= sk_fgetsize(fFILE.get());
213 }
214 
rewind()215 bool SkFILEStream::rewind() {
216     fOffset = fOriginalOffset;
217     return true;
218 }
219 
onDuplicate() const220 SkStreamAsset* SkFILEStream::onDuplicate() const {
221     return new SkFILEStream(fFILE, fSize, fOriginalOffset, fOriginalOffset);
222 }
223 
getPosition() const224 size_t SkFILEStream::getPosition() const {
225     SkASSERT(fOffset >= fOriginalOffset);
226     return fOffset - fOriginalOffset;
227 }
228 
seek(size_t position)229 bool SkFILEStream::seek(size_t position) {
230     fOffset = SkTMin(SkSafeMath::Add(position, fOriginalOffset), fSize);
231     return true;
232 }
233 
move(long offset)234 bool SkFILEStream::move(long offset) {
235     if (offset < 0) {
236         if (offset == std::numeric_limits<long>::min()
237                 || !SkTFitsIn<size_t>(-offset)
238                 || (size_t) (-offset) >= this->getPosition()) {
239             fOffset = fOriginalOffset;
240         } else {
241             fOffset += offset;
242         }
243     } else if (!SkTFitsIn<size_t>(offset)) {
244         fOffset = fSize;
245     } else {
246         fOffset = SkTMin(SkSafeMath::Add(fOffset, (size_t) offset), fSize);
247     }
248 
249     SkASSERT(fOffset >= fOriginalOffset && fOffset <= fSize);
250     return true;
251 }
252 
onFork() const253 SkStreamAsset* SkFILEStream::onFork() const {
254     return new SkFILEStream(fFILE, fSize, fOffset, fOriginalOffset);
255 }
256 
getLength() const257 size_t SkFILEStream::getLength() const {
258     return fSize - fOriginalOffset;
259 }
260 
261 ///////////////////////////////////////////////////////////////////////////////
262 
newFromParams(const void * src,size_t size,bool copyData)263 static sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) {
264     if (copyData) {
265         return SkData::MakeWithCopy(src, size);
266     } else {
267         return SkData::MakeWithoutCopy(src, size);
268     }
269 }
270 
SkMemoryStream()271 SkMemoryStream::SkMemoryStream() {
272     fData = SkData::MakeEmpty();
273     fOffset = 0;
274 }
275 
SkMemoryStream(size_t size)276 SkMemoryStream::SkMemoryStream(size_t size) {
277     fData = SkData::MakeUninitialized(size);
278     fOffset = 0;
279 }
280 
SkMemoryStream(const void * src,size_t size,bool copyData)281 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
282     fData = newFromParams(src, size, copyData);
283     fOffset = 0;
284 }
285 
SkMemoryStream(sk_sp<SkData> data)286 SkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) {
287     if (nullptr == fData) {
288         fData = SkData::MakeEmpty();
289     }
290     fOffset = 0;
291 }
292 
MakeCopy(const void * data,size_t length)293 std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) {
294     return skstd::make_unique<SkMemoryStream>(data, length, true);
295 }
296 
MakeDirect(const void * data,size_t length)297 std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) {
298     return skstd::make_unique<SkMemoryStream>(data, length, false);
299 }
300 
Make(sk_sp<SkData> data)301 std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) {
302     return skstd::make_unique<SkMemoryStream>(std::move(data));
303 }
304 
setMemoryOwned(const void * src,size_t size)305 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
306     fData = SkData::MakeFromMalloc(src, size);
307     fOffset = 0;
308 }
309 
setMemory(const void * src,size_t size,bool copyData)310 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
311     fData = newFromParams(src, size, copyData);
312     fOffset = 0;
313 }
314 
setData(sk_sp<SkData> data)315 void SkMemoryStream::setData(sk_sp<SkData> data) {
316     if (nullptr == data) {
317         fData = SkData::MakeEmpty();
318     } else {
319         fData = data;
320     }
321     fOffset = 0;
322 }
323 
skipToAlign4()324 void SkMemoryStream::skipToAlign4() {
325     // cast to remove unary-minus warning
326     fOffset += -(int)fOffset & 0x03;
327 }
328 
read(void * buffer,size_t size)329 size_t SkMemoryStream::read(void* buffer, size_t size) {
330     size_t dataSize = fData->size();
331 
332     if (size > dataSize - fOffset) {
333         size = dataSize - fOffset;
334     }
335     if (buffer) {
336         memcpy(buffer, fData->bytes() + fOffset, size);
337     }
338     fOffset += size;
339     return size;
340 }
341 
peek(void * buffer,size_t size) const342 size_t SkMemoryStream::peek(void* buffer, size_t size) const {
343     SkASSERT(buffer != nullptr);
344 
345     const size_t currentOffset = fOffset;
346     SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
347     const size_t bytesRead = nonConstThis->read(buffer, size);
348     nonConstThis->fOffset = currentOffset;
349     return bytesRead;
350 }
351 
isAtEnd() const352 bool SkMemoryStream::isAtEnd() const {
353     return fOffset == fData->size();
354 }
355 
rewind()356 bool SkMemoryStream::rewind() {
357     fOffset = 0;
358     return true;
359 }
360 
onDuplicate() const361 SkMemoryStream* SkMemoryStream::onDuplicate() const {
362     return new SkMemoryStream(fData);
363 }
364 
getPosition() const365 size_t SkMemoryStream::getPosition() const {
366     return fOffset;
367 }
368 
seek(size_t position)369 bool SkMemoryStream::seek(size_t position) {
370     fOffset = position > fData->size()
371             ? fData->size()
372             : position;
373     return true;
374 }
375 
move(long offset)376 bool SkMemoryStream::move(long offset) {
377     return this->seek(fOffset + offset);
378 }
379 
onFork() const380 SkMemoryStream* SkMemoryStream::onFork() const {
381     std::unique_ptr<SkMemoryStream> that(this->duplicate());
382     that->seek(fOffset);
383     return that.release();
384 }
385 
getLength() const386 size_t SkMemoryStream::getLength() const {
387     return fData->size();
388 }
389 
getMemoryBase()390 const void* SkMemoryStream::getMemoryBase() {
391     return fData->data();
392 }
393 
getAtPos()394 const void* SkMemoryStream::getAtPos() {
395     return fData->bytes() + fOffset;
396 }
397 
398 /////////////////////////////////////////////////////////////////////////////////////////////////////////
399 /////////////////////////////////////////////////////////////////////////////////////////////////////////
400 
SkFILEWStream(const char path[])401 SkFILEWStream::SkFILEWStream(const char path[])
402 {
403     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
404 }
405 
~SkFILEWStream()406 SkFILEWStream::~SkFILEWStream()
407 {
408     if (fFILE) {
409         sk_fclose(fFILE);
410     }
411 }
412 
bytesWritten() const413 size_t SkFILEWStream::bytesWritten() const {
414     return sk_ftell(fFILE);
415 }
416 
write(const void * buffer,size_t size)417 bool SkFILEWStream::write(const void* buffer, size_t size)
418 {
419     if (fFILE == nullptr) {
420         return false;
421     }
422 
423     if (sk_fwrite(buffer, size, fFILE) != size)
424     {
425         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
426         sk_fclose(fFILE);
427         fFILE = nullptr;
428         return false;
429     }
430     return true;
431 }
432 
flush()433 void SkFILEWStream::flush()
434 {
435     if (fFILE) {
436         sk_fflush(fFILE);
437     }
438 }
439 
fsync()440 void SkFILEWStream::fsync()
441 {
442     flush();
443     if (fFILE) {
444         sk_fsync(fFILE);
445     }
446 }
447 
448 ////////////////////////////////////////////////////////////////////////
449 
sk_memcpy_4bytes(void * dst,const void * src,size_t size)450 static inline void sk_memcpy_4bytes(void* dst, const void* src, size_t size) {
451     if (size == 4) {
452         memcpy(dst, src, 4);
453     } else {
454         memcpy(dst, src, size);
455     }
456 }
457 
458 #define SkDynamicMemoryWStream_MinBlockSize   4096
459 
460 struct SkDynamicMemoryWStream::Block {
461     Block*  fNext;
462     char*   fCurr;
463     char*   fStop;
464 
startSkDynamicMemoryWStream::Block465     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block466     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block467     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block468     size_t  written() const { return fCurr - this->start(); }
469 
initSkDynamicMemoryWStream::Block470     void init(size_t size) {
471         fNext = nullptr;
472         fCurr = this->start();
473         fStop = this->start() + size;
474     }
475 
appendSkDynamicMemoryWStream::Block476     const void* append(const void* data, size_t size) {
477         SkASSERT((size_t)(fStop - fCurr) >= size);
478         sk_memcpy_4bytes(fCurr, data, size);
479         fCurr += size;
480         return (const void*)((const char*)data + size);
481     }
482 };
483 
SkDynamicMemoryWStream()484 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
485     : fHead(nullptr), fTail(nullptr), fBytesWrittenBeforeTail(0)
486 {}
487 
~SkDynamicMemoryWStream()488 SkDynamicMemoryWStream::~SkDynamicMemoryWStream() {
489     this->reset();
490 }
491 
reset()492 void SkDynamicMemoryWStream::reset() {
493     Block*  block = fHead;
494     while (block != nullptr) {
495         Block*  next = block->fNext;
496         sk_free(block);
497         block = next;
498     }
499     fHead = fTail = nullptr;
500     fBytesWrittenBeforeTail = 0;
501 }
502 
bytesWritten() const503 size_t SkDynamicMemoryWStream::bytesWritten() const {
504     this->validate();
505 
506     if (fTail) {
507         return fBytesWrittenBeforeTail + fTail->written();
508     }
509     return 0;
510 }
511 
write(const void * buffer,size_t count)512 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
513     if (count > 0) {
514         size_t  size;
515 
516         if (fTail) {
517             if (fTail->avail() > 0) {
518                 size = SkTMin(fTail->avail(), count);
519                 buffer = fTail->append(buffer, size);
520                 SkASSERT(count >= size);
521                 count -= size;
522                 if (count == 0) {
523                     return true;
524                 }
525             }
526             // If we get here, we've just exhausted fTail, so update our tracker
527             fBytesWrittenBeforeTail += fTail->written();
528         }
529 
530         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block));
531         size = SkAlign4(size);  // ensure we're always a multiple of 4 (see padToAlign4())
532 
533         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
534         block->init(size);
535         block->append(buffer, count);
536 
537         if (fTail != nullptr)
538             fTail->fNext = block;
539         else
540             fHead = fTail = block;
541         fTail = block;
542         this->validate();
543     }
544     return true;
545 }
546 
read(void * buffer,size_t offset,size_t count)547 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) {
548     if (offset + count > this->bytesWritten()) {
549         return false; // test does not partially modify
550     }
551     Block* block = fHead;
552     while (block != nullptr) {
553         size_t size = block->written();
554         if (offset < size) {
555             size_t part = offset + count > size ? size - offset : count;
556             memcpy(buffer, block->start() + offset, part);
557             if (count <= part)
558                 return true;
559             count -= part;
560             buffer = (void*) ((char* ) buffer + part);
561         }
562         offset = offset > size ? offset - size : 0;
563         block = block->fNext;
564     }
565     return false;
566 }
567 
copyTo(void * dst) const568 void SkDynamicMemoryWStream::copyTo(void* dst) const {
569     Block* block = fHead;
570     while (block != nullptr) {
571         size_t size = block->written();
572         memcpy(dst, block->start(), size);
573         dst = (void*)((char*)dst + size);
574         block = block->fNext;
575     }
576 }
577 
writeToStream(SkWStream * dst) const578 bool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
579     for (Block* block = fHead; block != nullptr; block = block->fNext) {
580         if (!dst->write(block->start(), block->written())) {
581             return false;
582         }
583     }
584     return true;
585 }
586 
padToAlign4()587 void SkDynamicMemoryWStream::padToAlign4() {
588     // The contract is to write zeros until the entire stream has written a multiple of 4 bytes.
589     // Our Blocks are guaranteed always be (a) full (except the tail) and (b) a multiple of 4
590     // so it is sufficient to just examine the tail (if present).
591 
592     if (fTail) {
593         // cast to remove unary-minus warning
594         int padBytes = -(int)fTail->written() & 0x03;
595         if (padBytes) {
596             int zero = 0;
597             fTail->append(&zero, padBytes);
598         }
599     }
600 }
601 
602 
copyToAndReset(void * ptr)603 void SkDynamicMemoryWStream::copyToAndReset(void* ptr) {
604     // By looping through the source and freeing as we copy, we
605     // can reduce real memory use with large streams.
606     char* dst = reinterpret_cast<char*>(ptr);
607     Block* block = fHead;
608     while (block != nullptr) {
609         size_t len = block->written();
610         memcpy(dst, block->start(), len);
611         dst += len;
612         Block* next = block->fNext;
613         sk_free(block);
614         block = next;
615     }
616     fHead = fTail = nullptr;
617     fBytesWrittenBeforeTail = 0;
618 }
619 
writeToAndReset(SkWStream * dst)620 bool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) {
621     // By looping through the source and freeing as we copy, we
622     // can reduce real memory use with large streams.
623     bool dstStreamGood = true;
624     for (Block* block = fHead; block != nullptr; ) {
625         if (dstStreamGood && !dst->write(block->start(), block->written())) {
626             dstStreamGood = false;
627         }
628         Block* next = block->fNext;
629         sk_free(block);
630         block = next;
631     }
632     fHead = fTail = nullptr;
633     fBytesWrittenBeforeTail = 0;
634     return dstStreamGood;
635 }
636 
detachAsData()637 sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() {
638     const size_t size = this->bytesWritten();
639     if (0 == size) {
640         return SkData::MakeEmpty();
641     }
642     sk_sp<SkData> data = SkData::MakeUninitialized(size);
643     this->copyToAndReset(data->writable_data());
644     return data;
645 }
646 
647 #ifdef SK_DEBUG
validate() const648 void SkDynamicMemoryWStream::validate() const {
649     if (!fHead) {
650         SkASSERT(!fTail);
651         SkASSERT(fBytesWrittenBeforeTail == 0);
652         return;
653     }
654     SkASSERT(fTail);
655 
656     size_t bytes = 0;
657     const Block* block = fHead;
658     while (block) {
659         if (block->fNext) {
660             SkASSERT(block->avail() == 0);
661             bytes += block->written();
662             SkASSERT(bytes == SkAlign4(bytes)); // see padToAlign4()
663         }
664         block = block->fNext;
665     }
666     SkASSERT(bytes == fBytesWrittenBeforeTail);
667 }
668 #endif
669 
670 ////////////////////////////////////////////////////////////////////////////////////////////////
671 
672 class SkBlockMemoryRefCnt : public SkRefCnt {
673 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)674     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
675 
~SkBlockMemoryRefCnt()676     virtual ~SkBlockMemoryRefCnt() {
677         SkDynamicMemoryWStream::Block* block = fHead;
678         while (block != nullptr) {
679             SkDynamicMemoryWStream::Block* next = block->fNext;
680             sk_free(block);
681             block = next;
682         }
683     }
684 
685     SkDynamicMemoryWStream::Block* const fHead;
686 };
687 
688 class SkBlockMemoryStream : public SkStreamAsset {
689 public:
SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef,size_t size)690     SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef, size_t size)
691         : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead)
692         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
693 
read(void * buffer,size_t rawCount)694     size_t read(void* buffer, size_t rawCount) override {
695         size_t count = rawCount;
696         if (fOffset + count > fSize) {
697             count = fSize - fOffset;
698         }
699         size_t bytesLeftToRead = count;
700         while (fCurrent != nullptr) {
701             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
702             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
703             if (buffer) {
704                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
705                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
706             }
707             if (bytesLeftToRead <= bytesFromCurrent) {
708                 fCurrentOffset += bytesFromCurrent;
709                 fOffset += count;
710                 return count;
711             }
712             bytesLeftToRead -= bytesFromCurrent;
713             fCurrent = fCurrent->fNext;
714             fCurrentOffset = 0;
715         }
716         SkASSERT(false);
717         return 0;
718     }
719 
isAtEnd() const720     bool isAtEnd() const override {
721         return fOffset == fSize;
722     }
723 
peek(void * buff,size_t bytesToPeek) const724     size_t peek(void* buff, size_t bytesToPeek) const override {
725         SkASSERT(buff != nullptr);
726 
727         bytesToPeek = SkTMin(bytesToPeek, fSize - fOffset);
728 
729         size_t bytesLeftToPeek = bytesToPeek;
730         char* buffer = static_cast<char*>(buff);
731         const SkDynamicMemoryWStream::Block* current = fCurrent;
732         size_t currentOffset = fCurrentOffset;
733         while (bytesLeftToPeek) {
734             SkASSERT(current);
735             size_t bytesFromCurrent = SkTMin(current->written() - currentOffset, bytesLeftToPeek);
736             memcpy(buffer, current->start() + currentOffset, bytesFromCurrent);
737             bytesLeftToPeek -= bytesFromCurrent;
738             buffer += bytesFromCurrent;
739             current = current->fNext;
740             currentOffset = 0;
741         }
742         return bytesToPeek;
743     }
744 
rewind()745     bool rewind() override {
746         fCurrent = fBlockMemory->fHead;
747         fOffset = 0;
748         fCurrentOffset = 0;
749         return true;
750     }
751 
onDuplicate() const752     SkBlockMemoryStream* onDuplicate() const override {
753         return new SkBlockMemoryStream(fBlockMemory, fSize);
754     }
755 
getPosition() const756     size_t getPosition() const override {
757         return fOffset;
758     }
759 
seek(size_t position)760     bool seek(size_t position) override {
761         // If possible, skip forward.
762         if (position >= fOffset) {
763             size_t skipAmount = position - fOffset;
764             return this->skip(skipAmount) == skipAmount;
765         }
766         // If possible, move backward within the current block.
767         size_t moveBackAmount = fOffset - position;
768         if (moveBackAmount <= fCurrentOffset) {
769             fCurrentOffset -= moveBackAmount;
770             fOffset -= moveBackAmount;
771             return true;
772         }
773         // Otherwise rewind and move forward.
774         return this->rewind() && this->skip(position) == position;
775     }
776 
move(long offset)777     bool move(long offset) override {
778         return seek(fOffset + offset);
779     }
780 
onFork() const781     SkBlockMemoryStream* onFork() const override {
782         SkBlockMemoryStream* that = this->onDuplicate();
783         that->fCurrent = this->fCurrent;
784         that->fOffset = this->fOffset;
785         that->fCurrentOffset = this->fCurrentOffset;
786         return that;
787     }
788 
getLength() const789     size_t getLength() const override {
790         return fSize;
791     }
792 
getMemoryBase()793     const void* getMemoryBase() override {
794         if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) {
795             return fBlockMemory->fHead->start();
796         }
797         return nullptr;
798     }
799 
800 private:
801     sk_sp<SkBlockMemoryRefCnt> const fBlockMemory;
802     SkDynamicMemoryWStream::Block const * fCurrent;
803     size_t const fSize;
804     size_t fOffset;
805     size_t fCurrentOffset;
806 };
807 
detachAsStream()808 std::unique_ptr<SkStreamAsset> SkDynamicMemoryWStream::detachAsStream() {
809     std::unique_ptr<SkStreamAsset> stream
810             = skstd::make_unique<SkBlockMemoryStream>(sk_make_sp<SkBlockMemoryRefCnt>(fHead),
811                                                       this->bytesWritten());
812     fHead = nullptr;    // signal reset() to not free anything
813     this->reset();
814     return stream;
815 }
816 
817 ///////////////////////////////////////////////////////////////////////////////
818 ///////////////////////////////////////////////////////////////////////////////
819 
mmap_filename(const char path[])820 static sk_sp<SkData> mmap_filename(const char path[]) {
821     FILE* file = sk_fopen(path, kRead_SkFILE_Flag);
822     if (nullptr == file) {
823         return nullptr;
824     }
825 
826     auto data = SkData::MakeFromFILE(file);
827     sk_fclose(file);
828     return data;
829 }
830 
MakeFromFile(const char path[])831 std::unique_ptr<SkStreamAsset> SkStream::MakeFromFile(const char path[]) {
832     auto data(mmap_filename(path));
833     if (data) {
834         return skstd::make_unique<SkMemoryStream>(std::move(data));
835     }
836 
837     // If we get here, then our attempt at using mmap failed, so try normal file access.
838     auto stream = skstd::make_unique<SkFILEStream>(path);
839     if (!stream->isValid()) {
840         return nullptr;
841     }
842     return std::move(stream);
843 }
844 
845 // Declared in SkStreamPriv.h:
SkCopyStreamToData(SkStream * stream)846 sk_sp<SkData> SkCopyStreamToData(SkStream* stream) {
847     SkASSERT(stream != nullptr);
848 
849     if (stream->hasLength()) {
850         return SkData::MakeFromStream(stream, stream->getLength());
851     }
852 
853     SkDynamicMemoryWStream tempStream;
854     const size_t bufferSize = 4096;
855     char buffer[bufferSize];
856     do {
857         size_t bytesRead = stream->read(buffer, bufferSize);
858         tempStream.write(buffer, bytesRead);
859     } while (!stream->isAtEnd());
860     return tempStream.detachAsData();
861 }
862 
SkStreamCopy(SkWStream * out,SkStream * input)863 bool SkStreamCopy(SkWStream* out, SkStream* input) {
864     const char* base = static_cast<const char*>(input->getMemoryBase());
865     if (base && input->hasPosition() && input->hasLength()) {
866         // Shortcut that avoids the while loop.
867         size_t position = input->getPosition();
868         size_t length = input->getLength();
869         SkASSERT(length >= position);
870         return out->write(&base[position], length - position);
871     }
872     char scratch[4096];
873     size_t count;
874     while (true) {
875         count = input->read(scratch, sizeof(scratch));
876         if (0 == count) {
877             return true;
878         }
879         if (!out->write(scratch, count)) {
880             return false;
881         }
882     }
883 }
884