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