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