Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
52bool 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
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
122bool 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
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
180SkFILEStream::SkFILEStream(FILE* file, size_t size)
181 : SkFILEStream(file, size, file ? sk_ftell(file) : 0)
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
191 : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr)
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
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) {
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
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) {
278 return SkData::MakeWithCopy(src, size);
279 } else {
280 return SkData::MakeWithoutCopy(src, size);
281 }
282}
283
285 fData = SkData::MakeEmpty();
286 fOffset = 0;
287}
288
290 fData = SkData::MakeUninitialized(size);
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) {
319 fData = SkData::MakeFromMalloc(src, 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
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
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{
412 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
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);
487 sk_memcpy_4bytes(fCurr, data, 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
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
631void 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
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[]) {
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
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
954bool 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
976bool 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}
int count
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
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
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
constexpr size_t SkToSizeT(S x)
Definition SkTo.h:31
constexpr uint32_t SkToU32(S x)
Definition SkTo.h:26
Type::kYUV Type::kRGBA() int(0.7 *637)
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
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
size_t getPosition() const override
Definition SkStream.cpp:236
SkStreamAsset * onDuplicate() const override
Definition SkStream.cpp:232
SkStreamAsset * onFork() const override
Definition SkStream.cpp:266
~SkFILEStream() override
Definition SkStream.cpp:194
SkFILEStream(const char path[]=nullptr)
Definition SkStream.cpp:190
size_t bytesWritten() const override
Definition SkStream.cpp:422
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
SkMemoryStream * onDuplicate() const override
Definition SkStream.cpp:370
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
SkMemoryStream * onFork() const override
Definition SkStream.cpp:389
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)
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
static const uint8_t buffer[]
uint8_t value
static float min(float r, float g, float b)
Definition hsl.cpp:48
size_t length
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
Definition ref_ptr.h:256
Point offset
const void * append(const void *data, size_t size)
Definition SkStream.cpp:485
const char * start() const
Definition SkStream.cpp:474