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