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