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