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