Flutter Engine
The Flutter Engine
SkStream.cpp
Go to the documentation of this file.
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
9
10#include "include/core/SkData.h"
20#include "src/base/SkSafeMath.h"
21#include "src/core/SkOSFile.h"
23
24#include <algorithm>
25#include <cstddef>
26#include <cstring>
27#include <limits>
28#include <new>
29
30///////////////////////////////////////////////////////////////////////////////
31
32bool SkStream::readS8(int8_t* i) {
33 return this->read(i, sizeof(*i)) == sizeof(*i);
34}
35
36bool SkStream::readS16(int16_t* i) {
37 return this->read(i, sizeof(*i)) == sizeof(*i);
38}
39
40bool SkStream::readS32(int32_t* i) {
41 return this->read(i, sizeof(*i)) == sizeof(*i);
42}
43
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
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
74{
75}
76
78{
79}
80
82{
84 char* stop = SkStrAppendS32(buffer, dec);
85 return this->write(buffer, stop - buffer);
86}
87
88bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
89{
91 char* stop = SkStrAppendU64(buffer, dec, minDigits);
92 return this->write(buffer, stop - buffer);
93}
94
95bool 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
103{
105 char* stop = SkStrAppendScalar(buffer, value);
106 return this->write(buffer, stop - buffer);
107}
108
110 return this->write(&value, sizeof(value));
111}
112
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
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;
131 memcpy(&data[1], &value16, 2);
132 len = 3;
133 } else {
134 uint32_t value32 = SkToU32(value);
136 memcpy(&data[1], &value32, 4);
137 len = 5;
138 }
139 return this->write(data, len);
140}
141
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
162SkFILEStream::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
172SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t end, size_t start)
173 : SkFILEStream(std::move(file), end, start, start)
174{ }
175
176SkFILEStream::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
182{ }
183
185 : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose),
186 file ? sk_fgetsize(file) : 0,
187 file ? sk_ftell(file) : 0)
188{ }
189
192{ }
193
195 this->close();
196}
197
199 fFILE.reset();
200 fEnd = 0;
201 fStart = 0;
202 fCurrent = 0;
203}
204
205size_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
221 if (fCurrent == fEnd) {
222 return true;
223 }
224 return fCurrent >= sk_fgetsize(fFILE.get());
225}
226
228 fCurrent = fStart;
229 return true;
230}
231
232SkStreamAsset* SkFILEStream::onDuplicate() const {
233 return new SkFILEStream(fFILE, fEnd, fStart, fStart);
234}
235
237 SkASSERT(fCurrent >= fStart);
238 return fCurrent - fStart;
239}
240
241bool SkFILEStream::seek(size_t position) {
242 fCurrent = std::min(SkSafeMath::Add(position, fStart), fEnd);
243 return true;
244}
245
247 if (offset < 0) {
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
266SkStreamAsset* SkFILEStream::onFork() const {
267 return new SkFILEStream(fFILE, fEnd, fStart, fCurrent);
268}
269
271 return fEnd - fStart;
272}
273
274///////////////////////////////////////////////////////////////////////////////
275
276static sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) {
277 if (copyData) {
279 } else {
281 }
282}
283
285 fData = SkData::MakeEmpty();
286 fOffset = 0;
287}
288
291 fOffset = 0;
292}
293
294SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
295 fData = newFromParams(src, size, copyData);
296 fOffset = 0;
297}
298
300 if (nullptr == fData) {
301 fData = SkData::MakeEmpty();
302 }
303 fOffset = 0;
304}
305
306std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) {
307 return std::make_unique<SkMemoryStream>(data, length, true);
308}
309
310std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) {
311 return std::make_unique<SkMemoryStream>(data, length, false);
312}
313
314std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) {
315 return std::make_unique<SkMemoryStream>(std::move(data));
316}
317
318void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
320 fOffset = 0;
321}
322
323void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
324 fData = newFromParams(src, size, copyData);
325 fOffset = 0;
326}
327
329 if (nullptr == data) {
330 fData = SkData::MakeEmpty();
331 } else {
332 fData = data;
333 }
334 fOffset = 0;
335}
336
337size_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
351size_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
362 return fOffset == fData->size();
363}
364
366 fOffset = 0;
367 return true;
368}
369
370SkMemoryStream* SkMemoryStream::onDuplicate() const {
371 return new SkMemoryStream(fData);
372}
373
375 return fOffset;
376}
377
378bool SkMemoryStream::seek(size_t position) {
379 fOffset = position > fData->size()
380 ? fData->size()
381 : position;
382 return true;
383}
384
386 return this->seek(fOffset + offset);
387}
388
389SkMemoryStream* SkMemoryStream::onFork() const {
390 std::unique_ptr<SkMemoryStream> that(this->duplicate());
391 that->seek(fOffset);
392 return that.release();
393}
394
396 return fData->size();
397}
398
400 return fData->data();
401}
402
404 return fData->bytes() + fOffset;
405}
406
407/////////////////////////////////////////////////////////////////////////////////////////////////////////
408/////////////////////////////////////////////////////////////////////////////////////////////////////////
409
411{
413}
414
416{
417 if (fFILE) {
418 sk_fclose(fFILE);
419 }
420}
421
423 return sk_ftell(fFILE);
424}
425
426bool 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
443{
444 if (fFILE) {
445 sk_fflush(fFILE);
446 }
447}
448
450{
451 flush();
452 if (fFILE) {
453 sk_fsync(fFILE);
454 }
455}
456
457////////////////////////////////////////////////////////////////////////
458
459static 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
471 char* fCurr;
472 char* fStop;
473
474 const char* start() const { return (const char*)(this + 1); }
475 char* start() { return (char*)(this + 1); }
476 size_t avail() const { return fStop - fCurr; }
477 size_t written() const { return fCurr - this->start(); }
478
479 void init(size_t size) {
480 fNext = nullptr;
481 fCurr = this->start();
482 fStop = this->start() + size;
483 }
484
485 const void* append(const void* data, size_t size) {
486 SkASSERT((size_t)(fStop - fCurr) >= size);
488 fCurr += size;
489 return (const void*)((const char*)data + size);
490 }
491};
492
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
504 if (this != &other) {
506 new (this) SkDynamicMemoryWStream(std::move(other));
507 }
508 return *this;
509}
510
512 this->reset();
513}
514
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
527 this->validate();
528
529 if (fTail) {
530 return fBytesWrittenBeforeTail + fTail->written();
531 }
532 return 0;
533}
534
535bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
536 if (count > 0) {
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
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
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
609bool 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
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
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
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
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
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
708 const size_t size = this->bytesWritten();
709 if (0 == size) {
710 return SkData::MakeEmpty();
711 }
713 this->copyToAndReset(data->writable_data());
714 return data;
715}
716
717#ifdef SK_DEBUG
718void 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
741public:
743
746 while (block != nullptr) {
748 sk_free(block);
749 block = next;
750 }
751 }
752
754};
755
757public:
759 : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead)
760 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
761
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
788 bool isAtEnd() const override {
789 return fOffset == fSize;
790 }
791
792 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
813 bool rewind() override {
814 fCurrent = fBlockMemory->fHead;
815 fOffset = 0;
816 fCurrentOffset = 0;
817 return true;
818 }
819
821 return new SkBlockMemoryStream(fBlockMemory, fSize);
822 }
823
824 size_t getPosition() const override {
825 return fOffset;
826 }
827
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
845 bool move(long offset) override {
846 return seek(fOffset + offset);
847 }
848
849 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
857 size_t getLength() const override {
858 return fSize;
859 }
860
861 const void* getMemoryBase() override {
862 if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) {
863 return fBlockMemory->fHead->start();
864 }
865 return nullptr;
866 }
867
868private:
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
876std::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
898bool SkDebugfStream::write(const void* buffer, size_t size) {
899 SkDebugf("%.*s", (int)size, (const char*)buffer);
900 fBytesWritten += size;
901 return true;
902}
903
905 return fBytesWritten;
906}
907
908///////////////////////////////////////////////////////////////////////////////
909///////////////////////////////////////////////////////////////////////////////
910
911static sk_sp<SkData> mmap_filename(const char path[]) {
913 if (nullptr == file) {
914 return nullptr;
915 }
916
919 return data;
920}
921
922std::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:
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
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
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}
int count
Definition: FontMgrTest.cpp:50
static float next(float f)
static constexpr T SkAlign4(T x)
Definition: SkAlign.h:16
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SK_API void sk_free(void *)
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
Definition: SkMalloc.h:125
static void * sk_malloc_canfail(size_t size)
Definition: SkMalloc.h:93
SK_API void * sk_realloc_throw(void *buffer, size_t size)
FILE * sk_fopen(const char path[], SkFILE_Flags)
void sk_fclose(FILE *)
size_t sk_fwrite(const void *buffer, size_t byteCount, FILE *)
size_t sk_ftell(FILE *)
size_t sk_qread(FILE *, void *buffer, size_t count, size_t offset)
@ kRead_SkFILE_Flag
Definition: SkOSFile.h:20
@ kWrite_SkFILE_Flag
Definition: SkOSFile.h:21
void sk_fflush(FILE *)
void sk_fsync(FILE *)
size_t sk_fgetsize(FILE *)
#define SkDynamicMemoryWStream_MinBlockSize
Definition: SkStream.cpp:467
bool StreamRemainingLengthIsBelow(SkStream *stream, size_t len)
Definition: SkStream.cpp:976
#define SK_MAX_BYTE_FOR_U8
Definition: SkStream.cpp:48
static void sk_memcpy_4bytes(void *dst, const void *src, size_t size)
Definition: SkStream.cpp:459
bool SkStreamCopy(SkWStream *out, SkStream *input)
Definition: SkStream.cpp:954
sk_sp< SkData > SkCopyStreamToData(SkStream *stream)
Definition: SkStream.cpp:937
#define SK_BYTE_SENTINEL_FOR_U16
Definition: SkStream.cpp:49
static sk_sp< SkData > newFromParams(const void *src, size_t size, bool copyData)
Definition: SkStream.cpp:276
#define SK_BYTE_SENTINEL_FOR_U32
Definition: SkStream.cpp:50
static sk_sp< SkData > mmap_filename(const char path[])
Definition: SkStream.cpp:911
static constexpr int kSkStrAppendS32_MaxSize
Definition: SkString.h:89
char * SkStrAppendU64(char buffer[], uint64_t, int minDigits)
Definition: SkString.cpp:129
char * SkStrAppendScalar(char buffer[], SkScalar)
Definition: SkString.cpp:164
static constexpr int kSkStrAppendScalar_MaxSize
Definition: SkString.h:101
static constexpr int kSkStrAppendU64_MaxSize
Definition: SkString.h:86
char * SkStrAppendS32(char buffer[], int32_t)
Definition: SkString.cpp:120
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
constexpr uint32_t SkToU32(S x)
Definition: SkTo.h:26
SkDynamicMemoryWStream::Block *const fHead
Definition: SkStream.cpp:753
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block *head)
Definition: SkStream.cpp:742
~SkBlockMemoryRefCnt() override
Definition: SkStream.cpp:744
const void * getMemoryBase() override
Definition: SkStream.cpp:861
SkBlockMemoryStream * onDuplicate() const override
Definition: SkStream.cpp:820
SkBlockMemoryStream * onFork() const override
Definition: SkStream.cpp:849
size_t getLength() const override
Definition: SkStream.cpp:857
size_t getPosition() const override
Definition: SkStream.cpp:824
size_t peek(void *buff, size_t bytesToPeek) const override
Definition: SkStream.cpp:792
SkBlockMemoryStream(sk_sp< SkBlockMemoryRefCnt > headRef, size_t size)
Definition: SkStream.cpp:758
bool isAtEnd() const override
Definition: SkStream.cpp:788
bool seek(size_t position) override
Definition: SkStream.cpp:828
size_t read(void *buffer, size_t rawCount) override
Definition: SkStream.cpp:762
bool move(long offset) override
Definition: SkStream.cpp:845
bool rewind() override
Definition: SkStream.cpp:813
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition: SkData.h:116
const uint8_t * bytes() const
Definition: SkData.h:43
static sk_sp< SkData > MakeFromMalloc(const void *data, size_t length)
Definition: SkData.cpp:107
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
const void * data() const
Definition: SkData.h:37
void * writable_data()
Definition: SkData.h:52
static sk_sp< SkData > MakeFromFILE(FILE *f)
Definition: SkData.cpp:138
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
static sk_sp< SkData > MakeFromStream(SkStream *, size_t size)
Definition: SkData.cpp:208
static sk_sp< SkData > MakeEmpty()
Definition: SkData.cpp:94
size_t size() const
Definition: SkData.h:30
size_t bytesWritten() const override
Definition: SkStream.cpp:904
bool write(const void *buffer, size_t size) override
Definition: SkStream.cpp:898
size_t bytesWritten() const override
Definition: SkStream.cpp:526
~SkDynamicMemoryWStream() override
Definition: SkStream.cpp:511
bool writeToStream(SkWStream *dst) const
Definition: SkStream.cpp:642
bool writeToAndReset(SkWStream *dst)
Definition: SkStream.cpp:689
void copyToAndReset(void *dst)
Definition: SkStream.cpp:668
void copyTo(void *dst) const
Definition: SkStream.cpp:631
SkDynamicMemoryWStream()=default
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition: SkStream.cpp:876
bool write(const void *buffer, size_t size) override
Definition: SkStream.cpp:535
SkDynamicMemoryWStream & operator=(SkDynamicMemoryWStream &&)
Definition: SkStream.cpp:503
bool read(void *buffer, size_t offset, size_t size)
Definition: SkStream.cpp:609
void prependToAndReset(SkDynamicMemoryWStream *dst)
Definition: SkStream.cpp:591
sk_sp< SkData > detachAsData()
Definition: SkStream.cpp:707
bool move(long offset) override
Definition: SkStream.cpp:246
bool seek(size_t position) override
Definition: SkStream.cpp:241
size_t read(void *buffer, size_t size) override
Definition: SkStream.cpp:205
bool isAtEnd() const override
Definition: SkStream.cpp:220
size_t getLength() const override
Definition: SkStream.cpp:270
bool rewind() override
Definition: SkStream.cpp:227
void close()
Definition: SkStream.cpp:198
size_t getPosition() const override
Definition: SkStream.cpp:236
~SkFILEStream() override
Definition: SkStream.cpp:194
SkFILEStream(const char path[]=nullptr)
Definition: SkStream.cpp:190
size_t bytesWritten() const override
Definition: SkStream.cpp:422
void fsync()
Definition: SkStream.cpp:449
bool write(const void *buffer, size_t size) override
Definition: SkStream.cpp:426
void flush() override
Definition: SkStream.cpp:442
~SkFILEWStream() override
Definition: SkStream.cpp:415
SkFILEWStream(const char path[])
Definition: SkStream.cpp:410
virtual void setMemory(const void *data, size_t length, bool copyData=false)
Definition: SkStream.cpp:323
bool isAtEnd() const override
Definition: SkStream.cpp:361
bool move(long offset) override
Definition: SkStream.cpp:385
bool seek(size_t position) override
Definition: SkStream.cpp:378
size_t read(void *buffer, size_t size) override
Definition: SkStream.cpp:337
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition: SkStream.cpp:314
void setMemoryOwned(const void *data, size_t length)
Definition: SkStream.cpp:318
static std::unique_ptr< SkMemoryStream > MakeDirect(const void *data, size_t length)
Definition: SkStream.cpp:310
static std::unique_ptr< SkMemoryStream > MakeCopy(const void *data, size_t length)
Definition: SkStream.cpp:306
size_t getLength() const override
Definition: SkStream.cpp:395
size_t peek(void *buffer, size_t size) const override
Definition: SkStream.cpp:351
const void * getMemoryBase() override
Definition: SkStream.cpp:399
bool rewind() override
Definition: SkStream.cpp:365
void setData(sk_sp< SkData > data)
Definition: SkStream.cpp:328
size_t getPosition() const override
Definition: SkStream.cpp:374
const void * getAtPos()
Definition: SkStream.cpp:403
std::unique_ptr< SkMemoryStream > duplicate() const
Definition: SkStream.h:407
static size_t Add(size_t x, size_t y)
Definition: SkSafeMath.cpp:10
bool readS16(int16_t *)
Definition: SkStream.cpp:36
bool readScalar(SkScalar *)
Definition: SkStream.cpp:44
bool readS32(int32_t *)
Definition: SkStream.cpp:40
bool readS8(int8_t *)
Definition: SkStream.cpp:32
bool readPackedUInt(size_t *)
Definition: SkStream.cpp:52
virtual bool hasPosition() const
Definition: SkStream.h:117
virtual size_t getPosition() const
Definition: SkStream.h:119
static std::unique_ptr< SkStreamAsset > MakeFromFile(const char path[])
Definition: SkStream.cpp:922
bool readU16(uint16_t *i)
Definition: SkStream.h:84
size_t skip(size_t size)
Definition: SkStream.h:51
bool readU32(uint32_t *i)
Definition: SkStream.h:85
virtual size_t getLength() const
Definition: SkStream.h:137
virtual const void * getMemoryBase()
Definition: SkStream.h:141
virtual bool hasLength() const
Definition: SkStream.h:135
virtual size_t read(void *buffer, size_t size)=0
size_t size() const
Definition: SkString.h:131
void appendHex(uint32_t value, int minDigits=0)
Definition: SkString.h:212
const char * c_str() const
Definition: SkString.h:133
static int SizeOfPackedUInt(size_t value)
Definition: SkStream.cpp:113
bool writePackedUInt(size_t)
Definition: SkStream.cpp:122
virtual bool write(const void *buffer, size_t size)=0
bool writeScalarAsText(SkScalar)
Definition: SkStream.cpp:102
virtual void flush()
Definition: SkStream.cpp:77
bool writeHexAsText(uint32_t, int minDigits=0)
Definition: SkStream.cpp:95
bool writeStream(SkStream *input, size_t length)
Definition: SkStream.cpp:142
bool writeDecAsText(int32_t)
Definition: SkStream.cpp:81
bool writeBigDecAsText(int64_t, int minDigits=0)
Definition: SkStream.cpp:88
virtual ~SkWStream()
Definition: SkStream.cpp:73
bool writeScalar(SkScalar)
Definition: SkStream.cpp:109
float SkScalar
Definition: extension.cpp:12
glong glong end
uint8_t value
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
Definition: ref_ptr.h:256
SeparatedVector2 offset
const void * append(const void *data, size_t size)
Definition: SkStream.cpp:485
void init(size_t size)
Definition: SkStream.cpp:479
const char * start() const
Definition: SkStream.cpp:474
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63