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