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