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