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