1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkStream.h"
11 #include "SkStreamPriv.h"
12 #include "SkData.h"
13 #include "SkFixed.h"
14 #include "SkString.h"
15 #include "SkOSFile.h"
16 #include "SkTypes.h"
17
18 ///////////////////////////////////////////////////////////////////////////////
19
20
readS8()21 int8_t SkStream::readS8() {
22 int8_t value;
23 SkDEBUGCODE(size_t len =) this->read(&value, 1);
24 SkASSERT(1 == len);
25 return value;
26 }
27
readS16()28 int16_t SkStream::readS16() {
29 int16_t value;
30 SkDEBUGCODE(size_t len =) this->read(&value, 2);
31 SkASSERT(2 == len);
32 return value;
33 }
34
readS32()35 int32_t SkStream::readS32() {
36 int32_t value;
37 SkDEBUGCODE(size_t len =) this->read(&value, 4);
38 SkASSERT(4 == len);
39 return value;
40 }
41
readScalar()42 SkScalar SkStream::readScalar() {
43 SkScalar value;
44 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
45 SkASSERT(sizeof(SkScalar) == len);
46 return value;
47 }
48
49 #define SK_MAX_BYTE_FOR_U8 0xFD
50 #define SK_BYTE_SENTINEL_FOR_U16 0xFE
51 #define SK_BYTE_SENTINEL_FOR_U32 0xFF
52
readPackedUInt()53 size_t SkStream::readPackedUInt() {
54 uint8_t byte;
55 if (!this->read(&byte, 1)) {
56 return 0;
57 }
58 if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
59 return this->readU16();
60 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
61 return this->readU32();
62 } else {
63 return byte;
64 }
65 }
66
67 //////////////////////////////////////////////////////////////////////////////////////
68
~SkWStream()69 SkWStream::~SkWStream()
70 {
71 }
72
newline()73 void SkWStream::newline()
74 {
75 this->write("\n", 1);
76 }
77
flush()78 void SkWStream::flush()
79 {
80 }
81
writeText(const char text[])82 bool SkWStream::writeText(const char text[])
83 {
84 SkASSERT(text);
85 return this->write(text, strlen(text));
86 }
87
writeDecAsText(int32_t dec)88 bool SkWStream::writeDecAsText(int32_t dec)
89 {
90 char buffer[SkStrAppendS32_MaxSize];
91 char* stop = SkStrAppendS32(buffer, dec);
92 return this->write(buffer, stop - buffer);
93 }
94
writeBigDecAsText(int64_t dec,int minDigits)95 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
96 {
97 char buffer[SkStrAppendU64_MaxSize];
98 char* stop = SkStrAppendU64(buffer, dec, minDigits);
99 return this->write(buffer, stop - buffer);
100 }
101
writeHexAsText(uint32_t hex,int digits)102 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
103 {
104 SkString tmp;
105 tmp.appendHex(hex, digits);
106 return this->write(tmp.c_str(), tmp.size());
107 }
108
writeScalarAsText(SkScalar value)109 bool SkWStream::writeScalarAsText(SkScalar value)
110 {
111 char buffer[SkStrAppendScalar_MaxSize];
112 char* stop = SkStrAppendScalar(buffer, value);
113 return this->write(buffer, stop - buffer);
114 }
115
write8(U8CPU value)116 bool SkWStream::write8(U8CPU value) {
117 uint8_t v = SkToU8(value);
118 return this->write(&v, 1);
119 }
120
write16(U16CPU value)121 bool SkWStream::write16(U16CPU value) {
122 uint16_t v = SkToU16(value);
123 return this->write(&v, 2);
124 }
125
write32(uint32_t value)126 bool SkWStream::write32(uint32_t value) {
127 return this->write(&value, 4);
128 }
129
writeScalar(SkScalar value)130 bool SkWStream::writeScalar(SkScalar value) {
131 return this->write(&value, sizeof(value));
132 }
133
SizeOfPackedUInt(size_t value)134 int SkWStream::SizeOfPackedUInt(size_t value) {
135 if (value <= SK_MAX_BYTE_FOR_U8) {
136 return 1;
137 } else if (value <= 0xFFFF) {
138 return 3;
139 }
140 return 5;
141 }
142
writePackedUInt(size_t value)143 bool SkWStream::writePackedUInt(size_t value) {
144 uint8_t data[5];
145 size_t len = 1;
146 if (value <= SK_MAX_BYTE_FOR_U8) {
147 data[0] = value;
148 len = 1;
149 } else if (value <= 0xFFFF) {
150 uint16_t value16 = value;
151 data[0] = SK_BYTE_SENTINEL_FOR_U16;
152 memcpy(&data[1], &value16, 2);
153 len = 3;
154 } else {
155 uint32_t value32 = SkToU32(value);
156 data[0] = SK_BYTE_SENTINEL_FOR_U32;
157 memcpy(&data[1], &value32, 4);
158 len = 5;
159 }
160 return this->write(data, len);
161 }
162
writeStream(SkStream * stream,size_t length)163 bool SkWStream::writeStream(SkStream* stream, size_t length) {
164 char scratch[1024];
165 const size_t MAX = sizeof(scratch);
166
167 while (length != 0) {
168 size_t n = length;
169 if (n > MAX) {
170 n = MAX;
171 }
172 stream->read(scratch, n);
173 if (!this->write(scratch, n)) {
174 return false;
175 }
176 length -= n;
177 }
178 return true;
179 }
180
181 ///////////////////////////////////////////////////////////////////////////////
182
SkFILEStream(const char file[])183 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
184 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : nullptr;
185 }
186
SkFILEStream(FILE * file,Ownership ownership)187 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
188 : fFILE(file)
189 , fOwnership(ownership) {
190 }
191
~SkFILEStream()192 SkFILEStream::~SkFILEStream() {
193 if (fFILE && fOwnership != kCallerRetains_Ownership) {
194 sk_fclose(fFILE);
195 }
196 }
197
setPath(const char path[])198 void SkFILEStream::setPath(const char path[]) {
199 fName.set(path);
200 if (fFILE) {
201 sk_fclose(fFILE);
202 fFILE = nullptr;
203 }
204 if (path) {
205 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
206 }
207 }
208
read(void * buffer,size_t size)209 size_t SkFILEStream::read(void* buffer, size_t size) {
210 if (fFILE) {
211 return sk_fread(buffer, size, fFILE);
212 }
213 return 0;
214 }
215
isAtEnd() const216 bool SkFILEStream::isAtEnd() const {
217 return sk_feof(fFILE);
218 }
219
rewind()220 bool SkFILEStream::rewind() {
221 if (fFILE) {
222 if (sk_frewind(fFILE)) {
223 return true;
224 }
225 // we hit an error
226 sk_fclose(fFILE);
227 fFILE = nullptr;
228 }
229 return false;
230 }
231
duplicate() const232 SkStreamAsset* SkFILEStream::duplicate() const {
233 if (nullptr == fFILE) {
234 return new SkMemoryStream();
235 }
236
237 if (fData.get()) {
238 return new SkMemoryStream(fData);
239 }
240
241 if (!fName.isEmpty()) {
242 SkAutoTDelete<SkFILEStream> that(new SkFILEStream(fName.c_str()));
243 if (sk_fidentical(that->fFILE, this->fFILE)) {
244 return that.detach();
245 }
246 }
247
248 fData.reset(SkData::NewFromFILE(fFILE));
249 if (nullptr == fData.get()) {
250 return nullptr;
251 }
252 return new SkMemoryStream(fData);
253 }
254
getPosition() const255 size_t SkFILEStream::getPosition() const {
256 return sk_ftell(fFILE);
257 }
258
seek(size_t position)259 bool SkFILEStream::seek(size_t position) {
260 return sk_fseek(fFILE, position);
261 }
262
move(long offset)263 bool SkFILEStream::move(long offset) {
264 return sk_fmove(fFILE, offset);
265 }
266
fork() const267 SkStreamAsset* SkFILEStream::fork() const {
268 SkAutoTDelete<SkStreamAsset> that(this->duplicate());
269 that->seek(this->getPosition());
270 return that.detach();
271 }
272
getLength() const273 size_t SkFILEStream::getLength() const {
274 return sk_fgetsize(fFILE);
275 }
276
getMemoryBase()277 const void* SkFILEStream::getMemoryBase() {
278 if (nullptr == fData.get()) {
279 return nullptr;
280 }
281 return fData->data();
282 }
283
284 ///////////////////////////////////////////////////////////////////////////////
285
newFromParams(const void * src,size_t size,bool copyData)286 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
287 if (copyData) {
288 return SkData::NewWithCopy(src, size);
289 } else {
290 return SkData::NewWithoutCopy(src, size);
291 }
292 }
293
SkMemoryStream()294 SkMemoryStream::SkMemoryStream() {
295 fData = SkData::NewEmpty();
296 fOffset = 0;
297 }
298
SkMemoryStream(size_t size)299 SkMemoryStream::SkMemoryStream(size_t size) {
300 fData = SkData::NewUninitialized(size);
301 fOffset = 0;
302 }
303
SkMemoryStream(const void * src,size_t size,bool copyData)304 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
305 fData = newFromParams(src, size, copyData);
306 fOffset = 0;
307 }
308
SkMemoryStream(SkData * data)309 SkMemoryStream::SkMemoryStream(SkData* data) {
310 if (nullptr == data) {
311 fData = SkData::NewEmpty();
312 } else {
313 fData = data;
314 fData->ref();
315 }
316 fOffset = 0;
317 }
318
~SkMemoryStream()319 SkMemoryStream::~SkMemoryStream() {
320 fData->unref();
321 }
322
setMemoryOwned(const void * src,size_t size)323 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
324 fData->unref();
325 fData = SkData::NewFromMalloc(src, size);
326 fOffset = 0;
327 }
328
setMemory(const void * src,size_t size,bool copyData)329 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
330 fData->unref();
331 fData = newFromParams(src, size, copyData);
332 fOffset = 0;
333 }
334
copyToData() const335 SkData* SkMemoryStream::copyToData() const {
336 fData->ref();
337 return fData;
338 }
339
setData(SkData * data)340 SkData* SkMemoryStream::setData(SkData* data) {
341 fData->unref();
342 if (nullptr == data) {
343 fData = SkData::NewEmpty();
344 } else {
345 fData = data;
346 fData->ref();
347 }
348 fOffset = 0;
349 return data;
350 }
351
skipToAlign4()352 void SkMemoryStream::skipToAlign4() {
353 // cast to remove unary-minus warning
354 fOffset += -(int)fOffset & 0x03;
355 }
356
read(void * buffer,size_t size)357 size_t SkMemoryStream::read(void* buffer, size_t size) {
358 size_t dataSize = fData->size();
359
360 if (size > dataSize - fOffset) {
361 size = dataSize - fOffset;
362 }
363 if (buffer) {
364 memcpy(buffer, fData->bytes() + fOffset, size);
365 }
366 fOffset += size;
367 return size;
368 }
369
peek(void * buffer,size_t size) const370 size_t SkMemoryStream::peek(void* buffer, size_t size) const {
371 SkASSERT(buffer != nullptr);
372
373 const size_t currentOffset = fOffset;
374 SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
375 const size_t bytesRead = nonConstThis->read(buffer, size);
376 nonConstThis->fOffset = currentOffset;
377 return bytesRead;
378 }
379
isAtEnd() const380 bool SkMemoryStream::isAtEnd() const {
381 return fOffset == fData->size();
382 }
383
rewind()384 bool SkMemoryStream::rewind() {
385 fOffset = 0;
386 return true;
387 }
388
duplicate() const389 SkMemoryStream* SkMemoryStream::duplicate() const { return new SkMemoryStream(fData); }
390
getPosition() const391 size_t SkMemoryStream::getPosition() const {
392 return fOffset;
393 }
394
seek(size_t position)395 bool SkMemoryStream::seek(size_t position) {
396 fOffset = position > fData->size()
397 ? fData->size()
398 : position;
399 return true;
400 }
401
move(long offset)402 bool SkMemoryStream::move(long offset) {
403 return this->seek(fOffset + offset);
404 }
405
fork() const406 SkMemoryStream* SkMemoryStream::fork() const {
407 SkAutoTDelete<SkMemoryStream> that(this->duplicate());
408 that->seek(fOffset);
409 return that.detach();
410 }
411
getLength() const412 size_t SkMemoryStream::getLength() const {
413 return fData->size();
414 }
415
getMemoryBase()416 const void* SkMemoryStream::getMemoryBase() {
417 return fData->data();
418 }
419
getAtPos()420 const void* SkMemoryStream::getAtPos() {
421 return fData->bytes() + fOffset;
422 }
423
424 /////////////////////////////////////////////////////////////////////////////////////////////////////////
425 /////////////////////////////////////////////////////////////////////////////////////////////////////////
426
SkFILEWStream(const char path[])427 SkFILEWStream::SkFILEWStream(const char path[])
428 {
429 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
430 }
431
~SkFILEWStream()432 SkFILEWStream::~SkFILEWStream()
433 {
434 if (fFILE) {
435 sk_fclose(fFILE);
436 }
437 }
438
bytesWritten() const439 size_t SkFILEWStream::bytesWritten() const {
440 return sk_ftell(fFILE);
441 }
442
write(const void * buffer,size_t size)443 bool SkFILEWStream::write(const void* buffer, size_t size)
444 {
445 if (fFILE == nullptr) {
446 return false;
447 }
448
449 if (sk_fwrite(buffer, size, fFILE) != size)
450 {
451 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
452 sk_fclose(fFILE);
453 fFILE = nullptr;
454 return false;
455 }
456 return true;
457 }
458
flush()459 void SkFILEWStream::flush()
460 {
461 if (fFILE) {
462 sk_fflush(fFILE);
463 }
464 }
465
fsync()466 void SkFILEWStream::fsync()
467 {
468 flush();
469 if (fFILE) {
470 sk_fsync(fFILE);
471 }
472 }
473
474 ////////////////////////////////////////////////////////////////////////
475
SkMemoryWStream(void * buffer,size_t size)476 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
477 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
478 {
479 }
480
write(const void * buffer,size_t size)481 bool SkMemoryWStream::write(const void* buffer, size_t size) {
482 size = SkTMin(size, fMaxLength - fBytesWritten);
483 if (size > 0) {
484 memcpy(fBuffer + fBytesWritten, buffer, size);
485 fBytesWritten += size;
486 return true;
487 }
488 return false;
489 }
490
491 ////////////////////////////////////////////////////////////////////////
492
493 #define SkDynamicMemoryWStream_MinBlockSize 256
494
495 struct SkDynamicMemoryWStream::Block {
496 Block* fNext;
497 char* fCurr;
498 char* fStop;
499
startSkDynamicMemoryWStream::Block500 const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block501 char* start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block502 size_t avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block503 size_t written() const { return fCurr - this->start(); }
504
initSkDynamicMemoryWStream::Block505 void init(size_t size)
506 {
507 fNext = nullptr;
508 fCurr = this->start();
509 fStop = this->start() + size;
510 }
511
appendSkDynamicMemoryWStream::Block512 const void* append(const void* data, size_t size)
513 {
514 SkASSERT((size_t)(fStop - fCurr) >= size);
515 memcpy(fCurr, data, size);
516 fCurr += size;
517 return (const void*)((const char*)data + size);
518 }
519 };
520
SkDynamicMemoryWStream()521 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
522 : fHead(nullptr), fTail(nullptr), fBytesWritten(0), fCopy(nullptr)
523 {
524 }
525
~SkDynamicMemoryWStream()526 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
527 {
528 reset();
529 }
530
reset()531 void SkDynamicMemoryWStream::reset()
532 {
533 this->invalidateCopy();
534
535 Block* block = fHead;
536
537 while (block != nullptr) {
538 Block* next = block->fNext;
539 sk_free(block);
540 block = next;
541 }
542 fHead = fTail = nullptr;
543 fBytesWritten = 0;
544 }
545
write(const void * buffer,size_t count)546 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
547 {
548 if (count > 0) {
549 this->invalidateCopy();
550
551 fBytesWritten += count;
552
553 size_t size;
554
555 if (fTail != nullptr && fTail->avail() > 0) {
556 size = SkTMin(fTail->avail(), count);
557 buffer = fTail->append(buffer, size);
558 SkASSERT(count >= size);
559 count -= size;
560 if (count == 0)
561 return true;
562 }
563
564 size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
565 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
566 block->init(size);
567 block->append(buffer, count);
568
569 if (fTail != nullptr)
570 fTail->fNext = block;
571 else
572 fHead = fTail = block;
573 fTail = block;
574 }
575 return true;
576 }
577
write(const void * buffer,size_t offset,size_t count)578 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
579 {
580 if (offset + count > fBytesWritten) {
581 return false; // test does not partially modify
582 }
583
584 this->invalidateCopy();
585
586 Block* block = fHead;
587 while (block != nullptr) {
588 size_t size = block->written();
589 if (offset < size) {
590 size_t part = offset + count > size ? size - offset : count;
591 memcpy(block->start() + offset, buffer, part);
592 if (count <= part)
593 return true;
594 count -= part;
595 buffer = (const void*) ((char* ) buffer + part);
596 }
597 offset = offset > size ? offset - size : 0;
598 block = block->fNext;
599 }
600 return false;
601 }
602
read(void * buffer,size_t offset,size_t count)603 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
604 {
605 if (offset + count > fBytesWritten)
606 return false; // test does not partially modify
607 Block* block = fHead;
608 while (block != nullptr) {
609 size_t size = block->written();
610 if (offset < size) {
611 size_t part = offset + count > size ? size - offset : count;
612 memcpy(buffer, block->start() + offset, part);
613 if (count <= part)
614 return true;
615 count -= part;
616 buffer = (void*) ((char* ) buffer + part);
617 }
618 offset = offset > size ? offset - size : 0;
619 block = block->fNext;
620 }
621 return false;
622 }
623
copyTo(void * dst) const624 void SkDynamicMemoryWStream::copyTo(void* dst) const
625 {
626 if (fCopy) {
627 memcpy(dst, fCopy->data(), fBytesWritten);
628 } else {
629 Block* block = fHead;
630
631 while (block != nullptr) {
632 size_t size = block->written();
633 memcpy(dst, block->start(), size);
634 dst = (void*)((char*)dst + size);
635 block = block->fNext;
636 }
637 }
638 }
639
writeToStream(SkWStream * dst) const640 void SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
641 for (Block* block = fHead; block != nullptr; block = block->fNext) {
642 dst->write(block->start(), block->written());
643 }
644 }
645
padToAlign4()646 void SkDynamicMemoryWStream::padToAlign4()
647 {
648 // cast to remove unary-minus warning
649 int padBytes = -(int)fBytesWritten & 0x03;
650 if (padBytes == 0)
651 return;
652 int zero = 0;
653 write(&zero, padBytes);
654 }
655
copyToData() const656 SkData* SkDynamicMemoryWStream::copyToData() const {
657 if (nullptr == fCopy) {
658 SkData* data = SkData::NewUninitialized(fBytesWritten);
659 // be sure to call copyTo() before we assign to fCopy
660 this->copyTo(data->writable_data());
661 fCopy = data;
662 }
663 return SkRef(fCopy);
664 }
665
invalidateCopy()666 void SkDynamicMemoryWStream::invalidateCopy() {
667 if (fCopy) {
668 fCopy->unref();
669 fCopy = nullptr;
670 }
671 }
672
673 class SkBlockMemoryRefCnt : public SkRefCnt {
674 public:
SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block * head)675 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
676
~SkBlockMemoryRefCnt()677 virtual ~SkBlockMemoryRefCnt() {
678 SkDynamicMemoryWStream::Block* block = fHead;
679 while (block != nullptr) {
680 SkDynamicMemoryWStream::Block* next = block->fNext;
681 sk_free(block);
682 block = next;
683 }
684 }
685
686 SkDynamicMemoryWStream::Block* const fHead;
687 };
688
689 class SkBlockMemoryStream : public SkStreamAsset {
690 public:
SkBlockMemoryStream(SkDynamicMemoryWStream::Block * head,size_t size)691 SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
692 : fBlockMemory(new SkBlockMemoryRefCnt(head))
693 , fCurrent(head)
694 , fSize(size)
695 , fOffset(0)
696 , fCurrentOffset(0) {}
697
SkBlockMemoryStream(SkBlockMemoryRefCnt * headRef,size_t size)698 SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
699 : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
700 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
701
read(void * buffer,size_t rawCount)702 size_t read(void* buffer, size_t rawCount) override {
703 size_t count = rawCount;
704 if (fOffset + count > fSize) {
705 count = fSize - fOffset;
706 }
707 size_t bytesLeftToRead = count;
708 while (fCurrent != nullptr) {
709 size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
710 size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
711 if (buffer) {
712 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
713 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
714 }
715 if (bytesLeftToRead <= bytesFromCurrent) {
716 fCurrentOffset += bytesFromCurrent;
717 fOffset += count;
718 return count;
719 }
720 bytesLeftToRead -= bytesFromCurrent;
721 fCurrent = fCurrent->fNext;
722 fCurrentOffset = 0;
723 }
724 SkASSERT(false);
725 return 0;
726 }
727
isAtEnd() const728 bool isAtEnd() const override {
729 return fOffset == fSize;
730 }
731
peek(void * buff,size_t bytesToPeek) const732 size_t peek(void* buff, size_t bytesToPeek) const override {
733 SkASSERT(buff != nullptr);
734
735 bytesToPeek = SkTMin(bytesToPeek, fSize - fOffset);
736
737 size_t bytesLeftToPeek = bytesToPeek;
738 char* buffer = static_cast<char*>(buff);
739 const SkDynamicMemoryWStream::Block* current = fCurrent;
740 size_t currentOffset = fCurrentOffset;
741 while (bytesLeftToPeek) {
742 SkASSERT(current);
743 size_t bytesFromCurrent =
744 SkTMin(current->written() - currentOffset, bytesLeftToPeek);
745 memcpy(buffer, current->start() + currentOffset, bytesFromCurrent);
746 bytesLeftToPeek -= bytesFromCurrent;
747 buffer += bytesFromCurrent;
748 current = current->fNext;
749 currentOffset = 0;
750 }
751 return bytesToPeek;
752 }
753
rewind()754 bool rewind() override {
755 fCurrent = fBlockMemory->fHead;
756 fOffset = 0;
757 fCurrentOffset = 0;
758 return true;
759 }
760
duplicate() const761 SkBlockMemoryStream* duplicate() const override {
762 return new SkBlockMemoryStream(fBlockMemory.get(), fSize);
763 }
764
getPosition() const765 size_t getPosition() const override {
766 return fOffset;
767 }
768
seek(size_t position)769 bool seek(size_t position) override {
770 // If possible, skip forward.
771 if (position >= fOffset) {
772 size_t skipAmount = position - fOffset;
773 return this->skip(skipAmount) == skipAmount;
774 }
775 // If possible, move backward within the current block.
776 size_t moveBackAmount = fOffset - position;
777 if (moveBackAmount <= fCurrentOffset) {
778 fCurrentOffset -= moveBackAmount;
779 fOffset -= moveBackAmount;
780 return true;
781 }
782 // Otherwise rewind and move forward.
783 return this->rewind() && this->skip(position) == position;
784 }
785
move(long offset)786 bool move(long offset) override {
787 return seek(fOffset + offset);
788 }
789
fork() const790 SkBlockMemoryStream* fork() const override {
791 SkAutoTDelete<SkBlockMemoryStream> that(this->duplicate());
792 that->fCurrent = this->fCurrent;
793 that->fOffset = this->fOffset;
794 that->fCurrentOffset = this->fCurrentOffset;
795 return that.detach();
796 }
797
getLength() const798 size_t getLength() const override {
799 return fSize;
800 }
801
getMemoryBase()802 const void* getMemoryBase() override {
803 if (nullptr != fBlockMemory->fHead &&
804 nullptr == fBlockMemory->fHead->fNext) {
805 return fBlockMemory->fHead->start();
806 }
807 return nullptr;
808 }
809
810 private:
811 SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
812 SkDynamicMemoryWStream::Block const * fCurrent;
813 size_t const fSize;
814 size_t fOffset;
815 size_t fCurrentOffset;
816 };
817
detachAsStream()818 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
819 if (fCopy) {
820 SkMemoryStream* stream = new SkMemoryStream(fCopy);
821 this->reset();
822 return stream;
823 }
824 SkBlockMemoryStream* stream = new SkBlockMemoryStream(fHead, fBytesWritten);
825 fHead = 0;
826 this->reset();
827 return stream;
828 }
829
830 ///////////////////////////////////////////////////////////////////////////////
831
newline()832 void SkDebugWStream::newline()
833 {
834 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
835 SkDebugf("\n");
836 fBytesWritten++;
837 #endif
838 }
839
write(const void * buffer,size_t size)840 bool SkDebugWStream::write(const void* buffer, size_t size)
841 {
842 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
843 char* s = new char[size+1];
844 memcpy(s, buffer, size);
845 s[size] = 0;
846 SkDebugf("%s", s);
847 delete[] s;
848 fBytesWritten += size;
849 #endif
850 return true;
851 }
852
853 ///////////////////////////////////////////////////////////////////////////////
854 ///////////////////////////////////////////////////////////////////////////////
855
856
mmap_filename(const char path[])857 static SkData* mmap_filename(const char path[]) {
858 FILE* file = sk_fopen(path, kRead_SkFILE_Flag);
859 if (nullptr == file) {
860 return nullptr;
861 }
862
863 SkData* data = SkData::NewFromFILE(file);
864 sk_fclose(file);
865 return data;
866 }
867
NewFromFile(const char path[])868 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
869 SkAutoTUnref<SkData> data(mmap_filename(path));
870 if (data.get()) {
871 return new SkMemoryStream(data.get());
872 }
873
874 // If we get here, then our attempt at using mmap failed, so try normal
875 // file access.
876 SkFILEStream* stream = new SkFILEStream(path);
877 if (!stream->isValid()) {
878 delete stream;
879 stream = nullptr;
880 }
881 return stream;
882 }
883
884 // Declared in SkStreamPriv.h:
SkCopyStreamToData(SkStream * stream)885 SkData* SkCopyStreamToData(SkStream* stream) {
886 SkASSERT(stream != nullptr);
887
888 if (stream->hasLength()) {
889 return SkData::NewFromStream(stream, stream->getLength());
890 }
891
892 SkDynamicMemoryWStream tempStream;
893 const size_t bufferSize = 4096;
894 char buffer[bufferSize];
895 do {
896 size_t bytesRead = stream->read(buffer, bufferSize);
897 tempStream.write(buffer, bytesRead);
898 } while (!stream->isAtEnd());
899 return tempStream.copyToData();
900 }
901
SkStreamCopy(SkWStream * out,SkStream * input)902 bool SkStreamCopy(SkWStream* out, SkStream* input) {
903 const char* base = static_cast<const char*>(input->getMemoryBase());
904 if (base && input->hasPosition() && input->hasLength()) {
905 // Shortcut that avoids the while loop.
906 size_t position = input->getPosition();
907 size_t length = input->getLength();
908 SkASSERT(length >= position);
909 return out->write(&base[position], length - position);
910 }
911 char scratch[4096];
912 size_t count;
913 while (true) {
914 count = input->read(scratch, sizeof(scratch));
915 if (0 == count) {
916 return true;
917 }
918 if (!out->write(scratch, count)) {
919 return false;
920 }
921 }
922 }
923