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 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 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 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 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 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 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 78 SkWStream::~SkWStream() 79 { 80 } 81 82 void SkWStream::newline() 83 { 84 this->write("\n", 1); 85 } 86 87 void SkWStream::flush() 88 { 89 } 90 91 bool SkWStream::writeText(const char text[]) 92 { 93 SkASSERT(text); 94 return this->write(text, strlen(text)); 95 } 96 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 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 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 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 125 bool SkWStream::write8(U8CPU value) { 126 uint8_t v = SkToU8(value); 127 return this->write(&v, 1); 128 } 129 130 bool SkWStream::write16(U16CPU value) { 131 uint16_t v = SkToU16(value); 132 return this->write(&v, 2); 133 } 134 135 bool SkWStream::write32(uint32_t value) { 136 return this->write(&value, 4); 137 } 138 139 bool SkWStream::writeScalar(SkScalar value) { 140 return this->write(&value, sizeof(value)); 141 } 142 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 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 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 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 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 206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership) 207 : fFILE((SkFILE*)file) 208 , fOwnership(ownership) { 209 } 210 211 SkFILEStream::~SkFILEStream() { 212 if (fFILE && fOwnership != kCallerRetains_Ownership) { 213 sk_fclose(fFILE); 214 } 215 } 216 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 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 235 bool SkFILEStream::isAtEnd() const { 236 return sk_feof(fFILE); 237 } 238 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 251 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 274 size_t SkFILEStream::getPosition() const { 275 return sk_ftell(fFILE); 276 } 277 278 bool SkFILEStream::seek(size_t position) { 279 return sk_fseek(fFILE, position); 280 } 281 282 bool SkFILEStream::move(long offset) { 283 return sk_fmove(fFILE, offset); 284 } 285 286 SkStreamAsset* SkFILEStream::fork() const { 287 SkAutoTUnref<SkStreamAsset> that(this->duplicate()); 288 that->seek(this->getPosition()); 289 return that.detach(); 290 } 291 292 size_t SkFILEStream::getLength() const { 293 return sk_fgetsize(fFILE); 294 } 295 296 const void* SkFILEStream::getMemoryBase() { 297 if (NULL == fData.get()) { 298 return NULL; 299 } 300 return fData->data(); 301 } 302 303 /////////////////////////////////////////////////////////////////////////////// 304 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 313 SkMemoryStream::SkMemoryStream() { 314 fData = SkData::NewEmpty(); 315 fOffset = 0; 316 } 317 318 SkMemoryStream::SkMemoryStream(size_t size) { 319 fData = SkData::NewFromMalloc(sk_malloc_throw(size), size); 320 fOffset = 0; 321 } 322 323 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) { 324 fData = newFromParams(src, size, copyData); 325 fOffset = 0; 326 } 327 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 338 SkMemoryStream::~SkMemoryStream() { 339 fData->unref(); 340 } 341 342 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) { 343 fData->unref(); 344 fData = SkData::NewFromMalloc(src, size); 345 fOffset = 0; 346 } 347 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 354 SkData* SkMemoryStream::copyToData() const { 355 fData->ref(); 356 return fData; 357 } 358 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 371 void SkMemoryStream::skipToAlign4() { 372 // cast to remove unary-minus warning 373 fOffset += -(int)fOffset & 0x03; 374 } 375 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 389 bool SkMemoryStream::isAtEnd() const { 390 return fOffset == fData->size(); 391 } 392 393 bool SkMemoryStream::rewind() { 394 fOffset = 0; 395 return true; 396 } 397 398 SkMemoryStream* SkMemoryStream::duplicate() const { 399 return SkNEW_ARGS(SkMemoryStream, (fData)); 400 } 401 402 size_t SkMemoryStream::getPosition() const { 403 return fOffset; 404 } 405 406 bool SkMemoryStream::seek(size_t position) { 407 fOffset = position > fData->size() 408 ? fData->size() 409 : position; 410 return true; 411 } 412 413 bool SkMemoryStream::move(long offset) { 414 return this->seek(fOffset + offset); 415 } 416 417 SkMemoryStream* SkMemoryStream::fork() const { 418 SkAutoTUnref<SkMemoryStream> that(this->duplicate()); 419 that->seek(fOffset); 420 return that.detach(); 421 } 422 423 size_t SkMemoryStream::getLength() const { 424 return fData->size(); 425 } 426 427 const void* SkMemoryStream::getMemoryBase() { 428 return fData->data(); 429 } 430 431 const void* SkMemoryStream::getAtPos() { 432 return fData->bytes() + fOffset; 433 } 434 435 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 436 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 437 438 SkFILEWStream::SkFILEWStream(const char path[]) 439 { 440 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 441 } 442 443 SkFILEWStream::~SkFILEWStream() 444 { 445 if (fFILE) { 446 sk_fclose(fFILE); 447 } 448 } 449 450 size_t SkFILEWStream::bytesWritten() const { 451 return sk_ftell(fFILE); 452 } 453 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 470 void SkFILEWStream::flush() 471 { 472 if (fFILE) { 473 sk_fflush(fFILE); 474 } 475 } 476 477 //////////////////////////////////////////////////////////////////////// 478 479 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size) 480 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0) 481 { 482 } 483 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 503 const char* start() const { return (const char*)(this + 1); } 504 char* start() { return (char*)(this + 1); } 505 size_t avail() const { return fStop - fCurr; } 506 size_t written() const { return fCurr - this->start(); } 507 508 void init(size_t size) 509 { 510 fNext = NULL; 511 fCurr = this->start(); 512 fStop = this->start() + size; 513 } 514 515 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 524 SkDynamicMemoryWStream::SkDynamicMemoryWStream() 525 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL) 526 { 527 } 528 529 SkDynamicMemoryWStream::~SkDynamicMemoryWStream() 530 { 531 reset(); 532 } 533 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 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 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 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 627 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 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 653 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 663 void SkDynamicMemoryWStream::invalidateCopy() { 664 if (fCopy) { 665 fCopy->unref(); 666 fCopy = NULL; 667 } 668 } 669 670 class SkBlockMemoryRefCnt : public SkRefCnt { 671 public: 672 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { } 673 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: 688 SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size) 689 : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head) 690 , fSize(size) , fOffset(0), fCurrentOffset(0) { } 691 692 SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size) 693 : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead) 694 , fSize(size) , fOffset(0), fCurrentOffset(0) { } 695 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 722 virtual bool isAtEnd() const SK_OVERRIDE { 723 return fOffset == fSize; 724 } 725 726 virtual bool rewind() SK_OVERRIDE { 727 fCurrent = fBlockMemory->fHead; 728 fOffset = 0; 729 fCurrentOffset = 0; 730 return true; 731 } 732 733 virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE { 734 return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize)); 735 } 736 737 virtual size_t getPosition() const SK_OVERRIDE { 738 return fOffset; 739 } 740 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 758 virtual bool move(long offset) SK_OVERRIDE { 759 return seek(fOffset + offset); 760 } 761 762 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 770 virtual size_t getLength() const SK_OVERRIDE { 771 return fSize; 772 } 773 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 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 803 void SkDebugWStream::newline() 804 { 805 #if defined(SK_DEBUG) || defined(SK_DEVELOPER) 806 SkDebugf("\n"); 807 fBytesWritten++; 808 #endif 809 } 810 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 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 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