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