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