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 SK_DEFINE_INST_COUNT(SkStream) 17 SK_DEFINE_INST_COUNT(SkWStream) 18 SK_DEFINE_INST_COUNT(SkFILEStream) 19 SK_DEFINE_INST_COUNT(SkMemoryStream) 20 SK_DEFINE_INST_COUNT(SkFILEWStream) 21 SK_DEFINE_INST_COUNT(SkMemoryWStream) 22 SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream) 23 SK_DEFINE_INST_COUNT(SkDebugWStream) 24 25 /////////////////////////////////////////////////////////////////////////////// 26 27 28 int8_t SkStream::readS8() { 29 int8_t value; 30 SkDEBUGCODE(size_t len =) this->read(&value, 1); 31 SkASSERT(1 == len); 32 return value; 33 } 34 35 int16_t SkStream::readS16() { 36 int16_t value; 37 SkDEBUGCODE(size_t len =) this->read(&value, 2); 38 SkASSERT(2 == len); 39 return value; 40 } 41 42 int32_t SkStream::readS32() { 43 int32_t value; 44 SkDEBUGCODE(size_t len =) this->read(&value, 4); 45 SkASSERT(4 == len); 46 return value; 47 } 48 49 SkScalar SkStream::readScalar() { 50 SkScalar value; 51 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar)); 52 SkASSERT(sizeof(SkScalar) == len); 53 return value; 54 } 55 56 #define SK_MAX_BYTE_FOR_U8 0xFD 57 #define SK_BYTE_SENTINEL_FOR_U16 0xFE 58 #define SK_BYTE_SENTINEL_FOR_U32 0xFF 59 60 size_t SkStream::readPackedUInt() { 61 uint8_t byte; 62 if (!this->read(&byte, 1)) { 63 return 0; 64 } 65 if (SK_BYTE_SENTINEL_FOR_U16 == byte) { 66 return this->readU16(); 67 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) { 68 return this->readU32(); 69 } else { 70 return byte; 71 } 72 } 73 74 SkData* SkStream::readData() { 75 size_t size = this->readU32(); 76 if (0 == size) { 77 return SkData::NewEmpty(); 78 } else { 79 void* buffer = sk_malloc_throw(size); 80 this->read(buffer, size); 81 return SkData::NewFromMalloc(buffer, size); 82 } 83 } 84 85 ////////////////////////////////////////////////////////////////////////////////////// 86 87 SkWStream::~SkWStream() 88 { 89 } 90 91 void SkWStream::newline() 92 { 93 this->write("\n", 1); 94 } 95 96 void SkWStream::flush() 97 { 98 } 99 100 bool SkWStream::writeText(const char text[]) 101 { 102 SkASSERT(text); 103 return this->write(text, strlen(text)); 104 } 105 106 bool SkWStream::writeDecAsText(int32_t dec) 107 { 108 SkString tmp; 109 tmp.appendS32(dec); 110 return this->write(tmp.c_str(), tmp.size()); 111 } 112 113 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits) 114 { 115 SkString tmp; 116 tmp.appendS64(dec, minDigits); 117 return this->write(tmp.c_str(), tmp.size()); 118 } 119 120 bool SkWStream::writeHexAsText(uint32_t hex, int digits) 121 { 122 SkString tmp; 123 tmp.appendHex(hex, digits); 124 return this->write(tmp.c_str(), tmp.size()); 125 } 126 127 bool SkWStream::writeScalarAsText(SkScalar value) 128 { 129 SkString tmp; 130 tmp.appendScalar(value); 131 return this->write(tmp.c_str(), tmp.size()); 132 } 133 134 bool SkWStream::write8(U8CPU value) { 135 uint8_t v = SkToU8(value); 136 return this->write(&v, 1); 137 } 138 139 bool SkWStream::write16(U16CPU value) { 140 uint16_t v = SkToU16(value); 141 return this->write(&v, 2); 142 } 143 144 bool SkWStream::write32(uint32_t value) { 145 return this->write(&value, 4); 146 } 147 148 bool SkWStream::writeScalar(SkScalar value) { 149 return this->write(&value, sizeof(value)); 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 = 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(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 return data; 368 } 369 370 void SkMemoryStream::skipToAlign4() { 371 // cast to remove unary-minus warning 372 fOffset += -(int)fOffset & 0x03; 373 } 374 375 size_t SkMemoryStream::read(void* buffer, size_t size) { 376 size_t dataSize = fData->size(); 377 378 if (size > dataSize - fOffset) { 379 size = dataSize - fOffset; 380 } 381 if (buffer) { 382 memcpy(buffer, fData->bytes() + fOffset, size); 383 } 384 fOffset += size; 385 return size; 386 } 387 388 bool SkMemoryStream::isAtEnd() const { 389 return fOffset == fData->size(); 390 } 391 392 bool SkMemoryStream::rewind() { 393 fOffset = 0; 394 return true; 395 } 396 397 SkMemoryStream* SkMemoryStream::duplicate() const { 398 return SkNEW_ARGS(SkMemoryStream, (fData)); 399 } 400 401 size_t SkMemoryStream::getPosition() const { 402 return fOffset; 403 } 404 405 bool SkMemoryStream::seek(size_t position) { 406 fOffset = position > fData->size() 407 ? fData->size() 408 : position; 409 return true; 410 } 411 412 bool SkMemoryStream::move(long offset) { 413 return this->seek(fOffset + offset); 414 } 415 416 SkMemoryStream* SkMemoryStream::fork() const { 417 SkAutoTUnref<SkMemoryStream> that(this->duplicate()); 418 that->seek(fOffset); 419 return that.detach(); 420 } 421 422 size_t SkMemoryStream::getLength() const { 423 return fData->size(); 424 } 425 426 const void* SkMemoryStream::getMemoryBase() { 427 return fData->data(); 428 } 429 430 const void* SkMemoryStream::getAtPos() { 431 return fData->bytes() + fOffset; 432 } 433 434 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 435 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 436 437 SkFILEWStream::SkFILEWStream(const char path[]) 438 { 439 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 440 } 441 442 SkFILEWStream::~SkFILEWStream() 443 { 444 if (fFILE) 445 sk_fclose(fFILE); 446 } 447 448 bool SkFILEWStream::write(const void* buffer, size_t size) 449 { 450 if (fFILE == NULL) 451 return false; 452 453 if (sk_fwrite(buffer, size, fFILE) != size) 454 { 455 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);) 456 sk_fclose(fFILE); 457 fFILE = NULL; 458 return false; 459 } 460 return true; 461 } 462 463 void SkFILEWStream::flush() 464 { 465 if (fFILE) 466 sk_fflush(fFILE); 467 } 468 469 //////////////////////////////////////////////////////////////////////// 470 471 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size) 472 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0) 473 { 474 } 475 476 bool SkMemoryWStream::write(const void* buffer, size_t size) 477 { 478 size = SkMin32(size, fMaxLength - fBytesWritten); 479 if (size > 0) 480 { 481 memcpy(fBuffer + fBytesWritten, buffer, size); 482 fBytesWritten += size; 483 return true; 484 } 485 return false; 486 } 487 488 //////////////////////////////////////////////////////////////////////// 489 490 #define SkDynamicMemoryWStream_MinBlockSize 256 491 492 struct SkDynamicMemoryWStream::Block { 493 Block* fNext; 494 char* fCurr; 495 char* fStop; 496 497 const char* start() const { return (const char*)(this + 1); } 498 char* start() { return (char*)(this + 1); } 499 size_t avail() const { return fStop - fCurr; } 500 size_t written() const { return fCurr - this->start(); } 501 502 void init(size_t size) 503 { 504 fNext = NULL; 505 fCurr = this->start(); 506 fStop = this->start() + size; 507 } 508 509 const void* append(const void* data, size_t size) 510 { 511 SkASSERT((size_t)(fStop - fCurr) >= size); 512 memcpy(fCurr, data, size); 513 fCurr += size; 514 return (const void*)((const char*)data + size); 515 } 516 }; 517 518 SkDynamicMemoryWStream::SkDynamicMemoryWStream() 519 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL) 520 { 521 } 522 523 SkDynamicMemoryWStream::~SkDynamicMemoryWStream() 524 { 525 reset(); 526 } 527 528 void SkDynamicMemoryWStream::reset() 529 { 530 this->invalidateCopy(); 531 532 Block* block = fHead; 533 534 while (block != NULL) { 535 Block* next = block->fNext; 536 sk_free(block); 537 block = next; 538 } 539 fHead = fTail = NULL; 540 fBytesWritten = 0; 541 } 542 543 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) 544 { 545 if (count > 0) { 546 this->invalidateCopy(); 547 548 fBytesWritten += count; 549 550 size_t size; 551 552 if (fTail != NULL && fTail->avail() > 0) { 553 size = SkMin32(fTail->avail(), count); 554 buffer = fTail->append(buffer, size); 555 SkASSERT(count >= size); 556 count -= size; 557 if (count == 0) 558 return true; 559 } 560 561 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize); 562 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 563 block->init(size); 564 block->append(buffer, count); 565 566 if (fTail != NULL) 567 fTail->fNext = block; 568 else 569 fHead = fTail = block; 570 fTail = block; 571 } 572 return true; 573 } 574 575 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count) 576 { 577 if (offset + count > fBytesWritten) { 578 return false; // test does not partially modify 579 } 580 581 this->invalidateCopy(); 582 583 Block* block = fHead; 584 while (block != NULL) { 585 size_t size = block->written(); 586 if (offset < size) { 587 size_t part = offset + count > size ? size - offset : count; 588 memcpy(block->start() + offset, buffer, part); 589 if (count <= part) 590 return true; 591 count -= part; 592 buffer = (const void*) ((char* ) buffer + part); 593 } 594 offset = offset > size ? offset - size : 0; 595 block = block->fNext; 596 } 597 return false; 598 } 599 600 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) 601 { 602 if (offset + count > fBytesWritten) 603 return false; // test does not partially modify 604 Block* block = fHead; 605 while (block != NULL) { 606 size_t size = block->written(); 607 if (offset < size) { 608 size_t part = offset + count > size ? size - offset : count; 609 memcpy(buffer, block->start() + offset, part); 610 if (count <= part) 611 return true; 612 count -= part; 613 buffer = (void*) ((char* ) buffer + part); 614 } 615 offset = offset > size ? offset - size : 0; 616 block = block->fNext; 617 } 618 return false; 619 } 620 621 void SkDynamicMemoryWStream::copyTo(void* dst) const 622 { 623 if (fCopy) { 624 memcpy(dst, fCopy->data(), fBytesWritten); 625 } else { 626 Block* block = fHead; 627 628 while (block != NULL) { 629 size_t size = block->written(); 630 memcpy(dst, block->start(), size); 631 dst = (void*)((char*)dst + size); 632 block = block->fNext; 633 } 634 } 635 } 636 637 void SkDynamicMemoryWStream::padToAlign4() 638 { 639 // cast to remove unary-minus warning 640 int padBytes = -(int)fBytesWritten & 0x03; 641 if (padBytes == 0) 642 return; 643 int zero = 0; 644 write(&zero, padBytes); 645 } 646 647 SkData* SkDynamicMemoryWStream::copyToData() const { 648 if (NULL == fCopy) { 649 void* buffer = sk_malloc_throw(fBytesWritten); 650 this->copyTo(buffer); 651 fCopy = SkData::NewFromMalloc(buffer, fBytesWritten); 652 } 653 fCopy->ref(); 654 return fCopy; 655 } 656 657 void SkDynamicMemoryWStream::invalidateCopy() { 658 if (fCopy) { 659 fCopy->unref(); 660 fCopy = NULL; 661 } 662 } 663 664 class SkBlockMemoryRefCnt : public SkRefCnt { 665 public: 666 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { } 667 668 virtual ~SkBlockMemoryRefCnt() { 669 SkDynamicMemoryWStream::Block* block = fHead; 670 while (block != NULL) { 671 SkDynamicMemoryWStream::Block* next = block->fNext; 672 sk_free(block); 673 block = next; 674 } 675 } 676 677 SkDynamicMemoryWStream::Block* const fHead; 678 }; 679 680 class SkBlockMemoryStream : public SkStreamAsset { 681 public: 682 SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size) 683 : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head) 684 , fSize(size) , fOffset(0), fCurrentOffset(0) { } 685 686 SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size) 687 : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead) 688 , fSize(size) , fOffset(0), fCurrentOffset(0) { } 689 690 virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE { 691 size_t count = rawCount; 692 if (fOffset + count > fSize) { 693 count = fSize - fOffset; 694 } 695 size_t bytesLeftToRead = count; 696 while (fCurrent != NULL) { 697 size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset; 698 size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent 699 ? bytesLeftToRead : bytesLeftInCurrent; 700 if (buffer) { 701 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent); 702 } 703 if (bytesLeftToRead <= bytesFromCurrent) { 704 fCurrentOffset += bytesFromCurrent; 705 fOffset += count; 706 return count; 707 } 708 bytesLeftToRead -= bytesFromCurrent; 709 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent); 710 fCurrent = fCurrent->fNext; 711 fCurrentOffset = 0; 712 } 713 SkASSERT(false); 714 return 0; 715 } 716 717 virtual bool isAtEnd() const SK_OVERRIDE { 718 return fOffset == fSize; 719 } 720 721 virtual bool rewind() SK_OVERRIDE { 722 fCurrent = fBlockMemory->fHead; 723 fOffset = 0; 724 fCurrentOffset = 0; 725 return true; 726 } 727 728 virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE { 729 return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize)); 730 } 731 732 virtual size_t getPosition() const SK_OVERRIDE { 733 return fOffset; 734 } 735 736 virtual bool seek(size_t position) SK_OVERRIDE { 737 // If possible, skip forward. 738 if (position >= fOffset) { 739 size_t skipAmount = position - fOffset; 740 return this->skip(skipAmount) == skipAmount; 741 } 742 // If possible, move backward within the current block. 743 size_t moveBackAmount = fOffset - position; 744 if (moveBackAmount <= fCurrentOffset) { 745 fCurrentOffset -= moveBackAmount; 746 fOffset -= moveBackAmount; 747 return true; 748 } 749 // Otherwise rewind and move forward. 750 return this->rewind() && this->skip(position) == position; 751 } 752 753 virtual bool move(long offset) SK_OVERRIDE { 754 return seek(fOffset + offset); 755 } 756 757 virtual SkBlockMemoryStream* fork() const SK_OVERRIDE { 758 SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate()); 759 that->fCurrent = this->fCurrent; 760 that->fOffset = this->fOffset; 761 that->fCurrentOffset = this->fCurrentOffset; 762 return that.detach(); 763 } 764 765 virtual size_t getLength() const SK_OVERRIDE { 766 return fSize; 767 } 768 769 virtual const void* getMemoryBase() SK_OVERRIDE { 770 if (NULL == fBlockMemory->fHead->fNext) { 771 return fBlockMemory->fHead->start(); 772 } 773 return NULL; 774 } 775 776 private: 777 SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory; 778 SkDynamicMemoryWStream::Block const * fCurrent; 779 size_t const fSize; 780 size_t fOffset; 781 size_t fCurrentOffset; 782 }; 783 784 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() { 785 if (fCopy) { 786 SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy)); 787 this->reset(); 788 return stream; 789 } 790 SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten)); 791 fHead = 0; 792 this->reset(); 793 return stream; 794 } 795 796 /////////////////////////////////////////////////////////////////////////////// 797 798 void SkDebugWStream::newline() 799 { 800 #if defined(SK_DEBUG) || defined(SK_DEVELOPER) 801 SkDebugf("\n"); 802 #endif 803 } 804 805 bool SkDebugWStream::write(const void* buffer, size_t size) 806 { 807 #if defined(SK_DEBUG) || defined(SK_DEVELOPER) 808 char* s = new char[size+1]; 809 memcpy(s, buffer, size); 810 s[size] = 0; 811 SkDebugf("%s", s); 812 delete[] s; 813 #endif 814 return true; 815 } 816 817 /////////////////////////////////////////////////////////////////////////////// 818 /////////////////////////////////////////////////////////////////////////////// 819 820 821 static SkData* mmap_filename(const char path[]) { 822 SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag); 823 if (NULL == file) { 824 return NULL; 825 } 826 827 SkData* data = SkData::NewFromFILE(file); 828 sk_fclose(file); 829 return data; 830 } 831 832 SkStreamAsset* SkStream::NewFromFile(const char path[]) { 833 SkAutoTUnref<SkData> data(mmap_filename(path)); 834 if (data.get()) { 835 return SkNEW_ARGS(SkMemoryStream, (data.get())); 836 } 837 838 // If we get here, then our attempt at using mmap failed, so try normal 839 // file access. 840 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); 841 if (!stream->isValid()) { 842 stream->unref(); 843 stream = NULL; 844 } 845 return stream; 846 } 847