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