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