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