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